This is an automated email from the ASF dual-hosted git repository.
jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git
The following commit(s) were added to refs/heads/master by this push:
new 670a56b Tests.
670a56b is described below
commit 670a56ba8d243337bdde42c6180003565f024dbe
Author: JamesBognar <[email protected]>
AuthorDate: Sat May 12 20:11:18 2018 -0400
Tests.
---
.../juneau/rest/test/ErrorConditionsResource.java | 137 --------------
.../java/org/apache/juneau/rest/test/Root.java | 1 -
.../juneau/rest/test/ErrorConditionsTest.java | 210 ---------------------
.../org/apache/juneau/rest/test/_TestSuite.java | 1 -
.../org/apache/juneau/rest/StatusCodesTest.java | 201 +++++++++++++++++++-
5 files changed, 197 insertions(+), 353 deletions(-)
diff --git
a/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/ErrorConditionsResource.java
b/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/ErrorConditionsResource.java
deleted file mode 100644
index 1a6bf1f..0000000
---
a/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/ErrorConditionsResource.java
+++ /dev/null
@@ -1,137 +0,0 @@
-//
***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file *
-// * distributed with this work for additional information regarding copyright
ownership. The ASF licenses this file *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not
use this file except in compliance *
-// * with the License. You may obtain a copy of the License at
*
-// *
*
-// * http://www.apache.org/licenses/LICENSE-2.0
*
-// *
*
-// * Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
express or implied. See the License for the *
-// * specific language governing permissions and limitations under the
License. *
-//
***************************************************************************************************************************
-package org.apache.juneau.rest.test;
-
-import static org.apache.juneau.http.HttpMethodName.*;
-
-import org.apache.juneau.rest.*;
-import org.apache.juneau.rest.annotation.*;
-
-/**
- * JUnit automated testcase resource.
- * Validates correct parser is used.
- */
-@RestResource(
- path="/testErrorConditions"
-)
-public class ErrorConditionsResource extends BasicRestServlet {
- private static final long serialVersionUID = 1L;
-
-
//====================================================================================================
- // Test non-existent properties
-
//====================================================================================================
- @RestMethod(name=PUT, path="/testNonExistentBeanProperties")
- public String testNonExistentBeanProperties(@Body Test1 in) {
- return "OK";
- }
-
- public static class Test1 {
- public String f1;
- }
-
-
//====================================================================================================
- // Test trying to set properties to wrong data type
-
//====================================================================================================
- @RestMethod(name=PUT, path="/testWrongDataType")
- public String testWrongDataType(@Body Test2 in) {
- return "OK";
- }
-
- public static class Test2 {
- public int f1;
- }
-
-
//====================================================================================================
- // Test trying to parse into class with non-public no-arg constructor.
-
//====================================================================================================
- @RestMethod(name=PUT, path="/testParseIntoNonConstructableBean")
- public String testParseIntoNonConstructableBean(@Body Test3a in) {
- return "OK";
- }
-
- public static class Test3a {
- public int f1;
- private Test3a(){}
- }
-
-
//====================================================================================================
- // Test trying to parse into non-static inner class
-
//====================================================================================================
- @RestMethod(name=PUT, path="/testParseIntoNonStaticInnerClass")
- public String testParseIntoNonStaticInnerClass(@Body Test3b in) {
- return "OK";
- }
-
- public class Test3b {
- public Test3b(){}
- }
-
-
//====================================================================================================
- // Test trying to parse into non-public inner class
-
//====================================================================================================
- @RestMethod(name=PUT, path="/testParseIntoNonPublicInnerClass")
- public String testParseIntoNonPublicInnerClass(@Body Test3b1 in) {
- return "OK";
- }
-
- static class Test3b1 {
- public Test3b1(){}
- }
-
-
//====================================================================================================
- // Test exception thrown during bean construction.
-
//====================================================================================================
- @RestMethod(name=PUT, path="/testThrownConstructorException")
- public String testThrownConstructorException(@Body Test3c in) {
- return "OK";
- }
-
- public static class Test3c {
- public int f1;
- private Test3c(){}
- public static Test3c valueOf(String s) {
- throw new RuntimeException("Test error");
- }
- }
-
-
//====================================================================================================
- // Test trying to set parameters to invalid types.
-
//====================================================================================================
- @RestMethod(name=PUT, path="/testSetParameterToInvalidTypes/{a1}")
- public String testSetParameterToInvalidTypes(@Query("p1") int t1,
@Path("a1") int a1, @Header("h1") int h1) {
- return "OK";
- }
-
-
//====================================================================================================
- // Test SC_NOT_FOUND & SC_METHOD_NOT_ALLOWED
-
//====================================================================================================
- @RestMethod(name=GET, path="/test404and405")
- public String test404and405() {
- return "OK";
- }
-
-
//====================================================================================================
- // Test SC_PRECONDITION_FAILED
-
//====================================================================================================
- @RestMethod(name=GET, path="/test412", matchers=NeverMatcher.class)
- public String test412() {
- return "OK";
- }
-
- public static class NeverMatcher extends RestMatcher {
- @Override /* RestMatcher */
- public boolean matches(RestRequest req) {
- return false;
- }
- }
-}
diff --git
a/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/Root.java
b/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/Root.java
index dfabcf8..d78303f 100644
---
a/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/Root.java
+++
b/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/Root.java
@@ -32,7 +32,6 @@ import org.apache.juneau.rest.helper.*;
ClientFuturesResource.class,
ClientVersionResource.class,
ConfigResource.class,
- ErrorConditionsResource.class,
TransformsResource.class,
FormDataResource.class,
GroupsResource.class,
diff --git
a/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/ErrorConditionsTest.java
b/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/ErrorConditionsTest.java
deleted file mode 100644
index 6206efb..0000000
---
a/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/ErrorConditionsTest.java
+++ /dev/null
@@ -1,210 +0,0 @@
-//
***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file *
-// * distributed with this work for additional information regarding copyright
ownership. The ASF licenses this file *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not
use this file except in compliance *
-// * with the License. You may obtain a copy of the License at
*
-// *
*
-// * http://www.apache.org/licenses/LICENSE-2.0
*
-// *
*
-// * Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
express or implied. See the License for the *
-// * specific language governing permissions and limitations under the
License. *
-//
***************************************************************************************************************************
-package org.apache.juneau.rest.test;
-
-import static javax.servlet.http.HttpServletResponse.*;
-import static org.apache.juneau.microservice.testutils.TestUtils.*;
-import static org.junit.Assert.*;
-
-import org.apache.juneau.*;
-import org.apache.juneau.rest.client.*;
-import org.junit.*;
-
-
-public class ErrorConditionsTest extends RestTestcase {
-
- private static String URL = "/testErrorConditions";
- private static boolean debug = false;
- private RestClient client = TestMicroservice.DEFAULT_CLIENT;
-
-
-
//====================================================================================================
- // Test non-existent properties
-
//====================================================================================================
- @Test
- public void testNonExistentBeanProperties() throws Exception {
- String url = URL + "/testNonExistentBeanProperties";
-
- try {
- client.doPut(url + "?noTrace=true", new
ObjectMap("{f2:'foo'}")).getResponseAsString();
- fail("Exception expected");
- } catch (RestCallException e) {
- checkErrorResponse(debug, e, SC_BAD_REQUEST,
- "Could not convert request body content to
class type 'org.apache.juneau.rest.test.ErrorConditionsResource$Test1' using
parser 'org.apache.juneau.json.JsonParser'",
- "Unknown property 'f2' encountered while trying
to parse into class
'org.apache.juneau.rest.test.ErrorConditionsResource$Test1'");
- }
-
- try {
- client.doPut(url + "?noTrace=true", new
ObjectMap("{f1:'foo', f2:'foo'}")).getResponseAsString();
- fail("Exception expected");
- } catch (RestCallException e) {
- checkErrorResponse(debug, e, SC_BAD_REQUEST,
- "Could not convert request body content to
class type 'org.apache.juneau.rest.test.ErrorConditionsResource$Test1' using
parser 'org.apache.juneau.json.JsonParser'",
- "Unknown property 'f2' encountered while trying
to parse into class
'org.apache.juneau.rest.test.ErrorConditionsResource$Test1'");
- }
- }
-
-
//====================================================================================================
- // Test trying to set properties to wrong data type
-
//====================================================================================================
- @Test
- public void testWrongDataType() throws Exception {
- String url = URL + "/testWrongDataType";
- try {
- client.doPut(url + "?noTrace=true", new
ObjectMap("{f1:'foo'}")).getResponseAsString();
- fail("Exception expected");
- } catch (RestCallException e) {
- checkErrorResponse(debug, e, SC_BAD_REQUEST,
- "Invalid number");
- }
- }
-
-
//====================================================================================================
- // Test trying to parse into class with non-public no-arg constructor.
-
//====================================================================================================
- @Test
- public void testParseIntoNonConstructableBean() throws Exception {
- String url = URL + "/testParseIntoNonConstructableBean";
- try {
- client.doPut(url + "?noTrace=true", new
ObjectMap("{f1:1}")).getResponseAsString();
- fail("Exception expected");
- } catch (RestCallException e) {
- checkErrorResponse(debug, e, SC_BAD_REQUEST,
- "Class
'org.apache.juneau.rest.test.ErrorConditionsResource$Test3a' could not be
instantiated.");
- }
- }
-
-
//====================================================================================================
- // Test trying to parse into non-static inner class
-
//====================================================================================================
- @Test
- public void testParseIntoNonStaticInnerClass() throws Exception {
- String url = URL + "/testParseIntoNonStaticInnerClass";
- try {
- client.doPut(url + "?noTrace=true", new
ObjectMap("{f1:1}")).getResponseAsString();
- fail("Exception expected");
- } catch (RestCallException e) {
- checkErrorResponse(debug, e, SC_BAD_REQUEST,
- "Class
'org.apache.juneau.rest.test.ErrorConditionsResource$Test3b' could not be
instantiated. Reason: 'No properties detected on bean class'");
- }
- }
-
-
//====================================================================================================
- // Test trying to parse into non-public inner class
-
//====================================================================================================
- @Test
- public void testParseIntoNonPublicInnerClass() throws Exception {
- String url = URL + "/testParseIntoNonPublicInnerClass";
- try {
- client.doPut(url + "?noTrace=true", new
ObjectMap("{f1:1}")).getResponseAsString();
- fail("Exception expected");
- } catch (RestCallException e) {
- checkErrorResponse(debug, e, SC_BAD_REQUEST,
- "Class
'org.apache.juneau.rest.test.ErrorConditionsResource$Test3b1' could not be
instantiated",
- "Class is not public");
- }
- }
-
-
//====================================================================================================
- // Test exception thrown during bean construction.
-
//====================================================================================================
- @Test
- public void testThrownConstructorException() throws Exception {
- String url = URL + "/testThrownConstructorException";
- try {
- client.doPut(url + "?noTrace=true",
"'foo'").getResponseAsString();
- fail("Exception expected");
- } catch (RestCallException e) {
- checkErrorResponse(debug, e, SC_BAD_REQUEST,
- "Could not convert request body content to
class type 'org.apache.juneau.rest.test.ErrorConditionsResource$Test3c' using
parser 'org.apache.juneau.json.JsonParser'.",
- "Test error");
- }
- }
-
-
//====================================================================================================
- // Test trying to set parameters to invalid types.
-
//====================================================================================================
- @Test
- public void testSetParameterToInvalidTypes() throws Exception {
- String url = URL + "/testSetParameterToInvalidTypes";
- try {
- client.doPut(url + "/1?noTrace=true&p1=foo",
"").getResponseAsString();
- fail("Exception expected");
- } catch (RestCallException e) {
- checkErrorResponse(debug, e, SC_BAD_REQUEST,
- "Could not convert QUERY 'p1' to type 'int' on
method
'org.apache.juneau.rest.test.ErrorConditionsResource.testSetParameterToInvalidTypes'");
- }
-
- try {
- client.doPut(url + "/foo?noTrace=true&p1=1",
"").getResponseAsString();
- fail("Exception expected");
- } catch (RestCallException e) {
- checkErrorResponse(debug, e, SC_BAD_REQUEST,
- "Could not convert PATH 'a1' to type 'int' on
method
'org.apache.juneau.rest.test.ErrorConditionsResource.testSetParameterToInvalidTypes'");
- }
-
- try {
- client.doPut(url + "/1?noTrace=true&p1=1",
"").header("h1", "foo").getResponseAsString();
- fail("Exception expected");
- } catch (RestCallException e) {
- checkErrorResponse(debug, e, SC_BAD_REQUEST,
- "Could not convert HEADER 'h1' to type 'int' on
method
'org.apache.juneau.rest.test.ErrorConditionsResource.testSetParameterToInvalidTypes'");
- }
- }
-
-
//====================================================================================================
- // Test SC_NOT_FOUND & SC_METHOD_NOT_ALLOWED
-
//====================================================================================================
- @Test
- public void test404and405() throws Exception {
- String url = URL + "/test404and405";
- try {
- client.doGet(URL +
"/testNonExistent?noTrace=true").getResponseAsString();
- fail("Exception expected");
- } catch (RestCallException e) {
- checkErrorResponse(debug, e, SC_NOT_FOUND,
- "Method 'GET' not found on resource with
matching pattern on path '/testNonExistent'");
- }
-
- try {
- client.doPut(url + "?noTrace=true",
"").getResponseAsString();
- fail("Exception expected");
- } catch (RestCallException e) {
- checkErrorResponse(debug, e, SC_NOT_FOUND,
- "Method 'PUT' not found on resource with
matching pattern on path '/test404and405'");
- }
-
- try {
- client.doPost(url + "?noTrace=true",
"").getResponseAsString();
- fail("Exception expected");
- } catch (RestCallException e) {
- checkErrorResponse(debug, e, SC_METHOD_NOT_ALLOWED,
- "Method 'POST' not found on resource.");
- }
- }
-
-
//====================================================================================================
- // Test SC_PRECONDITION_FAILED
-
//====================================================================================================
- @Test
- public void test412() throws Exception {
- String url = URL + "/test412";
- try {
- client.doGet(url +
"?noTrace=true").getResponseAsString();
- fail("Exception expected");
- } catch (RestCallException e) {
- checkErrorResponse(debug, e, SC_PRECONDITION_FAILED,
- "Method 'GET' not found on resource on path
'/test412' with matching matcher.");
- }
- }
-}
diff --git
a/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/_TestSuite.java
b/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/_TestSuite.java
index c2a802a..589f004 100644
---
a/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/_TestSuite.java
+++
b/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/_TestSuite.java
@@ -31,7 +31,6 @@ import org.junit.runners.Suite.*;
ClientFuturesTest.class,
ClientVersionTest.class,
ConfigTest.class,
- ErrorConditionsTest.class,
FormDataTest.class,
GroupsTest.class,
GzipTest.class,
diff --git
a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/StatusCodesTest.java
b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/StatusCodesTest.java
index ce9d03b..d4fac10 100644
---
a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/StatusCodesTest.java
+++
b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/StatusCodesTest.java
@@ -16,6 +16,7 @@ import static org.apache.juneau.http.HttpMethodName.*;
import java.io.*;
+import org.apache.juneau.json.*;
import org.apache.juneau.rest.annotation.*;
import org.apache.juneau.rest.mock.*;
import org.junit.*;
@@ -27,9 +28,8 @@ import org.junit.*;
public class StatusCodesTest {
//=================================================================================================================
- // OK
+ // OK (200)
//=================================================================================================================
-
@RestResource
public static class A {
@RestMethod(name=PUT)
@@ -37,7 +37,6 @@ public class StatusCodesTest {
return new StringReader(b);
}
}
-
private static MockRest a = MockRest.create(A.class);
@Test
@@ -45,5 +44,199 @@ public class StatusCodesTest {
a.request("PUT", "/").body("foo").execute().assertStatus(200);
}
- // TODO - Test all the status codes
+
+
//====================================================================================================
+ // Bad Request (400)
+
//====================================================================================================
+ @RestResource(parsers=JsonParser.class)
+ public static class B {
+ @RestMethod(name=PUT, path="/nonExistentBeanProperties")
+ public String b01(@Body B01 in) {
+ return "OK";
+ }
+ public static class B01 {
+ public String f1;
+ }
+ @RestMethod(name=PUT, path="/wrongDataType")
+ public String b02(@Body B02 in) {
+ return "OK";
+ }
+ public static class B02 {
+ public int f1;
+ }
+ @RestMethod(name=PUT, path="/parseIntoNonConstructableBean")
+ public String b03(@Body B03 in) {
+ return "OK";
+ }
+ public static class B03 {
+ public int f1;
+ private B03(){}
+ }
+ @RestMethod(name=PUT, path="/parseIntoNonStaticInnerClass")
+ public String b04(@Body B04 in) {
+ return "OK";
+ }
+ public class B04 {
+ public B04(){}
+ }
+ @RestMethod(name=PUT, path="/parseIntoNonPublicInnerClass")
+ public String b05(@Body B05 in) {
+ return "OK";
+ }
+ static class B05 {
+ public B05(){}
+ }
+ @RestMethod(name=PUT, path="/thrownConstructorException")
+ public String b06(@Body B06 in) {
+ return "OK";
+ }
+ public static class B06 {
+ public int f1;
+ private B06(){}
+ public static B06 valueOf(String s) {
+ throw new RuntimeException("Test error");
+ }
+ }
+ @RestMethod(name=PUT, path="/setParameterToInvalidTypes/{a1}")
+ public String b07(@Query("p1") int t1, @Path("a1") int a1,
@Header("h1") int h1) {
+ return "OK";
+ }
+ }
+ private static MockRest b = MockRest.create(B.class);
+
+ @Test
+ public void b01a_nonExistentBeanProperties() throws Exception {
+ b.request("PUT",
"/nonExistentBeanProperties?noTrace=true").body("{f2:'foo'}").json().execute()
+ .assertStatus(400)
+ .assertBodyContains(
+ "Unknown property 'f2' encountered while trying
to parse into class 'org.apache.juneau.rest.StatusCodesTest$B$B01'"
+ );
+ }
+ @Test
+ public void b01b_nonExistentBeanProperties() throws Exception {
+ b.request("PUT",
"/nonExistentBeanProperties?noTrace=true").body("{f1:'foo',
f2:'foo'}").json().execute()
+ .assertStatus(400)
+ .assertBodyContains(
+ "Unknown property 'f2' encountered while trying
to parse into class 'org.apache.juneau.rest.StatusCodesTest$B$B01'"
+ );
+ }
+ @Test
+ public void b02_wrongDataType() throws Exception {
+ b.request("PUT",
"/wrongDataType?noTrace=true").body("{f1:'foo'}").json().execute()
+ .assertStatus(400)
+ .assertBodyContains(
+ "Invalid number"
+ );
+ }
+ @Test
+ public void b03_parseIntoNonConstructableBean() throws Exception {
+ b.request("PUT",
"/parseIntoNonConstructableBean?noTrace=true").body("{f1:1}").json().execute()
+ .assertStatus(400)
+ .assertBodyContains(
+ "could not be instantiated"
+ );
+ }
+ @Test
+ public void b04_parseIntoNonStaticInnerClass() throws Exception {
+ b.request("PUT",
"/parseIntoNonStaticInnerClass?noTrace=true").body("{f1:1}").json().execute()
+ .assertStatus(400)
+ .assertBodyContains(
+ "could not be instantiated"
+ );
+ }
+ @Test
+ public void b05_parseIntoNonStaticInnerClass() throws Exception {
+ b.request("PUT",
"/parseIntoNonPublicInnerClass?noTrace=true").body("{f1:1}").json().execute()
+ .assertStatus(400)
+ .assertBodyContains(
+ "Class is not public"
+ );
+ }
+ @Test
+ public void b06_thrownConstructorException() throws Exception {
+ b.request("PUT",
"/thrownConstructorException?noTrace=true").body("'foo'").json().execute()
+ .assertStatus(400)
+ .assertBodyContains(
+ "Test error"
+ );
+ }
+ @Test
+ public void b07a_setParameterToInvalidTypes_Query() throws Exception {
+ b.request("PUT",
"/setParameterToInvalidTypes/123?noTrace=true&p1=foo").body("'foo'").json().execute()
+ .assertStatus(400)
+ .assertBodyContains(
+ "Could not convert QUERY 'p1' to type 'int'"
+ );
+ }
+ @Test
+ public void b07a_setParameterToInvalidTypes_Path() throws Exception {
+ b.request("PUT",
"/setParameterToInvalidTypes/foo?noTrace=true&p1=1").body("'foo'").json().execute()
+ .assertStatus(400)
+ .assertBodyContains(
+ "Could not convert PATH 'a1' to type 'int'"
+ );
+ }
+ @Test
+ public void b07a_setParameterToInvalidTypes_Header() throws Exception {
+ b.request("PUT",
"/setParameterToInvalidTypes/123?noTrace=true&p1=1").header("h1",
"foo").body("'foo'").json().execute()
+ .assertStatus(400)
+ .assertBodyContains(
+ "Could not convert HEADER 'h1' to type 'int'"
+ );
+ }
+
+
//====================================================================================================
+ // Not Found (404) and Method Not Allowed (405)
+
//====================================================================================================
+ @RestResource
+ public static class C {
+ @RestMethod(name=GET, path="/")
+ public String c() {
+ return "OK";
+ }
+ }
+ private static MockRest c = MockRest.create(C.class);
+
+ @Test
+ public void c01_badPath() throws Exception {
+ c.request("GET", "/bad?noTrace=true").execute()
+ .assertStatus(404)
+ .assertBodyContains(
+ "Method 'GET' not found on resource with
matching pattern on path '/bad'"
+ );
+ }
+ public void c02_badMethod() throws Exception {
+ c.request("PUT", "?noTrace=true").execute()
+ .assertStatus(405)
+ .assertBodyContains(
+ "Method 'PUT' not found on resource."
+ );
+ }
+
+
//====================================================================================================
+ // Precondition Failed (412)
+
//====================================================================================================
+ @RestResource
+ public static class D {
+ @RestMethod(name=GET, matchers=NeverMatcher.class)
+ public String d() {
+ return "OK";
+ }
+ public static class NeverMatcher extends RestMatcher {
+ @Override /* RestMatcher */
+ public boolean matches(RestRequest req) {
+ return false;
+ }
+ }
+ }
+ private static MockRest d = MockRest.create(D.class);
+
+ @Test
+ public void d01() throws Exception {
+ d.request("GET", "/?noTrace=true").execute()
+ .assertStatus(412)
+ .assertBodyContains(
+ "Method 'GET' not found on resource on path '/'
with matching matcher."
+ );
+ }
}
--
To stop receiving notification emails like this one, please contact
[email protected].