Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package com.thealgorithms.searches;

import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import org.junit.jupiter.api.Test;

/**
* Determinism checks for {@link HowManyTimesRotated#rotated(int[])}.
*
* <p>Source facts (HowManyTimesRotated.java):
* <ul>
* <li>line 13: the array cannot contain duplicates (precondition for every fixture below)</li>
* <li>line 45: {@code rotated(int[] a)} is the only logic; its sole input is {@code a}</li>
* <li>lines 46-47: {@code low = 0}, {@code high = a.length - 1} are local state</li>
* <li>line 49: the loop is skipped when {@code a.length == 1}, so line 58 returns 0</li>
* <li>line 58: the result is the index of the minimum element</li>
* </ul>
* Expected values are calculated by hand (index of the minimum), not by calling the method.
*/
public class HowManyTimesRotatedDeterminismTest {

// Smallest valid input. Precondition: line 49 loop is not entered when length == 1.
private static int[] smallest() {
return new int[] {7};
}

// Ordinary input. Precondition: distinct values (line 13); minimum 2 is at index 2.
private static int[] ordinary() {
return new int[] {15, 17, 2, 3, 5};
}

// Another valid input. Precondition: distinct values (line 13); minimum 2 is at index 4.
private static int[] other() {
return new int[] {11, 12, 15, 18, 2, 5, 6, 8};
}

@Test
public void smallestInputRepeatedCallsGiveSameResult() {
assertEquals(0, HowManyTimesRotated.rotated(smallest()));
assertEquals(0, HowManyTimesRotated.rotated(smallest()));
}

@Test
public void ordinaryInputRepeatedCallsGiveSameResult() {
assertEquals(2, HowManyTimesRotated.rotated(ordinary()));
assertEquals(2, HowManyTimesRotated.rotated(ordinary()));
}

@Test
public void earlierCallsDoNotAffectLaterResult() {
assertEquals(2, HowManyTimesRotated.rotated(ordinary()));
assertEquals(4, HowManyTimesRotated.rotated(other()));
assertEquals(0, HowManyTimesRotated.rotated(smallest()));
// Same ordinary fixture again, after other valid inputs ran in between.
assertEquals(2, HowManyTimesRotated.rotated(ordinary()));
}

@Test
public void inputArrayIsNotMutated() {
int[] input = ordinary();
int[] expectedContents = {15, 17, 2, 3, 5};
HowManyTimesRotated.rotated(input);
assertArrayEquals(expectedContents, input);

int[] single = smallest();
HowManyTimesRotated.rotated(single);
assertArrayEquals(new int[] {7}, single);
}

@Test
public void sameArrayInstanceCanBeReused() {
int[] shared = ordinary();
assertEquals(2, HowManyTimesRotated.rotated(shared));
assertEquals(2, HowManyTimesRotated.rotated(shared));
}

/** rotated() has no external dependency: it must not read stdin (only main() does, lines 34-39). */
@Test
public void resultDoesNotDependOnStandardInput() {
InputStream original = System.in;
try {
System.setIn(new ByteArrayInputStream(new byte[0]));
assertEquals(2, HowManyTimesRotated.rotated(ordinary()));
System.setIn(new ByteArrayInputStream("999 1 2 3".getBytes()));
assertEquals(2, HowManyTimesRotated.rotated(ordinary()));
} finally {
System.setIn(original);
}
}
}

59 changes: 59 additions & 0 deletions work/R45-T015/check.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#!/usr/bin/env python3
"""Runner for task R45-T015: determinism checks for HowManyTimesRotated.

Runs the focused JUnit test through Maven, requires a nonzero test count,
saves evidence into work/R45-T015/, and exits non-zero on any failure.
"""
import glob
import subprocess
import sys
import xml.etree.ElementTree as ET
from pathlib import Path

HERE = Path(__file__).resolve().parent
REPO = HERE.parent.parent
TEST_CLASS = "HowManyTimesRotatedDeterminismTest"
CMD = ["mvn", "-B", "test", f"-Dtest={TEST_CLASS}", "-Dsurefire.failIfNoSpecifiedTests=false"]


def tool_version(cmd):
try:
out = subprocess.run(cmd, capture_output=True, text=True, cwd=REPO)
return "\n".join(l for l in (out.stdout + out.stderr).splitlines()
if not l.startswith("Picked up")).strip()
except FileNotFoundError:
return f"{cmd[0]}: not found"


def main():
(HERE / "tool_versions.txt").write_text(
"java:\n" + tool_version(["java", "-version"]) + "\n\nmvn:\n"
+ tool_version(["mvn", "-v"]) + "\n\npython:\n" + sys.version + "\n")

print("Running:", " ".join(CMD))
proc = subprocess.run(CMD, capture_output=True, text=True, cwd=REPO)
(HERE / "mvn_output.txt").write_text(proc.stdout + proc.stderr)

