Skip to content

[CSM-439]: Add unit tests for cache pull component - #5

Open
boztopuz wants to merge 1 commit into
mainfrom
test/CSM-439
Open

[CSM-439]: Add unit tests for cache pull component#5
boztopuz wants to merge 1 commit into
mainfrom
test/CSM-439

Conversation

@boztopuz

@boztopuz boztopuz commented Sep 8, 2026

Copy link
Copy Markdown

Linear: CSM-439

Adds a unit test suite for appcircle-cache-pull-component, following the conventions established in CSM-230, CSM-231 and the sibling CSM-417 cache push PR: a single self-executing test/test_main.rb, RSpec + Ruby stdlib only (no Gemfile/Bundler), the shared ReadableFormatter, and a coverage report printed after the run.

Results

✔  All 50 tests passed
main.rb  ████████████████████  100.0%  (70/70 lines)
merged from this process + 35 subprocess run(s)

What is covered

Both the positive and the negative path for every function in scope.

Function Happy path Negative / error branch
get_env_variable returns the value, strips surrounding whitespace missing key, empty string, whitespace-only → nil
run_command command string passed to system untouched, silent on success non-zero child status → @@[error] Unexpected exit with code N + SystemExit(0); nilTypeError
run_command_with_log logs @@[command], runs, prints took Ns failure exits 0 and never prints took; nilTypeError after logging; empty string
abort_with0 prints @@[error] <msg>, exits 0 empty and nil message still exit 0

Script-level behaviour, exercised by running main.rb in a subprocess:

  • Env validationAC_CACHE_LABEL, AC_TOKEN_ID and AC_CALLBACK_URL each have a missing and an empty test, asserting the @@[error] line, the deliberate exit code 0, and that the script stopped before doing any work. AC_REPOSITORY_DIR is asserted to be genuinely optional.
  • AC_CACHE_GET_URL — this variable is set by main.rb from the getUrl field of the signed-URL response rather than supplied by the user, so it is covered through the curl target it produces: value present, getUrl absent from the JSON, getUrl empty, and a stale pre-set value being overwritten. Both provider branches are covered, including AC_CACHE_PROVIDER unset (confirming nil.eql? is safe here).
  • Signed URL request — the composed ?action=getCacheUrls&cacheKey=…&tokenId=… query, empty response body skipping the download, and malformed JSON failing with a non-zero exit.
  • Download and restore — label sanitization, exit 0 when the archive is absent or zero bytes, the MD5 digest and its appended .md5 sidecar, the top-level unzip, and the nested-archive loop that maps a cached folder named after an AC_ directory variable back to that path.

No real side effects

Kernel#system and Net::HTTP.get are replaced in the child through a RUBYOPT-preloaded stub, so no unzip, curl, rm or mkdir is ever executed and no socket is opened. Stubbed calls are echoed to stdout, which is what lets the tests assert the exact composed command strings. All fixtures live in Dir.mktmpdir and the script is run with chdir pointed at it, so nothing is written outside a temp directory.

Every mutation tried against main.rb while validating the suite (exit 0exit 1, dropping --fail, loosening the label sanitizer, removing .strip, 'a''w' on the sidecar) was caught by at least one test.

Changes to main.rb

Only the if __FILE__ == $PROGRAM_NAME guard around the top-level script body, so the file can be required from the test. Reviewing with git diff -w shows the guard is the entire change — no logic, ordering or behaviour was touched. All four requires are stdlib, so no LoadError guards were needed.

Notes for the reviewer

Two pre-existing behaviours were found while writing the tests. Per the issue scope they are documented by the tests rather than changed, and are worth a look:

  1. A zip sitting directly in the cache folder (ac_cache/<label>/foo.zip, no folder segment) resolves base_path to "", so the restore runs unzip … -d / and mkdir -p with no operand. Same for a folder that is not a known AC_ variable, which resolves to an absolute /<name>/.
  2. unless ac_token_id.empty? (main.rb:66) can never be false — get_env_variable returns nil for an empty value and abort_with0 has already exited by that point.

How to run

gem install rspec   # once
ruby test/test_main.rb

🤖 Generated with Claude Code

Add test/test_main.rb covering every function in main.rb plus the script's
env-var validation and download/restore flow.

- get_env_variable, run_command, run_command_with_log and abort_with0 are
  tested in-process with Kernel#system stubbed, on both the happy path and
  the error branch (empty/nil input, non-zero child status, SystemExit).
- The full script runs in a subprocess with Kernel#system and Net::HTTP.get
  replaced through a RUBYOPT-preloaded stub, so no unzip/curl/rm/mkdir is
  ever executed, no network connection is opened and nothing is written
  outside a tmpdir. Stubbed calls are echoed so the composed command
  strings can be asserted.
- AC_CACHE_LABEL, AC_TOKEN_ID and AC_CALLBACK_URL each have a missing and an
  empty validation test; AC_CACHE_GET_URL is covered through the curl target
  it produces for both cache providers.
- A merged (in-process + subprocess) coverage report is printed after the run.

main.rb only gains the `if __FILE__ == $PROGRAM_NAME` guard around the
top-level script body so the file can be required; no logic is changed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 8, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 2beb4a5f-6856-487a-abad-f736a362051f


Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant