Issue #19 - Fail subsequent tests eagerly when metadata fails

This commit is contained in:
Joshua Darnell 2020-04-08 04:22:10 -07:00
parent 26e2a3d915
commit 7be1cb7d1b
7 changed files with 309 additions and 727 deletions

Binary file not shown.

View File

@ -20,7 +20,7 @@ Feature: Web API Server 1.0.2 Certification
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
And the XML Metadata response is valid XML
And the XML metadata returned by the server are valid
And the XML Metadata returned by the server are valid
And Edm metadata are requested from the service root in "ClientSettings_WebAPIURI"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -32,6 +32,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-END2 @core @2.4.1 @core-endorsement @datasystem
Scenario: REQ-WA103-END2 - Data System Endpoint test
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-END2"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -41,6 +42,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QR1 @core @2.4.1 @query-functions-endorsement
Scenario: REQ-WA103-QR1 - Search Parameters: Select KeyOrKeyNumeric Field
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QR1"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -50,6 +52,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QR3 @core @2.4.2 @query-functions-endorsement
Scenario: REQ-WA103-QR3 - Query Support: $select
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QR3"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -60,6 +63,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QR4 @core @2.4.2 @client-paging-endorsement
Scenario: REQ-WA103-QR4 - Query Support: $top
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QR4"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -71,6 +75,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QR5 @core @2.4.2 @query-support-endorsement
Scenario: REQ-WA103-QR5 - Query Support: $skip
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QR5"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -89,6 +94,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO1.1 @core @2.4.4 @core-endorsement @OData-4.0
Scenario: REQ-WA103-QO1.1 - Query Support: $select case-sensitivity for OData 4.0
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO1.1"
And the server has an OData-Version header value of "4.0" or "4.01"
Then the server responds with a status code of 400 if the server reports OData-Version "4.0"
@ -96,6 +102,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO1.2 @core @2.4.4 @core-endorsement @OData-4.0
Scenario: REQ-WA103-QO1.2 - Query Support: $filter case-sensitivity for OData 4.0
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO1.2"
And the server has an OData-Version header value of "4.0" or "4.01"
Then the server responds with a status code of 400 if the server reports OData-Version "4.0"
@ -103,6 +110,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO1.3 @core @2.4.4 @core-endorsement @OData-4.0
Scenario: REQ-WA103-QO1.3 - Query Support: $orderby asc case-sensitivity for OData 4.0
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO1.3"
And the server has an OData-Version header value of "4.0" or "4.01"
Then the server responds with a status code of 400 if the server reports OData-Version "4.0"
@ -110,6 +118,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO1.4 @core @2.4.4 @core-endorsement @OData-4.0
Scenario: REQ-WA103-QO1.4 - Query Support: $orderby desc case-sensitivity for OData 4.0
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO1.4"
And the server has an OData-Version header value of "4.0" or "4.01"
Then the server responds with a status code of 400 if the server reports OData-Version "4.0"
@ -117,6 +126,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO2 @core @2.4.4 @filterability-endorsement
Scenario: REQ-WA103-QO2 - Query Support: $filter - Integer Comparison: eq
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO2"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -128,6 +138,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO3 @core @2.4.4 @filterability-endorsement
Scenario: REQ-WA103-QO3 - Query Support: $filter - Integer Comparison: ne
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO3"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -139,6 +150,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO4 @core @2.4.4 @filterability-endorsement
Scenario: REQ-WA103-QO4 - Query Support: $filter - Integer Comparison: gt
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO4"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -150,6 +162,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO5 @core @2.4.4 @filterability-endorsement
Scenario: REQ-WA103-QO5 - Query Support: $filter - Integer Comparison: ge
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO5"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -161,6 +174,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO6 @core @2.4.4 @filterability-endorsement
Scenario: REQ-WA103-QO6 - Query Support: $filter - Integer Comparison: lt
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO6"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -172,6 +186,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO7 @core @2.4.4 @filterability-endorsement
Scenario: REQ-WA103-QO7 - Query Support: $filter - Integer Comparison: le
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO7"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -183,6 +198,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO9 @core @2.4.4 @filterability-endorsement
Scenario: REQ-WA103-QO9 - Query Support: $filter - Integer Comparison: and
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO9"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -194,6 +210,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO10 @core @2.4.4 @filterability-endorsement
Scenario: REQ-WA103-QO10 - Query Support: $filter - Integer Comparison: or
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO10"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -205,6 +222,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO11 @core @2.4.4 @filterability-endorsement
Scenario: REQ-WA103-QO11 - Query Support: $filter - Integer Comparison: not() (operator)
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO11"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -216,6 +234,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO25 @core @2.4.4 @filterability-endorsement
Scenario: REQ-WA103-QO25 - Query Support: $filter: Date portion of EdmDateTimeOffset field is greater than EdmDate value
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO25"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -227,6 +246,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO26 @core @2.4.4 @filterability-endorsement
Scenario: REQ-WA103-QO26 - Query Support: $filter: Time portion of EdmDateTimeOffset field is less than EdmTime value
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO26"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -238,6 +258,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO26.2 @core @2.4.4 @filterability-endorsement
Scenario: REQ-WA103-QO26.2 - Query Support: $filter: Date: EdmDateTimeOffset field is less than EdmDateTimeOffset value
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO26.2"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -249,6 +270,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO27 @core @2.4.4 @filterability-endorsement
Scenario: REQ-WA103-QO27 - Query Support: $filter: DateTimeOffset le now()
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO27"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -265,24 +287,28 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-END1 @core @2.4.1 @core-endorsement
Scenario: REQ-WA103-END1 - Service Endpoint
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-END1"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@REQ-WA103-RC3 @core @2.5.2 @core-endorsement
Scenario: REQ-WA103-RC3 - 200 OK Request
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-RC3"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@REQ-WA103-RC5 @core @2.4.2 @core-endorsement
Scenario: REQ-WA103-RC5 - 400 Bad Request
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-RC5"
Then the server responds with a status code of 400
And the server has an OData-Version header value of "4.0" or "4.01"
@REQ-WA103-RC07 @core @2.5.2 @core-endorsement
Scenario: REQ-WA103-RC07 - 404 Not Found Request
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-RC07"
Then the server responds with a status code of 404
And the server has an OData-Version header value of "4.0" or "4.01"
@ -293,6 +319,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QM7 @bronze @2.4.9 @filterability-endorsement
Scenario: REQ-WA103-QM7 - Support Single Value Lookups
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QM7"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -304,6 +331,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QM8 @bronze @2.4.10 @filterability-endorsement
Scenario: REQ-WA103-QM8 - Support Multi Value Lookups
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QM8"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -315,6 +343,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QM8.2 @bronze @2.4.10 @filterability-endorsement
Scenario: REQ-WA103-QM8.2 - Support Multi Value Lookups multiple values
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QM8.2"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -327,6 +356,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO8 @bronze @2.4.4 @filterability-endorsement
Scenario: REQ-WA103-QO8 - Query Support: $filter - Comparison: has
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO8"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -338,6 +368,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO28.1 @bronze @2.4.4 @sortability-endorsement
Scenario: REQ-WA103-QO28.1 - Query Support: $orderby asc filtered
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO28.1"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -349,6 +380,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO28.2 @bronze @2.4.4 @sortability-endorsement
Scenario: REQ-WA103-QO28.2 - Query Support: $orderby asc no filter
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO28.2"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -360,6 +392,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO28.3 @bronze @2.4.4 @sortability-endorsement
Scenario: REQ-WA103-QO28.3 - Query Support: $orderby desc filtered
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO28.3"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -371,6 +404,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO28.4 @bronze @2.4.4 @sortability-endorsement
Scenario: REQ-WA103-QO28.4 - Query Support: $orderby desc no filter
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO28.4"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -387,6 +421,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO18.1 @gold @2.4.4 @filterability-endorsement
Scenario: REQ-WA103-QO18.1 - Query Support: $filter: Date: year
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO18.1"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -398,6 +433,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO18.2 @gold @2.4.4 @filterability-endorsement
Scenario: REQ-WA103-QO18.2 - Query Support: $filter: Date: year comparison with timestamp
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO18.2"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -409,6 +445,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO19.1 @gold @2.4.4 @filterability-endorsement
Scenario: REQ-WA103-QO19.1 - Query Support: $filter: Date: month
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO19.1"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -420,6 +457,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO19.2 @gold @2.4.4 @filterability-endorsement
Scenario: REQ-WA103-QO19.2 - Query Support: $filter: Date: month comparison with timestamp
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO19.2"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -431,6 +469,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO20.1 @gold @2.4.4 @filterability-endorsement
Scenario: REQ-WA103-QO20.1 - Query Support: $filter: Date: day
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO20.1"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -442,6 +481,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO20.2 @gold @2.4.4 @filterability-endorsement
Scenario: REQ-WA103-QO20.2 - Query Support: $filter: Date: day comparison with timestamp
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO20.2"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -453,6 +493,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO21 @gold @2.4.4 @filterability-endorsement
Scenario: REQ-WA103-QO21 - Query Support: $filter: Date: hour comparison with timestamp
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO21"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -464,6 +505,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO22 @gold @2.4.4 @filterability-endorsement
Scenario: REQ-WA103-QO22 - Query Support: $filter: Date: minute comparison with timestamp
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO22"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -475,6 +517,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO23 @gold @2.4.4 @filterability-endorsement
Scenario: REQ-WA103-QO23 - Query Support: $filter: Date: second comparison with timestamp
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO23"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -486,6 +529,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO24 @gold @2.4.4 @filterability-endorsement
Scenario: REQ-WA103-QO24 - Query Support: $filter: Date: fractional seconds comparison with timestamp
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO24"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -501,6 +545,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO13 @platinum @2.4.4 @filterability-endorsement
Scenario: REQ-WA103-QO13 - Query Support: $filter - String: contains
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO13"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -512,6 +557,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO14 @platinum @2.4.4 @filterability-endorsement
Scenario: REQ-WA103-QO14 - Query Support: $filter - String: ends with
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO14"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -523,6 +569,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO15 @platinum @2.4.4 @filterability-endorsement
Scenario: REQ-WA103-QO15 - Query Support: $filter - String: starts with
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO15"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -534,6 +581,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO16 @platinum @2.4.4 @filterability-endorsement
Scenario: REQ-WA103-QO16 - Query Support: $filter - String: tolower() support
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO16"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -545,6 +593,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO17 @platinum @2.4.4 @filterability-endorsement
Scenario: REQ-WA103-QO17 - Query Support: $filter - String: toupper() support
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO17"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -556,6 +605,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO29.1 @platinum @2.4.4 @expandability-endorsement
Scenario: REQ-WA103-QO29.1 - Query Support: $expand
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO29.1"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -569,6 +619,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO29.2 @platinum @2.4.4 @expandability-endorsement @todo
Scenario: REQ-WA103-QO29.2 - Query Support: $expand media photo count (TODO)
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO29.2"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -579,6 +630,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO29.3 @platinum @2.4.4 @expandability-endorsement @todo
Scenario: REQ-WA103-QO29.3 - Query Support: $expand required field (TODO)
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO29.3"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -589,6 +641,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QM3 @platinum @2.4.6 @queryability-endorsement @todo
Scenario: REQ-WA103-QM3 - Support Literals: any() Lambda Expression (TODO)
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QM3"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -599,6 +652,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QM4 @platinum @2.4.6 @queryability-endorsement @todo
Scenario: REQ-WA103-QM4 - Query Support Literals: all() Lambda Operator (TODO)
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QM4"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -609,6 +663,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QM5.1 @platinum @2.4.7 @queryability-endorsement @geospatial @todo
Scenario: REQ-WA103-QM5.1 - Query Support: GeoSpatial Search Implementation (TODO)
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QM5.1"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -619,6 +674,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QM5.2 @platinum @2.4.7 @queryability-endorsement @geospatial @todo
Scenario: REQ-WA103-QM5.2 - Query Support: GeoSpatial Search Implementation (TODO)
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QM5.2"
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"
@ -629,6 +685,7 @@ Feature: Web API Server 1.0.2 Certification
@REQ-WA103-QO12 @platinum @2.4.4 @filterability-endorsement @filterability-endorsement
Scenario: REQ-WA103-QO12 - Query Support: $filter - Grouping: filter (ge, le) and (gt, lt) and expect (gt, lt)
Given valid metadata have been retrieved
When a GET request is made to the resolved Url in "REQ-WA103-QO12" using the OData Client
Then the server responds with a status code of 200
And the server has an OData-Version header value of "4.0" or "4.01"