reports = glob.glob(str(REPO / "target/surefire-reports" / f"TEST-*{TEST_CLASS}.xml"))
if not reports:
print("FAIL: no surefire report found")
return 1
suite = ET.parse(reports[0]).getroot()
tests = int(suite.get("tests", 0))
failures = int(suite.get("failures", 0)) + int(suite.get("errors", 0))
skipped = int(suite.get("skipped", 0))
summary = (f"command: {' '.join(CMD)}\ntests={tests} failures/errors={failures} "
f"skipped={skipped} mvn_exit={proc.returncode}\n")
(HERE / "result.txt").write_text(summary)
print(summary)

if proc.returncode != 0 or failures or tests == 0:
print("FAIL")
return 1
print("PASS")
return 0


if __name__ == "__main__":
sys.exit(main())

49 changes: 49 additions & 0 deletions work/R45-T015/mvn_output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
[INFO] Scanning for projects...
[INFO] Loaded 24447 auto-discovered prefixes for remote repository central (prefixes-central.txt)
[INFO]
[INFO] -----------------------< com.thealgorithms:Java >-----------------------
[INFO] Building Java 1.0-SNAPSHOT
[INFO] from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- jacoco:0.8.16:prepare-agent (default) @ Java ---
[INFO] Loaded 64 auto-discovered prefixes for remote repository apache.snapshots (prefixes-apache.snapshots.txt)
[INFO] argLine set to -javaagent:/Users/shyamlibakale/.m2/repository/org/jacoco/org.jacoco.agent/0.8.16/org.jacoco.agent-0.8.16-runtime.jar=destfile=/Users/shyamlibakale/TheAlgorithms-Java/TheAlgorithms-Java/target/jacoco.exec
[INFO]
[INFO] --- resources:3.5.0:resources (default-resources) @ Java ---
[INFO] skip non existing resourceDirectory /Users/shyamlibakale/TheAlgorithms-Java/TheAlgorithms-Java/src/main/resources
[INFO]
[INFO] --- compiler:3.16.0:compile (default-compile) @ Java ---
[INFO] Recompiling the module because of changed source code.
[INFO] Compiling 848 source files with javac [debug release 21] to target/classes
[INFO]
[INFO] --- resources:3.5.0:testResources (default-testResources) @ Java ---
[INFO] skip non existing resourceDirectory /Users/shyamlibakale/TheAlgorithms-Java/TheAlgorithms-Java/src/test/resources
[INFO]
[INFO] --- compiler:3.16.0:testCompile (default-testCompile) @ Java ---
[INFO] Recompiling the module because of changed dependency.
[INFO] Compiling 797 source files with javac [debug release 21] to target/test-classes
[INFO]
[INFO] --- surefire:3.6.0:test (default-test) @ Java ---
[INFO] Using auto detected provider org.apache.maven.surefire.junitplatform.JUnitPlatformProvider
[INFO]
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.thealgorithms.searches.HowManyTimesRotatedDeterminismTest
[INFO] Tests run: 6, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.024 s -- in com.thealgorithms.searches.HowManyTimesRotatedDeterminismTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 6, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO]
[INFO] --- jacoco:0.8.16:report (generate-code-coverage-report) @ Java ---
[INFO] Loading execution data file /Users/shyamlibakale/TheAlgorithms-Java/TheAlgorithms-Java/target/jacoco.exec
[INFO] Analyzed bundle 'Java' with 1073 classes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 5.833 s
[INFO] Finished at: 2026-11-11T15:49:12+05:30
[INFO] ------------------------------------------------------------------------
2 changes: 2 additions & 0 deletions work/R45-T015/result.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
command: mvn -B test -Dtest=HowManyTimesRotatedDeterminismTest -Dsurefire.failIfNoSpecifiedTests=false
tests=6 failures/errors=0 skipped=0 mvn_exit=0
14 changes: 14 additions & 0 deletions work/R45-T015/tool_versions.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
java:
openjdk version "21.0.13" 2026-10-20 LTS
OpenJDK Runtime Environment Temurin-21.0.13+9 (build 21.0.13+9-LTS)
OpenJDK 64-Bit Server VM Temurin-21.0.13+9 (build 21.0.13+9-LTS, mixed mode, sharing)

mvn:
Apache Maven 3.10.0 (c43a36b8d67be7e0805a411bc0898af1a51f5472)
Maven home: /opt/homebrew/Cellar/maven/3.10.0/libexec
Java version: 21.0.13, vendor: Eclipse Adoptium, runtime: /Library/Java/JavaVirtualMachines/temurin-21.jdk/Contents/Home
Default locale: en_IN, platform encoding: UTF-8, time zone: Asia/Kolkata
OS name: "mac os x", version: "27.0", arch: "aarch64", family: "mac"

python:
3.14.7 (v3.14.7:823f0323ee6, Aug 5 2026, 07:07:01) [Clang 21.0.0 (clang-2100.1.1.101)]