|  | 
| 8 | 8 | 
 | 
| 9 | 9 | import com.atlassian.oai.validator.model.SimpleRequest; | 
| 10 | 10 | import com.atlassian.oai.validator.report.ValidationReport; | 
|  | 11 | +import com.getyourguide.openapi.validation.api.log.LogLevel; | 
| 11 | 12 | import com.getyourguide.openapi.validation.api.model.OpenApiViolation; | 
| 12 | 13 | import com.getyourguide.openapi.validation.api.model.RequestMetaData; | 
|  | 14 | +import com.getyourguide.openapi.validation.api.model.ResponseMetaData; | 
| 13 | 15 | import com.getyourguide.openapi.validation.core.exclusions.InternalViolationExclusions; | 
| 14 | 16 | import com.getyourguide.openapi.validation.core.mapper.ValidationReportToOpenApiViolationsMapper; | 
| 15 | 17 | import com.getyourguide.openapi.validation.core.validator.OpenApiInteractionValidatorWrapper; | 
|  | 
| 19 | 21 | import java.util.concurrent.Executor; | 
| 20 | 22 | import java.util.concurrent.RejectedExecutionException; | 
| 21 | 23 | import org.junit.jupiter.api.BeforeEach; | 
|  | 24 | +import org.junit.jupiter.api.DisplayName; | 
|  | 25 | +import org.junit.jupiter.api.Nested; | 
| 22 | 26 | import org.junit.jupiter.api.Test; | 
| 23 | 27 | import org.mockito.ArgumentCaptor; | 
| 24 | 28 | import org.mockito.Mockito; | 
| @@ -51,49 +55,178 @@ public void setup() { | 
| 51 | 55 |     } | 
| 52 | 56 | 
 | 
| 53 | 57 |     @Test | 
|  | 58 | +    @DisplayName("When thread pool executor rejects execution then it should not throw") | 
| 54 | 59 |     public void testWhenThreadPoolExecutorRejectsExecutionThenItShouldNotThrow() { | 
| 55 | 60 |         Mockito.doThrow(new RejectedExecutionException()).when(executor).execute(any()); | 
| 56 | 61 | 
 | 
| 57 | 62 |         openApiRequestValidator.validateRequestObjectAsync(mock(), null, null, mock()); | 
| 58 | 63 |     } | 
| 59 | 64 | 
 | 
