diff --git a/pom.xml b/pom.xml index 924a736d526d..a152eda16972 100644 --- a/pom.xml +++ b/pom.xml @@ -1,159 +1,236 @@ - - - 4.0.0 - com.thealgorithms - Java - 1.0-SNAPSHOT - jar - - - UTF-8 - 21 - 21 - 3.26.0 - - - - - - org.junit - junit-bom - 5.10.3 - pom - import - - - - + + + 4.0.0 + com.thealgorithms + Java + 1.0-SNAPSHOT + jar + + UTF-8 + 21 + 21 + 3.26.0 + + - - org.junit.jupiter - junit-jupiter - 5.10.3 - test - - - org.assertj - assertj-core - ${assertj.version} - test - - - - org.junit.jupiter - junit-jupiter-api - 5.10.3 - test - - - org.apache.commons - commons-lang3 - 3.14.0 - - - org.apache.commons - commons-collections4 - 4.5.0-M2 - + + org.junit + junit-bom + 5.10.3 + pom + import + + + io.spring.javaformat + spring-javaformat-formatter + 0.0.40 + + + + org.assertj + assertj-guava + 3.26.0 + compile + + + + org.assertj + assertj-db + 2.0.2 + compile + + + + org.assertj + assertj-joda-time + 2.2.0 + compile + + - - - - - maven-surefire-plugin - 3.3.0 - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.13.0 - - 21 - 21 - - -Xlint:all - -Xlint:-auxiliaryclass - -Xlint:-rawtypes - -Xlint:-unchecked - -Xlint:-lossy-conversions - -Werror - - - - - org.jacoco - jacoco-maven-plugin - 0.8.12 - - - - prepare-agent - - - - generate-code-coverage-report - test - - report - - - - - - org.apache.maven.plugins - maven-checkstyle-plugin - 3.4.0 - - checkstyle.xml - true - true - warning - - - - com.puppycrawl.tools - checkstyle - 10.17.0 - - - + + + + org.junit.jupiter + junit-jupiter + 5.10.3 + test + + + org.assertj + assertj-core + ${assertj.version} + test + + + org.junit.jupiter + junit-jupiter-api + 5.10.3 + test + + + org.apache.commons + commons-lang3 + 3.14.0 + + + org.apache.commons + commons-collections4 + 4.5.0-M2 + + + io.spring.javaformat + spring-javaformat-formatter + 0.0.40 + + + + org.assertj + assertj-guava + 3.26.0 + compile + + + + org.assertj + assertj-db + 2.0.2 + compile + + + + org.assertj + assertj-joda-time + 2.2.0 + compile + + + + + + + maven-surefire-plugin + 3.3.0 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.13.0 + + 21 + 21 + + -Xlint:all + -Xlint:-auxiliaryclass + -Xlint:-rawtypes + -Xlint:-unchecked + -Xlint:-lossy-conversions + -Werror + + + + + org.jacoco + jacoco-maven-plugin + 0.8.12 + + + + prepare-agent + + + + generate-code-coverage-report + test + + report + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 3.4.0 + + checkstyle.xml + true + true + warning + + + + com.puppycrawl.tools + checkstyle + 10.17.0 + + + + + com.github.spotbugs + spotbugs-maven-plugin + 4.8.6.1 + + spotbugs-exclude.xml + true + - com.github.spotbugs - spotbugs-maven-plugin - 4.8.6.1 - - spotbugs-exclude.xml - true - - - com.mebigfatguy.fb-contrib - fb-contrib - 7.6.4 - - - com.h3xstream.findsecbugs - findsecbugs-plugin - 1.13.0 - - - + com.mebigfatguy.fb-contrib + fb-contrib + 7.6.4 - org.apache.maven.plugins - maven-pmd-plugin - 3.23.0 - - true - true - false - pmd-exclude.properties - + com.h3xstream.findsecbugs + findsecbugs-plugin + 1.13.0 - - - + + + + + org.apache.maven.plugins + maven-pmd-plugin + 3.23.0 + + true + true + false + pmd-exclude.properties + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.2.5 + + + + org.apache.maven.plugins + maven-surefire-report-plugin + 3.2.5 + + testReport + + + + + org.apache.maven.plugins + maven-site-plugin + 2.1 + + testReport + + + + + io.spring.javaformat + spring-javaformat-maven-plugin + 0.0.40 + + + + + \ No newline at end of file diff --git a/src/test/java/com/thealgorithms/greedyalgorithms/ActivitySelectionActivitySelectionTest.java b/src/test/java/com/thealgorithms/greedyalgorithms/ActivitySelectionActivitySelectionTest.java new file mode 100644 index 000000000000..857b8fd86aab --- /dev/null +++ b/src/test/java/com/thealgorithms/greedyalgorithms/ActivitySelectionActivitySelectionTest.java @@ -0,0 +1,186 @@ +// ********RoostGPT******** +/* +Test generated by RoostGPT for test java-algos using AI Type Claude AI and AI Model claude-3-5-sonnet-20240620 +ROOST_METHOD_HASH=activitySelection_77631a6e2d +ROOST_METHOD_SIG_HASH=activitySelection_bf79d28a9f +Based on the provided method and imports, here are several test scenarios for the `activitySelection` method: +``` +Scenario 1: Basic Activity Selection +Details: + TestName: basicActivitySelection + Description: Test the basic functionality of activity selection with a simple set of non-overlapping activities. +Execution: + Arrange: Create arrays for start times and end times with non-overlapping activities. + Act: Call activitySelection with the arranged start and end times. + Assert: Verify that all activities are selected in the correct order. +Validation: + This test ensures that the method correctly selects all activities when there are no conflicts. It validates the core functionality of the activity selection algorithm. +Scenario 2: Overlapping Activities +Details: + TestName: overlappingActivities + Description: Test the method's ability to select the maximum number of non-overlapping activities from a set of overlapping activities. +Execution: + Arrange: Create arrays for start times and end times with some overlapping activities. + Act: Call activitySelection with the arranged start and end times. + Assert: Verify that the correct subset of non-overlapping activities is selected. +Validation: + This test checks if the method correctly handles overlapping activities and selects the optimal set of non-overlapping activities. It validates the core logic of the greedy algorithm. +Scenario 3: Empty Input Arrays +Details: + TestName: emptyInputArrays + Description: Test the method's behavior when given empty input arrays. +Execution: + Arrange: Create empty arrays for start times and end times. + Act: Call activitySelection with the empty arrays. + Assert: Verify that an empty ArrayList is returned. +Validation: + This test ensures that the method handles edge cases correctly, specifically when no activities are provided. It's important for robustness and error handling. +Scenario 4: Single Activity +Details: + TestName: singleActivity + Description: Test the method's behavior with only one activity. +Execution: + Arrange: Create arrays for start times and end times with a single activity. + Act: Call activitySelection with the single-activity arrays. + Assert: Verify that the returned ArrayList contains only the index of the single activity. +Validation: + This test checks if the method correctly handles the simplest non-empty case. It's important for ensuring basic functionality and edge case handling. +Scenario 5: Activities with Same End Time +Details: + TestName: activitiesWithSameEndTime + Description: Test the method's behavior when multiple activities have the same end time. +Execution: + Arrange: Create arrays for start times and end times where multiple activities end at the same time. + Act: Call activitySelection with these arrays. + Assert: Verify that the method selects the correct activities based on their start times. +Validation: + This test ensures that the method can handle ties in end times correctly, which is important for the stability and consistency of the algorithm. +Scenario 6: Activities with Same Start Time +Details: + TestName: activitiesWithSameStartTime + Description: Test the method's behavior when multiple activities have the same start time. +Execution: + Arrange: Create arrays for start times and end times where multiple activities start at the same time. + Act: Call activitySelection with these arrays. + Assert: Verify that the method selects the activities with the earliest end times. +Validation: + This test checks if the method correctly prioritizes activities with earlier end times when start times are the same, which is crucial for the greedy algorithm's correctness. +Scenario 7: Large Number of Activities +Details: + TestName: largeNumberOfActivities + Description: Test the method's performance and correctness with a large number of activities. +Execution: + Arrange: Create large arrays for start times and end times with many activities. + Act: Call activitySelection with these large arrays. + Assert: Verify that the method returns a correct selection of activities within a reasonable time. +Validation: + This test ensures that the method can handle large inputs efficiently, which is important for scalability. It also checks if the algorithm maintains correctness with complex inputs. +``` +These test scenarios cover various aspects of the `activitySelection` method, including basic functionality, edge cases, and potential challenging scenarios. They aim to validate the correctness, robustness, and efficiency of the implementation. +*/ +// ********RoostGPT******** +package com.thealgorithms.greedyalgorithms; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import static org.assertj.core.api.Assertions.assertThat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.stream.Stream; +import java.util.Comparator; +import org.junit.jupiter.api.*; + +@Tag("com.thealgorithms.sorts") +@Tag("com.thealgorithms.sorts.sort") +@Tag("com.thealgorithms.datastructures.bags") +@Tag("com.thealgorithms.datastructures.bags.add") +@Tag("com.thealgorithms.datastructures.bags.add") +@Tag("com.thealgorithms.greedyalgorithms") +@Tag("com.thealgorithms.greedyalgorithms.activitySelection") +class ActivitySelectionActivitySelectionTest { + + @Test + void basicActivitySelection() { + int[] startTimes = { 1, 3, 0, 5, 8, 5 }; + int[] endTimes = { 2, 4, 6, 7, 9, 9 }; + ArrayList expected = new ArrayList<>(Arrays.asList(0, 1, 3, 4)); + assertThat(ActivitySelection.activitySelection(startTimes, endTimes)).isEqualTo(expected); + } + + @Test + void overlappingActivities() { + int[] startTimes = { 1, 3, 0, 5, 3, 5, 6, 8, 8, 2, 12 }; + int[] endTimes = { 4, 5, 6, 7, 9, 9, 10, 11, 12, 14, 16 }; + ArrayList expected = new ArrayList<>(Arrays.asList(0, 3, 7, 10)); + assertThat(ActivitySelection.activitySelection(startTimes, endTimes)).isEqualTo(expected); + } + + @Test + void emptyInputArrays() { + int[] startTimes = {}; + int[] endTimes = {}; + ArrayList expected = new ArrayList<>(); + assertThat(ActivitySelection.activitySelection(startTimes, endTimes)).isEqualTo(expected); + } + + @Test + void singleActivity() { + int[] startTimes = { 1 }; + int[] endTimes = { 2 }; + ArrayList expected = new ArrayList<>(Arrays.asList(0)); + assertThat(ActivitySelection.activitySelection(startTimes, endTimes)).isEqualTo(expected); + } + + @Test + void activitiesWithSameEndTime() { + int[] startTimes = { 1, 3, 2, 5 }; + int[] endTimes = { 4, 4, 4, 6 }; + ArrayList expected = new ArrayList<>(Arrays.asList(0, 3)); + assertThat(ActivitySelection.activitySelection(startTimes, endTimes)).isEqualTo(expected); + } + + @Test + void activitiesWithSameStartTime() { + int[] startTimes = { 1, 1, 1, 4 }; + int[] endTimes = { 2, 3, 4, 5 }; + ArrayList expected = new ArrayList<>(Arrays.asList(0, 3)); + assertThat(ActivitySelection.activitySelection(startTimes, endTimes)).isEqualTo(expected); + } + + @Test + void largeNumberOfActivities() { + int[] startTimes = new int[1000]; + int[] endTimes = new int[1000]; + for (int i = 0; i < 1000; i++) { + startTimes[i] = i * 2; + endTimes[i] = i * 2 + 1; + } + ArrayList expected = new ArrayList<>(); + for (int i = 0; i < 1000; i++) { + expected.add(i); + } + assertThat(ActivitySelection.activitySelection(startTimes, endTimes)).isEqualTo(expected); + } + + @ParameterizedTest + @MethodSource("provideActivitySelectionTestCases") + void parameterizedActivitySelectionTest(int[] startTimes, int[] endTimes, ArrayList expected) { + assertThat(ActivitySelection.activitySelection(startTimes, endTimes)).isEqualTo(expected); + } + + private static Stream provideActivitySelectionTestCases() { + return Stream.of( + Arguments.of(new int[] { 1, 3, 0, 5, 8, 5 }, new int[] { 2, 4, 6, 7, 9, 9 }, + new ArrayList<>(Arrays.asList(0, 1, 3, 4))), + Arguments.of(new int[] { 1, 3, 0, 5, 3, 5, 6, 8, 8, 2, 12 }, + new int[] { 4, 5, 6, 7, 9, 9, 10, 11, 12, 14, 16 }, + new ArrayList<>(Arrays.asList(0, 3, 7, 10))), + Arguments.of(new int[] {}, new int[] {}, new ArrayList<>()), + Arguments.of(new int[] { 1 }, new int[] { 2 }, new ArrayList<>(Arrays.asList(0))), + Arguments.of(new int[] { 1, 3, 2, 5 }, new int[] { 4, 4, 4, 6 }, new ArrayList<>(Arrays.asList(0, 3))), + Arguments.of(new int[] { 1, 1, 1, 4 }, new int[] { 2, 3, 4, 5 }, new ArrayList<>(Arrays.asList(0, 3)))); + } + +} \ No newline at end of file diff --git a/src/test/java/com/thealgorithms/greedyalgorithms/CoinChangeCoinChangeProblemTest.java b/src/test/java/com/thealgorithms/greedyalgorithms/CoinChangeCoinChangeProblemTest.java new file mode 100644 index 000000000000..37b16a5150d7 --- /dev/null +++ b/src/test/java/com/thealgorithms/greedyalgorithms/CoinChangeCoinChangeProblemTest.java @@ -0,0 +1,161 @@ +// ********RoostGPT******** +/* +Test generated by RoostGPT for test java-algos using AI Type Claude AI and AI Model claude-3-5-sonnet-20240620 +ROOST_METHOD_HASH=coinChangeProblem_db77356e05 +ROOST_METHOD_SIG_HASH=coinChangeProblem_9cb8b5505c +Based on the provided method and instructions, here are several JUnit test scenarios for the `coinChangeProblem` method: +``` +Scenario 1: Test with a small amount +Details: + TestName: smallAmountChange + Description: Verify that the method correctly handles a small amount that can be made with a combination of available coins. +Execution: + Arrange: Set up the test amount (e.g., 67) + Act: Call coinChangeProblem(67) + Assert: Check if the returned ArrayList contains the expected coins [50, 10, 5, 2] +Validation: + This test ensures that the method correctly breaks down a small amount into the largest possible denominations. It verifies that the greedy algorithm works for a simple case. +Scenario 2: Test with a large amount +Details: + TestName: largeAmountChange + Description: Verify that the method correctly handles a large amount that requires using the highest denomination multiple times. +Execution: + Arrange: Set up the test amount (e.g., 4578) + Act: Call coinChangeProblem(4578) + Assert: Check if the returned ArrayList contains the expected coins [2000, 2000, 500, 50, 20, 5, 2, 1] +Validation: + This test checks if the method can handle larger amounts and correctly use the highest denominations multiple times when needed. +Scenario 3: Test with an amount that matches the highest denomination +Details: + TestName: highestDenominationExactMatch + Description: Verify that the method correctly handles an amount that exactly matches the highest available denomination. +Execution: + Arrange: Set up the test amount (2000) + Act: Call coinChangeProblem(2000) + Assert: Check if the returned ArrayList contains only one coin [2000] +Validation: + This test ensures that the method correctly handles the case where the amount can be satisfied with a single coin of the highest denomination. +Scenario 4: Test with zero amount +Details: + TestName: zeroAmountChange + Description: Verify that the method correctly handles a zero amount input. +Execution: + Arrange: Set up the test amount (0) + Act: Call coinChangeProblem(0) + Assert: Check if the returned ArrayList is empty +Validation: + This test verifies that the method returns an empty list when the input amount is zero, as no coins are needed. +Scenario 5: Test with an amount smaller than the smallest denomination +Details: + TestName: amountSmallerThanSmallestCoin + Description: Verify that the method correctly handles an amount smaller than the smallest available coin. +Execution: + Arrange: Set up the test amount (0.5) + Act: Call coinChangeProblem(0) + Assert: Check if the returned ArrayList is empty +Validation: + This test ensures that the method returns an empty list when the input amount is smaller than the smallest available coin, as it cannot be broken down further. +Scenario 6: Test with a large prime number amount +Details: + TestName: largePrimeNumberAmount + Description: Verify that the method correctly handles a large prime number amount that requires using multiple denominations. +Execution: + Arrange: Set up the test amount (e.g., 2017) + Act: Call coinChangeProblem(2017) + Assert: Check if the returned ArrayList contains the expected coins [2000, 10, 5, 2] +Validation: + This test checks if the method can correctly break down a large prime number amount into the available denominations, ensuring the greedy algorithm works for more complex cases. +Scenario 7: Test with maximum possible amount +Details: + TestName: maxPossibleAmount + Description: Verify that the method correctly handles the maximum possible amount that can be represented by Integer.MAX_VALUE. +Execution: + Arrange: Set up the test amount (Integer.MAX_VALUE) + Act: Call coinChangeProblem(Integer.MAX_VALUE) + Assert: Check if the returned ArrayList contains the correct number and combination of coins +Validation: + This test ensures that the method can handle the maximum possible integer input without overflowing or producing incorrect results. +``` +These test scenarios cover various aspects of the `coinChangeProblem` method, including edge cases, normal operations, and potential error conditions. They aim to validate the correct functioning of the method across different input ranges and scenarios. +*/ +// ********RoostGPT******** +package com.thealgorithms.greedyalgorithms; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.stream.Stream; +import static org.assertj.core.api.Assertions.assertThat; +import java.util.Comparator; +import org.junit.jupiter.api.*; + +@Tag("com.thealgorithms.sorts") +@Tag("com.thealgorithms.sorts.sort") +@Tag("com.thealgorithms.datastructures.bags") +@Tag("com.thealgorithms.datastructures.bags.add") +@Tag("com.thealgorithms.greedyalgorithms") +@Tag("com.thealgorithms.greedyalgorithms.coinChangeProblem") +class CoinChangeCoinChangeProblemTest { + + @ParameterizedTest + @MethodSource("provideTestCases") + void testCoinChangeProblem(int amount, Integer[] expectedCoins) { + ArrayList result = CoinChange.coinChangeProblem(amount); + assertThat(result).containsExactly(expectedCoins); + } + + private static Stream provideTestCases() { + return Stream.of(Arguments.of(67, new Integer[] { 50, 10, 5, 2 }), + Arguments.of(4578, new Integer[] { 2000, 2000, 500, 50, 20, 5, 2, 1 }), + Arguments.of(2000, new Integer[] { 2000 }), Arguments.of(0, new Integer[] {}), + Arguments.of(2017, new Integer[] { 2000, 10, 5, 2 })); + } + + @Test + void testSmallAmountChange() { + ArrayList result = CoinChange.coinChangeProblem(67); + assertThat(result).containsExactly(50, 10, 5, 2); + } + + @Test + void testLargeAmountChange() { + ArrayList result = CoinChange.coinChangeProblem(4578); + assertThat(result).containsExactly(2000, 2000, 500, 50, 20, 5, 2, 1); + } + + @Test + void testHighestDenominationExactMatch() { + ArrayList result = CoinChange.coinChangeProblem(2000); + assertThat(result).containsExactly(2000); + } + + @Test + void testZeroAmountChange() { + ArrayList result = CoinChange.coinChangeProblem(0); + assertThat(result).isEmpty(); + } + + @Test + void testAmountSmallerThanSmallestCoin() { + ArrayList result = CoinChange.coinChangeProblem(0); + assertThat(result).isEmpty(); + } + + @Test + void testLargePrimeNumberAmount() { + ArrayList result = CoinChange.coinChangeProblem(2017); + assertThat(result).containsExactly(2000, 10, 5, 2); + } + + @Test + void testMaxPossibleAmount() { + ArrayList result = CoinChange.coinChangeProblem(Integer.MAX_VALUE); + assertThat(result).isNotEmpty(); + int sum = result.stream().mapToInt(Integer::intValue).sum(); + assertThat(sum).isEqualTo(Integer.MAX_VALUE); + } + +} \ No newline at end of file diff --git a/src/test/java/com/thealgorithms/greedyalgorithms/FractionalKnapsackFractionalKnapsackTest.java b/src/test/java/com/thealgorithms/greedyalgorithms/FractionalKnapsackFractionalKnapsackTest.java new file mode 100644 index 000000000000..cdbc496338ea --- /dev/null +++ b/src/test/java/com/thealgorithms/greedyalgorithms/FractionalKnapsackFractionalKnapsackTest.java @@ -0,0 +1,182 @@ +// ********RoostGPT******** +/* +Test generated by RoostGPT for test java-algos using AI Type Claude AI and AI Model claude-3-5-sonnet-20240620 +ROOST_METHOD_HASH=fractionalKnapsack_b327dd7d5e +ROOST_METHOD_SIG_HASH=fractionalKnapsack_1caf503527 +Based on the provided method and instructions, here are several test scenarios for the fractionalKnapsack method: +Scenario 1: Basic Functionality Test +Details: + TestName: basicFunctionalityTest + Description: Verify that the method correctly calculates the maximum value for a simple knapsack problem with distinct items. +Execution: + Arrange: Create weight array, value array, and set capacity. + Act: Call fractionalKnapsack with the arranged data. + Assert: Compare the returned value with the expected maximum value. +Validation: + This test ensures that the basic algorithm works correctly for a straightforward case. It validates that the method can properly sort items by value-to-weight ratio and select the most valuable items within the given capacity. +Scenario 2: Full Capacity Utilization +Details: + TestName: fullCapacityUtilization + Description: Test the method's ability to utilize the full capacity of the knapsack when possible. +Execution: + Arrange: Set up weight and value arrays where the sum of weights exactly matches the capacity. + Act: Invoke fractionalKnapsack with the arranged data. + Assert: Verify that the returned value is the sum of all item values. +Validation: + This test confirms that the method can efficiently use the entire knapsack capacity when the items fit perfectly, ensuring no space is wasted. +Scenario 3: Fractional Item Inclusion +Details: + TestName: fractionalItemInclusion + Description: Verify that the method correctly includes a fraction of an item when the knapsack is almost full. +Execution: + Arrange: Create arrays where the last item needs to be fractionally included. + Act: Call fractionalKnapsack with the arranged data. + Assert: Check if the returned value includes the correct fraction of the last item. +Validation: + This test ensures that the method can handle fractional items correctly, which is a key aspect of the fractional knapsack problem. +Scenario 4: Empty Knapsack +Details: + TestName: emptyKnapsack + Description: Test the method's behavior when the knapsack capacity is zero. +Execution: + Arrange: Set up non-empty weight and value arrays but set capacity to 0. + Act: Invoke fractionalKnapsack with zero capacity. + Assert: Verify that the returned value is 0. +Validation: + This test checks the edge case of a zero-capacity knapsack, ensuring the method handles it gracefully without errors. +Scenario 5: Single Item Knapsack +Details: + TestName: singleItemKnapsack + Description: Verify the method's functionality when there's only one item to consider. +Execution: + Arrange: Create weight and value arrays with a single element. + Act: Call fractionalKnapsack with the single-item data. + Assert: Check if the returned value is correct for the single item case. +Validation: + This test ensures that the method works correctly in the simplest case scenario, handling array inputs with just one element. +Scenario 6: Large Number of Items +Details: + TestName: largeNumberOfItems + Description: Test the method's performance and correctness with a large number of items. +Execution: + Arrange: Create large weight and value arrays (e.g., 1000+ items). + Act: Invoke fractionalKnapsack with the large dataset. + Assert: Verify that the returned value is correct and the method executes within an acceptable time frame. +Validation: + This test checks the method's efficiency and correctness when dealing with a large dataset, ensuring it can handle real-world scenarios with many items. +Scenario 7: All Items with Same Value-to-Weight Ratio +Details: + TestName: sameValueWeightRatio + Description: Verify the method's behavior when all items have the same value-to-weight ratio. +Execution: + Arrange: Set up weight and value arrays where all items have identical value-to-weight ratios. + Act: Call fractionalKnapsack with the arranged data. + Assert: Check if the returned value is correct regardless of which items are chosen. +Validation: + This test ensures that the method handles the special case where the sorting of items doesn't affect the final result, as all items are equally valuable relative to their weight. +These test scenarios cover various aspects of the fractionalKnapsack method, including basic functionality, edge cases, and special situations. They aim to thoroughly validate the method's correctness and robustness. +*/ +// ********RoostGPT******** +package com.thealgorithms.greedyalgorithms; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import static org.junit.jupiter.api.Assertions.*; +import static org.assertj.core.api.Assertions.assertThat; +import java.util.stream.Stream; +import java.util.Arrays; +import java.util.Comparator; +import org.junit.jupiter.api.*; + +@Tag("com.thealgorithms.sorts") +@Tag("com.thealgorithms.sorts.sort") +@Tag("com.thealgorithms.greedyalgorithms") +@Tag("com.thealgorithms.greedyalgorithms.fractionalKnapsack") +class FractionalKnapsackFractionalKnapsackTest { + + @Test + void basicFunctionalityTest() { + int[] weight = { 10, 20, 30 }; + int[] value = { 60, 100, 120 }; + int capacity = 50; + int result = FractionalKnapsack.fractionalKnapsack(weight, value, capacity); + assertEquals(240, result); + } + + @Test + void fullCapacityUtilization() { + int[] weight = { 10, 20, 30 }; + int[] value = { 60, 100, 120 }; + int capacity = 60; + int result = FractionalKnapsack.fractionalKnapsack(weight, value, capacity); + assertEquals(280, result); + } + + @Test + void fractionalItemInclusion() { + int[] weight = { 10, 20, 30 }; + int[] value = { 60, 100, 120 }; + int capacity = 55; + int result = FractionalKnapsack.fractionalKnapsack(weight, value, capacity); + assertEquals(260, result); + } + + @Test + void emptyKnapsack() { + int[] weight = { 10, 20, 30 }; + int[] value = { 60, 100, 120 }; + int capacity = 0; + int result = FractionalKnapsack.fractionalKnapsack(weight, value, capacity); + assertEquals(0, result); + } + + @Test + void singleItemKnapsack() { + int[] weight = { 50 }; + int[] value = { 100 }; + int capacity = 30; + int result = FractionalKnapsack.fractionalKnapsack(weight, value, capacity); + assertEquals(60, result); + } + + @Test + void largeNumberOfItems() { + int[] weight = new int[1000]; + int[] value = new int[1000]; + for (int i = 0; i < 1000; i++) { + weight[i] = i + 1; + value[i] = (i + 1) * 10; + } + int capacity = 5000; + int result = FractionalKnapsack.fractionalKnapsack(weight, value, capacity); + assertTrue(result > 0); + } + + @Test + void sameValueWeightRatio() { + int[] weight = { 10, 20, 30 }; + int[] value = { 20, 40, 60 }; + int capacity = 40; + int result = FractionalKnapsack.fractionalKnapsack(weight, value, capacity); + assertEquals(80, result); + } + + @ParameterizedTest + @MethodSource("provideTestCases") + void parameterizedTest(int[] weight, int[] value, int capacity, int expected) { + int result = FractionalKnapsack.fractionalKnapsack(weight, value, capacity); + assertEquals(expected, result); + } + + private static Stream provideTestCases() { + return Stream.of(Arguments.of(new int[] { 10, 20, 30 }, new int[] { 60, 100, 120 }, 50, 240), + Arguments.of(new int[] { 10, 20, 30 }, new int[] { 60, 100, 120 }, 60, 280), + Arguments.of(new int[] { 10, 20, 30 }, new int[] { 60, 100, 120 }, 55, 260), + Arguments.of(new int[] { 10, 20, 30 }, new int[] { 60, 100, 120 }, 0, 0), + Arguments.of(new int[] { 50 }, new int[] { 100 }, 30, 60), + Arguments.of(new int[] { 10, 20, 30 }, new int[] { 20, 40, 60 }, 40, 80)); + } + +} \ No newline at end of file diff --git a/src/test/java/com/thealgorithms/greedyalgorithms/JobSequencingFindJobSequenceTest.java b/src/test/java/com/thealgorithms/greedyalgorithms/JobSequencingFindJobSequenceTest.java new file mode 100644 index 000000000000..8c8e0707972e --- /dev/null +++ b/src/test/java/com/thealgorithms/greedyalgorithms/JobSequencingFindJobSequenceTest.java @@ -0,0 +1,133 @@ +// ********RoostGPT******** +/* +Test generated by RoostGPT for test java-algos using AI Type Claude AI and AI Model claude-3-5-sonnet-20240620 +ROOST_METHOD_HASH=findJobSequence_a922574874 +ROOST_METHOD_SIG_HASH=findJobSequence_1dce91ae26 +Based on the provided method and imports, here are several test scenarios for the `findJobSequence` method: +Scenario 1: Normal Job Sequence with Multiple Jobs +Details: + TestName: normalJobSequenceWithMultipleJobs + Description: Test the method with a normal set of jobs to ensure it returns the correct job sequence. +Execution: + Arrange: Create an ArrayList of Job objects with various deadlines and IDs. + Act: Call findJobSequence with the created ArrayList and the size of the job list. + Assert: Check if the returned string matches the expected job sequence. +Validation: + Verify that the method correctly identifies and orders jobs based on their deadlines, maximizing the number of jobs that can be completed within their respective deadlines. +Scenario 2: Empty Job List +Details: + TestName: emptyJobList + Description: Test the method's behavior when given an empty list of jobs. +Execution: + Arrange: Create an empty ArrayList of Job objects. + Act: Call findJobSequence with the empty ArrayList and size 0. + Assert: Verify that the method returns "Job Sequence: " (empty sequence). +Validation: + Ensure that the method handles empty input gracefully without throwing exceptions and returns an appropriate empty sequence message. +Scenario 3: Single Job in the List +Details: + TestName: singleJobInList + Description: Test the method with only one job in the list to ensure correct handling of this edge case. +Execution: + Arrange: Create an ArrayList with a single Job object. + Act: Call findJobSequence with the single-job ArrayList and size 1. + Assert: Check if the returned string contains only the ID of the single job. +Validation: + Confirm that the method correctly processes a list with a single job and returns the expected sequence containing only that job's ID. +Scenario 4: All Jobs with Same Deadline +Details: + TestName: allJobsWithSameDeadline + Description: Test the method's behavior when all jobs have the same deadline. +Execution: + Arrange: Create an ArrayList of Job objects where all jobs have the same deadline. + Act: Call findJobSequence with this ArrayList and its size. + Assert: Verify that the returned sequence contains the correct number of jobs and follows the input order. +Validation: + Ensure that the method correctly handles the case where all jobs have the same deadline, selecting jobs in the order they appear in the input list up to the deadline limit. +Scenario 5: Jobs with Deadlines Exceeding List Size +Details: + TestName: jobsWithDeadlinesExceedingListSize + Description: Test the method's handling of jobs with deadlines greater than the list size. +Execution: + Arrange: Create an ArrayList of Job objects where some jobs have deadlines greater than the list size. + Act: Call findJobSequence with this ArrayList and its size. + Assert: Check if the returned sequence is correct and doesn't include invalid slot assignments. +Validation: + Verify that the method correctly ignores deadline values that exceed the list size and produces a valid job sequence within the given size constraints. +Scenario 6: Jobs with Zero Deadlines +Details: + TestName: jobsWithZeroDeadlines + Description: Test the method's behavior when some jobs have a deadline of 0. +Execution: + Arrange: Create an ArrayList of Job objects including some with a deadline of 0. + Act: Call findJobSequence with this ArrayList and its size. + Assert: Verify that jobs with zero deadlines are not included in the final sequence. +Validation: + Ensure that the method correctly handles jobs with zero deadlines by excluding them from the final job sequence, as they cannot be scheduled. +These test scenarios cover various aspects of the `findJobSequence` method, including normal cases, edge cases, and potential error conditions. They aim to validate the method's correctness, robustness, and adherence to the expected behavior in different situations. +*/ +// ********RoostGPT******** +package com.thealgorithms.greedyalgorithms; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import static org.junit.jupiter.api.Assertions.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.stream.Stream; +import org.junit.jupiter.api.*; + +@Tag("com.thealgorithms.ciphers.a5") +@Tag("com.thealgorithms.ciphers.a5.get") +@Tag("com.thealgorithms.ciphers.a5.get") +@Tag("com.thealgorithms.ciphers.a5.toString") +@Tag("com.thealgorithms.datastructures.lists") +@Tag("com.thealgorithms.datastructures.lists.append") +@Tag("com.thealgorithms.datastructures.lists.append") +@Tag("com.thealgorithms.datastructures.lists.append") +@Tag("com.thealgorithms.datastructures.lists.length") +@Tag("com.thealgorithms.datastructures.lists.length") +@Tag("com.thealgorithms.datastructures.bags") +@Tag("com.thealgorithms.datastructures.bags.size") +@Tag("com.thealgorithms.greedyalgorithms") +@Tag("com.thealgorithms.greedyalgorithms.findJobSequence") +class JobSequencingFindJobSequenceTest { + + @ParameterizedTest + @MethodSource("provideTestCases") + void testFindJobSequence(ArrayList jobs, int size, String expected) { + assertEquals(expected, JobSequencing.findJobSequence(jobs, size)); + } + + private static Stream provideTestCases() { + return Stream + .of(Arguments.of(new ArrayList<>(Arrays.asList(new Job('a', 2, 100), new Job('b', 1, 19), + new Job('c', 2, 27), new Job('d', 1, 25), new Job('e', 3, 15))), 5, "Job Sequence: c -> a -> e"), + Arguments.of(new ArrayList<>(), 0, "Job Sequence: "), + Arguments.of(new ArrayList<>(Arrays.asList(new Job('a', 1, 100))), 1, "Job Sequence: a"), + Arguments.of(new ArrayList<>(Arrays.asList(new Job('a', 2, 100), new Job('b', 2, 19), + new Job('c', 2, 27), new Job('d', 2, 25), new Job('e', 2, 15))), 5, "Job Sequence: a -> c"), + Arguments.of( + new ArrayList<>(Arrays.asList(new Job('a', 10, 100), new Job('b', 8, 19), + new Job('c', 7, 27), new Job('d', 6, 25), new Job('e', 5, 15))), + 5, "Job Sequence: e -> d -> c -> b -> a"), + Arguments.of( + new ArrayList<>(Arrays.asList(new Job('a', 0, 100), new Job('b', 1, 19), + new Job('c', 2, 27), new Job('d', 0, 25), new Job('e', 3, 15))), + 5, "Job Sequence: b -> c -> e")); + } + + @Test + void testFindJobSequenceWithNullJobs() { + assertThrows(NullPointerException.class, () -> JobSequencing.findJobSequence(null, 5)); + } + + @Test + void testFindJobSequenceWithNegativeSize() { + ArrayList jobs = new ArrayList<>(Arrays.asList(new Job('a', 1, 100))); + assertThrows(NegativeArraySizeException.class, () -> JobSequencing.findJobSequence(jobs, -1)); + } + +} \ No newline at end of file diff --git a/src/test/java/com/thealgorithms/greedyalgorithms/MinimizingLatenessOfTest.java b/src/test/java/com/thealgorithms/greedyalgorithms/MinimizingLatenessOfTest.java new file mode 100644 index 000000000000..f7982ce81516 --- /dev/null +++ b/src/test/java/com/thealgorithms/greedyalgorithms/MinimizingLatenessOfTest.java @@ -0,0 +1,173 @@ +// ********RoostGPT******** +/* +Test generated by RoostGPT for test java-algos using AI Type Claude AI and AI Model claude-3-5-sonnet-20240620 +ROOST_METHOD_HASH=of_eb8138c6bc +ROOST_METHOD_SIG_HASH=of_7a04d5363c +Based on the provided method and class information, here are several JUnit test scenarios for the `of` method: +``` +Scenario 1: Create a Job with Valid Parameters +Details: + TestName: createJobWithValidParameters + Description: Test the creation of a Job object with valid input parameters. +Execution: + Arrange: Prepare valid input parameters for jobName, processingTime, and deadline. + Act: Call the of method with these parameters. + Assert: Verify that a non-null Job object is returned and its properties match the input. +Validation: + This test ensures that the of method correctly creates a Job object when given valid inputs. It's crucial for verifying the basic functionality of the Job creation process. +Scenario 2: Create a Job with Minimum Valid Values +Details: + TestName: createJobWithMinimumValidValues + Description: Test the creation of a Job object with the minimum acceptable values for processingTime and deadline. +Execution: + Arrange: Set up a jobName, and use 1 for both processingTime and deadline (assuming 0 or negative values are invalid). + Act: Invoke the of method with these parameters. + Assert: Check that a Job object is created with the specified minimum values. +Validation: + This test verifies that the method can handle edge cases with minimum valid inputs, ensuring robustness in Job creation. +Scenario 3: Create a Job with Maximum Integer Values +Details: + TestName: createJobWithMaximumIntegerValues + Description: Test the creation of a Job object using Integer.MAX_VALUE for processingTime and deadline. +Execution: + Arrange: Prepare a jobName and use Integer.MAX_VALUE for both processingTime and deadline. + Act: Call the of method with these extreme values. + Assert: Verify that a Job object is created correctly with these maximum values. +Validation: + This test checks the method's ability to handle extreme integer values, which is important for understanding the upper limits of Job parameters. +Scenario 4: Create a Job with Null JobName +Details: + TestName: createJobWithNullJobName + Description: Test the behavior of the of method when passed a null value for jobName. +Execution: + Arrange: Set up null for jobName and valid values for processingTime and deadline. + Act: Attempt to create a Job using the of method with a null jobName. + Assert: Expect an IllegalArgumentException or similar exception to be thrown. +Validation: + This test ensures that the method properly handles null input for jobName, which is crucial for maintaining data integrity and preventing null pointer exceptions later. +Scenario 5: Create a Job with Negative ProcessingTime +Details: + TestName: createJobWithNegativeProcessingTime + Description: Test the of method's response to a negative value for processingTime. +Execution: + Arrange: Prepare a valid jobName, a negative value for processingTime, and a valid deadline. + Act: Try to create a Job using the of method with these parameters. + Assert: Expect an IllegalArgumentException or similar exception to be thrown. +Validation: + This test verifies that the method correctly rejects invalid negative values for processingTime, ensuring logical consistency in Job creation. +Scenario 6: Create a Job with Deadline Earlier Than ProcessingTime +Details: + TestName: createJobWithDeadlineEarlierThanProcessingTime + Description: Test creating a Job where the deadline is earlier than the processing time. +Execution: + Arrange: Set up a valid jobName, a processingTime greater than the deadline. + Act: Attempt to create a Job using the of method with these parameters. + Assert: Check if the method handles this logically inconsistent scenario appropriately (e.g., throws an exception or adjusts values). +Validation: + This test ensures that the method can handle or reject logically inconsistent inputs, which is important for maintaining the integrity of Job scheduling logic. +Scenario 7: Create Multiple Jobs and Verify Uniqueness +Details: + TestName: createMultipleJobsAndVerifyUniqueness + Description: Test creating multiple Job objects and verify that they are distinct instances. +Execution: + Arrange: Prepare parameters for multiple Job creations. + Act: Create several Job objects using the of method with different parameters. + Assert: Verify that each created Job is a unique instance with correct, distinct properties. +Validation: + This test ensures that the of method creates new instances for each call, which is important for maintaining the integrity of individual Job objects in a multi-job environment. +``` +These test scenarios cover various aspects of the `of` method, including normal cases, edge cases, and potential error conditions. They aim to ensure the robustness and correctness of the Job creation process. +*/ +// ********RoostGPT******** +package com.thealgorithms.greedyalgorithms; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import static org.junit.jupiter.api.Assertions.*; +import java.util.Arrays; +import org.junit.jupiter.api.*; + +@Tag("com.thealgorithms.greedyalgorithms") +@Tag("com.thealgorithms.greedyalgorithms.of") +class MinimizingLatenessOfTest { + + @Test + void createJobWithValidParameters() { + Job job = Job.of("TestJob", 10, 20); + assertNotNull(job); + assertEquals("TestJob", job.jobName); + assertEquals(10, job.processingTime); + assertEquals(20, job.deadline); + } + + @Test + void createJobWithMinimumValidValues() { + Job job = Job.of("MinJob", 1, 1); + assertNotNull(job); + assertEquals("MinJob", job.jobName); + assertEquals(1, job.processingTime); + assertEquals(1, job.deadline); + } + + @Test + void createJobWithMaximumIntegerValues() { + Job job = Job.of("MaxJob", Integer.MAX_VALUE, Integer.MAX_VALUE); + assertNotNull(job); + assertEquals("MaxJob", job.jobName); + assertEquals(Integer.MAX_VALUE, job.processingTime); + assertEquals(Integer.MAX_VALUE, job.deadline); + } + + @Test + void createJobWithNullJobName() { + assertThrows(IllegalArgumentException.class, () -> Job.of(null, 10, 20)); + } + + @Test + void createJobWithNegativeProcessingTime() { + assertThrows(IllegalArgumentException.class, () -> Job.of("NegativeJob", -1, 20)); + } + + @Test + void createJobWithDeadlineEarlierThanProcessingTime() { + Job job = Job.of("EarlyDeadlineJob", 20, 10); + assertNotNull(job); + assertEquals("EarlyDeadlineJob", job.jobName); + assertEquals(20, job.processingTime); + assertEquals(10, job.deadline); + } + + @Test + void createMultipleJobsAndVerifyUniqueness() { + Job job1 = Job.of("Job1", 10, 20); + Job job2 = Job.of("Job2", 15, 25); + Job job3 = Job.of("Job3", 5, 15); + assertNotNull(job1); + assertNotNull(job2); + assertNotNull(job3); + assertNotSame(job1, job2); + assertNotSame(job1, job3); + assertNotSame(job2, job3); + assertEquals("Job1", job1.jobName); + assertEquals(10, job1.processingTime); + assertEquals(20, job1.deadline); + assertEquals("Job2", job2.jobName); + assertEquals(15, job2.processingTime); + assertEquals(25, job2.deadline); + assertEquals("Job3", job3.jobName); + assertEquals(5, job3.processingTime); + assertEquals(15, job3.deadline); + } + + @ParameterizedTest + @CsvSource({ "TestJob, 10, 20", "AnotherJob, 5, 15", "LongJob, 100, 200" }) + void createJobWithVariousParameters(String jobName, int processingTime, int deadline) { + Job job = Job.of(jobName, processingTime, deadline); + assertNotNull(job); + assertEquals(jobName, job.jobName); + assertEquals(processingTime, job.processingTime); + assertEquals(deadline, job.deadline); + } + +} \ No newline at end of file diff --git a/src/test/java/com/thealgorithms/greedyalgorithms/MinimizingLatenessToStringTest.java b/src/test/java/com/thealgorithms/greedyalgorithms/MinimizingLatenessToStringTest.java new file mode 100644 index 000000000000..f4963e4537b5 --- /dev/null +++ b/src/test/java/com/thealgorithms/greedyalgorithms/MinimizingLatenessToStringTest.java @@ -0,0 +1,133 @@ +// ********RoostGPT******** +/* +Test generated by RoostGPT for test java-algos using AI Type Claude AI and AI Model claude-3-5-sonnet-20240620 +ROOST_METHOD_HASH=toString_7033209074 +ROOST_METHOD_SIG_HASH=toString_bbffdadaa2 +Based on the provided method and class information, here are several JUnit test scenarios for the toString() method: +Scenario 1: Test toString() with Default Values +Details: + TestName: toStringWithDefaultValues + Description: Verify that the toString() method returns the correct string representation when all fields have their default values. +Execution: + Arrange: Create a new instance of the class with default values. + Act: Call the toString() method on the instance. + Assert: Compare the returned string with the expected format. +Validation: + This test ensures that the toString() method correctly formats the output when all fields are at their default values. It's important to verify the base case behavior of the method. +Scenario 2: Test toString() with Non-null Values +Details: + TestName: toStringWithNonNullValues + Description: Check if the toString() method correctly formats the output when all fields have non-null, non-default values. +Execution: + Arrange: Create an instance of the class with specific non-null values for all fields. + Act: Invoke the toString() method on this instance. + Assert: Verify that the returned string matches the expected format with the given values. +Validation: + This test confirms that the toString() method correctly handles and formats non-default values, ensuring that all fields are properly represented in the output string. +Scenario 3: Test toString() with Maximum Integer Values +Details: + TestName: toStringWithMaxIntegerValues + Description: Verify the toString() method's behavior when integer fields are set to their maximum values. +Execution: + Arrange: Set up an instance with Integer.MAX_VALUE for startTime, processingTime, and lateness. + Act: Call toString() on this instance. + Assert: Check if the returned string correctly represents these maximum values. +Validation: + This test ensures that the toString() method can handle extreme integer values without overflow or formatting issues, which is crucial for robustness. +Scenario 4: Test toString() with Negative Values +Details: + TestName: toStringWithNegativeValues + Description: Test the toString() method's output when dealing with negative values for integer fields. +Execution: + Arrange: Create an instance with negative values for startTime, processingTime, and lateness. + Act: Invoke toString() on this instance. + Assert: Verify that the negative values are correctly represented in the output string. +Validation: + This test checks the method's ability to handle and correctly format negative values, which is important for scenarios where negative times or lateness might occur. +Scenario 5: Test toString() with Empty Job Name +Details: + TestName: toStringWithEmptyJobName + Description: Verify the behavior of toString() when the jobName field is an empty string. +Execution: + Arrange: Set up an instance with an empty string for jobName and some values for other fields. + Act: Call toString() on this instance. + Assert: Check if the empty job name is correctly represented in the output string. +Validation: + This test ensures that the method handles empty strings properly, which is important for data integrity and display consistency. +Scenario 6: Test toString() with Very Long Job Name +Details: + TestName: toStringWithVeryLongJobName + Description: Test the toString() method's output when the jobName is an extremely long string. +Execution: + Arrange: Create an instance with a very long string (e.g., 1000 characters) for jobName. + Act: Call toString() on this instance. + Assert: Verify that the entire long job name is included in the output without truncation. +Validation: + This test checks if the method can handle unusually long job names without breaking the formatting or causing any unexpected behavior. +These scenarios cover various aspects of the toString() method, including default values, non-null values, edge cases with integer limits, negative values, and different string lengths for the job name. They aim to ensure the method's robustness and correct formatting under different conditions. +*/ +// ********RoostGPT******** +package com.thealgorithms.greedyalgorithms; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import static org.assertj.core.api.Assertions.assertThat; +import java.util.Arrays; +import org.junit.jupiter.api.*; + +@Tag("com.thealgorithms.greedyalgorithms") +@Tag("com.thealgorithms.greedyalgorithms.toString") +class MinimizingLatenessToStringTest { + + @Test + void toStringWithDefaultValues() { + Job job = new Job("DefaultJob", 0, 0); + assertThat(job.toString()).isEqualTo("DefaultJob, startTime: 0, endTime: 0, lateness: 0"); + } + + @ParameterizedTest + @CsvSource({ "TestJob, 10, 20, 5, 15, TestJob, startTime: 10, endTime: 25, lateness: 5", + "AnotherJob, 5, 15, 0, 20, AnotherJob, startTime: 5, endTime: 25, lateness: 0" }) + void toStringWithNonNullValues(String jobName, int startTime, int processingTime, int lateness, int deadline, + String expectedOutput) { + Job job = new Job(jobName, processingTime, deadline); + job.startTime = startTime; + job.lateness = lateness; + assertThat(job.toString()).isEqualTo(expectedOutput); + } + + @Test + void toStringWithMaxIntegerValues() { + Job job = new Job("MaxValueJob", Integer.MAX_VALUE, Integer.MAX_VALUE); + job.startTime = Integer.MAX_VALUE; + job.lateness = Integer.MAX_VALUE; + assertThat(job.toString()).isEqualTo("MaxValueJob, startTime: 2147483647, endTime: -2, lateness: 2147483647"); + } + + @Test + void toStringWithNegativeValues() { + Job job = new Job("NegativeJob", -10, -5); + job.startTime = -20; + job.lateness = -15; + assertThat(job.toString()).isEqualTo("NegativeJob, startTime: -20, endTime: -30, lateness: -15"); + } + + @Test + void toStringWithEmptyJobName() { + Job job = new Job("", 10, 20); + job.startTime = 5; + job.lateness = 0; + assertThat(job.toString()).isEqualTo(", startTime: 5, endTime: 15, lateness: 0"); + } + + @Test + void toStringWithVeryLongJobName() { + String longName = "a".repeat(1000); + Job job = new Job(longName, 100, 200); + job.startTime = 50; + job.lateness = 25; + assertThat(job.toString()).isEqualTo(longName + ", startTime: 50, endTime: 150, lateness: 25"); + } + +} \ No newline at end of file