Skip to content

test: add unit tests for rez.utils.base26 - #2156

Open
darrenhuai wants to merge 1 commit into
AcademySoftwareFoundation:mainfrom
darrenhuai:test/utils-base26-coverage
Open

test: add unit tests for rez.utils.base26#2156
darrenhuai wants to merge 1 commit into
AcademySoftwareFoundation:mainfrom
darrenhuai:test/utils-base26-coverage

Conversation

@darrenhuai

@darrenhuai darrenhuai commented Jul 19, 2026

Copy link
Copy Markdown

rez.utils.base26 had no tests at all - get_next_base26 (the letter-increment logic for variant shortlink IDs) and create_unique_base26_symlink were both uncovered.

Tests for get_next_base26 cover the increment/rollover cases directly (a->b, z->aa, az->ba, zz->aaa, etc) and invalid input. For create_unique_base26_symlink I mocked the filesystem calls (os.listdir, os.symlink, find_matching_symlink) instead of creating real symlinks, since that needs elevated privileges on Windows without Developer Mode - this still covers the existing-match short circuit, picking the next id after the highest existing one, the EEXIST retry-on-race path, non-EEXIST errors propagating, and giving up after too much contention.

Ran the full suite locally (332 passed), flake8 and ruff clean on the new file.

Refs #2092


Disclosure: Claude (Sonnet 5) was used to assist in writing the test code and drafting this commit message and PR description.

get_next_base26 and create_unique_base26_symlink had no dedicated
tests. Covers the letter-increment/rollover logic directly, and the
symlink creation/collision-retry logic via mocks (real symlink
creation needs elevated privileges on some platforms, e.g. Windows
without Developer Mode, so the filesystem boundary is mocked instead).

Refs AcademySoftwareFoundation#2092

Signed-off-by: darrenhuai <60621295+darrenhuai@users.noreply.github.com>
@darrenhuai
darrenhuai requested a review from a team as a code owner July 19, 2026 23:46
@linux-foundation-easycla

linux-foundation-easycla Bot commented Jul 19, 2026

Copy link
Copy Markdown

CLA Signed
The committers listed above are authorized under a signed CLA.

  • ✅ login: darrenhuai / name: darrenhuai (47fe68d)

@maxnbk

maxnbk commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Hi @darrenhuai , thank you for the testing contribs.
Were these (this and previous PR) generated using LLMs?
If so, we need a disclosure in the PR title stating the LLM used and what they were used for.
This is in response to ASWF TAC discussions and will be added to our CONTRIBUTING.md shortly.
Thank you.

@codecov

codecov Bot commented Jul 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 61.34%. Comparing base (3a50d1b) to head (47fe68d).
⚠️ Report is 6 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2156      +/-   ##
==========================================
+ Coverage   61.29%   61.34%   +0.04%     
==========================================
  Files         164      164              
  Lines       20568    20568              
  Branches     3575     3575              
==========================================
+ Hits        12607    12617      +10     
+ Misses       7089     7081       -8     
+ Partials      872      870       -2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@darrenhuai

Copy link
Copy Markdown
Author

Yes, both PRs were AI-assisted. Claude assisted in writing the test code, and drafting the commit messages and PR descriptions. I reviewed the diffs and the test/lint output before pushing each one and made the call on what to ship. Happy to add a disclosure to the PR title, is there a format you'd prefer, since the policy isn't finalized yet? Thank you!

@maxnbk

maxnbk commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

@darrenhuai Something as simple as what I'm putting on my PRs is fine for now, like this, in the PR description (not the title):

Disclosure: GLM-5.2 was used to assist in diagnostics, docstring, and test-writing. Or something to that effect.

Just to explain (as a point of reference), we're not barring LLM-generated code, it's just so that we the maintainers can:

  1. Review MRs better, because humans and LLMs tend to make different kinds of mistakes that can require different attitudes when evaluating
  2. Understand better how much LLM usage is helping devs/maintainers work on the project.

@darrenhuai

Copy link
Copy Markdown
Author

perfect thank you! will do so

@maxnbk maxnbk added this to the Next milestone Jul 22, 2026

@JeanChristopheMorinPerso JeanChristopheMorinPerso left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I threw a coding agent at your PR and it found two bugs in base26.py that would be very easy to fix in this PR if you want. I don't consider these blocking as they are probably corner cases.

Comment on lines +70 to +77
"os.listdir", return_value=['a', 'b', 'c']
), patch(
"os.path.islink", return_value=True
), patch("os.symlink") as symlink:
result = create_unique_base26_symlink("/pkgs", "/source/2.0")

symlink.assert_called_once_with("/source/2.0", result)
self.assertTrue(result.endswith('d'))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
"os.listdir", return_value=['a', 'b', 'c']
), patch(
"os.path.islink", return_value=True
), patch("os.symlink") as symlink:
result = create_unique_base26_symlink("/pkgs", "/source/2.0")
symlink.assert_called_once_with("/source/2.0", result)
self.assertTrue(result.endswith('d'))
"os.listdir", return_value=['a', 'b', 'c', 'z', 'aa']
), patch(
"os.path.islink", return_value=True
), patch("os.symlink") as symlink:
result = create_unique_base26_symlink("/pkgs", "/source/2.0")
symlink.assert_called_once_with("/source/2.0", result)
self.assertTrue(result.endswith('ab'))

Doing this will highlight that there's actually a bug in create_unique_base26_symlink. max(names) should be replaced with max(names, key=lambda x: (len(x), x)).

That's because:

>>> max(['z', 'aa'])
'z'

In other words, the tests have full coverage purely in terms of code, but not in terms of logic.

Comment on lines +35 to +37
for bad in ('A', 'a1', 'a-b', ' a', 'a '):
with self.assertRaises(ValueError):
get_next_base26(bad)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
for bad in ('A', 'a1', 'a-b', ' a', 'a '):
with self.assertRaises(ValueError):
get_next_base26(bad)
for bad in ('A', 'a1', 'a-b', ' a', 'a '):
with self.subTest(item=bad):
with self.assertRaises(ValueError):
get_next_base26(bad)

This will more clearly show that we are testing multiple things.

ALso, note how there's a but in the get_next_base26 where it accepts a trailing \n. We should replace match with fullmatch.

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.

3 participants