From 70f7be9176e969c43caf5e9da01f6e297e83178b Mon Sep 17 00:00:00 2001 From: Oleg Kopysov Date: Tue, 22 Oct 2024 09:27:53 +0300 Subject: [PATCH] refactor: Divide file save function into 2 parts, add UTs Signed-off-by: Oleg Kopysov --- .../java/com/lpvs/util/LPVSCommentUtil.java | 7 + src/main/java/com/lpvs/util/LPVSFileUtil.java | 132 +++++++++++------- .../java/com/lpvs/util/LPVSPayloadUtil.java | 7 + .../service/scan/LPVSDetectServiceTest.java | 5 + .../com/lpvs/util/LPVSCommentUtilTest.java | 24 +++- .../java/com/lpvs/util/LPVSFileUtilTest.java | 61 +++++++- .../com/lpvs/util/LPVSPayloadUtilTest.java | 20 +++ 7 files changed, 199 insertions(+), 57 deletions(-) diff --git a/src/main/java/com/lpvs/util/LPVSCommentUtil.java b/src/main/java/com/lpvs/util/LPVSCommentUtil.java index 4b1d59b8..f9ad91db 100644 --- a/src/main/java/com/lpvs/util/LPVSCommentUtil.java +++ b/src/main/java/com/lpvs/util/LPVSCommentUtil.java @@ -25,6 +25,13 @@ @Slf4j public class LPVSCommentUtil { + /** + * Private constructor to prevent instantiation of utility class + */ + private LPVSCommentUtil() { + throw new UnsupportedOperationException("Utility class, cannot be instantiated."); + } + /** * Generates a formatted string containing links to matched lines in a file. * diff --git a/src/main/java/com/lpvs/util/LPVSFileUtil.java b/src/main/java/com/lpvs/util/LPVSFileUtil.java index 3e2bdabd..38c62143 100644 --- a/src/main/java/com/lpvs/util/LPVSFileUtil.java +++ b/src/main/java/com/lpvs/util/LPVSFileUtil.java @@ -17,7 +17,7 @@ import java.io.FileWriter; import java.io.BufferedWriter; import java.io.IOException; -import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -33,73 +33,101 @@ @Slf4j public class LPVSFileUtil { + /** + * Private constructor to prevent instantiation of utility class + */ + private LPVSFileUtil() { + throw new UnsupportedOperationException("Utility class, cannot be instantiated."); + } + /** * Saves a file with the specified content in a given directory. * * @param fileName The name of the file to be saved. * @param directoryPath The path to the directory where the file will be saved. * @param patchedLines The content to be written to the file. + * @return {@code true} if file is saved, {@code false} otherwise. */ - public static void saveFile(String fileName, String directoryPath, List patchedLines) { - try { - if (patchedLines == null || patchedLines.size() == 0) { - log.error("Empty patch for file " + fileName); - return; + public static boolean saveFile( + String fileName, String directoryPath, List patchedLines) { + if (patchedLines == null || patchedLines.isEmpty()) { + log.error("Empty patch for file " + fileName); + return false; + } + int cnt = 1; + StringBuilder prettyPatch = new StringBuilder(); + for (String patchedLine : patchedLines) { + // empty line + if (patchedLine.isEmpty()) { + prettyPatch.append("\n"); + cnt++; } - int cnt = 1; - StringBuilder prettyPatch = new StringBuilder(); - for (String patchedLine : patchedLines) { - // empty line - if (patchedLine.isEmpty()) { - prettyPatch.append("\n"); - cnt++; - } - // added and unchanged lines - else if (patchedLine.charAt(0) == '+' || patchedLine.charAt(0) == ' ') { - prettyPatch.append(patchedLine.substring(1)); + // added and unchanged lines + else if (patchedLine.charAt(0) == '+' || patchedLine.charAt(0) == ' ') { + prettyPatch.append(patchedLine.substring(1)); + prettyPatch.append("\n"); + cnt++; + } + // information(location, number of lines) about changed lines + else if (patchedLine.charAt(0) == '@') { + int fIndex = patchedLine.indexOf("+") + 1; + int lIndex = patchedLine.indexOf(',', fIndex); + if (lIndex == -1) lIndex = patchedLine.indexOf(' ', fIndex); + int startLine = Integer.parseInt(patchedLine.substring(fIndex, lIndex)); + log.debug("Line from: " + startLine + " Git string: " + patchedLine); + for (int i = cnt; i < startLine; i++) { prettyPatch.append("\n"); - cnt++; - } - // information(location, number of lines) about changed lines - else if (patchedLine.charAt(0) == '@') { - int fIndex = patchedLine.indexOf("+") + 1; - int lIndex = patchedLine.indexOf(',', fIndex); - if (lIndex == -1) lIndex = patchedLine.indexOf(' ', fIndex); - int startLine = Integer.parseInt(patchedLine.substring(fIndex, lIndex)); - log.debug("Line from: " + startLine + " Git string: " + patchedLine); - for (int i = cnt; i < startLine; i++) { - prettyPatch.append("\n"); - } - cnt = startLine; } + cnt = startLine; } + } - if (fileName.contains("/")) { - String filepath = fileName.substring(0, fileName.lastIndexOf("/")); - Path resultFolder = Paths.get(directoryPath + File.separator + filepath); - if (!Files.exists(resultFolder)) { - try { - // create folder - Files.createDirectories(resultFolder); - log.debug("Folder created successfully."); - } catch (IOException e) { - log.error("Failed to create folder " + resultFolder + e); - } - } else { - log.debug("Folder already exists."); - } + if (!prettyPatch.isEmpty()) { + try { + saveFileToDisk(directoryPath, fileName, prettyPatch.toString()); + } catch (IOException e) { + log.error(e.getMessage()); + return false; } - if (prettyPatch.length() > 0) { - try (FileWriter fileWriter = - new FileWriter( - directoryPath + File.separator + fileName, - Charset.forName("UTF8")); - BufferedWriter writer = new BufferedWriter(fileWriter)) { - writer.write(prettyPatch.toString()); + } + return true; + } + + /** + * Saves the given content to a file with the specified filename in the provided directory. + * @param localDirectoryPath The local directory path where the file should be saved. + * @param fileName The name of the file to be saved. + * @param content The content to be written to the file. + * @throws IOException If there is an error while creating the folder or writing the file. + */ + public static void saveFileToDisk(String localDirectoryPath, String fileName, String content) + throws IOException { + if (fileName.contains("/")) { + String filepath = fileName.substring(0, fileName.lastIndexOf("/")); + Path resultFolder = Paths.get(localDirectoryPath + File.separator + filepath); + if (!Files.exists(resultFolder)) { + try { + // create folder + Files.createDirectories(resultFolder); + log.debug("Folder created successfully."); + } catch (IOException e) { + log.error(e.getMessage()); + throw new IOException("Failed to create folder " + resultFolder); } + } else { + log.debug("Folder already exists."); } + } + + try (FileWriter fileWriter = + new FileWriter( + localDirectoryPath + File.separator + fileName, + StandardCharsets.UTF_8); + BufferedWriter writer = new BufferedWriter(fileWriter)) { + writer.write(content); } catch (IOException e) { - log.error("Error while writing file " + fileName + ": " + e.getMessage()); + log.error(e.getMessage()); + throw new IOException("Error while writing file " + fileName); } } diff --git a/src/main/java/com/lpvs/util/LPVSPayloadUtil.java b/src/main/java/com/lpvs/util/LPVSPayloadUtil.java index d726378d..d45fc797 100644 --- a/src/main/java/com/lpvs/util/LPVSPayloadUtil.java +++ b/src/main/java/com/lpvs/util/LPVSPayloadUtil.java @@ -31,6 +31,13 @@ @Slf4j public class LPVSPayloadUtil { + /** + * Private constructor to prevent instantiation of utility class + */ + private LPVSPayloadUtil() { + throw new UnsupportedOperationException("Utility class, cannot be instantiated."); + } + /** * Creates an InputStreamReader object with the specified input stream and UTF-8 encoding. * diff --git a/src/test/java/com/lpvs/service/scan/LPVSDetectServiceTest.java b/src/test/java/com/lpvs/service/scan/LPVSDetectServiceTest.java index d2f27ebc..d0374deb 100644 --- a/src/test/java/com/lpvs/service/scan/LPVSDetectServiceTest.java +++ b/src/test/java/com/lpvs/service/scan/LPVSDetectServiceTest.java @@ -740,6 +740,11 @@ public void testGetPathByPullRequest() { assertNotNull(result); } + @Test + public void testGetPathByPullRequest_N() { + assertNull(LPVSFileUtil.getPathByPullRequest(null)); + } + @Test public void testRunScan__Scanoss() { try { diff --git a/src/test/java/com/lpvs/util/LPVSCommentUtilTest.java b/src/test/java/com/lpvs/util/LPVSCommentUtilTest.java index 4f6207f6..f9bcd059 100644 --- a/src/test/java/com/lpvs/util/LPVSCommentUtilTest.java +++ b/src/test/java/com/lpvs/util/LPVSCommentUtilTest.java @@ -16,7 +16,11 @@ import org.mockito.Mockito; import org.mockito.MockitoAnnotations; -import static org.junit.jupiter.api.Assertions.assertEquals; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + +import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.fail; public class LPVSCommentUtilTest { @@ -84,4 +88,22 @@ public void testGetMatchedLinesAsLinkWithNonGitHubVcsMultipleLines() { + "9-12 (https://gerrit.org/repo/blob/headCommitSHA/exampleFile.txt#L9L12) ", result); } + + @Test + void testConstructorThrowsException_N() { + try { + Constructor constructor = + LPVSCommentUtil.class.getDeclaredConstructor(); + constructor.setAccessible(true); + constructor.newInstance(); + fail("Expected UnsupportedOperationException to be thrown"); + } catch (InvocationTargetException e) { + assertInstanceOf( + UnsupportedOperationException.class, + e.getCause(), + "UnsupportedOperationException expected"); + } catch (Exception e) { + fail("Unexpected exception type thrown: " + e.getCause()); + } + } } diff --git a/src/test/java/com/lpvs/util/LPVSFileUtilTest.java b/src/test/java/com/lpvs/util/LPVSFileUtilTest.java index b4c2f745..42d51bd0 100644 --- a/src/test/java/com/lpvs/util/LPVSFileUtilTest.java +++ b/src/test/java/com/lpvs/util/LPVSFileUtilTest.java @@ -14,14 +14,16 @@ import java.io.File; import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import static com.lpvs.util.LPVSFileUtil.copyFiles; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.*; public class LPVSFileUtilTest { private LPVSQueue webhookConfig = null; @@ -213,11 +215,11 @@ public void testSaveFileWithEmptyPatchedLines() { String directoryPath = "testDirectory"; List patchedLines = new ArrayList<>(); - LPVSFileUtil.saveFile(fileName, directoryPath, patchedLines); + assertFalse(LPVSFileUtil.saveFile(fileName, directoryPath, patchedLines)); Boolean result1 = Files.exists(Paths.get(directoryPath, fileName)); assert (result1.equals(false)); - LPVSFileUtil.saveFile(fileName, directoryPath, null); + assertFalse(LPVSFileUtil.saveFile(fileName, directoryPath, null)); Boolean result2 = Files.exists(Paths.get(directoryPath, fileName)); assert (result2.equals(false)); } @@ -279,4 +281,55 @@ private void deleteDirectory(File directory) { } directory.delete(); } + + @Test + void testConstructorThrowsException_N() { + try { + Constructor constructor = LPVSFileUtil.class.getDeclaredConstructor(); + constructor.setAccessible(true); + constructor.newInstance(); + fail("Expected UnsupportedOperationException to be thrown"); + } catch (InvocationTargetException e) { + assertInstanceOf( + UnsupportedOperationException.class, + e.getCause(), + "UnsupportedOperationException expected"); + } catch (Exception e) { + fail("Unexpected exception type thrown: " + e.getCause()); + } + } + + @Test + public void saveFileToDiskTest() throws IOException { + sourceDir = Files.createTempDirectory("source").toFile(); + String content = "Hello, World!"; + String fileName = "file.txt"; + LPVSFileUtil.saveFileToDisk(sourceDir.getAbsolutePath(), fileName, content); + assertTrue(new File(sourceDir.getAbsolutePath() + File.separator + fileName).exists()); + deleteDirectory(sourceDir); + } + + @Test + public void saveFileToDiskTest_N() throws IOException { + sourceDir = Files.createTempDirectory("source").toFile(); + String content = "Hello, World!"; + String fileName = + "zxcvbnmasdfghjklqwertyuiopoiuytrewqasdfghjklmnbvcxzaqwsxcderfvbgtyhnmjuikzxcvbnmasdfsdsdsdhjhjghjklqwertyuiopoiuytrewqasdfghjklmnbvcxzaqwsxcderfvbgtyhnmjuikzxcvbnmasdfghjklqwertyuiopoiuytrewqasdfghjklmnbvcxzaqwsxcderfvbgtyhnmjuikzxcvbnmasdfghjklqwertyuiopoiuytrewqasdfg/file.txt"; + assertThrows( + IOException.class, + () -> LPVSFileUtil.saveFileToDisk(sourceDir.getAbsolutePath(), fileName, content)); + deleteDirectory(sourceDir); + } + + @Test + public void saveFileTest_N() throws IOException { + sourceDir = Files.createTempDirectory("source").toFile(); + String content = "+Hello, World!"; + String fileName = + "zxcvbnmasdfghjklqwertyuiopoiuytrewqasdfghjklmnbvcxzaqwsxcderfvbgtyhnmjuikzxcvbnmasdfsdsdsdhjhjghjklqwertyuiopoiuytrewqasdfghjklmnbvcxzaqwsxcderfvbgtyhnmjuikzxcvbnmasdfghjklqwertyuiopoiuytrewqasdfghjklmnbvcxzaqwsxcderfvbgtyhnmjuikzxcvbnmasdfghjklqwertyuiopoiuytrewqasdfg/file.txt"; + assertFalse( + LPVSFileUtil.saveFile( + fileName, sourceDir.getAbsolutePath(), Collections.singletonList(content))); + deleteDirectory(sourceDir); + } } diff --git a/src/test/java/com/lpvs/util/LPVSPayloadUtilTest.java b/src/test/java/com/lpvs/util/LPVSPayloadUtilTest.java index 782b62bc..e2c1b836 100644 --- a/src/test/java/com/lpvs/util/LPVSPayloadUtilTest.java +++ b/src/test/java/com/lpvs/util/LPVSPayloadUtilTest.java @@ -16,6 +16,8 @@ import org.springframework.http.HttpHeaders; import java.io.*; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; import java.net.URISyntaxException; import java.nio.file.Files; import java.nio.file.Path; @@ -436,4 +438,22 @@ public void testConvertInputStreamToString_ThrowsException_N() { () -> LPVSPayloadUtil.convertInputStreamToString(inputStream)); } } + + @Test + void testConstructorThrowsException_N() { + try { + Constructor constructor = + LPVSPayloadUtil.class.getDeclaredConstructor(); + constructor.setAccessible(true); + constructor.newInstance(); + fail("Expected UnsupportedOperationException to be thrown"); + } catch (InvocationTargetException e) { + assertInstanceOf( + UnsupportedOperationException.class, + e.getCause(), + "UnsupportedOperationException expected"); + } catch (Exception e) { + fail("Unexpected exception type thrown: " + e.getCause()); + } + } }