Closed G-Rath closed 7 months ago
it seems like this also might impact the general writing/updating of snapshots - I've been finding while working on https://github.com/google/osv-scanner/pull/889 that I have to run the suite twice to ensure all snapshots are updated
Hey 👋 sorry I have been off sick. But will have a look asap when I am back. Thanks for the investigation and creating this issue.
Hey no worries - you focus on getting better :)
For now I've written a python script that ill post shortly to do the sorting and cleanup which seems to be working well
Hey I am partially back 😄 . I have rewritten this message three times thinking i knew what the problem is 😅 This time I think I know. I think the problem lies at https://github.com/gkampitakis/go-snaps/blob/main/snaps/snapshot.go#L131 not being protected with a lock. Will try to verify my theory the coming days and create a pr if you want to test it with. Needs some thinking the way I am handling locking there.
Again thank you for opening this issue and sorry for the inconvenience.
awesome stuff! fwiw this is the Python script I wrote:
#!/usr/bin/env python
import glob
import re
def deduplicate_snapshots(snapshots):
by_name = {}
for snapshot in snapshots:
if snapshot[1] in by_name:
are_identical = len(snapshot) == len(by_name[snapshot[1]]) and [
i for i, j in zip(snapshot, by_name[snapshot[1]]) if i == j
]
print(
" removed duplicate of",
snapshot[1].strip(),
"(were identical)" if are_identical else "",
)
continue
by_name[snapshot[1]] = snapshot
return by_name.values()
def sort_snapshots(snapshots):
return sorted(
snapshots,
key=lambda lines: [
int(x) if x.isdigit() else x for x in re.split(r"(\d+)", lines[1])
],
)
def sort_snapshots_in_file(filename):
snapshots = []
snapshot = []
with open(filename, "r") as f:
for line in f.readlines():
if line == "---\n": # marks the start of a new snapshot
snapshots.append(snapshot)
snapshot = []
else:
snapshot.append(line)
print("found", len(snapshots), "snapshots in", filename)
snapshots = deduplicate_snapshots(snapshots)
snapshots = sort_snapshots(snapshots)
if filename.endswith("v_test.snap") or filename.endswith("v_test2.snap"):
return
with open(filename, "w") as f:
for snapshot in snapshots:
f.writelines(snapshot)
f.writelines("---\n")
for snapshot_file in glob.iglob("**/__snapshots__/*.snap", recursive=True):
sort_snapshots_in_file(snapshot_file)
(I want to share it somewhere since it won't even need to go into a PR now 😅)
Sorry for the need of the script. Hope the change solves this problem 😄 Feel free to reopen the issue if you still notice an error.
Description
It seems there's a race condition with cleaning up snapshots when using parallel tests that means if a snapshot changes there's a chance any of the snapshots in the same file could be duplicates, moved around, etc.
Steps to Reproduce
Run with
UPDATE_SNAPS=true go test ./...
:Running it multiple times will compound the result:
Note that you can reproduce this without the looping, it just makes it a lot easier - but importantly my
TestMain
here is not interfering with the cleanup function.Commenting out the
t.Parallel
calls resolves the issueExpected Behavior
The snapshot order is stable, and snapshots are not duplicated.