@@ -14,6 +14,8 @@ import (
1414 snapshotstore "github.com/kernel/hypeman/lib/snapshot"
1515 "github.com/stretchr/testify/assert"
1616 "github.com/stretchr/testify/require"
17+ otelmetric "go.opentelemetry.io/otel/sdk/metric"
18+ "go.opentelemetry.io/otel/sdk/metric/metricdata"
1719)
1820
1921func TestNormalizeCompressionConfig (t * testing.T ) {
@@ -433,6 +435,101 @@ func newSnapshotCompressionTestManager(t *testing.T) *manager {
433435 }
434436}
435437
438+ func TestStartCompressionJobSkipsFirecrackerStandbySharedMemory (t * testing.T ) {
439+ mgr := newSnapshotCompressionTestManager (t )
440+ reader := otelmetric .NewManualReader ()
441+ provider := otelmetric .NewMeterProvider (otelmetric .WithReader (reader ))
442+ metrics , err := newInstanceMetrics (provider .Meter ("test" ), nil , mgr )
443+ require .NoError (t , err )
444+ mgr .metrics = metrics
445+
446+ snapshotDir := t .TempDir ()
447+ rawPath := filepath .Join (snapshotDir , "memory" )
448+ require .NoError (t , os .WriteFile (rawPath , []byte ("shared firecracker standby memory" ), 0o644 ))
449+
450+ mgr .sharingInspector = func (path string ) (snapshotMemorySharing , error ) {
451+ assert .Equal (t , rawPath , path )
452+ return snapshotMemorySharing {SharedBytes : 1024 , PrivateBytes : 512 }, nil
453+ }
454+
455+ target := compressionTarget {
456+ Key : "instance:shared-firecracker" ,
457+ OwnerID : "shared-firecracker" ,
458+ SnapshotDir : snapshotDir ,
459+ HypervisorType : hypervisor .TypeFirecracker ,
460+ Source : snapshotCompressionSourceStandby ,
461+ Policy : snapshotstore.SnapshotCompressionConfig {
462+ Enabled : true ,
463+ Algorithm : snapshotstore .SnapshotCompressionAlgorithmZstd ,
464+ Level : intPtr (1 ),
465+ },
466+ }
467+
468+ mgr .startCompressionJob (context .Background (), target )
469+
470+ require .Eventually (t , func () bool {
471+ mgr .compressionMu .Lock ()
472+ defer mgr .compressionMu .Unlock ()
473+ _ , ok := mgr .compressionJobs [target .Key ]
474+ return ! ok
475+ }, time .Second , 10 * time .Millisecond )
476+
477+ _ , err = os .Stat (rawPath )
478+ require .NoError (t , err , "shared raw memory should remain uncompressed" )
479+ _ , err = os .Stat (rawPath + ".zst" )
480+ require .Error (t , err )
481+ assert .True (t , os .IsNotExist (err ))
482+
483+ var rm metricdata.ResourceMetrics
484+ require .NoError (t , reader .Collect (t .Context (), & rm ))
485+ jobsMetric := findMetric (t , rm , "hypeman_snapshot_compression_jobs_total" )
486+ jobs , ok := jobsMetric .Data .(metricdata.Sum [int64 ])
487+ require .True (t , ok )
488+ require .Len (t , jobs .DataPoints , 1 )
489+ assert .Equal (t , "skipped" , metricLabel (t , jobs .DataPoints [0 ].Attributes , "result" ))
490+ assert .Equal (t , "shared_extents" , metricLabel (t , jobs .DataPoints [0 ].Attributes , "reason" ))
491+ }
492+
493+ func TestStartCompressionJobDoesNotSkipNonFirecrackerSharedMemory (t * testing.T ) {
494+ mgr := newSnapshotCompressionTestManager (t )
495+
496+ snapshotDir := t .TempDir ()
497+ rawPath := filepath .Join (snapshotDir , "memory" )
498+ require .NoError (t , os .WriteFile (rawPath , []byte ("cloud hypervisor memory" ), 0o644 ))
499+
500+ mgr .sharingInspector = func (string ) (snapshotMemorySharing , error ) {
501+ return snapshotMemorySharing {SharedBytes : 1024 }, nil
502+ }
503+
504+ target := compressionTarget {
505+ Key : "instance:shared-cloud-hypervisor" ,
506+ OwnerID : "shared-cloud-hypervisor" ,
507+ SnapshotDir : snapshotDir ,
508+ HypervisorType : hypervisor .TypeCloudHypervisor ,
509+ Source : snapshotCompressionSourceStandby ,
510+ Policy : snapshotstore.SnapshotCompressionConfig {
511+ Enabled : true ,
512+ Algorithm : snapshotstore .SnapshotCompressionAlgorithmZstd ,
513+ Level : intPtr (1 ),
514+ },
515+ }
516+
517+ mgr .startCompressionJob (context .Background (), target )
518+
519+ require .Eventually (t , func () bool {
520+ mgr .compressionMu .Lock ()
521+ defer mgr .compressionMu .Unlock ()
522+ _ , ok := mgr .compressionJobs [target .Key ]
523+ return ! ok
524+ }, time .Second , 10 * time .Millisecond )
525+
526+ _ , err := os .Stat (rawPath )
527+ require .Error (t , err )
528+ assert .True (t , os .IsNotExist (err ))
529+ _ , _ , compressed := findCompressedSnapshotMemoryFile (snapshotDir )
530+ assert .True (t , compressed )
531+ }
532+
436533func TestStartCompressionJobDelayedCancellationRecordsSkipped (t * testing.T ) {
437534 t .Parallel ()
438535
0 commit comments