From caf34749548dc051ad899fb53237ff6724a2918c Mon Sep 17 00:00:00 2001 From: Arif Burak Demiray <57103426+arifBurakDemiray@users.noreply.github.com> Date: Fri, 22 Sep 2023 15:15:33 +0300 Subject: [PATCH 1/2] refactor: github action push test results (#73) * refactor: github action push test results * fix: try action * fix: add folder for test results * feat: test results * fix: make him comment * fix: make him comment change version * fix: create comment call * feat: html preview * feat: test result * fix: semicolon * fix: remove seperatoor * fix: try gthub output * fix: try oout jon summary * feat: junit report * feat: comment tests * feat: github ction to see test results * fix: time unit * fix: fix failed tests --- .github/workflows/gradle.yml | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 4b0a7a706..3a9cad6dd 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -1,5 +1,9 @@ name: Java Gradle Build and Test +permissions: + checks: write + pull-requests: write + on: push: branches: @@ -16,7 +20,8 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - name: Checkout code + uses: actions/checkout@v4 - name: Set up JDK 8 uses: actions/setup-java@v3 @@ -24,7 +29,15 @@ jobs: java-version: '8' distribution: 'corretto' - - name: Build with Gradle - uses: gradle/gradle-build-action@749f47bda3e44aa060e82d7b3ef7e40d953bd629 + - name: Build and Test with Gradle + run: ./gradlew build + + - name: Publish Test Results + uses: EnricoMi/publish-unit-test-result-action@v2 + if: always() with: - arguments: build \ No newline at end of file + check_name: "Unit Test Results :rocket:" + comment_title: "Unit Test Results :rocket:" + files: | + sdk-java/build/test-results/**/*.xml + From b35a08f26f26bf4fc020e821a401958769bc62e6 Mon Sep 17 00:00:00 2001 From: Arif Burak Demiray <57103426+arifBurakDemiray@users.noreply.github.com> Date: Fri, 22 Sep 2023 15:36:07 +0300 Subject: [PATCH 2/2] [Java] Move storage init to init and get event queue for tests (#72) * feat: new way of storage init * feat: read file util * feat: read file content tests * feat: use read file content in storage * feat: test utils to read event queue * Taking care of potential null pointer * fix: add logging * fix: code style * fix: foormatting --------- Co-authored-by: ArtursK --- .../count/sdk/java/internal/SDKStorage.java | 25 +++---- .../ly/count/sdk/java/internal/Storage.java | 12 ++-- .../ly/count/sdk/java/internal/Utils.java | 37 +++++++++- .../ly/count/sdk/java/internal/TestUtils.java | 65 +++++++++++++++-- .../count/sdk/java/internal/UtilsTests.java | 69 +++++++++++++++++++ 5 files changed, 181 insertions(+), 27 deletions(-) diff --git a/sdk-java/src/main/java/ly/count/sdk/java/internal/SDKStorage.java b/sdk-java/src/main/java/ly/count/sdk/java/internal/SDKStorage.java index 415c31d25..fb4724f56 100644 --- a/sdk-java/src/main/java/ly/count/sdk/java/internal/SDKStorage.java +++ b/sdk-java/src/main/java/ly/count/sdk/java/internal/SDKStorage.java @@ -1,13 +1,11 @@ package ly.count.sdk.java.internal; -import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; -import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.nio.channels.FileLock; @@ -21,11 +19,9 @@ public class SDKStorage { private Log L; private CtxCore ctx; - - private static final String FILE_NAME_PREFIX = "[CLY]"; - private static final String FILE_NAME_SEPARATOR = "_"; - - private static final String EVENT_QUEUE_FILE_NAME = "event_queue"; + protected static final String FILE_NAME_PREFIX = "[CLY]"; + protected static final String FILE_NAME_SEPARATOR = "_"; + protected static final String EVENT_QUEUE_FILE_NAME = "event_queue"; protected SDKStorage() { @@ -34,6 +30,7 @@ protected SDKStorage() { public void init(CtxCore ctx, Log logger) { this.L = logger; this.ctx = ctx; + Storage.init(); } public void stop(ly.count.sdk.java.internal.CtxCore ctx, boolean clear) { @@ -302,21 +299,15 @@ protected String readEventQueue() { L.d("[SDKStorage] Getting event queue"); File file = new File(ctx.getContext(), FILE_NAME_PREFIX + FILE_NAME_SEPARATOR + EVENT_QUEUE_FILE_NAME); - if (!file.exists()) { - return ""; - } + String eventQueue = ""; - StringBuilder eventQueue = new StringBuilder(); - try (BufferedReader reader = new BufferedReader(new FileReader(file))) { - String line; - while ((line = reader.readLine()) != null) { - eventQueue.append(line); - } + try { + eventQueue = Utils.readFileContent(file, L); } catch (IOException e) { // Handle the error if reading fails L.e("[SDKStorage] Failed to read EQ from json file: " + e); } - return eventQueue.toString(); + return eventQueue; } } diff --git a/sdk-java/src/main/java/ly/count/sdk/java/internal/Storage.java b/sdk-java/src/main/java/ly/count/sdk/java/internal/Storage.java index b8d59081b..8d565317f 100644 --- a/sdk-java/src/main/java/ly/count/sdk/java/internal/Storage.java +++ b/sdk-java/src/main/java/ly/count/sdk/java/internal/Storage.java @@ -1,7 +1,5 @@ package ly.count.sdk.java.internal; -import java.util.Collections; -import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutionException; @@ -15,7 +13,11 @@ public class Storage { - private static final Tasks tasks = new Tasks("storage", null); + private static Tasks tasks; + + static void init() { + tasks = new Tasks("storage", null); + } public static String name(Storable storable) { return storable.storagePrefix() + "_" + storable.storageId(); @@ -362,6 +364,8 @@ public Boolean call() throws Exception { } public static void stop() { - tasks.shutdown(); + if (tasks != null) { + tasks.shutdown(); + } } } diff --git a/sdk-java/src/main/java/ly/count/sdk/java/internal/Utils.java b/sdk-java/src/main/java/ly/count/sdk/java/internal/Utils.java index e899412b7..ddc60ad8d 100644 --- a/sdk-java/src/main/java/ly/count/sdk/java/internal/Utils.java +++ b/sdk-java/src/main/java/ly/count/sdk/java/internal/Utils.java @@ -1,6 +1,9 @@ package ly.count.sdk.java.internal; +import java.io.BufferedReader; import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; @@ -16,7 +19,6 @@ import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; /** * Utility class @@ -291,6 +293,39 @@ public static boolean isValidDataType(Object value) { value instanceof Float; } + /** + * Read file content using UTF-8 encoding into a string and + * append lines to a "StringBuilder" and return it + * If file doesn't exist, return empty string + * + * @param file to read + * @param logger to log errors + * @return file contents or empty string + * @throws IOException if file exists but couldn't be read + */ + public static String readFileContent(File file, Log logger) throws IOException { + StringBuilder fileContent = new StringBuilder(); + + if (!file.exists()) { + logger.v("[Utils] readFileContent : File doesn't exist: " + file.getAbsolutePath() + ". returning empty string"); + return fileContent.toString(); + } + + if (!file.canRead()) { + logger.v("[Utils] readFileContent : File exists but can't be read: " + file.getAbsolutePath() + ". returning empty string"); + return fileContent.toString(); + } + + try (BufferedReader reader = new BufferedReader(new FileReader(file))) { + String line; + while ((line = reader.readLine()) != null) { + fileContent.append(line); + } + } + + return fileContent.toString(); + } + public static class Base64 { public static String encode(byte[] bytes) { return ly.count.sdk.java.internal.Base64.encodeBytes(bytes); diff --git a/sdk-java/src/test/java/ly/count/sdk/java/internal/TestUtils.java b/sdk-java/src/test/java/ly/count/sdk/java/internal/TestUtils.java index 2f75c15ff..e393c1ce3 100644 --- a/sdk-java/src/test/java/ly/count/sdk/java/internal/TestUtils.java +++ b/sdk-java/src/test/java/ly/count/sdk/java/internal/TestUtils.java @@ -2,15 +2,24 @@ import java.io.File; import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Comparator; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Scanner; import java.util.stream.Stream; +import static ly.count.sdk.java.internal.SDKStorage.EVENT_QUEUE_FILE_NAME; +import static ly.count.sdk.java.internal.SDKStorage.FILE_NAME_PREFIX; +import static ly.count.sdk.java.internal.SDKStorage.FILE_NAME_SEPARATOR; + public class TestUtils { - public TestUtils() { + private static String DELIMETER = ":::"; + + private TestUtils() { } /** @@ -20,7 +29,7 @@ public TestUtils() { * @param logger logger * @return array of request params */ - public Map[] getCurrentRequestQueue(File targetFolder, Log logger) { + protected static Map[] getCurrentRequestQueue(File targetFolder, Log logger) { //check whether target folder is a directory or not if (!targetFolder.isDirectory()) { @@ -48,13 +57,59 @@ public Map[] getCurrentRequestQueue(File targetFolder, Log logge return resultMapArray; } + /** + * Get current event queue from target folder + * + * @param targetFolder where events are stored + * @param logger logger + * @return array of json events + */ + protected static List getCurrentEventQueue(File targetFolder, Log logger) { + List events = new ArrayList<>(); + + if (!targetFolder.isDirectory()) { + logger.e("[TestUtils] " + targetFolder.getAbsolutePath() + " is not a directory"); + return events; + } + + File file = new File(targetFolder, FILE_NAME_PREFIX + FILE_NAME_SEPARATOR + EVENT_QUEUE_FILE_NAME); + String fileContent = ""; + try { + fileContent = Utils.readFileContent(file, logger); + } catch (IOException e) { + //do nothing + } + + //EventImplQueue.DELIMITER + Arrays.stream(fileContent.split(DELIMETER)).forEach(s -> { + final EventImpl event = EventImpl.fromJSON(s, (ev) -> { + }, logger); + if (event != null) { + events.add(event); + } + }); + + return events; + } + + /** + * Get last item from list + * + * @param list + * @param type of list + * @return last item from list + */ + public static T getLastItem(List list) { + return list.isEmpty() ? null : list.get(list.size() - 1); + } + /** * Get request files from target folder, sorted by last modified * * @param targetFolder folder where requests are stored * @return array of request files sorted by last modified */ - private File[] getRequestFiles(File targetFolder) { + private static File[] getRequestFiles(File targetFolder) { File[] files = targetFolder.listFiles(); if (files == null) { @@ -76,7 +131,7 @@ private File[] getRequestFiles(File targetFolder) { * @return map of request params * @throws IOException if file cannot be read */ - private Map parseRequestParams(File file) throws IOException { + private static Map parseRequestParams(File file) throws IOException { try (Scanner scanner = new Scanner(file)) { String firstLine = scanner.nextLine(); String urlDecodedStr = Utils.urldecode(firstLine); @@ -96,4 +151,4 @@ private Map parseRequestParams(File file) throws IOException { return paramMap; } } -} +} \ No newline at end of file diff --git a/sdk-java/src/test/java/ly/count/sdk/java/internal/UtilsTests.java b/sdk-java/src/test/java/ly/count/sdk/java/internal/UtilsTests.java index a062630c5..717bf2e31 100644 --- a/sdk-java/src/test/java/ly/count/sdk/java/internal/UtilsTests.java +++ b/sdk-java/src/test/java/ly/count/sdk/java/internal/UtilsTests.java @@ -1,5 +1,8 @@ package ly.count.sdk.java.internal; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Collection; @@ -18,6 +21,8 @@ public class UtilsTests { Log logger; + static final String TEST_FILE_NAME = "testFile"; + @Before public void setupEveryTest() { logger = new Log(Config.LoggingLevel.VERBOSE, null); @@ -234,4 +239,68 @@ public void isValidDataType() { Assert.assertFalse(Utils.isValidDataType(new ArrayList<>())); Assert.assertFalse(Utils.isValidDataType(new HashMap<>())); } + + /** + * It checks if the "readFileContent" method is called. + * And if the created file is read correctly. + */ + @Test + public void readFileContent() throws IOException { + String fileName = "testFile"; + String fileContent = "testContent"; + + File file = new File(fileName); + file.createNewFile(); + FileWriter writer = new FileWriter(file); + writer.write(fileContent); + writer.close(); + + String result = Utils.readFileContent(file, logger); + //delete file + file.delete(); + Assert.assertEquals(fileContent, result); + } + + /** + * If the file does not exist, + * the method should return an empty string. + */ + @Test + public void readFileContent_fileNotExist() throws IOException { + String fileName = "testFile"; + String fileContent = "testContent"; + + File file = new File(fileName); + + String result = Utils.readFileContent(file, logger); + + Assert.assertNotEquals(fileContent, result); + Assert.assertEquals("", result); + } + + /** + * If the file is not readable for some reason, + * the method should return empty string. + */ + @Test + public void readFileContent_fileNotReadable() throws IOException { + try { + String fileContent = "testContent"; + + File file = new File(TEST_FILE_NAME); + file.createNewFile(); + FileWriter writer = new FileWriter(file); + writer.write(fileContent); + writer.close(); + file.setReadable(false); + + String content = Utils.readFileContent(file, logger); + Assert.assertEquals("", content); + } finally { + File file = new File(TEST_FILE_NAME); + if (file.exists()) { + file.delete(); + } + } + } }