Project 5

Sabotage Recovery

Apologetic question: "How do we find what is wrong with ourselves?"

Project 5 — Sabotage Recovery

“Search me, O God, and know my heart! Try me and know my thoughts!” — Psalm 139:23

Chapter: 5 — Debugging Discipline Due: End of Week 5 Submit: A link to your code — an OnlineGDB project URL or a public GitHub repo URL. Main source files are Sabotaged.java, your test class, and bug-log.txt. See Coding 1’s online-coding workflow appendix for the full workflow. Allowed tools: the Java compiler, JUnit (or hand-rolled assertions), a non-AI editor, the textbook, your own past code. Not allowed (Phase 1 — AI is OFF): ChatGPT, Claude, Copilot, Cursor, GitHub Copilot Chat, any other AI assistant. Phase 2 begins in Week 9. Until then, no AI.


The Setup

You and the senior engineer on your imaginary team are pair-programming. The senior leaves for lunch and, on the way out, hands you a working program of theirs. “I’ve planted three bugs in it,” they say. “Find them. Document each one. Five runs maximum. Back in an hour.”

That’s this project. You will receive a Sabotaged.java file (download Sabotaged.java) — a working program from earlier in this course that has been deliberately broken by the addition of three bugs. The program comes with a small test suite (download SabotagedTest.java) that would pass on the un-sabotaged version. Some of the tests now fail; some still pass.

Your job: find the three bugs, fix them, document each one in the prescribed format, and add regression tests so the same bugs cannot return.

The constraint — five runs maximum at Normal — is the discipline. It forces you to think between runs, not to mash the run button. Senior engineers do not have a five-run limit in real life, but the habit of thinking before running is the senior engineer’s signature. This project trains it.


Setup

A starter zip is provided on the course portal. Unzip into a fresh directory. Inside, you’ll find:

  • Sabotaged.java — the saboted program. Read it. Do not run it yet. (download Sabotaged.java)
  • SabotagedTest.java — a test suite covering the program’s intended behavior. Some tests will fail on the saboted code. (download SabotagedTest.java)
  • expected-output.txt — for Normal and Medium, the expected output of a known input run. (download expected-output.txt)
  • bug-log.template.txt — the template you’ll fill in for each bug. (The template is reproduced under Required features below — copy it into your own bug-log.txt.)

The saboted program is one of the small classes you wrote in Chapters 2–4: a small bank Account, a Roster, a simple Calculator, or similar. The grader has the un-saboted reference. You don’t.


Learning Targets

By completing this project, you will demonstrate that you can:

  • Read a stack trace and identify both the immediate failure and the underlying cause.
  • Form a written hypothesis about a bug before changing a line of code.
  • Probe a hypothesis with the smallest change that distinguishes it from rivals.
  • Fix bugs minimally — without introducing new ones or “while-I’m-here” refactors.
  • Write a regression test that fails on the bug and passes on the fix.
  • Stay within a runs budget by thinking between runs rather than reacting.

Normal Tier

Goal: Find and fix all three planted bugs in Sabotaged.java. Document each one. Add a regression test for each. Stay within five runs of the main program (test runs do not count against the budget — but running the full main app does).

Required features

  1. All three bugs are found and fixed. All tests in SabotagedTest.java pass after your fix.

  2. bug-log.txt is filled out for each bug, using the provided template:

    ## Bug N
    - **Symptom (what I observed):**
    - **Hypothesis (what I thought was causing it):**
    - **Probe (the smallest thing I did to confirm):**
    - **Cause (the actual line):**
    - **Fix (the actual change):**
    - **Regression test (the test name in `SabotagedTest.java`):**
  3. A regression test exists for each bug in SabotagedTest.java. The test must:

    • Have a descriptive name (e.g., transferDoesNotLoseMoneyOnSelfTransfer).
    • Include a // Regression: comment naming the bug.
    • Fail on the original saboted code (verify this once before your final fix).
    • Pass on your fixed code.
  4. You ran the main program no more than five times. Honor system. The bug log records each run with a one-line note: “Run 3 — confirmed hypothesis 2 by printing intermediate total.”

  5. You did not modify the program structurally beyond the fix. Don’t rewrite methods that weren’t bugged. Don’t add helper classes. The fix is minimal.

  6. You did not use AI. Sign the AI Honesty line in bug-log.txt.

