CNA-BUG-201: StorageDeviceDeleteContainerTest writes to and deletes inside the developer's real per-user data directory

CNA snapshot 009d40f5  ·  Known Issues › Current bugs  ·  source links pinned to 009d40f5

✓

Evidence basis: source-verified at the pinned commit; tests exist (not executed for this page). Claims on this page were checked by reading the CNA source at commit 009d40f5; unless a sentence says otherwise, nothing here was built or executed. Nothing on this page was executed unless the Evidence section says so.

The StorageDevice deletion tests resolve their fixture root from the real XDG_DATA_HOME/LOCALAPPDATA/HOME environment, remove_all() it in TearDown, and then recreate the default game's save directory, while a comment still reasons about an SDL preference path.

Identifier
CNA-BUG-201
Category
Bug
Subsystem
Testing & evidence
Status
Open
Verified against
CNA 009d40f5 (009d40f5dd085c4e674d3479675fac84b12b3e0a)
Severity
Low (a triage suggestion, not a project priority)
Evidence basis
Source-verified: read at TARGET, not executed
Tests touching this area
Yes: see Current tests
Affected contract
StorageDeviceDeleteContainerTest fixture (SetUp, TearDown) in CnaTests

Expected behaviour

The fixture's own comment promises that every test is isolated “to its own real, disposable storage root” and avoids “the real user's storage state”. A test should therefore run inside a sandbox it creates (a temporary directory named through the environment variables StorageDevice reads) and leave nothing behind.

Actual behaviour at TARGET

SetUp sets the application name CnaTestsContent002StorageDevice and takes the root StorageDevice::EnsureStorageRoot resolves from the caller's real environment (XDG_DATA_HOME, LOCALAPPDATA, HOME, else the working directory). TearDown calls std::filesystem::remove_all on it and then SetAppNameEXT(""), which re-resolves the root for the default application name game and creates <data root>/game: the directory every CNA game without an application name saves into. The CnaTests registration sets no storage environment, and concurrent test processes share the fixed directory. The comment in EscapingTitleNameThrowsAndDeletesNothing still justifies its escape path with “a SDL pref-path directory is always several levels deep”, which no longer describes the root.

Source locations

Evidence

Checked by reading StorageDeviceTests.cpp and StorageDevice.cpp at 009d40f5. The escape assertions stay valid, because extra .. segments stop at the filesystem root; the problem is where the fixture writes, not what it asserts. Not executed.

Independently observed as a separate finding (merged): StorageDeviceDeleteContainerTest and GamerServicesStoreGuard use fixed application names under the real per-user data root, delete their directories and leave others behind, because the CnaTests registration sets no storage environment.

Focused reproduction

Illustrative: with XDG_DATA_HOME unset on Linux, run CnaTests --gtest_filter=StorageDeviceDeleteContainerTest.*; afterwards ~/.local/share/game exists even if it did not before.

Current tests

The fixture itself is the affected code. GamerServicesGamerTests.cpp' store guard, which the fixture cites as its model, is not part of this entry.

Regression test

Make the fixture point XDG_DATA_HOME (and LOCALAPPDATA on Windows) at a fresh temporary directory before the first SetAppNameEXT, restore the previous values afterwards, and assert that the real data root is untouched.

Blast radius

Developers and CI hosts that run CnaTests without redirecting the data root: an empty game directory appears in the real per-user data directory, and parallel test processes race on one fixed directory. The storage implementation itself is not affected.

Workaround

Run CnaTests with XDG_DATA_HOME (Linux) or LOCALAPPDATA (Windows) pointing at a throw-away directory.

The same subject is explained at several altitudes. These are the neighbouring pages at each one.

Tests and validation
Testing: recipes
Known issues
Bug index