Skip to content

Commit c4aeb3e

Browse files
committed
add smoketest
1 parent 1eea258 commit c4aeb3e

1 file changed

Lines changed: 92 additions & 0 deletions

File tree

src/test/java/SmokeTest.java

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
// REBELLION 10014
2+
3+
import static org.junit.jupiter.api.Assertions.fail;
4+
5+
import edu.wpi.first.hal.HAL;
6+
import edu.wpi.first.wpilibj.RobotBase;
7+
import frc.robot.Robot;
8+
import java.io.ByteArrayOutputStream;
9+
import java.io.PrintStream;
10+
import java.util.concurrent.atomic.AtomicReference;
11+
import org.junit.jupiter.api.AfterAll;
12+
import org.junit.jupiter.api.AfterEach;
13+
import org.junit.jupiter.api.BeforeEach;
14+
import org.junit.jupiter.api.Test;
15+
16+
class SmokeTest {
17+
static Thread robotThread;
18+
static AtomicReference<Throwable> threadCrashException;
19+
20+
// Streams for intercepting WPILib console output
21+
static ByteArrayOutputStream errContent;
22+
static PrintStream originalErr;
23+
24+
@BeforeEach
25+
void setup() {
26+
// 1. Setup exception catcher for the robot thread
27+
threadCrashException = new AtomicReference<>();
28+
robotThread = new Thread(() -> RobotBase.startRobot(Robot::new));
29+
robotThread.setUncaughtExceptionHandler((th, ex) -> threadCrashException.set(ex));
30+
31+
// 2. Intercept System.err to catch DriverStation errors/warnings
32+
errContent = new ByteArrayOutputStream();
33+
originalErr = System.err;
34+
System.setErr(new PrintStream(errContent));
35+
36+
assert HAL.initialize(500, 0); // initialize the HAL, crash if failed
37+
robotThread.start();
38+
}
39+
40+
@Test
41+
void fiveSecondTest() throws InterruptedException {
42+
long startTime = System.currentTimeMillis();
43+
long timeout = 5000; // 5 seconds timeout
44+
45+
while (System.currentTimeMillis() - startTime < timeout) {
46+
// Check if the thread threw a fatal exception
47+
if (threadCrashException.get() != null) {
48+
fail(
49+
"Robot crashed with exception: "
50+
+ threadCrashException.get().getMessage(),
51+
threadCrashException.get());
52+
}
53+
54+
// Check if the thread died silently
55+
if (robotThread.getState() == Thread.State.TERMINATED) {
56+
fail("Robot thread terminated unexpectedly without a caught exception.");
57+
}
58+
59+
// Yield to prevent the while loop from hogging the CPU
60+
Thread.sleep(100);
61+
}
62+
63+
// 3. Analyze the intercepted error stream
64+
String consoleOutput = errContent.toString();
65+
66+
// Check for WPILib-specific error tags or general exceptions
67+
if (consoleOutput.contains("Error") || consoleOutput.contains("Exception")) {
68+
fail("WPILib reported errors during the smoke test:\n" + consoleOutput);
69+
}
70+
71+
// Optional: You can also fail on warnings, but WPILib often prints benign
72+
// warnings (like missing joysticks in sim), so use this with caution!
73+
// if (consoleOutput.contains("Warning")) { ... }
74+
}
75+
76+
@AfterEach
77+
void tearDown() {
78+
// Restore the original System.err so regular testing output isn't hidden
79+
System.setErr(originalErr);
80+
}
81+
82+
@AfterAll
83+
static void cleanup() {
84+
// Stop the robot thread
85+
if (robotThread != null && robotThread.isAlive()) {
86+
robotThread.interrupt();
87+
}
88+
89+
HAL.exitMain();
90+
HAL.shutdown();
91+
}
92+
}

0 commit comments

Comments
 (0)