From 1b621e0ce6fe0a93ae501037a7913c2bfc9318b9 Mon Sep 17 00:00:00 2001 From: "helmi.nour" Date: Fri, 19 May 2023 12:33:46 +0100 Subject: [PATCH 1/4] mock multipart response with relation id removed from the arrow part name --- rai-sdk-examples/pom.xml | 11 ++ .../src/main/resources/log4j.properties | 5 + rai-sdk/pom.xml | 12 ++ .../com/relationalai/MultipartReader.java | 4 +- .../relationalai/ExecuteAsyncMockedTest.java | 131 ++++++++++++++++++ rai-sdk/src/test/resources/multipart.data | Bin 0 -> 1912 bytes 6 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 rai-sdk-examples/src/main/resources/log4j.properties create mode 100644 rai-sdk/src/test/java/com/relationalai/ExecuteAsyncMockedTest.java create mode 100644 rai-sdk/src/test/resources/multipart.data diff --git a/rai-sdk-examples/pom.xml b/rai-sdk-examples/pom.xml index 17e46d60..ac1a78d2 100644 --- a/rai-sdk-examples/pom.xml +++ b/rai-sdk-examples/pom.xml @@ -39,6 +39,11 @@ rai-sdk ${project.parent.version} + + org.slf4j + slf4j-reload4j + 2.0.6 + @@ -62,5 +67,11 @@ maven-dependency-plugin + + + src/main/resources + true + + diff --git a/rai-sdk-examples/src/main/resources/log4j.properties b/rai-sdk-examples/src/main/resources/log4j.properties new file mode 100644 index 00000000..1a679393 --- /dev/null +++ b/rai-sdk-examples/src/main/resources/log4j.properties @@ -0,0 +1,5 @@ +log4j.rootLogger=DEBUG, stdout +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target=System.out +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} %p : %m%n diff --git a/rai-sdk/pom.xml b/rai-sdk/pom.xml index 224b969d..406f7c7f 100644 --- a/rai-sdk/pom.xml +++ b/rai-sdk/pom.xml @@ -40,6 +40,18 @@ 5.8.2 test + + org.mockito + mockito-core + 4.1.0 + test + + + org.mockito + mockito-junit-jupiter + 4.1.0 + test + commons-fileupload commons-fileupload diff --git a/rai-sdk/src/main/java/com/relationalai/MultipartReader.java b/rai-sdk/src/main/java/com/relationalai/MultipartReader.java index 12ecc6ec..a8abb368 100644 --- a/rai-sdk/src/main/java/com/relationalai/MultipartReader.java +++ b/rai-sdk/src/main/java/com/relationalai/MultipartReader.java @@ -136,9 +136,11 @@ private static String getFieldName(String contentDisposition) { // parameter parser can handle null input Map params = parser.parse(contentDisposition, ';'); - fieldName = (String) params.get("name"); + fieldName = params.get("name"); if (fieldName != null) { fieldName = fieldName.trim(); + } else { + fieldName = ""; } } diff --git a/rai-sdk/src/test/java/com/relationalai/ExecuteAsyncMockedTest.java b/rai-sdk/src/test/java/com/relationalai/ExecuteAsyncMockedTest.java new file mode 100644 index 00000000..03d83c98 --- /dev/null +++ b/rai-sdk/src/test/java/com/relationalai/ExecuteAsyncMockedTest.java @@ -0,0 +1,131 @@ +/* + * Copyright 2022 RelationalAI, Inc. + * + * Licensed 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 com.relationalai; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mockito; +import relationalai.protocol.Message; + +import javax.net.ssl.SSLSession; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.http.HttpClient; +import java.net.http.HttpHeaders; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.*; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +@ExtendWith({TestExtension.class}) +public class ExecuteAsyncMockedTest extends UnitTest { + + @Test + void testExecuteAsync() throws HttpError, InterruptedException, IOException, URISyntaxException { + var client = createClient(); + client.setHttpClient(mockedHttpClient()); + + var query = "x, x^2, x^3, x^4 from x in {1; 2; 3; 4; 5}"; + + var rsp = client.executeAsync("mockedDB", "mockedEngine", query, true); + + var results = new ArrayList () { + { + add(new ArrowRelation("", Arrays.asList(new Object[] {1L, 2L, 3L, 4L, 5L}) )); + add(new ArrowRelation("", Arrays.asList(new Object[] {1L, 4L, 9L, 16L, 25L}) )); + add(new ArrowRelation("", Arrays.asList(new Object[] {1L, 8L, 27L, 64L, 125L}) )); + add(new ArrowRelation("", Arrays.asList(new Object[] {1L, 16L, 81L, 256L, 625L}) )); + } + }; + + var problems = new ArrayList(); + + var metadata = Message.MetadataInfo.parseFrom( + Files.readAllBytes( + Path.of(Paths.get(getClass().getResource("/metadata.pb").toURI()).toString()) + ) + ); + + assertEquals(rsp.metadata.toString(), metadata.toString()); + assertEquals(rsp.results, results); + assertEquals(rsp.problems, problems); + } + + HttpClient mockedHttpClient() throws IOException, InterruptedException, URISyntaxException { + var httpRequest = HttpRequest.newBuilder() + .headers("User-Agent", "rai-sdk-java") + .uri(new URI("https://mocked/path/to/transactions")).build(); + var httpResponse = new HttpResponse<>() { + @Override + public int statusCode() { + return 200; + } + @Override + public HttpRequest request() { + return httpRequest; + } + @Override + public Optional> previousResponse() { + return Optional.empty(); + } + @Override + public HttpHeaders headers() { + Map> headers = new HashMap<>() {{ + put("Content-Type", new ArrayList<>() {{ add ("multipart/form-data; boundary=b11385ead6144ee0a9550db3672a7ccf"); }}); + }}; + return HttpHeaders.of(headers, (k, v) -> true); + } + @Override + public Object body() { + try { + return Files.readAllBytes( + Path.of(Paths.get(getClass().getResource("/multipart.data").toURI()).toString()) + ); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + @Override + public Optional sslSession() { + return Optional.empty(); + } + @Override + public URI uri() { + return null; + } + @Override + public HttpClient.Version version() { + return HttpClient.Version.HTTP_1_1; + } + }; + + var httpClient = Mockito.mock(HttpClient.class); + Mockito.when(httpClient.send(any(HttpRequest.class), any(HttpResponse.BodyHandler.class))).thenReturn(httpResponse); + return httpClient; + } +} diff --git a/rai-sdk/src/test/resources/multipart.data b/rai-sdk/src/test/resources/multipart.data new file mode 100644 index 0000000000000000000000000000000000000000..4bd88bc6f95a8d6f68525bcdbc74779eceda099e GIT binary patch literal 1912 zcmb_c&2G~`5Z*L_nk7b2R8T57M0?`Erg457SD;F550yX^skf@C*7imOCAP6Qp{Vo) zc!C}|aNt3B1m362*t;rCm8wOVYIb&JKF@wLyD8_MAoLv<- z{2EKQF5-AR@&y7nKBZA;Q=6W#QNUc*^JFmW_kF(E>JIqO4YxcYW zd&Lq7M8Z^_APJ#PW->|fSeLaL%|-_hsS-+pzw`dx!P~vVyA&P z9%kqbAf%#eZ01t8y|`1JeeO-+VcV3xp>4Wu71>i-vI><-)uxZF%J;&<{8qBy%FVU9 z+H8mT7P%^4Veljc?GxbEcMl2qofCLE3;V`G(;@?k20TDBUOnM z6CC^{h*cn@LQp6vgIc5nYaT1W-hw}pSzL4d2{r)jX#X43!5Vp;6|x3d=a9Q)UtZ{%rJfd`at8*;Pe*BOPw&*;EZqVfk|j Date: Fri, 19 May 2023 13:27:45 +0100 Subject: [PATCH 2/4] simplify httpResponse mock --- .../relationalai/ExecuteAsyncMockedTest.java | 56 ++++--------------- 1 file changed, 10 insertions(+), 46 deletions(-) diff --git a/rai-sdk/src/test/java/com/relationalai/ExecuteAsyncMockedTest.java b/rai-sdk/src/test/java/com/relationalai/ExecuteAsyncMockedTest.java index 03d83c98..c1874905 100644 --- a/rai-sdk/src/test/java/com/relationalai/ExecuteAsyncMockedTest.java +++ b/rai-sdk/src/test/java/com/relationalai/ExecuteAsyncMockedTest.java @@ -48,7 +48,7 @@ public class ExecuteAsyncMockedTest extends UnitTest { @Test void testExecuteAsync() throws HttpError, InterruptedException, IOException, URISyntaxException { var client = createClient(); - client.setHttpClient(mockedHttpClient()); + client.setHttpClient(getMockedHttpClient()); var query = "x, x^2, x^3, x^4 from x in {1; 2; 3; 4; 5}"; @@ -76,55 +76,19 @@ void testExecuteAsync() throws HttpError, InterruptedException, IOException, URI assertEquals(rsp.problems, problems); } - HttpClient mockedHttpClient() throws IOException, InterruptedException, URISyntaxException { + HttpClient getMockedHttpClient() throws IOException, InterruptedException, URISyntaxException { var httpRequest = HttpRequest.newBuilder() .headers("User-Agent", "rai-sdk-java") .uri(new URI("https://mocked/path/to/transactions")).build(); - var httpResponse = new HttpResponse<>() { - @Override - public int statusCode() { - return 200; - } - @Override - public HttpRequest request() { - return httpRequest; - } - @Override - public Optional> previousResponse() { - return Optional.empty(); - } - @Override - public HttpHeaders headers() { - Map> headers = new HashMap<>() {{ - put("Content-Type", new ArrayList<>() {{ add ("multipart/form-data; boundary=b11385ead6144ee0a9550db3672a7ccf"); }}); - }}; - return HttpHeaders.of(headers, (k, v) -> true); - } - @Override - public Object body() { - try { - return Files.readAllBytes( - Path.of(Paths.get(getClass().getResource("/multipart.data").toURI()).toString()) - ); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - @Override - public Optional sslSession() { - return Optional.empty(); - } - @Override - public URI uri() { - return null; - } - @Override - public HttpClient.Version version() { - return HttpClient.Version.HTTP_1_1; - } - }; - var httpClient = Mockito.mock(HttpClient.class); + var httpResponse = Mockito.mock(HttpResponse.class); + + Mockito.when(httpResponse.statusCode()).thenReturn(200); + Mockito.when(httpResponse.request()).thenReturn(httpRequest); + Mockito.when(httpResponse.headers()).thenReturn( + HttpHeaders.of(new HashMap<>() {{put("Content-Type", new ArrayList<>() {{ add ("multipart/form-data; boundary=b11385ead6144ee0a9550db3672a7ccf"); }}); + }}, (k, v) -> true)); + Mockito.when(httpResponse.body()).thenReturn(Files.readAllBytes(Path.of(Paths.get(getClass().getResource("/multipart.data").toURI()).toString()))); Mockito.when(httpClient.send(any(HttpRequest.class), any(HttpResponse.BodyHandler.class))).thenReturn(httpResponse); return httpClient; } From 2c32b53f8db15042a8c2e6b48fbab1f42ce7c090 Mon Sep 17 00:00:00 2001 From: "helmi.nour" Date: Mon, 22 May 2023 21:02:11 +0100 Subject: [PATCH 3/4] fix oauth mocked http call --- .../relationalai/ExecuteAsyncMockedTest.java | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/rai-sdk/src/test/java/com/relationalai/ExecuteAsyncMockedTest.java b/rai-sdk/src/test/java/com/relationalai/ExecuteAsyncMockedTest.java index c1874905..2878d7ed 100644 --- a/rai-sdk/src/test/java/com/relationalai/ExecuteAsyncMockedTest.java +++ b/rai-sdk/src/test/java/com/relationalai/ExecuteAsyncMockedTest.java @@ -16,15 +16,12 @@ package com.relationalai; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mockito; import relationalai.protocol.Message; -import javax.net.ssl.SSLSession; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; @@ -38,15 +35,14 @@ import java.util.*; import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.*; @TestInstance(TestInstance.Lifecycle.PER_CLASS) @ExtendWith({TestExtension.class}) public class ExecuteAsyncMockedTest extends UnitTest { @Test - void testExecuteAsync() throws HttpError, InterruptedException, IOException, URISyntaxException { + void testExecuteAsyncMocked() throws HttpError, InterruptedException, IOException, URISyntaxException { var client = createClient(); client.setHttpClient(getMockedHttpClient()); @@ -81,15 +77,25 @@ HttpClient getMockedHttpClient() throws IOException, InterruptedException, URISy .headers("User-Agent", "rai-sdk-java") .uri(new URI("https://mocked/path/to/transactions")).build(); var httpClient = Mockito.mock(HttpClient.class); - var httpResponse = Mockito.mock(HttpResponse.class); + var txnhttpResponse = Mockito.mock(HttpResponse.class); + var oauthHttpResponse = Mockito.mock(HttpResponse.class); - Mockito.when(httpResponse.statusCode()).thenReturn(200); - Mockito.when(httpResponse.request()).thenReturn(httpRequest); - Mockito.when(httpResponse.headers()).thenReturn( + + Mockito.when(oauthHttpResponse.statusCode()).thenReturn(200); + Mockito.when(oauthHttpResponse.request()).thenReturn(httpRequest); + Mockito.when(oauthHttpResponse.body()).thenReturn( + "{\"access_token\": \"mocked_token\", \"scope\": \"mocked_scope\", \"expires_in\": 3600}" + ); + + Mockito.when(txnhttpResponse.statusCode()).thenReturn(200); + Mockito.when(txnhttpResponse.request()).thenReturn(httpRequest); + Mockito.when(txnhttpResponse.headers()).thenReturn( HttpHeaders.of(new HashMap<>() {{put("Content-Type", new ArrayList<>() {{ add ("multipart/form-data; boundary=b11385ead6144ee0a9550db3672a7ccf"); }}); }}, (k, v) -> true)); - Mockito.when(httpResponse.body()).thenReturn(Files.readAllBytes(Path.of(Paths.get(getClass().getResource("/multipart.data").toURI()).toString()))); - Mockito.when(httpClient.send(any(HttpRequest.class), any(HttpResponse.BodyHandler.class))).thenReturn(httpResponse); + Mockito.when(txnhttpResponse.body()).thenReturn(Files.readAllBytes(Path.of(Paths.get(getClass().getResource("/multipart.data").toURI()).toString()))); + + Mockito.when(httpClient.send(any(), any())).thenReturn(oauthHttpResponse, txnhttpResponse); + return httpClient; } } From 00e6e5bb828e9b36cbb00bc50c873113e43e7afa Mon Sep 17 00:00:00 2001 From: "helmi.nour" Date: Tue, 23 May 2023 13:21:16 +0100 Subject: [PATCH 4/4] fix --- .../java/com/relationalai/ExecuteAsyncMockedTest.java | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/rai-sdk/src/test/java/com/relationalai/ExecuteAsyncMockedTest.java b/rai-sdk/src/test/java/com/relationalai/ExecuteAsyncMockedTest.java index 2878d7ed..e4c1b543 100644 --- a/rai-sdk/src/test/java/com/relationalai/ExecuteAsyncMockedTest.java +++ b/rai-sdk/src/test/java/com/relationalai/ExecuteAsyncMockedTest.java @@ -78,14 +78,6 @@ HttpClient getMockedHttpClient() throws IOException, InterruptedException, URISy .uri(new URI("https://mocked/path/to/transactions")).build(); var httpClient = Mockito.mock(HttpClient.class); var txnhttpResponse = Mockito.mock(HttpResponse.class); - var oauthHttpResponse = Mockito.mock(HttpResponse.class); - - - Mockito.when(oauthHttpResponse.statusCode()).thenReturn(200); - Mockito.when(oauthHttpResponse.request()).thenReturn(httpRequest); - Mockito.when(oauthHttpResponse.body()).thenReturn( - "{\"access_token\": \"mocked_token\", \"scope\": \"mocked_scope\", \"expires_in\": 3600}" - ); Mockito.when(txnhttpResponse.statusCode()).thenReturn(200); Mockito.when(txnhttpResponse.request()).thenReturn(httpRequest); @@ -94,7 +86,7 @@ HttpClient getMockedHttpClient() throws IOException, InterruptedException, URISy }}, (k, v) -> true)); Mockito.when(txnhttpResponse.body()).thenReturn(Files.readAllBytes(Path.of(Paths.get(getClass().getResource("/multipart.data").toURI()).toString()))); - Mockito.when(httpClient.send(any(), any())).thenReturn(oauthHttpResponse, txnhttpResponse); + Mockito.when(httpClient.send(any(), any())).thenReturn(txnhttpResponse); return httpClient; }