Normal-tier rubric (out of 100)

CriterionPoints
All planted bugs found and fixed24
bug-log.txt filled out completely for each bug (3 × 7 pts)21
Each fix has a corresponding regression test, named and commented15
Tests in SabotagedTest.java all pass after the fix10
Runs budget honored (no more than 5 main-program runs)8
Fixes are minimal (no unrelated edits, no rewritten methods)8
Code compiles cleanly with no warnings4
Reflection comment at top of Sabotaged.java (tier, AI honesty)5
bug-log.txt reads as actual investigation, not post-hoc fiction5

Medium Tier (+up to 25% extra credit)

M1. The Second Sabotage

The portal also contains Sabotaged2.java (download Sabotaged2.java) and Sabotaged2Test.java (download Sabotaged2Test.java). Three subtler bugs — bugs that don’t crash, don’t produce obviously wrong output on the happy path, and only manifest on edge cases or unusual inputs. Same five-run budget. Same bug-log.txt discipline (in bug-log-2.txt).

Subtler bugs include things like: a comparison that uses > where it should use >=, a counter that initializes to 1 instead of 0, a method that returns the right value but with a sign error, a string that has a trailing space.

M2. Test Suite Audit

For both Sabotaged.java and Sabotaged2.java, audit the provided test suite. The provided tests catch most bugs, but they have gaps — places where a planted bug could slip through. For each program, add at least two new tests that close gaps you discovered. Document the gap each test closes in bug-log.txt.


Hard Tier (+up to 25% additional extra credit)

H1. The Third Sabotage — No Oracle

Sabotaged3.java (download Sabotaged3.java) contains five planted bugs. There is no test suite provided. There is no expected-output.txt. There is only the program’s spec (a Javadoc comment at the top of the file) and your judgment.

You must:

  1. Read the spec and infer the expected behavior.
  2. Write your own test suite — at least 10 tests — that exercises the spec.
  3. Use your test suite to find all five bugs.
  4. Fix each one, with a bug-log-3.txt entry.
  5. Run the main program at most ten times for this version.

This is the closest the project gets to real-world debugging. In production, you do not get a test suite handed to you. The senior engineer expects you to write one yourself, from the spec, while you are debugging. That dual task — writing tests and finding bugs simultaneously — is the engineering reality.

H2. The Hypothesis Tournament

Pair with a classmate. Exchange the bug logs from Normal tier. For each bug your classmate fixed, write the next hypothesis you would have formed if their first guess had been wrong. Submit the exchange as hypothesis-tournament.docx.

The point: there is rarely only one plausible hypothesis. Practicing the second hypothesis builds the skill of not getting locked into the first one.

H3. The Sabotage Author

Pick one of your own past projects from Coding 1 or earlier Coding 2 weeks. Plant three bugs in a copy of it — bugs that obey these rules:

  • Each bug must compile cleanly.
  • Each bug must produce different observable behavior than the correct code.
  • At least one bug must be subtle (not a crash, not an obvious off-by-one — something that requires hypothesis-driven investigation to catch).

Hand the saboted copy to a classmate, along with the original test suite. Have them run Project 5 against it. Did they find all three? How many runs did they need? Compare notes.

Submit:

  • Your saboted file.
  • Your “answer key” describing each planted bug.
  • A short reflection on what was hard about planting the bugs — what made one bug “fair” and another “cheap.”

This is the rep that makes you better at reviewing AI-generated code later, because authoring subtle bugs and reviewing subtle bugs are the same skill seen from two sides.


Submission