| 60 |  | -    @Test | 
| 61 |  | -    public void testWhenEncodedQueryParamIsPassedThenValidationShouldHappenWithQueryParamDecoded() { | 
| 62 |  | -        var uri = URI.create("https://api.example.com?ids=1%2C2%2C3&text=e%3Dmc2%20%26%20more&spaces=this+is+a+sparta"); | 
| 63 |  | -        var request = new RequestMetaData("GET", uri, new HashMap<>()); | 
|  | 65 | +    @Nested | 
|  | 66 | +    @DisplayName("validateRequestObject") | 
|  | 67 | +    public class ValidateRequestObjectTests { | 
|  | 68 | + | 
|  | 69 | +        @Test | 
|  | 70 | +        @DisplayName("When encoded query param is passed then validation should happen with query param decoded") | 
|  | 71 | +        public void testWhenEncodedQueryParamIsPassedThenValidationShouldHappenWithQueryParamDecoded() { | 
|  | 72 | +            var uri = URI.create("https://api.example.com?ids=1%2C2%2C3&text=e%3Dmc2%20%26%20more&spaces=this+is+a+sparta"); | 
|  | 73 | +            var request = new RequestMetaData("GET", uri, new HashMap<>()); | 
|  | 74 | + | 
|  | 75 | +            openApiRequestValidator.validateRequestObject(request, null); | 
|  | 76 | + | 
|  | 77 | +            var simpleRequestArgumentCaptor = ArgumentCaptor.forClass(SimpleRequest.class); | 
|  | 78 | +            verify(validator).validateRequest(simpleRequestArgumentCaptor.capture()); | 
|  | 79 | +            verifyQueryParamValueEquals(simpleRequestArgumentCaptor, "ids", "1,2,3"); | 
|  | 80 | +            verifyQueryParamValueEquals(simpleRequestArgumentCaptor, "text", "e=mc2 & more"); | 
|  | 81 | +            verifyQueryParamValueEquals(simpleRequestArgumentCaptor, "spaces", "this is a sparta"); | 
|  | 82 | +        } | 
|  | 83 | + | 
|  | 84 | +        @Test | 
|  | 85 | +        @DisplayName("When violation is excluded then it should not be returned") | 
|  | 86 | +        public void testWhenViolationIsExcludedThenItShouldNotBeReturned() { | 
|  | 87 | +            var validationReport = mock(ValidationReport.class); | 
|  | 88 | +            when(validator.validateRequest(any())).thenReturn(validationReport); | 
|  | 89 | +            var violationExcluded = mock(OpenApiViolation.class); | 
|  | 90 | +            var violations = List.of(violationExcluded, mock(OpenApiViolation.class)); | 
|  | 91 | +            when(mapper.map(any(), any(), any(), any(), any())).thenReturn(violations); | 
|  | 92 | +            when(internalViolationExclusions.isExcluded(violationExcluded)).thenReturn(true); | 
|  | 93 | + | 
|  | 94 | +            var result = openApiRequestValidator.validateRequestObject(createRequest(), null); | 
|  | 95 | + | 
|  | 96 | +            assertEquals(1, result.size()); | 
|  | 97 | +            assertEquals(violations.get(1), result.getFirst()); | 
|  | 98 | +        } | 
|  | 99 | + | 
|  | 100 | +        @Test | 
|  | 101 | +        @DisplayName("When violation has log level IGNORE then it should not be returned") | 
|  | 102 | +        public void testWhenRequestViolationHasLogLevelIgnoreThenItShouldNotBeReturned() { | 
|  | 103 | +            var violationIgnored = createViolation(LogLevel.IGNORE); | 
|  | 104 | +            var violationError = createViolation(LogLevel.ERROR); | 
|  | 105 | +            mockRequestValidation(List.of(violationIgnored, violationError)); | 
|  | 106 | + | 
|  | 107 | +            var result = openApiRequestValidator.validateRequestObject(createRequest(), null); | 
|  | 108 | + | 
|  | 109 | +            assertSingleViolationReturned(result, violationError); | 
|  | 110 | +        } | 
|  | 111 | + | 
|  | 112 | +        @Test | 
|  | 113 | +        @DisplayName("When violation has log level IGNORE and another is excluded then both should not be returned") | 
|  | 114 | +        public void testWhenRequestViolationHasLogLevelIgnoreAndIsExcludedThenItShouldNotBeReturned() { | 
|  | 115 | +            var violationIgnored = createViolation(LogLevel.IGNORE); | 
|  | 116 | +            var violationExcluded = createViolation(LogLevel.WARN); | 
|  | 117 | +            when(internalViolationExclusions.isExcluded(violationExcluded)).thenReturn(true); | 
|  | 118 | +            var violationError = createViolation(LogLevel.ERROR); | 
|  | 119 | +            mockRequestValidation(List.of(violationIgnored, violationExcluded, violationError)); | 
|  | 120 | + | 
|  | 121 | +            var result = openApiRequestValidator.validateRequestObject(createRequest(), null); | 
|  | 122 | + | 
|  | 123 | +            assertSingleViolationReturned(result, violationError); | 
|  | 124 | +        } | 
|  | 125 | + | 
|  | 126 | +        @Test | 
|  | 127 | +        @DisplayName("When all violations are ignored then empty list is returned") | 
|  | 128 | +        public void testWhenAllRequestViolationsAreIgnoredThenEmptyListIsReturned() { | 
|  | 129 | +            var violation1 = createViolation(LogLevel.IGNORE); | 
|  | 130 | +            var violation2 = createViolation(LogLevel.IGNORE); | 
|  | 131 | +            mockRequestValidation(List.of(violation1, violation2)); | 
|  | 132 | + | 
|  | 133 | +            var result = openApiRequestValidator.validateRequestObject(createRequest(), null); | 
|  | 134 | + | 
|  | 135 | +            assertNoViolationsReturned(result); | 
|  | 136 | +        } | 
|  | 137 | +    } | 
|  | 138 | + | 
|  | 139 | +    @Nested | 
|  | 140 | +    @DisplayName("validateResponseObject") | 
|  | 141 | +    public class ValidateResponseObjectTests { | 
|  | 142 | + | 
|  | 143 | +        @Test | 
|  | 144 | +        @DisplayName("When violation has log level IGNORE then it should not be returned") | 
|  | 145 | +        public void testWhenResponseViolationHasLogLevelIgnoreThenItShouldNotBeReturned() { | 
|  | 146 | +            var violationIgnored = createViolation(LogLevel.IGNORE); | 
|  | 147 | +            var violationWarn = createViolation(LogLevel.WARN); | 
|  | 148 | +            mockResponseValidation(List.of(violationIgnored, violationWarn)); | 
|  | 149 | + | 
|  | 150 | +            var result = executeValidateResponseObject(); | 
|  | 151 | + | 
|  | 152 | +            assertSingleViolationReturned(result, violationWarn); | 
|  | 153 | +        } | 
|  | 154 | + | 
|  | 155 | +        @Test | 
|  | 156 | +        @DisplayName("When violation has log level IGNORE and another is excluded then both should not be returned") | 
|  | 157 | +        public void testWhenResponseViolationHasLogLevelIgnoreAndIsExcludedThenItShouldNotBeReturned() { | 
|  | 158 | +            var violationIgnored = createViolation(LogLevel.IGNORE); | 
|  | 159 | +            var violationExcluded = createViolation(LogLevel.INFO); | 
|  | 160 | +            when(internalViolationExclusions.isExcluded(violationExcluded)).thenReturn(true); | 
|  | 161 | +            var violationError = createViolation(LogLevel.ERROR); | 
|  | 162 | +            mockResponseValidation(List.of(violationIgnored, violationExcluded, violationError)); | 
|  | 163 | + | 
|  | 164 | +            var result = executeValidateResponseObject(); | 
|  | 165 | + | 
|  | 166 | +            assertSingleViolationReturned(result, violationError); | 
|  | 167 | +        } | 
|  | 168 | + | 
|  | 169 | +        @Test | 
|  | 170 | +        @DisplayName("When all violations are ignored then empty list is returned") | 
|  | 171 | +        public void testWhenAllResponseViolationsAreIgnoredThenEmptyListIsReturned() { | 
|  | 172 | +            var violation1 = createViolation(LogLevel.IGNORE); | 
|  | 173 | +            var violation2 = createViolation(LogLevel.IGNORE); | 
|  | 174 | +            mockResponseValidation(List.of(violation1, violation2)); | 
|  | 175 | + | 
|  | 176 | +            var result = executeValidateResponseObject(); | 
|  | 177 | + | 
|  | 178 | +            assertNoViolationsReturned(result); | 
|  | 179 | +        } | 
|  | 180 | + | 
|  | 181 | +        private List<OpenApiViolation> executeValidateResponseObject() { | 
|  | 182 | +            var request = createRequest(); | 
|  | 183 | +            var response = createResponse(); | 
|  | 184 | +            return openApiRequestValidator.validateResponseObject(request, response, null); | 
|  | 185 | +        } | 
|  | 186 | +    } | 
| 64 | 187 | 
 | 
| 65 |  | -        openApiRequestValidator.validateRequestObject(request, null); | 
|  | 188 | +    private void verifyQueryParamValueEquals( | 
|  | 189 | +        ArgumentCaptor<SimpleRequest> simpleRequestArgumentCaptor, | 
|  | 190 | +        String name, | 
|  | 191 | +        String expected | 
|  | 192 | +    ) { | 
|  | 193 | +        var ids = simpleRequestArgumentCaptor.getValue().getQueryParameterValues(name).iterator().next(); | 
|  | 194 | +        assertEquals(expected, ids); | 
|  | 195 | +    } | 
| 66 | 196 | 
 | 
| 67 |  | -        var simpleRequestArgumentCaptor = ArgumentCaptor.forClass(SimpleRequest.class); | 
| 68 |  | -        verify(validator).validateRequest(simpleRequestArgumentCaptor.capture()); | 
| 69 |  | -        verifyQueryParamValueEquals(simpleRequestArgumentCaptor, "ids", "1,2,3"); | 
| 70 |  | -        verifyQueryParamValueEquals(simpleRequestArgumentCaptor, "text", "e=mc2 & more"); | 
| 71 |  | -        verifyQueryParamValueEquals(simpleRequestArgumentCaptor, "spaces", "this is a sparta"); | 
|  | 197 | +    private OpenApiViolation createViolation(LogLevel level) { | 
|  | 198 | +        var violation = mock(OpenApiViolation.class); | 
|  | 199 | +        when(violation.getLevel()).thenReturn(level); | 
|  | 200 | +        return violation; | 
| 72 | 201 |     } | 
| 73 | 202 | 
 | 
| 74 |  | -    @Test | 
| 75 |  | -    public void testWhenViolationIsExcludedThenItShouldNotBeReturned() { | 
|  | 203 | +    private RequestMetaData createRequest() { | 
| 76 | 204 |         var uri = URI.create("https://api.example.com/path"); | 
| 77 |  | -        var request = new RequestMetaData("GET", uri, new HashMap<>()); | 
|  | 205 | +        return new RequestMetaData("GET", uri, new HashMap<>()); | 
|  | 206 | +    } | 
|  | 207 | + | 
|  | 208 | +    private ResponseMetaData createResponse() { | 
|  | 209 | +        return new ResponseMetaData(200, "application/json", new HashMap<>()); | 
|  | 210 | +    } | 
|  | 211 | + | 
|  | 212 | +    private void mockRequestValidation(List<OpenApiViolation> violations) { | 
| 78 | 213 |         var validationReport = mock(ValidationReport.class); | 
| 79 | 214 |         when(validator.validateRequest(any())).thenReturn(validationReport); | 
| 80 |  | -        var violationExcluded = mock(OpenApiViolation.class); | 
| 81 |  | -        var violations = List.of(violationExcluded, mock(OpenApiViolation.class)); | 
| 82 | 215 |         when(mapper.map(any(), any(), any(), any(), any())).thenReturn(violations); | 
| 83 |  | -        when(internalViolationExclusions.isExcluded(violationExcluded)).thenReturn(true); | 
|  | 216 | +    } | 
| 84 | 217 | 
 | 
| 85 |  | -        var result = openApiRequestValidator.validateRequestObject(request, null); | 
|  | 218 | +    private void mockResponseValidation(List<OpenApiViolation> violations) { | 
|  | 219 | +        var validationReport = mock(ValidationReport.class); | 
|  | 220 | +        when(validator.validateResponse(any(), any(), any())).thenReturn(validationReport); | 
|  | 221 | +        when(mapper.map(any(), any(), any(), any(), any())).thenReturn(violations); | 
|  | 222 | +    } | 
| 86 | 223 | 
 | 
|  | 224 | +    private void assertSingleViolationReturned(List<OpenApiViolation> result, OpenApiViolation expected) { | 
| 87 | 225 |         assertEquals(1, result.size()); | 
| 88 |  | -        assertEquals(violations.get(1), result.getFirst()); | 
|  | 226 | +        assertEquals(expected, result.getFirst()); | 
| 89 | 227 |     } | 
| 90 | 228 | 
 | 
| 91 |  | -    private void verifyQueryParamValueEquals( | 
| 92 |  | -        ArgumentCaptor<SimpleRequest> simpleRequestArgumentCaptor, | 
| 93 |  | -        String name, | 
| 94 |  | -        String expected | 
| 95 |  | -    ) { | 
| 96 |  | -        var ids = simpleRequestArgumentCaptor.getValue().getQueryParameterValues(name).iterator().next(); | 
| 97 |  | -        assertEquals(expected, ids); | 
|  | 229 | +    private void assertNoViolationsReturned(List<OpenApiViolation> result) { | 
|  | 230 | +        assertEquals(0, result.size()); | 
| 98 | 231 |     } | 
| 99 | 232 | } | 
0 commit comments