Skip to content

Fixed simulate diff mode aborting on repeated unversioned package installs - #6424

Open
djbclark wants to merge 1 commit into
cfengine:masterfrom
djbclark:fix/simulate-pkg-unversioned-install-assert
Open

djbclark wants to merge 1 commit into
cfengine:masterfrom
djbclark:fix/simulate-pkg-unversioned-install-assert

Conversation

@djbclark

Copy link
Copy Markdown
Contributor

--simulate=diff aborted an assert-enabled cf-agent when the same package was recorded as installed twice without a version: DiffPkgOperations() passed the two empty versions to PkgVersionIsGreater(), which asserts both non-empty. ManifestPkgOperations() already guards that comparison; the diff branch now uses the same guard and keeps the same record (versioned over unversioned, otherwise the higher version, otherwise the first). Release builds compile the assert out and already picked the same record, so nothing changes for them. Two unit tests; the first aborts on the unguarded code (library built with asserts on):

$ tests/unit/simulate_mode_test      # without the fix
test_diff_repeated_unversioned_install: Starting test
simulate_mode_test: simulate_mode.c:676: PkgVersionIsGreater: Assertion `!NULL_OR_EMPTY(ver1) && !NULL_OR_EMPTY(ver2)' failed.
Aborted
$ tests/unit/simulate_mode_test      # with the fix
test_diff_repeated_unversioned_install: Test completed successfully.
test_diff_unversioned_then_versioned_install: Test completed successfully.
All 7 tests passed

Ubuntu 24.04 (--enable-debug): make -C tests/unit check → All 76 tests passed; tests/acceptance/29_simulate_mode/ as root → 4 of 4 Pass. Fork CI: djbclark#45

AI-assisted. I can't vouch for the C syntax beyond a basic level, but I did look at the logic and it seemed sound.

🤖 Generated with Claude Code

@cf-bottom

Copy link
Copy Markdown

Thanks for submitting a PR! Maybe @larsewi can review this?

@larsewi larsewi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution 🚀 Could you also add tests for:

  • Two unversioned, reported once
  • An unversioned record never replaces an existing one
  • A versioned record replaces a unversioned one
  • First is higher version, keep first
  • Last is higher version, keep last
  • Same version, reported once

Comment thread cf-agent/simulate_mode.c
}

return msg;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe you could break this up a bit so that it is easier to read for a human? E.g.:

Suggested change
}
static bool PkgRecordShouldBeReplaced(const PkgOperationRecord *prev_record,
const char *new_ver)
{
if (prev_record == NULL)
{
/* Nothing recorded yet */
return true;
}
if (NULL_OR_EMPTY(new_ver))
{
/* An unversioned record never replaces an existing one */
return false;
}
if (NULL_OR_EMPTY(prev_record->pkg_ver))
{
/* A versioned record is more specific than an unversioned one */
return true;
}
/* Both are versioned, keep the higher version */
return PkgVersionIsGreater(new_ver, prev_record->pkg_ver);
}

Then use this function as the if condition.

assert_true(call_with_captured_stdout(&DiffPkgOperations, output, sizeof(output)));

const char *msg = "Package 'foo' would be installed";
const char *first = strstr(output, msg);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you replace the strstr() function calls with StringContains from string_lib.h?

…talls

DiffPkgOperations() compared the versions of two recorded installations
of the same package without checking that both were set, which
PkgVersionIsGreater() asserts. The diff report now keeps the record the
way the manifest report does: a versioned record over an unversioned
one, otherwise the higher version, otherwise the first one recorded.

Ticket: none
Changelog: Title
Signed-off-by: Daniel JB Clark <djbclark@gmail.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@djbclark
djbclark force-pushed the fix/simulate-pkg-unversioned-install-assert branch from d5052b7 to fdad2cd Compare November 3, 2026 11:23
@djbclark

djbclark commented Nov 3, 2026

Copy link
Copy Markdown
Contributor Author

Added unit tests for all requested cases in simulate_mode_test.c:

  • Two unversioned, reported once (test_diff_repeated_unversioned_install)
  • An unversioned record never replaces an existing one (test_diff_versioned_then_unversioned_install)
  • A versioned record replaces an unversioned one (test_diff_unversioned_then_versioned_install)
  • First is higher version, keep first (test_diff_install_higher_version_first_keeps_first)
  • Last is higher version, keep last (test_diff_install_higher_version_last_keeps_last)
  • Same version, reported once (test_diff_repeated_versioned_install)

@djbclark

djbclark commented Nov 3, 2026 via email

Copy link
Copy Markdown
Contributor Author

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

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants