From b14a9e5bfa9fe09942dfd1a7898e15deaadd1983 Mon Sep 17 00:00:00 2001 From: navneetprabhakar Date: Wed, 20 May 2026 07:51:58 +0530 Subject: [PATCH 1/2] chore(executespec): augment .gitignore with missing vendored-path ignores --- .gitignore | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.gitignore b/.gitignore index ceaf2d3..38f9579 100644 --- a/.gitignore +++ b/.gitignore @@ -40,3 +40,18 @@ out/ ### VS Code ### .vscode/ + +# >>> ExecuteSpec — added missing vendored-path ignores at clone time (see VendoredPathGuard) +node_modules/ +venv/ +.venv/ +__pycache__/ +.next/ +coverage/ +bower_components/ +vendor/ +.pytest_cache/ +.mypy_cache/ +.tox/ +.nyc_output/ +# <<< ExecuteSpec From 23882b0e4c01c1f1ddf06144cbcc199bc8df233f Mon Sep 17 00:00:00 2001 From: ExecuteSpec Agent Date: Wed, 20 May 2026 08:06:10 +0530 Subject: [PATCH 2/2] Add MIT LICENSE and CONTRIBUTING.md with project guidelines (executor) Repo: navneetprabhakar/executor Run: 9eb919e8 Files changed (4): CONTRIBUTING.md LICENSE gradle-8.5-bin.zip src/test/java/com/navneet/executor/utils/FileUtilsTest.java Co-Authored-By: ExecuteSpec Agent --- CONTRIBUTING.md | 109 ++++ LICENSE | 21 + gradle-8.5-bin.zip | 615 ++++++++++++++++++ .../navneet/executor/utils/FileUtilsTest.java | 212 ++++++ 4 files changed, 957 insertions(+) create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE create mode 100644 gradle-8.5-bin.zip create mode 100644 src/test/java/com/navneet/executor/utils/FileUtilsTest.java diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..eee6aec --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,109 @@ +# Contributing to Executor + +Thank you for your interest in contributing to the Executor project! This document provides guidelines and instructions for contributing. + +## Getting Started + +### Prerequisites +- Java 17 or higher +- Gradle (or use the included `./gradlew` wrapper) +- Git + +### Building the Project + +To build the project, use the Gradle wrapper: + +```bash +./gradlew build +``` + +This command will: +- Compile the source code +- Run all unit tests +- Generate the build artifacts + +### Running Tests + +To run only the tests: + +```bash +./gradlew test +``` + +To run a specific test class: + +```bash +./gradlew test --tests com.navneet.executor.utils.FileUtilsTest +``` + +## Branch Naming Convention + +Please follow these naming conventions for branches: + +- **Feature branches**: `feature/description-of-feature` + - Example: `feature/add-async-processing` +- **Bug fix branches**: `bugfix/description-of-bug` + - Example: `bugfix/fix-null-pointer-exception` +- **Documentation branches**: `docs/description-of-docs` + - Example: `docs/update-readme` +- **Refactoring branches**: `refactor/description-of-refactor` + - Example: `refactor/simplify-upload-logic` + +## Pull Request Process + +1. **Create a feature branch** from `main` using the naming convention above +2. **Make your changes** and ensure they follow the project's code style +3. **Write or update tests** for any new functionality or bug fixes +4. **Run the full build** to ensure everything compiles and tests pass: + ```bash + ./gradlew build + ``` +5. **Commit your changes** with clear, descriptive commit messages +6. **Push your branch** to the repository +7. **Open a Pull Request** with: + - A clear title describing the change + - A detailed description of what was changed and why + - Reference to any related issues (e.g., "Fixes #123") + - Evidence that tests pass (build output or screenshots) + +## Code Style Guidelines + +- Follow standard Java conventions +- Use meaningful variable and method names +- Add JavaDoc comments for public methods and classes +- Keep methods focused and reasonably sized +- Use Lombok annotations where appropriate (e.g., `@Log4j2`, `@Autowired`) + +## Testing Requirements + +- **All new public methods** must have unit tests +- **All new endpoints** must have integration tests +- **Bug fixes** should include a test that reproduces the bug and verifies the fix +- Aim for at least 80% code coverage for new code + +### Test File Location + +Test files should be placed in `src/test/java/` with the same package structure as the code being tested. + +Example: +- Source: `src/main/java/com/navneet/executor/utils/FileUtils.java` +- Test: `src/test/java/com/navneet/executor/utils/FileUtilsTest.java` + +## Reporting Issues + +When reporting bugs or suggesting features: + +1. Check if the issue already exists +2. Provide a clear description of the problem or suggestion +3. Include steps to reproduce (for bugs) +4. Provide relevant environment information (Java version, OS, etc.) + +## License + +By contributing to this project, you agree that your contributions will be licensed under the MIT License. + +## Questions? + +If you have any questions about contributing, feel free to open an issue or contact the project maintainers. + +Thank you for contributing! diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..99e69d5 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 navneetprabhakar + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/gradle-8.5-bin.zip b/gradle-8.5-bin.zip new file mode 100644 index 0000000..b01ed27 --- /dev/null +++ b/gradle-8.5-bin.zip @@ -0,0 +1,615 @@ + + + + + + + Gradle | Thank you for downloading Gradle! + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+

