Work on this exercise locally

This web app is a reference guide — you can read instructions, browse starter code, and view tests here. To actually complete the exercise, you need to work in your local development environment.

1Clone the repo: git clone https://github.com/weihaoqu/program-analysis-bootcamp-student
2Edit the starter file in your editor (VS Code, Vim, etc.) — replace failwith "TODO" with your implementation.
3Run the tests: dune runtest modules/module1-foundations/exercises/calculator-bugs

Calculator Bugs

3. Exercise 1: Calculator Bugs

Goal: Find 8 bugs in a JavaScript calculator using static analysis (ESLint) and dynamic analysis (a test suite), then compare what each approach catches.

Time: ~30 minutes

Files:

FilePurpose
exercises/calculator-bugs/starter/calculator.jsThe buggy calculator -- edit this
exercises/calculator-bugs/starter/test-calculator.jsTest suite -- read only
exercises/calculator-bugs/starter/.eslintrc.jsonESLint configuration -- read only
exercises/calculator-bugs/starter/analysis-report-template.mdYour report -- fill this out
exercises/calculator-bugs/starter/package.jsonnpm project -- do not edit

Step-by-step

Step 1: Install dependencies

cd modules/module1-foundations/exercises/calculator-bugs/starter
npm install

This creates a node_modules/ directory with ESLint.

Step 2: Run static analysis (ESLint)

npx eslint calculator.js

ESLint examines the source code without executing it and reports issues based on the rules configured in .eslintrc.json. Record every finding (line number, rule name, description) in Part 1 of the analysis report.

The enabled ESLint rules are:

RuleWhat it catches
no-undefReferences to undefined variables
no-unreachableCode after return statements
no-fallthroughMissing break in switch cases
eqeqeq== instead of === (type coercion risk)
no-unused-varsDeclared but never-used variables
no-constant-conditionif (true) and similar always-true/false guards

Step 3: Run dynamic analysis (test suite)

node test-calculator.js

The test suite runs 16 tests that exercise the calculator functions at runtime. Some tests will PASS; others will FAIL. Record each failure (test name, error message, root cause) in Part 2 of the analysis report.

Step 4: Compare the two approaches

Fill out Parts 3 and 4 of analysis-report-template.md:

  • Which bugs did only static analysis catch?
  • Which bugs did only dynamic analysis catch?
  • Which bugs were found by both approaches?
  • Why can't either approach catch everything on its own?

Step 5: Fix all 8 bugs

Go back to calculator.js and fix every bug. After fixing, re-run both tools to confirm:

npx eslint calculator.js        # should report 0 errors, 0 warnings
node test-calculator.js          # all tests should PASS

The 8 bugs at a glance

The source comments label each bug (Bug 1 through Bug 8). Do not read these comments until you have tried to find them with the tools first.

Bug #   Function      Category
─────   ──────────    ────────────────────────
  1     add()         Undefined variable
  2     subtract()    Unreachable code
  3     calculate()   Switch fallthrough
  4     divide()      Division by zero
  5     factorial()   Infinite recursion
  6     multiply()    Type coercion (== vs ===)
  7     power()       Unused variable
  8     absolute()    Constant condition

Self-check

When you are done:

  • ESLint reports no issues
  • The test suite reports all tests passed
  • Your analysis report has all four parts filled out with concrete findings