View File

@ -21,7 +21,7 @@ import org.apache.olingo.commons.api.edm.provider.CsdlEntityContainer;
import org.apache.olingo.commons.api.edm.provider.CsdlNavigationProperty;
import org.apache.olingo.commons.api.format.ContentType;
import org.reso.commander.Commander;
import org.reso.commander.TestUtils;
import org.reso.commander.common.TestUtils;
import org.reso.commander.certfication.containers.WebApiTestContainer;
import org.reso.models.Request;
import org.reso.models.Settings;
@ -40,11 +40,11 @@ import java.util.concurrent.atomic.AtomicReference;
import static io.restassured.path.json.JsonPath.from;
import static org.junit.Assert.*;
import static org.reso.commander.Commander.*;
import static org.reso.commander.TestUtils.*;
import static org.reso.commander.TestUtils.Operators.*;
import static org.reso.commander.common.TestUtils.*;
import static org.reso.commander.common.TestUtils.Operators.*;
import static org.reso.commander.certfication.containers.WebApiTestContainer.*;
import static org.reso.common.ErrorMsg.getAssertResponseCodeErrorMessage;
import static org.reso.common.ErrorMsg.getDefaultErrorMessage;
import static org.reso.commander.common.ErrorMsg.getAssertResponseCodeErrorMessage;
import static org.reso.commander.common.ErrorMsg.getDefaultErrorMessage;
/**
* Contains the glue code for the Web API Server 1.0.2 Platinum Certification
@ -66,43 +66,8 @@ public class WebAPIServer_1_0_2 implements En {
* Entry point to the Web API Server tests
*/
public WebAPIServer_1_0_2() {
/*
* Background
*/
Given("^a RESOScript file was provided$", () -> {
if (getTestContainer().getPathToRESOScript() == null) {
getTestContainer().setPathToRESOScript(System.getProperty("pathToRESOScript"));
}
assertNotNull("ERROR: pathToRESOScript must be present in command arguments, see README", getTestContainer().getPathToRESOScript());
LOG.info("Using RESOScript: " + getTestContainer().getPathToRESOScript());
});
And("^Client Settings and Parameters were read from the file$", () -> {
if (getTestContainer().getSettings() == null) {
getTestContainer().setSettings(Settings.loadFromRESOScript(new File(System.getProperty("pathToRESOScript"))));
}
assertNotNull("ERROR: Settings could not be loaded.", getTestContainer().getSettings());
LOG.info("RESOScript loaded successfully!");
});
Given("^a test container was successfully created from the given RESOScript$", () -> {
getTestContainer().initialize();
});
/*
* Ensures that the client either uses Authorization Codes or Client Credentials
*/
And("^the test container uses an authorization_code or client_credentials for authentication$", () -> {
assertNotNull(getTestContainer().getCommander());
assertTrue("ERROR: Commander must either have a valid Authorization Code or Client Credentials configuration.",
getTestContainer().getCommander().isTokenClient() || (getTestContainer().getCommander().isOAuthClient() && getTestContainer().getCommander().hasValidAuthConfig()));
if (getTestContainer().getCommander().isTokenClient()) {
LOG.info("Authentication Type: authorization_code");
} else if (getTestContainer().getCommander().isOAuthClient()) {
LOG.info("Authentication Type: client_credentials");
}
});
runBackground();
/*
* REQ-WA103-END2 - validate DataSystem endpoint, if present.
@ -141,6 +106,7 @@ public class WebAPIServer_1_0_2 implements En {
try {
boolean isValid = getTestContainer().getCommander().validateMetadata(getTestContainer().getEdm());
getTestContainer().setIsValidEdm(isValid);
LOG.info("Edm Metadata is " + (isValid ? "valid" : "invalid") + "!");
assertTrue("Edm Metadata at the given service root is not valid! " + getTestContainer().getServiceRoot(), isValid);
} catch (Exception ex) {
@ -151,11 +117,12 @@ public class WebAPIServer_1_0_2 implements En {
/*
* XML Metadata Validator
*/
And("^the XML metadata returned by the server are valid$", () -> {
And("^the XML Metadata returned by the server are valid$", () -> {
assertNotNull("ERROR: XML Metadata (EDMX) Exists!", getTestContainer().getXMLMetadata());
try {
boolean isValid = getTestContainer().getCommander().validateMetadata(getTestContainer().getXMLMetadata());
getTestContainer().setIsValidXMLMetadata(isValid);
LOG.info("XML Metadata is " + (isValid ? "valid" : "invalid") + "!");
assertTrue("XML Metadata at the given service root is not valid! " + getTestContainer().getServiceRoot(), isValid);
} catch (Exception ex) {
@ -274,7 +241,7 @@ public class WebAPIServer_1_0_2 implements En {
getTestContainer().setRequestUri(Commander.prepareURI(
Settings.resolveParameters(getTestContainer().getSettings().getRequest(requestId), getTestContainer().getSettings()).getUrl()
+ AMPERSAND + ODATA_QUERY_PARAMS.SKIP + EQUALS + skipCount));
getTestContainer().executePreparedGetRequest();
getTestContainer().executePreparedRawGetRequest();
} catch (Exception ex) {
fail(getDefaultErrorMessage(ex));
}
@ -308,7 +275,7 @@ public class WebAPIServer_1_0_2 implements En {
/*
* GET request by requirementId (see generic.resoscript)
*/
When("^a GET request is made to the resolved Url in \"([^\"]*)\"$", this::prepareAndExecuteGetRequest);
When("^a GET request is made to the resolved Url in \"([^\"]*)\"$", this::prepareAndExecuteRawGetRequest);
/*
* Assert response code
@ -339,8 +306,15 @@ public class WebAPIServer_1_0_2 implements En {
* validate XML wrapper
*/
And("^the XML Metadata response is valid XML$", () -> {
LOG.info("Validating XML Metadata response to ensure it's valid XML and matches OASIS OData XSDs...");
LOG.info( "See: https://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/schemas/");
assertNotNull("XML response data were not found in the test container! Please ensure the XML Metadata request succeeded.",
getTestContainer().getXMLResponseData());
try {
assertTrue("ERROR: invalid XML response!", Commander.validateXML(getTestContainer().getXMLResponseData()));
boolean isValid = Commander.validateXML(getTestContainer().getXMLResponseData());
getTestContainer().setIsXMLMetadataValidXML(isValid);
assertTrue("ERROR: invalid XML response!", isValid);
LOG.info("Response is valid XML!");
} catch (Exception ex) {
fail(getDefaultErrorMessage(ex));
@ -351,6 +325,9 @@ public class WebAPIServer_1_0_2 implements En {
* validate JSON wrapper
*/
And("^the response is valid JSON$", () -> {
assertNotNull(getDefaultErrorMessage("JSON response data were not found in the test container! Please ensure your request succeeded.",
getTestContainer().getResponseData()));
try {
assertTrue("ERROR: invalid JSON response!", TestUtils.isValidJson(getTestContainer().getResponseData()));
LOG.info("Response is valid JSON!");
@ -776,8 +753,12 @@ public class WebAPIServer_1_0_2 implements En {
getTestContainer().getSelectList().forEach(fieldName -> {
//need to skip the expand field when looking through the metadata
if (getTestContainer().getExpandField() == null || !fieldName.contentEquals(getTestContainer().getExpandField())) {
assertNotNull("ERROR: Field name '" + fieldName + "' is not present in server metadata!", getTestContainer().getCsdlForFieldName(fieldName));
LOG.info("Found: '" + fieldName.trim() + "'");
try {
assertNotNull("ERROR: Field name '" + fieldName + "' is not present in server metadata!", getTestContainer().getCsdlForFieldName(fieldName));
LOG.info("Found: '" + fieldName.trim() + "'");
} catch (Exception ex) {
LOG.error(getDefaultErrorMessage(ex));
}
}
});
} catch (Exception ex) {
@ -807,18 +788,19 @@ public class WebAPIServer_1_0_2 implements En {
*/
And("^XML Metadata are requested from the service root in \"([^\"]*)\"$", (String clientSettingsServiceRoot) -> {
final String serviceRoot = Settings.resolveParametersString(clientSettingsServiceRoot, getTestContainer().getSettings());
assertEquals("ERROR: given service root doesn't match the one configured in the Commander", serviceRoot, getTestContainer().getCommander().getServiceRoot());
assertEquals(getDefaultErrorMessage("given service root doesn't match the one configured in the Commander"),
serviceRoot,
getTestContainer().getCommander().getServiceRoot());
LOG.info("Requesting XML Metadata from: " + serviceRoot);
try {
assertNotNull("ERROR: could not find valid XML Metadata for given service root: " + serviceRoot, getTestContainer().getXMLMetadata());
assertNotNull(getDefaultErrorMessage("could not find valid XML Metadata for given service root:", serviceRoot),
getTestContainer().getXMLMetadata());
} catch (ODataClientErrorException cex) {
getTestContainer().setResponseCode(cex.getStatusLine().getStatusCode());
fail(cex.toString());
} catch (IllegalArgumentException aex) {
fail(getDefaultErrorMessage(aex.toString()));
fail(getDefaultErrorMessage(cex));
} catch (Exception ex) {
fail("ERROR: "+ ex.toString());
fail(getDefaultErrorMessage(ex));
}
});
@ -932,8 +914,12 @@ public class WebAPIServer_1_0_2 implements En {
AtomicBoolean found = new AtomicBoolean(false);
requiredResources.forEach(requiredResource -> {
if (!found.get())
found.set(found.get() || getTestContainer().getEdm().getEntityContainer().getEntitySet(requiredResource) != null);
try {
if (!found.get())
found.set(found.get() || getTestContainer().getEdm().getEntityContainer().getEntitySet(requiredResource) != null);
} catch (Exception ex) {
fail(getDefaultErrorMessage(ex));
}
});
assertTrue("ERROR: could not find one of the following Standard Resource Names in the default entity container: " + requiredResourceString.replace(FIELD_SEPARATOR, PRETTY_FIELD_SEPARATOR),
@ -1031,12 +1017,29 @@ public class WebAPIServer_1_0_2 implements En {
|| getTestContainer().getServerODataHeaderVersion().contentEquals(val2) );
});
/*
* Ensures valid metadata have been retrieved from the server
*/
Given("^valid metadata have been retrieved$", () -> {
if (getTestContainer().hasNotFetchedMetadata()) {
getTestContainer().setIsValidXMLMetadata(getTestContainer().getCommander().validateMetadata(getTestContainer().getXMLMetadata()));
getTestContainer().setIsXMLMetadataValidXML(Commander.validateXML(getTestContainer().getXMLResponseData()));
if (getTestContainer().getIsValidXMLMetadata() && getTestContainer().getIsXMLMetadataValidXML()) {
getTestContainer().setIsValidEdm(getTestContainer().getCommander().validateMetadata(getTestContainer().getEdm()));
}
}
assertTrue(getDefaultErrorMessage("Valid metadata could not be retrieved from the server! Please check the log for more information."),
getTestContainer().getIsMetadataValid());
});
}
/*
* Execute Get Request Wrapper
*/
void prepareAndExecuteGetRequest(String requestId) {
void prepareAndExecuteRawGetRequest(String requestId) {
try {
//reset local state each time a get request is run
getTestContainer().resetState();
@ -1051,7 +1054,7 @@ public class WebAPIServer_1_0_2 implements En {
LOG.info("Request URI: " + getTestContainer().getRequestUri().toString());
//execute request
getTestContainer().executePreparedGetRequest();
getTestContainer().executePreparedRawGetRequest();
} catch (Exception ex) {
LOG.debug("Exception was thrown in " + this.getClass() + ": " + ex.toString());
}
@ -1060,4 +1063,47 @@ public class WebAPIServer_1_0_2 implements En {
static WebApiTestContainer getTestContainer() {
return container.get();
}
/**
* Contains background logic - make sure to update if the background changes
*/
final void runBackground() {
/*
* Background
*/
Given("^a RESOScript file was provided$", () -> {
if (getTestContainer().getPathToRESOScript() == null) {
getTestContainer().setPathToRESOScript(System.getProperty("pathToRESOScript"));
}
assertNotNull("ERROR: pathToRESOScript must be present in command arguments, see README", getTestContainer().getPathToRESOScript());
LOG.info("Using RESOScript: " + getTestContainer().getPathToRESOScript());
});
And("^Client Settings and Parameters were read from the file$", () -> {
if (getTestContainer().getSettings() == null) {
getTestContainer().setSettings(Settings.loadFromRESOScript(new File(System.getProperty("pathToRESOScript"))));
}
assertNotNull("ERROR: Settings could not be loaded.", getTestContainer().getSettings());
LOG.info("RESOScript loaded successfully!");
});
Given("^a test container was successfully created from the given RESOScript$", () -> {
getTestContainer().initialize();
});
/*
* Ensures that the client either uses Authorization Codes or Client Credentials
*/
And("^the test container uses an authorization_code or client_credentials for authentication$", () -> {
assertNotNull(getTestContainer().getCommander());
assertTrue("ERROR: Commander must either have a valid Authorization Code or Client Credentials configuration.",
getTestContainer().getCommander().isTokenClient() || (getTestContainer().getCommander().isOAuthClient() && getTestContainer().getCommander().hasValidAuthConfig()));
if (getTestContainer().getCommander().isTokenClient()) {
LOG.info("Authentication Type: authorization_code");
} else if (getTestContainer().getCommander().isOAuthClient()) {
LOG.info("Authentication Type: client_credentials");
}
});
}
}

View File

@ -22,6 +22,7 @@ import org.apache.olingo.commons.api.edm.Edm;
import org.apache.olingo.commons.api.format.ContentType;
import org.reso.auth.OAuth2HttpClientFactory;
import org.reso.auth.TokenHttpClientFactory;
import org.reso.commander.common.TestUtils;
import org.xml.sax.*;
import javax.xml.XMLConstants;
@ -79,17 +80,6 @@ public class Commander {
//private constructor, should not be used. Use Builder instead.
}
/**
* Validates XML for the given xmlMetadata item
*
* @param xmlMetadata the XML metadata to validate
* @return true if valid, false otherwise
* @throws ODataSerializerException if the given XML metadata could not be serialized
*/
public static boolean validateXML(XMLMetadata xmlMetadata) throws ODataSerializerException {
return validateXML(serializeXMLMetadataToXMLString(xmlMetadata));
}
/**
* Uses an XML validator to validate that the given string contains valid XML.
*
@ -212,19 +202,6 @@ public class Commander {
return null;
}
/**
* Serializes XML Metadata to an XML string
*
* @param xmlMetadata the metadata to serialize
* @return a String containing the metadata
* @throws ODataSerializerException
*/
private static String serializeXMLMetadataToXMLString(XMLMetadata xmlMetadata) throws ODataSerializerException {
StringWriter writer = new StringWriter();
client.getSerializer(ContentType.APPLICATION_XML).write(writer, xmlMetadata);
return writer.getBuffer().toString();
}
/**
* Metadata Pretty Printer
*

View File

@ -1,568 +0,0 @@
package org.reso.commander;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.http.Header;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.olingo.client.api.communication.response.ODataRawResponse;
import org.apache.olingo.client.api.communication.response.ODataResponse;
import org.apache.olingo.client.api.edm.xml.XMLMetadata;
import org.apache.olingo.commons.api.edm.Edm;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
import org.apache.olingo.commons.api.edm.provider.CsdlEntityContainer;
import org.apache.olingo.commons.api.edm.provider.CsdlNavigationProperty;
import org.apache.olingo.commons.api.edm.provider.CsdlProperty;
import org.apache.olingo.commons.api.edm.provider.CsdlSchema;
import org.apache.olingo.commons.core.edm.primitivetype.EdmDate;
import org.apache.olingo.commons.core.edm.primitivetype.EdmDateTimeOffset;
import org.apache.olingo.commons.core.edm.primitivetype.EdmTimeOfDay;
import org.reso.models.Settings;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.sql.Time;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.OffsetDateTime;
import java.time.Year;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import static io.restassured.path.json.JsonPath.from;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
public final class TestUtils {
public static final String JSON_VALUE_PATH = "value";
public static final String HEADER_ODATA_VERSION = "OData-Version";
private static final Logger LOG = LogManager.getLogger(TestUtils.class);
/**
* Used to prepare URIs given that the input queryStrings can sometimes contain special characters
* that need to be ensured that they be processed.
*
* @param queryString the queryString to prepare
* @return the prepared URI with special characters in the queryString processed.
*/
public static URI prepareUri(final String queryString) {
/* replace spaces with %20 */
return URI.create(
queryString.replace(" ", "%20")
/* add other handlers here */
);
}
/**
* Finds the default entity container for the given configuration.
*
* @param xmlMetadata XML Metadata to search through
* @return the default CSDL Container for the given XMLMetadata
* @throws Exception if required metadata cannot be parsed, an exception will be thrown with an appropriate message.
*/
public static CsdlEntityContainer findDefaultEntityContainer(Edm edm, XMLMetadata xmlMetadata) {
assertNotNull("Edm Cannot be Null!", edm);
assertNotNull("XMLMetadata Cannot be Null!", xmlMetadata);
assertNotNull("ERROR: Could not find default EntityContainer for given service root!", edm.getEntityContainer());
String entityContainerNamespace = edm.getEntityContainer().getNamespace();
assertNotNull("ERROR: no default EntityContainer namespace could be found", entityContainerNamespace);
return xmlMetadata.getSchema(entityContainerNamespace).getEntityContainer();
}
/**
* Gets a list of CsdlProperty items for the given entityTypeName.
*
* @param xmlMetadata the metadata to search.
* @param entityTypeName the name of the entityType to search for. MUST be in the default EntityContainer.
* @return a list of CsdlProperty items for the given entityTypeName
* @throws Exception is thrown if the given metadata doesn't contain the given type name.
*/
public static List<CsdlProperty> findEntityTypesForEntityTypeName(Edm edm, XMLMetadata xmlMetadata, String entityTypeName) {
assertNotNull("ERROR: Edm Cannot be Null!", edm);
assertNotNull("ERROR: XMLMetadata Cannot be Null!", xmlMetadata);
assertNotNull("ERROR: entityTypeName cannot be null!", entityTypeName);
CsdlEntityContainer entityContainer = findDefaultEntityContainer(edm, xmlMetadata);
assertNotNull("ERROR: could not find a default entity container for the given server!", entityContainer);
CsdlSchema schemaForType = xmlMetadata.getSchema(entityContainer.getEntitySet(entityTypeName).getTypeFQN().getNamespace());
assertNotNull("ERROR: could not find type corresponding to given type name: " + entityTypeName, schemaForType);
return schemaForType.getEntityType(entityTypeName).getProperties();
}
/**
* Gets a list of CsdlProperty items for the given entityTypeName.
*
* @param xmlMetadata the metadata to search.
* @param entityTypeName the name of the entityType to search for. MUST be in the default EntityContainer.
* @return a list of CsdlProperty items for the given entityTypeName
* @throws Exception is thrown if the given metadata doesn't contain the given type name.
*/
public static List<CsdlNavigationProperty> findNavigationPropertiesForEntityTypeName(Edm edm, XMLMetadata xmlMetadata, String entityTypeName) {
assertNotNull("ERROR: Edm Cannot be Null!", edm);
assertNotNull("ERROR: XMLMetadata Cannot be Null!", xmlMetadata);
assertNotNull("ERROR: entityTypeName cannot be null!", entityTypeName);
CsdlEntityContainer entityContainer = findDefaultEntityContainer(edm, xmlMetadata);
assertNotNull("ERROR: could not find a default entity container for the given server!", entityContainer);
CsdlSchema schemaForType = xmlMetadata.getSchema(entityContainer.getEntitySet(entityTypeName).getTypeFQN().getNamespace());
assertNotNull("ERROR: could not find type corresponding to given type name: " + entityTypeName, schemaForType);
return schemaForType.getEntityType(entityTypeName).getNavigationProperties();
}
/**
* Returns true if each item in the list is true
*
* @param lhs Integer value
* @param op an OData binary operator for use for comparisons
* @param rhs Integer value
* @return true if lhs op rhs produces true, false otherwise
*/
public static boolean compare(Integer lhs, String op, Integer rhs) {
String operator = op.toLowerCase();
boolean result = false;
if (operator.contentEquals(Operators.GREATER_THAN)) {
result = lhs > rhs;
} else if (operator.contentEquals(Operators.GREATER_THAN_OR_EQUAL)) {
result = lhs >= rhs;
} else if (operator.contentEquals(Operators.EQ)) {
result = lhs.equals(rhs);
} else if (operator.contentEquals(Operators.NE)) {
result = !lhs.equals(rhs);
} else if (operator.contentEquals(Operators.LESS_THAN)) {
result = lhs < rhs;
} else if (operator.contentEquals(Operators.LESS_THAN_OR_EQUAL)) {
result = lhs <= rhs;
}
LOG.info("Compare: " + lhs + " " + operator + " " + rhs + " ==> " + result);
return result;
}
/**
* Returns true if each item in the list is true
*
* @param lhs Integer value
* @param op an OData binary operator for use for comparisons
* @param rhs Integer value
* @return true if lhs op rhs produces true, false otherwise
*/
public static boolean compare(String lhs, String op, String rhs) {
String operator = op.toLowerCase();
boolean result = false;
if (operator.contentEquals(Operators.CONTAINS)) {
result = lhs.contains(rhs);
} else if (operator.contentEquals(Operators.STARTS_WITH)) {
result = lhs.startsWith(rhs);
} else if (operator.contentEquals(Operators.ENDS_WITH)) {
result = lhs.endsWith(rhs);
} else if (operator.contentEquals(Operators.TO_LOWER)) {
result = lhs.toLowerCase().equals(rhs);
} else if (operator.contentEquals(Operators.TO_UPPER)) {
result = lhs.toUpperCase().equals(rhs);
}
LOG.info("Compare: \"" + lhs + "\" " + operator + " \"" + rhs + "\" ==> " + result);
return result;
}
/**
* Timestamp Comparator
*
* @param lhs Timestamp to compare
* @param op an OData binary operator to use for comparisons
* @param rhs Timestamp to compare
* @return true if lhs op rhs, false otherwise
*/
public static boolean compare(Timestamp lhs, String op, Timestamp rhs) {
String operator = op.toLowerCase();
boolean result = false;
if (operator.contentEquals(Operators.GREATER_THAN)) {
result = lhs.after(rhs);
} else if (operator.contentEquals(Operators.GREATER_THAN_OR_EQUAL)) {
result = lhs.after(rhs) || lhs.equals(rhs);
} else if (operator.contentEquals(Operators.EQ)) {
result = lhs.equals(rhs);
} else if (operator.contentEquals(Operators.NE)) {
result = !lhs.equals(rhs);
} else if (operator.contentEquals(Operators.LESS_THAN)) {
result = lhs.before(rhs);
} else if (operator.contentEquals(Operators.LESS_THAN_OR_EQUAL)) {
result = lhs.before(rhs) || lhs.equals(rhs);
}
LOG.info("Compare: " + lhs + " " + operator + " " + rhs + " ==> " + result);
return result;
}
/**
* Year Comparator
*
* @param lhs Year to compare
* @param op an OData binary operator to use for comparisons
* @param rhs Timestamp to compare
* @return true if lhs op rhs, false otherwise
*/
public static boolean compare(Year lhs, String op, Year rhs) {
String operator = op.toLowerCase();
boolean result = false;
if (operator.contentEquals(Operators.GREATER_THAN)) {
result = lhs.isAfter(rhs);
} else if (operator.contentEquals(Operators.GREATER_THAN_OR_EQUAL)) {
result = lhs.isAfter(rhs) || lhs.equals(rhs);
} else if (operator.contentEquals(Operators.EQ)) {
result = lhs.equals(rhs);
} else if (operator.contentEquals(Operators.NE)) {
result = !lhs.equals(rhs);
} else if (operator.contentEquals(Operators.LESS_THAN)) {
result = lhs.isBefore(rhs);
} else if (operator.contentEquals(Operators.LESS_THAN_OR_EQUAL)) {
result = lhs.isBefore(rhs) || lhs.equals(rhs);
}
LOG.info("Compare: " + lhs + " " + operator + " " + rhs + " ==> " + result);
return result;
}
/**
* Time Comparator
*
* @param lhs Time to compare
* @param op an OData binary operator to use for comparisons
* @param rhs Time to compare
* @return true if lhs op rhs, false otherwise
*/
public static boolean compare(Time lhs, String op, Time rhs) {
String operator = op.toLowerCase();
boolean result = false;
if (operator.contentEquals(Operators.GREATER_THAN)) {
result = lhs.toLocalTime().isAfter(rhs.toLocalTime());
} else if (operator.contentEquals(Operators.GREATER_THAN_OR_EQUAL)) {
result = lhs.toLocalTime().isAfter(rhs.toLocalTime()) || lhs.toLocalTime().equals(rhs.toLocalTime());
} else if (operator.contentEquals(Operators.EQ)) {
result = lhs.toLocalTime().equals(rhs.toLocalTime());
} else if (operator.contentEquals(Operators.NE)) {
result = !lhs.toLocalTime().equals(rhs.toLocalTime());
} else if (operator.contentEquals(Operators.LESS_THAN)) {
result = lhs.toLocalTime().isBefore(rhs.toLocalTime());
} else if (operator.contentEquals(Operators.LESS_THAN_OR_EQUAL)) {
result = lhs.toLocalTime().isBefore(rhs.toLocalTime()) || lhs.toLocalTime().equals(rhs.toLocalTime());
}
LOG.info("Compare: " + lhs + " " + operator + " " + rhs + " ==> " + result);
return result;
}
/**
* Date Comparator
*
* @param lhs Date to compare
* @param op an OData binary operator to use for comparisons
* @param rhs Date to compare
* @return true if lhs op rhs, false otherwise
*/
public static boolean compare(Date lhs, String op, Date rhs) {
String operator = op.toLowerCase();
boolean result = false;
if (operator.contentEquals(Operators.GREATER_THAN)) {
result = lhs.after(rhs);
} else if (operator.contentEquals(Operators.GREATER_THAN_OR_EQUAL)) {
result = lhs.after(rhs) || lhs.equals(rhs);
} else if (operator.contentEquals(Operators.EQ)) {
result = lhs.equals(rhs);
} else if (operator.contentEquals(Operators.NE)) {
result = !lhs.equals(rhs);
} else if (operator.contentEquals(Operators.LESS_THAN)) {
result = lhs.before(rhs);
} else if (operator.contentEquals(Operators.LESS_THAN_OR_EQUAL)) {
result = lhs.before(rhs) || lhs.equals(rhs);
}
LOG.info("Compare: " + lhs + " " + operator + " " + rhs + " ==> " + result);
return result;
}
/**
* Tests the given string to see if it's valid JSON
*
* @param jsonString the JSON string to test the validity of
* @return true if valid, false otherwise. Throws {@link IOException}
*/
public static boolean isValidJson(String jsonString) {
try {
final ObjectMapper mapper = new ObjectMapper();
mapper.readTree(jsonString);
return true;
} catch (IOException e) {
return false;
}
}
/**
* Returns the String data contained within a given ODataRawResponse.
*
* @param oDataRawResponse the response to convert.
* @return the response stream as a string.
*/
public static String getResponseData(ODataRawResponse oDataRawResponse) {
return convertInputStreamToString(oDataRawResponse.getRawResponse());
}
/**
* Helper method to find headers with a given key in an an array of headers
* @param key the header to get
* @param headers an array containing Header objects
* @return the value of the header with key, or null
*/
public static String getHeaderData(String key, Collection<Header> headers) {
String data = null;
for (Header header : headers) {
if (header.getName().toLowerCase().contains(key.toLowerCase())) {
data = header.getValue();
}
}
return data;
}
/**
* Helper method to unpack headers from a raw OData response
* @param key the header to get
* @param oDataResponse the OData raw response from the request
* @return the value of the header with key, or null
*/
public static String getHeaderData(String key, ODataResponse oDataResponse) {
if (key == null || oDataResponse.getHeader(key) == null) return null;
ArrayList<String> result = new ArrayList<>(oDataResponse.getHeader(key));
if (result.size() > 0) {
return result.get(0);
} else {
return null;
}
}
/**
* Parses the given edmDateTimeOffsetString into a Java Instant (the type expected by the Olingo type converter).
*
* @param edmDateTimeOffsetString string representation of an Edm DateTimeOffset to parse.
* @return the corresponding Instant value.
* @throws EdmPrimitiveTypeException thrown if given value cannot be parsed.
*/
public static Timestamp parseTimestampFromEdmDateTimeOffsetString(String edmDateTimeOffsetString) throws EdmPrimitiveTypeException {
return EdmDateTimeOffset.getInstance().valueOfString(edmDateTimeOffsetString, true, null, null, null, null, Timestamp.class);
}
/**
* Parses the given edmDateString into a Java Timestamp.
*
* @param edmDateString the date string to convert.
* @return the corresponding Timestamp value.
* @throws EdmPrimitiveTypeException thrown if given value cannot be parsed.
*/
public static Timestamp parseTimestampFromEdmDateString(String edmDateString) throws EdmPrimitiveTypeException {
return EdmDate.getInstance().valueOfString(edmDateString, true, null, null, null, null, Timestamp.class);
}
/**
* Parses the given edmDateString into a Java Time.
*
* @param edmTimeOfDayOffsetString the date string to convert.
* @return the corresponding Time value.
* @throws EdmPrimitiveTypeException thrown if given value cannot be parsed.
*/
public static Time parseTimeOfDayFromEdmTimeOfDayString(String edmTimeOfDayOffsetString) throws EdmPrimitiveTypeException {
return EdmTimeOfDay.getInstance().valueOfString(edmTimeOfDayOffsetString, true, null, null, null, null, Time.class);
}
/**
* Parses the given DateTimeOffsetString into a Java Time.
*
* @param edmDateTimeOffsetString the DateTimeOffsetString to parse.
* @return the corresponding Time value.
* @throws EdmPrimitiveTypeException thrown if given value cannot be parsed.
*/
public static Time parseTimeOfDayFromEdmDateTimeOffsetString(String edmDateTimeOffsetString) throws EdmPrimitiveTypeException {
return EdmDateTimeOffset.getInstance().valueOfString(edmDateTimeOffsetString, true, null, null, null, null, Time.class);
}
/**
* Parses the given edmDateString into a Java Date
*
* @param edmDateString the date string to convert.
* @return the corresponding Date value.
* @throws EdmPrimitiveTypeException thrown if given value cannot be parsed.
*/
public static Date parseDateFromEdmDateString(String edmDateString) throws EdmPrimitiveTypeException {
return EdmDate.getInstance().valueOfString(edmDateString, true, null, null, null, null, Date.class);
}
/**
* Parses the given edmDateTimeOffsetString into a Java Date
*
* @param edmDateTimeOffsetString string representation of an Edm DateTimeOffset to parse.
* @return the corresponding Date value.
* @throws EdmPrimitiveTypeException thrown if given value cannot be parsed.
*/
public static Date parseDateFromEdmDateTimeOffsetString(String edmDateTimeOffsetString) throws EdmPrimitiveTypeException {
return EdmDateTimeOffset.getInstance().valueOfString(edmDateTimeOffsetString, true, null, null, null, null, Date.class);
}
/***
* Tries to parse datePart from the given Object value
* @param datePart the timestamp part, "Year", "Month", "Day", etc. to try and parse
* @param value the value to try and parse
* @return the Integer portion of the date if successful, otherwise throws an Exception
* @exception throws an exception if value cannot be parsed into a date.
*/
public static Integer getDatePart(String datePart, Object value) throws EdmPrimitiveTypeException {
LocalDate date = LocalDate.parse(parseDateFromEdmDateString(value.toString()).toString());
switch (datePart) {
case DateParts.YEAR:
return date.getYear();
case DateParts.MONTH:
return date.getMonthValue();
case DateParts.DAY:
return date.getDayOfMonth();
default:
return null;
}
}
/***
* Tries to parse datePart from the given Object value
* @param timestampPart the timestamp part, "Year", "Month", "Day", etc. to try and parse
* @param value the value to try and parse
* @return the Integer portion of the date if successful, otherwise throws an Exception
*/
public static Integer getTimestampPart(String timestampPart, Object value) throws EdmPrimitiveTypeException {
//Turns nanoseconds into two most significant 2 digits for fractional comparisons
Integer ADJUSTMENT_FACTOR = 10000000;
OffsetDateTime offsetDateTime = OffsetDateTime.parse(value.toString());
if (timestampPart.equals(DateParts.YEAR)) {
return offsetDateTime.getYear();
} else if (timestampPart.equals(DateParts.MONTH)) {
return offsetDateTime.getMonthValue();
} else if (timestampPart.equals(DateParts.DAY)) {
return offsetDateTime.getDayOfMonth();
} else if (timestampPart.equals(DateParts.HOUR)) {
return offsetDateTime.getHour();
} else if (timestampPart.equals(DateParts.MINUTE)) {
return offsetDateTime.getMinute();
} else if (timestampPart.equals(DateParts.SECOND)) {
return offsetDateTime.getSecond();
} else if (timestampPart.equals(DateParts.FRACTIONAL)) {
return offsetDateTime.getNano() / ADJUSTMENT_FACTOR;
} else {
return null;
}
}
/**
* Converts the given inputStream to a string.
*
* @param inputStream the input stream to convert.
* @return the string value contained in the stream.
*/
public static String convertInputStreamToString(InputStream inputStream) {
InputStreamReader isReader = new InputStreamReader(inputStream);
BufferedReader reader = new BufferedReader(isReader);
StringBuilder sb = new StringBuilder();
String str;
try {
while ((str = reader.readLine()) != null) {
sb.append(str);
}
return sb.toString();
} catch (Exception ex) {
LOG.error("Error in convertInputStreamToString: " + ex);
}
return null;
}
/**
* For each parameterFieldName value in responseData, assertTrue(value op timestamp)
*
* @param parameterFieldName the field name containing data
* @param op an OData binary operator to be used for comparsions
* @param parameterAssertedValue value to be used for comparisons
* @param responseData string containing JSON response data
*/
public static void assertDateTimeOffset(String parameterFieldName, String op, String parameterAssertedValue, String responseData, Settings settings) {
AtomicReference<Timestamp> assertedValue = new AtomicReference<>();
try {
assertedValue.set(parseTimestampFromEdmDateTimeOffsetString(Settings.resolveParametersString(parameterAssertedValue, settings)));
assertDateTimeOffset(parameterFieldName, op, assertedValue.get(), responseData, settings);
} catch (EdmPrimitiveTypeException tex) {
LOG.error("ERROR: Cannot Convert the value in "
+ Settings.resolveParametersString(parameterAssertedValue, settings) + " to a Timestamp value!!" + tex);
}
}
/**
* For each parameterFieldName value in responseData, assertTrue(value op timestamp)
*
* @param parameterFieldName the field name containing data
* @param op an OData binary operator to be used for comparsions
* @param timestamp value to be used for comparisons
* @param responseData string containing JSON response data
*/
public static void assertDateTimeOffset(String parameterFieldName, String op, Timestamp timestamp, String responseData, Settings settings) {
LOG.info("Asserted time is: " + timestamp);
String fieldName = Settings.resolveParametersString(parameterFieldName, settings);
AtomicReference<Timestamp> fieldValue = new AtomicReference<>();
from(responseData).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> {
try {
fieldValue.set(parseTimestampFromEdmDateTimeOffsetString(item.get(fieldName).toString()));
assertTrue(compare(fieldValue.get(), op, timestamp));
} catch (EdmPrimitiveTypeException tex) {
LOG.error("ERROR: Cannot Convert the value in " + fieldValue.get() + " to a Timestamp value!!" + tex);
}
});
}
/**
* Contains the list of supported operators for use in query expressions.
*/
public static class Operators {
public static final String
AND = "and",
OR = "or",
NE = "ne",
EQ = "eq",
GREATER_THAN = "gt",
GREATER_THAN_OR_EQUAL = "ge",
LESS_THAN = "lt",
LESS_THAN_OR_EQUAL = "le",
CONTAINS = "contains",
ENDS_WITH = "endswith",
STARTS_WITH = "startswith",
TO_LOWER = "tolower",
TO_UPPER = "toupper";
}
public static class DateParts {
public static final String
YEAR = "year",
MONTH = "month",
DAY = "day",
HOUR = "hour",
MINUTE = "minute",
SECOND = "second",
FRACTIONAL = "fractional";
}
}

View File

@ -16,7 +16,7 @@ import org.apache.olingo.commons.api.edm.Edm;
import org.apache.olingo.commons.api.edm.provider.CsdlProperty;
import org.apache.olingo.commons.api.format.ContentType;
import org.reso.commander.Commander;
import org.reso.commander.TestUtils;
import org.reso.commander.common.TestUtils;
import org.reso.models.ClientSettings;
import org.reso.models.Parameters;
import org.reso.models.Request;
@ -26,60 +26,25 @@ import java.io.ByteArrayInputStream;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import static org.junit.Assert.*;
import static org.reso.commander.Commander.AMPERSAND;
import static org.reso.commander.Commander.EQUALS;
import static org.reso.commander.TestUtils.HEADER_ODATA_VERSION;
import static org.reso.common.ErrorMsg.getDefaultErrorMessage;
import static org.reso.commander.common.ErrorMsg.getDefaultErrorMessage;
import static org.reso.commander.common.TestUtils.HEADER_ODATA_VERSION;
/**
* Encapsulates Commander Requests and Responses during runtime
*/
public final class WebApiTestContainer implements TestContainer {
private static final Logger LOG = LogManager.getLogger(WebApiTestContainer.class);
public static final String FIELD_SEPARATOR = ",";
public static final String EMPTY_STRING = "";
public static final String SINGLE_SPACE = " ";
public static final String DOLLAR_SIGN = "$";
public static final String PRETTY_FIELD_SEPARATOR = FIELD_SEPARATOR + SINGLE_SPACE;
public Map<String, CsdlProperty> getFieldMap() {
if (fieldMap.get() == null) {
fieldMap.set(new HashMap<>());
LOG.info("Building Field Map...this may take a moment depending on size of metadata and connection speed.");
//build a map of all of the discovered fields on the server for the given resource by field name
//this can also be used to look up type information
TestUtils.findEntityTypesForEntityTypeName(getEdm(), getXMLMetadata(), getSettings().getParameters().getValue(Parameters.WELL_KNOWN.RESOURCE_NAME))
.forEach(csdlProperty -> fieldMap.get().put(csdlProperty.getName(), csdlProperty));
assertTrue("ERROR: No field were found in the server's metadata!", fieldMap.get().size() > 0);
LOG.info("Metadata Field Map created!");
}
return fieldMap.get();
}
public String getXMLResponseData() {
return xmlResponseData.get();
}
public static final class ODATA_QUERY_PARAMS {
private static String format = DOLLAR_SIGN + "%s";
//TODO: add additional items as needed, and see if there's a lib for this in Olingo
public static final String
COUNT = String.format(format, QueryOption.COUNT),
EXPAND = String.format(format, QueryOption.EXPAND),
FILTER = String.format(format, QueryOption.FILTER),
ORDERBY = String.format(format, QueryOption.ORDERBY),
SELECT = String.format(format, QueryOption.SELECT),
SEARCH = String.format(format, QueryOption.SEARCH),
SKIP = String.format(format, QueryOption.SKIP),
TOP = String.format(format, QueryOption.TOP);
}
private static final Logger LOG = LogManager.getLogger(WebApiTestContainer.class);
private AtomicReference<Commander> commander = new AtomicReference<>();
private AtomicReference<XMLMetadata> xmlMetadata = new AtomicReference<>();
private AtomicReference<Edm> edm = new AtomicReference<>();
@ -96,6 +61,12 @@ public final class WebApiTestContainer implements TestContainer {
private AtomicReference<Map<String, CsdlProperty>> fieldMap = new AtomicReference<>();
private AtomicReference<String> xmlResponseData = new AtomicReference<>();
// Metadata state variables
private AtomicBoolean isValidXMLMetadata = new AtomicBoolean(false);
private AtomicBoolean isValidEdm = new AtomicBoolean(false);
private AtomicBoolean isXMLMetadataValidXML = new AtomicBoolean(false);
private AtomicBoolean hasXMLMetadataBeenRequested = new AtomicBoolean(false);
private AtomicBoolean hasEdmBeenRequested = new AtomicBoolean(false);
// request instance variables - these get reset with every request
private AtomicReference<String> selectList = new AtomicReference<>();
@ -114,6 +85,25 @@ public final class WebApiTestContainer implements TestContainer {
private AtomicReference<ODataRetrieveResponse<ClientEntitySet>> clientEntitySetResponse = new AtomicReference<>();
private AtomicReference<ClientEntitySet> clientEntitySet = new AtomicReference<>();
public Map<String, CsdlProperty> getFieldMap() throws Exception {
if (fieldMap.get() == null) {
fieldMap.set(new HashMap<>());
LOG.info("Building Field Map...this may take a moment depending on size of metadata and connection speed.");
//build a map of all of the discovered fields on the server for the given resource by field name
//this can also be used to look up type information
TestUtils.findEntityTypesForEntityTypeName(getEdm(), getXMLMetadata(), getSettings().getParameters().getValue(Parameters.WELL_KNOWN.RESOURCE_NAME))
.forEach(csdlProperty -> fieldMap.get().put(csdlProperty.getName(), csdlProperty));
assertTrue("ERROR: No field were found in the server's metadata!", fieldMap.get().size() > 0);
LOG.info("Metadata Field Map created!");
}
return fieldMap.get();
}
public String getXMLResponseData() {
return xmlResponseData.get();
}
/**
* Resets the state of the test container
*/
@ -188,7 +178,7 @@ public final class WebApiTestContainer implements TestContainer {
* Executes HTTP GET request and sets the expected local variables in the WebApiTestContainer
* Handles exceptions and sets response codes as well.
*/
public void executePreparedGetRequest() {
public void executePreparedRawGetRequest() throws Exception {
try {
setRawRequest(getCommander().getClient().getRetrieveRequestFactory().getRawRequest(getRequestUri()));
getRawRequest().setFormat(ContentType.JSON.toContentTypeString());
@ -197,21 +187,8 @@ public final class WebApiTestContainer implements TestContainer {
setServerODataHeaderVersion(TestUtils.getHeaderData(HEADER_ODATA_VERSION, getODataRawResponse()));
setResponseCode(getODataRawResponse().getStatusCode());
LOG.info("Request succeeded..." + getResponseData().getBytes().length + " bytes received.");
} catch (ODataClientErrorException cex) {
LOG.debug("ODataClientErrorException caught. Check tests for asserted conditions...");
LOG.debug(cex);
setODataClientErrorException(cex);
setServerODataHeaderVersion(TestUtils.getHeaderData(HEADER_ODATA_VERSION, Arrays.asList(cex.getHeaderInfo())));
setResponseCode(cex.getStatusLine().getStatusCode());
} catch (ODataServerErrorException ode) {
LOG.debug("ODataServerErrorException thrown in executeGetRequest. Check tests for asserted conditions...");
//TODO: look for better ways to do this in Olingo or open PR
if (ode.getMessage().contains(Integer.toString(HttpStatus.SC_NOT_IMPLEMENTED))) {
setResponseCode(HttpStatus.SC_NOT_IMPLEMENTED);
}
setODataServerErrorException(ode);
} catch (Exception ex) {
fail("ERROR: unhandled Exception in executeGetRequest()!\n" + ex.toString());
processODataRequestException(ex);
}
}
@ -221,7 +198,7 @@ public final class WebApiTestContainer implements TestContainer {
* @param fieldName the name of the field to retrieve metadata about
* @return the metadata for the given field
*/
public CsdlProperty getCsdlForFieldName(String fieldName) {
public CsdlProperty getCsdlForFieldName(String fieldName) throws Exception {
return getFieldMap().get(fieldName);
}
@ -230,22 +207,26 @@ public final class WebApiTestContainer implements TestContainer {
*
* @return gets the local collection of Csdl Properties
*/
public Collection<CsdlProperty> getCsdlProperties() {
public Collection<CsdlProperty> getCsdlProperties() throws Exception {
return getFieldMap().values();
}
/**
* Parses an OData $select list
* @return the de-duplicated set of select list items
*/
public Collection<String> getSelectList() {
Arrays.stream(getRequestUri().getQuery().split(AMPERSAND)).forEach(fragment -> {
if (fragment.contains(QueryOption.SELECT.toString())) {
selectList.set(fragment.replace(ODATA_QUERY_PARAMS.SELECT, EMPTY_STRING).replace(EQUALS, EMPTY_STRING));
}
});
return new ArrayList<>(Arrays.asList(selectList.get().split(FIELD_SEPARATOR)));
return new LinkedHashSet<>((Arrays.asList(selectList.get().split(FIELD_SEPARATOR))));
}
/**
* Settings getter
*
* @return local settings instance
*/
public Settings getSettings() {
@ -254,6 +235,7 @@ public final class WebApiTestContainer implements TestContainer {
/**
* Settings setter
*
* @param settings sets local settings instance to the given settings
*/
public void setSettings(Settings settings) {
@ -262,6 +244,7 @@ public final class WebApiTestContainer implements TestContainer {
/**
* Gets the Expand field from the RESOScript
*
* @return the configured Expand field
*/
public String getExpandField() {
@ -274,19 +257,26 @@ public final class WebApiTestContainer implements TestContainer {
* @return
* @implNote the data in this item are cached in the test container once fetched
*/
public Edm getEdm() {
public Edm getEdm() throws Exception {
if (edm.get() == null) {
ODataRetrieveResponse<Edm> response = getCommander().prepareEdmMetadataRequest().execute();
responseCode.set(response.getStatusCode());
setServerODataHeaderVersion(TestUtils.getHeaderData(HEADER_ODATA_VERSION, response));
edm.set(response.getBody());
try {
LOG.info("Requesting the entity data model (Edm) from service root at: " + getServiceRoot());
ODataRetrieveResponse<Edm> response = getCommander().prepareEdmMetadataRequest().execute();
responseCode.set(response.getStatusCode());
setServerODataHeaderVersion(TestUtils.getHeaderData(HEADER_ODATA_VERSION, response));
edm.set(response.getBody());
} catch(Exception ex){
processODataRequestException(ex);
} finally {
hasEdmBeenRequested.set(true);
}
}
return edm.get();
}
/**
* Gets server metadata in XMLMetadata format.
*
* <p>
* Note: this method takes a slightly different approach than getting XML Metadata did previously in that
* rather than fetching the metadata directly from the server using the Olingo getXmlMetadata method,
* we make a raw request instead so that we can capture the response string for XML validation, and
@ -295,7 +285,7 @@ public final class WebApiTestContainer implements TestContainer {
* @return XMLMetadata representation of the server metadata.
* @implNote the data in this item are cached in the test container once fetched
*/
public XMLMetadata getXMLMetadata() {
public XMLMetadata getXMLMetadata() throws Exception {
if (xmlMetadata.get() == null) {
try {
String requestUri = Settings.resolveParameters(getSettings().getRequest(Request.WELL_KNOWN.METADATA_ENDPOINT), getSettings()).getUrl();
@ -304,20 +294,22 @@ public final class WebApiTestContainer implements TestContainer {
ODataRawRequest request = getCommander().getClient().getRetrieveRequestFactory().getRawRequest(URI.create(requestUri));
request.setFormat(ContentType.JSON.toContentTypeString());
LOG.info("Requesting XML Metadata from service root at: " + getServiceRoot());
ODataRawResponse response = request.execute();
responseCode.set(response.getStatusCode());
setServerODataHeaderVersion(TestUtils.getHeaderData(HEADER_ODATA_VERSION, response));
xmlResponseData.set(TestUtils.convertInputStreamToString(response.getRawResponse()));
//deserialize response into XML Metadata - will throw an exception if metadata are in valid
XMLMetadata metadata = getCommander().getClient().getDeserializer(ContentType.APPLICATION_XML)
.toMetadata(new ByteArrayInputStream(xmlResponseData.get().getBytes(StandardCharsets.UTF_8)));
responseCode.set(response.getStatusCode());
setServerODataHeaderVersion(TestUtils.getHeaderData(HEADER_ODATA_VERSION, response));
xmlMetadata.set(metadata);
} catch (Exception ex) {
getDefaultErrorMessage(ex);
processODataRequestException(ex);
} finally {
hasXMLMetadataBeenRequested.set(true);
}
}
return xmlMetadata.get();
@ -518,4 +510,82 @@ public final class WebApiTestContainer implements TestContainer {
public void setPathToRESOScript(String pathToRESOScript) {
this.pathToRESOScript.set(pathToRESOScript);
}
private void processODataRequestException(Exception exception, boolean bubble) throws Exception {
if (exception instanceof ODataClientErrorException) processODataRequestException((ODataClientErrorException)exception);
else if (exception instanceof ODataServerErrorException) processODataRequestException(((ODataServerErrorException)exception));
else LOG.error(getDefaultErrorMessage(exception));
if (bubble) throw exception;
}
private void processODataRequestException(Exception exception) throws Exception {
processODataRequestException(exception, true);
}
private void processODataRequestException(ODataClientErrorException exception) {
LOG.debug("ODataClientErrorException caught. Check tests for asserted conditions...");
LOG.debug(exception);
setODataClientErrorException(exception);
setServerODataHeaderVersion(TestUtils.getHeaderData(HEADER_ODATA_VERSION, Arrays.asList(exception.getHeaderInfo())));
setResponseCode(exception.getStatusLine().getStatusCode());
}
private void processODataRequestException(ODataServerErrorException exception) {
LOG.debug("ODataServerErrorException thrown in executeGetRequest. Check tests for asserted conditions...");
//TODO: look for better ways to do this in Olingo or open PR
if (exception.getMessage().contains(Integer.toString(HttpStatus.SC_NOT_IMPLEMENTED))) {
setResponseCode(HttpStatus.SC_NOT_IMPLEMENTED);
}
setODataServerErrorException(exception);
}
public boolean getIsMetadataValid() {
return xmlMetadata.get() != null && getIsValidXMLMetadata()
&& xmlResponseData.get() != null && getIsXMLMetadataValidXML()
&& edm.get() != null && getIsValidEdm();
}
public boolean getIsValidXMLMetadata() {
return isValidXMLMetadata.get();
}
public void setIsValidXMLMetadata(boolean isValid) {
isValidXMLMetadata.set(isValid);
}
public boolean getIsValidEdm() {
return isValidEdm.get();
}
public void setIsValidEdm(boolean isValid) {
isValidEdm.set(isValid);
}
public boolean getIsXMLMetadataValidXML() {
return isXMLMetadataValidXML.get();
}
public void setIsXMLMetadataValidXML(boolean isValid) {
isXMLMetadataValidXML.set(isValid);
}
public boolean hasNotFetchedMetadata() {
return !hasXMLMetadataBeenRequested.get() && !hasEdmBeenRequested.get();
}
public static final class ODATA_QUERY_PARAMS {
private static String format = DOLLAR_SIGN + "%s";
//TODO: add additional items as needed, and see if there's a lib for this in Olingo
public static final String
COUNT = String.format(format, QueryOption.COUNT),
EXPAND = String.format(format, QueryOption.EXPAND),
FILTER = String.format(format, QueryOption.FILTER),
ORDERBY = String.format(format, QueryOption.ORDERBY),
SELECT = String.format(format, QueryOption.SELECT),
SEARCH = String.format(format, QueryOption.SEARCH),
SKIP = String.format(format, QueryOption.SKIP),
TOP = String.format(format, QueryOption.TOP);
}
}

View File

@ -1,6 +1,6 @@
package org.reso.common;
package org.reso.commander.common;
import static org.reso.commander.certfication.containers.WebApiTestContainer.EMPTY_STRING;
import static org.reso.commander.certfication.containers.WebApiTestContainer.SINGLE_SPACE;
public final class ErrorMsg {
private static final String ERROR_MESSAGE_TEMPLATE = "ERROR: %s";
@ -12,7 +12,7 @@ public final class ErrorMsg {
* @return a string containing the default error message for display
*/
public static String getDefaultErrorMessage(final String... msgs) {
return String.format(ERROR_MESSAGE_TEMPLATE, String.join(EMPTY_STRING, msgs));
return String.format(ERROR_MESSAGE_TEMPLATE, String.join(SINGLE_SPACE, msgs));
}
/**
@ -21,7 +21,7 @@ public final class ErrorMsg {
* @return formatted error message using the default format
*/
public static String getDefaultErrorMessage(final Exception ex) {
return String.format(ex.toString());
return getDefaultErrorMessage(ex.toString());
}
/**