Submit one URL via the course portal:

  • OnlineGDB project link (recommended for Coding 2). Make sure JUnit is configured in the project settings (Appendix B for the JUnit setup).
  • GitHub repo link (optional).

What the linked project must contain

  1. Sabotaged.java (and Sabotaged2.java, Sabotaged3.java if attempted), with your fixes.
  2. SabotagedTest.java (and Sabotaged2Test.java, etc.), with the regression tests added.
  3. bug-log.txt (and additional logs per tier), filled out per template.
  4. Reflection comment block at the top of Sabotaged.java:
/*
 * Tier targeted:     Normal / Medium / Hard
 * Bugs found:        N of N
 * Runs used:         X of 5 (or 10 for Hard)
 * What I learned:    one short paragraph
 * Hardest bug:       which one, and why
 * AI usage:          NONE — this is Phase 1.  (signed) <your name>
 */
  1. Program left runnablejava -ea Sabotaged (or however your build is configured) should execute the main path. The grader will also run the test suite.

Hints (Read Before You Begin, Not Mid-Debug)

  • Read the program once, top to bottom, without running it. You will be tempted to compile and run immediately. Don’t. Reading first lets you form initial hypotheses that the first run will then confirm or refute. That’s worth one “run” of pure observation, paid for in advance.

  • Run 1 is for symptoms, not diagnoses. Just run the program with the supplied input and the test suite. Write down what you see. Do not change anything. The cost of Run 1 is one of your five.

  • Between runs, do not touch the code unless you have a written hypothesis. If you find yourself wanting to “just try” something, stop, write down the hypothesis, then make the change.

  • Probe with the smallest possible change. Adding one println to confirm “is count zero at this point in the loop?” is a probe. Rewriting the loop is not.

  • Fix one bug at a time. Confirm the fix. Run the test suite. Then look for the next bug. Trying to fix two bugs in a single run is how you ship a new bug that masks the first.

  • The bug-log.txt is graded as heavily as the fixes. A perfect fix with a missing hypothesis is partial credit. An imperfect fix with rigorous documentation is also partial credit. We are training the discipline, not just the result.

  • If you blow the runs budget, finish anyway. Document honestly. A truthful “I ran the program 8 times because my first two hypotheses were wrong” is better than a lie. Honest 8 beats fake 5.


What Mastery Looks Like (Beyond the Rubric)

A great Project 5 reads like a detective’s notebook. The hypothesis comes first. The probe is small. The fix is minimal. The regression test names the bug it prevents. Every entry is dated, every change explainable.

A great Project 5 catches at least one bug without running the program — by reading the code and noticing something doesn’t match the spec. Static analysis (with your eyes) is faster than dynamic analysis (with the compiler) for some classes of bug. Senior engineers do both.

A great Project 5 does not introduce a new bug while fixing an old one. Check this explicitly: after each fix, run the full test suite, not just the one test you were targeting. If a previously-passing test now fails, you have a regression. Back out, hypothesize again, try a different fix.

Coach’s Note — The first time a student does this project honestly, three things tend to happen. (1) They are slower than they expected to be. (2) They are more confident in the fixes they did ship. (3) The next bug they meet, in any project for the rest of the course, gets the same treatment by reflex. The reflex is the deliverable. The bugs are just the gym equipment.


When You’re Done

  1. Re-read your own bug-log.txt slowly. For each bug: does the hypothesis genuinely precede the fix in the narrative, or did you write it after the fact?
  2. Run the full test suite one final time. All green?
  3. Update your reflection comment.
  4. Submit.
  5. Read Chapter 6. Files, data, and the discipline of careful reading and careful writing.

A theological footnote. The Christian tradition has called this kind of slow, honest self-examination the examen — a nightly review where you ask, with God’s help, where was I wrong today, and why? The answer is rarely flattering. The discipline is in asking anyway. Debugging is the secular cousin. Both crafts require the courage to keep looking after the easy answer has failed.

See you next week.