assertIsArray($referenceFiles, 'Unable to list .pro files in all-songs directory.'); sort($referenceFiles, SORT_STRING); $paths = []; foreach ($referenceFiles as $path) { if ($path === self::EMPTY_SKIP_FILE) { continue; } $bytes = @file_get_contents($path); $this->assertIsString($bytes, 'Unable to read file: ' . $path); if ($bytes === '') { $this->fail('Unexpected empty file not in skip list: ' . $path); } $paths[] = $path; } $paths[] = self::TEST_PRO_PATH; $this->assertCount( self::EXPECTED_NON_EMPTY_ALL_SONGS + 1, $paths, 'Expected 168 non-empty all-songs files plus Test.pro.' ); $failures = []; $byteIdenticalCount = 0; foreach ($paths as $path) { $original = @file_get_contents($path); $this->assertIsString($original, 'Unable to read file: ' . $path); $presentation = new Presentation(); try { $presentation->mergeFromString($original); } catch (\Throwable $throwable) { $failures[] = [ 'path' => $path, 'reason' => 'decode_error', 'message' => $throwable->getMessage(), ]; continue; } $reencoded = $presentation->serializeToString(); if ($original === $reencoded) { $byteIdenticalCount++; } $roundTrip = new Presentation(); try { $roundTrip->mergeFromString($reencoded); } catch (\Throwable $throwable) { $failures[] = [ 'path' => $path, 'reason' => 'reencode_decode_error', 'message' => $throwable->getMessage(), ]; continue; } $originalJson = json_decode($presentation->serializeToJsonString(), true); $roundTripJson = json_decode($roundTrip->serializeToJsonString(), true); if ($originalJson !== $roundTripJson) { $failures[] = [ 'path' => $path, 'reason' => 'semantic_mismatch', ]; } } $total = count($paths); $mismatchCount = count($failures); $testProIdentical = !in_array(self::TEST_PRO_PATH, array_column($failures, 'path'), true); $message = "Round-trip results: {$byteIdenticalCount}/{$total} byte-identical, {$mismatchCount} semantic/decode failures. Test.pro byte-identical: " . ($testProIdentical ? 'yes' : 'no') . '.'; if ($mismatchCount > 0) { $message .= "\nDetails:\n" . json_encode($failures, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); } $this->assertSame([], $failures, $message); } }