Skip to content

Commit 6614958

Browse files
authored
Fix flaky uplc-evaluator integration tests (#7557)
Two issues caused intermittent test failures on CI: 1. Race condition in result file reading: Tests detected file existence before service finished writing, causing JSON parse errors ("Unexpected end-of-input"). Fixed by using atomic writes - write to a temp file first, then rename to final path. 2. Overly strict timing assertions: Very fast evaluations (especially in CI environments) can complete in <1ns, causing cpu_time_ns=0. Relaxed assertions from `> 0` to `>= 0` since 0ns is legitimate for trivial programs.
1 parent 48cc3a0 commit 6614958

File tree

2 files changed

+16
-11
lines changed

2 files changed

+16
-11
lines changed

plutus-benchmark/uplc-evaluator/Main.hs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -398,14 +398,16 @@ processProgram Config {..} inputPath = do
398398
`catch` \(e :: SomeException) ->
399399
hPutStrLn stderr $ "Failed to rename file: " ++ show e
400400

401-
-- | Write successful result to JSON file
401+
-- | Write successful result to JSON file (atomic write via temp file)
402402
writeResult :: FilePath -> EvalResult -> IO ()
403403
writeResult outputDir result = do
404404
let outputPath = outputDir </> T.unpack (erProgramId result) ++ ".result.json"
405-
BSL.writeFile outputPath (Aeson.encode result)
405+
tempPath = outputPath ++ ".tmp"
406+
BSL.writeFile tempPath (Aeson.encode result)
407+
renameFile tempPath outputPath
406408
hPutStrLn stderr $ "Wrote result: " ++ outputPath
407409

408-
-- | Write error result to JSON file
410+
-- | Write error result to JSON file (atomic write via temp file)
409411
writeError :: FilePath -> Text -> Text -> Text -> IO ()
410412
writeError outputDir programId errorType errorMessage = do
411413
let evalError =
@@ -416,7 +418,9 @@ writeError outputDir programId errorType errorMessage = do
416418
, eeErrorMessage = errorMessage
417419
}
418420
outputPath = outputDir </> T.unpack programId ++ ".error.json"
419-
BSL.writeFile outputPath (Aeson.encode evalError)
421+
tempPath = outputPath ++ ".tmp"
422+
BSL.writeFile tempPath (Aeson.encode evalError)
423+
renameFile tempPath outputPath
420424
hPutStrLn stderr $ "Wrote error: " ++ outputPath
421425

422426
-- | Main evaluation loop

plutus-benchmark/uplc-evaluator/test/Spec.hs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -98,13 +98,14 @@ main = withUtf8 do
9898
("timing_samples should have 10-20 entries, got " ++ show sampleCount)
9999
(sampleCount >= 10 && sampleCount <= 20)
100100

101-
-- Verify each timing sample has positive cpu_time_ns
101+
-- Verify each timing sample has non-negative cpu_time_ns
102+
-- Note: Very fast evaluations can report 0ns due to measurement resolution
102103
mapM_
103104
( \s -> do
104-
-- Check that cpu_time_ns is in reasonable range
105+
-- Check that cpu_time_ns is in reasonable range (>= 0, bounded above)
105106
assertBool
106-
("cpu_time_ns should be > 0, got " ++ show (tsCpuTimeNs s))
107-
(tsCpuTimeNs s > 0)
107+
("cpu_time_ns should be >= 0, got " ++ show (tsCpuTimeNs s))
108+
(tsCpuTimeNs s >= 0)
108109
)
109110
(erTimingSamples result)
110111

@@ -555,13 +556,13 @@ main = withUtf8 do
555556
(erMemoryBytes result > 0)
556557

557558
-- cpu_time_ns values may vary (timing is non-deterministic)
558-
-- We just verify they exist and are positive
559+
-- We verify they exist and are non-negative (can be 0 for very fast evaluations)
559560
let cpuTimes = map tsCpuTimeNs samples
560561
mapM_
561562
( \t ->
562563
assertBool
563-
("cpu_time_ns should be > 0, got " ++ show t)
564-
(t > 0)
564+
("cpu_time_ns should be >= 0, got " ++ show t)
565+
(t >= 0)
565566
)
566567
cpuTimes
567568
]

0 commit comments

Comments
 (0)