Thank you for downloading Gradle!

+
+
+ +
+
+ + +

Your download should start shortly. If it doesn't, use the + direct link. +

+
+
+ +
+ +
+ +
+
+ +
+ +
+ + + +
+ + + + + + + + + + + + diff --git a/src/test/java/com/navneet/executor/utils/FileUtilsTest.java b/src/test/java/com/navneet/executor/utils/FileUtilsTest.java new file mode 100644 index 0000000..57173dc --- /dev/null +++ b/src/test/java/com/navneet/executor/utils/FileUtilsTest.java @@ -0,0 +1,212 @@ +package com.navneet.executor.utils; + +import com.navneet.executor.models.CustomerInfo; +import com.univocity.parsers.common.IterableResult; +import com.univocity.parsers.common.ParsingContext; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; +import org.springframework.boot.test.context.SpringBootTest; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.Path; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for FileUtils class + * Tests CSV reading and line counting functionality + */ +@SpringBootTest +class FileUtilsTest { + + private FileUtils fileUtils; + + @TempDir + Path tempDir; + + @BeforeEach + void setUp() { + fileUtils = new FileUtils(); + } + + /** + * Happy path test: Read valid CSV file with customer data + */ + @Test + void testReadDataFromCsvWithValidFile() throws IOException { + // Arrange + File csvFile = createValidCsvFile(); + + // Act + IterableResult result = fileUtils.readDataFromCsv( + csvFile.getAbsolutePath(), + CustomerInfo.class + ); + + // Assert + assertNotNull(result, "Result should not be null"); + int count = 0; + for (CustomerInfo customer : result) { + assertNotNull(customer, "Customer object should not be null"); + assertNotNull(customer.getId(), "Customer ID should not be null"); + assertNotNull(customer.getName(), "Customer name should not be null"); + count++; + } + assertEquals(3, count, "Should have read 3 customer records"); + } + + /** + * Happy path test: Count lines in a valid file + */ + @Test + void testNumberOfLinesWithValidFile() throws IOException { + // Arrange + File csvFile = createValidCsvFile(); + + // Act + int lineCount = fileUtils.numberOfLines(csvFile.getAbsolutePath()); + + // Assert + assertEquals(4, lineCount, "Should count 4 lines (1 header + 3 data rows)"); + } + + /** + * Happy path test: Count lines in a single-line file + */ + @Test + void testNumberOfLinesWithSingleLineFile() throws IOException { + // Arrange + File singleLineFile = tempDir.resolve("single_line.txt").toFile(); + try (FileWriter writer = new FileWriter(singleLineFile)) { + writer.write("This is a single line"); + } + + // Act + int lineCount = fileUtils.numberOfLines(singleLineFile.getAbsolutePath()); + + // Assert + assertEquals(1, lineCount, "Should count 1 line"); + } + + /** + * Error case test: Read from non-existent file + */ + @Test + void testReadDataFromCsvWithNonExistentFile() { + // Arrange + String nonExistentPath = "/non/existent/path/file.csv"; + + // Act + IterableResult result = fileUtils.readDataFromCsv( + nonExistentPath, + CustomerInfo.class + ); + + // Assert + assertNull(result, "Result should be null for non-existent file"); + } + + /** + * Error case test: Count lines in non-existent file + */ + @Test + void testNumberOfLinesWithNonExistentFile() { + // Arrange + String nonExistentPath = "/non/existent/path/file.txt"; + + // Act & Assert + assertThrows( + java.io.FileNotFoundException.class, + () -> fileUtils.numberOfLines(nonExistentPath), + "Should throw FileNotFoundException for non-existent file" + ); + } + + /** + * Edge case test: Empty CSV file + */ + @Test + void testNumberOfLinesWithEmptyFile() throws IOException { + // Arrange + File emptyFile = tempDir.resolve("empty.csv").toFile(); + emptyFile.createNewFile(); + + // Act + int lineCount = fileUtils.numberOfLines(emptyFile.getAbsolutePath()); + + // Assert + assertEquals(0, lineCount, "Should count 0 lines for empty file"); + } + + /** + * Edge case test: File with multiple consecutive newlines + */ + @Test + void testNumberOfLinesWithMultipleNewlines() throws IOException { + // Arrange + File multiNewlineFile = tempDir.resolve("multi_newline.txt").toFile(); + try (FileWriter writer = new FileWriter(multiNewlineFile)) { + writer.write("Line 1\n\n\nLine 2\n"); + } + + // Act + int lineCount = fileUtils.numberOfLines(multiNewlineFile.getAbsolutePath()); + + // Assert + assertEquals(4, lineCount, "Should count 4 newline characters"); + } + + /** + * Happy path test: Read CSV with special characters + */ + @Test + void testReadDataFromCsvWithSpecialCharacters() throws IOException { + // Arrange + File csvFile = createCsvFileWithSpecialCharacters(); + + // Act + IterableResult result = fileUtils.readDataFromCsv( + csvFile.getAbsolutePath(), + CustomerInfo.class + ); + + // Assert + assertNotNull(result, "Result should not be null"); + int count = 0; + for (CustomerInfo customer : result) { + assertNotNull(customer, "Customer object should not be null"); + count++; + } + assertTrue(count > 0, "Should have read at least one record"); + } + + /** + * Helper method to create a valid CSV file with test data + */ + private File createValidCsvFile() throws IOException { + File csvFile = tempDir.resolve("customers.csv").toFile(); + try (FileWriter writer = new FileWriter(csvFile)) { + writer.write("id,name,mobile,email,address,city,state,pincode\n"); + writer.write("1,John Doe,9876543210,john@example.com,123 Main St,New York,NY,10001\n"); + writer.write("2,Jane Smith,9876543211,jane@example.com,456 Oak Ave,Los Angeles,CA,90001\n"); + writer.write("3,Bob Johnson,9876543212,bob@example.com,789 Pine Rd,Chicago,IL,60601\n"); + } + return csvFile; + } + + /** + * Helper method to create a CSV file with special characters + */ + private File createCsvFileWithSpecialCharacters() throws IOException { + File csvFile = tempDir.resolve("customers_special.csv").toFile(); + try (FileWriter writer = new FileWriter(csvFile)) { + writer.write("id,name,mobile,email,address,city,state,pincode\n"); + writer.write("1,José García,9876543210,jose@example.com,Calle Principal 123,Madrid,MA,28001\n"); + writer.write("2,François Müller,9876543211,francois@example.com,Rue de la Paix 456,Paris,PA,75001\n"); + } + return csvFile; + } +}