1818import com .aws .greengrass .logging .impl .GreengrassLogMessage ;
1919import com .aws .greengrass .logging .impl .Slf4jLogAdapter ;
2020import com .aws .greengrass .status .model .ComponentStatusDetails ;
21+ import com .aws .greengrass .testcommons .testutilities .GGExtension ;
2122import com .aws .greengrass .testcommons .testutilities .NoOpPathOwnershipHandler ;
2223import com .aws .greengrass .util .Pair ;
23- import com .aws .greengrass .util .platforms .unix .linux .Cgroup ;
24- import com .aws .greengrass .util .platforms .unix .linux .LinuxSystemResourceController ;
24+ import com .aws .greengrass .util .platforms .unix .linux .CgroupManager ;
25+ import com .aws .greengrass .util .platforms .unix .linux .CgroupV1 ;
26+ import com .aws .greengrass .util .platforms .unix .linux .CgroupV2 ;
2527import org .apache .commons .lang3 .SystemUtils ;
2628import org .junit .jupiter .api .AfterEach ;
2729import org .junit .jupiter .api .BeforeEach ;
28- import org .junit .jupiter .api .Disabled ;
2930import org .junit .jupiter .api .Test ;
3031import org .junit .jupiter .api .condition .EnabledOnOs ;
3132import org .junit .jupiter .api .condition .OS ;
33+ import org .junit .jupiter .api .extension .ExtendWith ;
3234import org .junit .jupiter .api .extension .ExtensionContext ;
3335import org .junit .jupiter .params .ParameterizedTest ;
3436import org .junit .jupiter .params .provider .Arguments ;
3537import org .junit .jupiter .params .provider .MethodSource ;
38+ import org .mockito .junit .jupiter .MockitoExtension ;
3639
3740import java .io .IOException ;
3841import java .nio .charset .StandardCharsets ;
3942import java .nio .file .FileSystemException ;
4043import java .nio .file .Files ;
4144import java .nio .file .Path ;
45+ import java .nio .file .Paths ;
4246import java .util .ArrayList ;
4347import java .util .List ;
4448import java .util .concurrent .CompletableFuture ;
6468import static com .aws .greengrass .testcommons .testutilities .TestUtils .createCloseableLogListener ;
6569import static com .aws .greengrass .util .platforms .unix .UnixPlatform .STDOUT ;
6670import static org .hamcrest .MatcherAssert .assertThat ;
67- import static org .hamcrest .Matchers .anyOf ;
6871import static org .hamcrest .Matchers .contains ;
6972import static org .hamcrest .Matchers .containsString ;
7073import static org .hamcrest .Matchers .equalTo ;
8386import static org .mockito .Mockito .times ;
8487import static org .mockito .Mockito .verify ;
8588
86-
89+ @ ExtendWith ({ GGExtension . class , MockitoExtension . class })
8790class GenericExternalServiceIntegTest extends BaseITCase {
8891
8992 private Kernel kernel ;
@@ -581,7 +584,6 @@ void GIVEN_bootstrap_command_WHEN_runs_longer_than_5_sec_THEN_timeout_exception_
581584 assertThrows (TimeoutException .class , serviceWithJustBootstrapAndShouldTimeout ::bootstrap );
582585 }
583586
584- @ Disabled
585587 @ EnabledOnOs ({OS .LINUX , OS .MAC })
586588 @ ParameterizedTest
587589 @ MethodSource ("posixTestUserConfig" )
@@ -637,10 +639,12 @@ void GIVEN_posix_default_user_WHEN_runs_THEN_runs_with_default_user(String file,
637639 }
638640 }
639641
640- @ Disabled
641642 @ EnabledOnOs ({OS .LINUX })
642643 @ Test
643644 void GIVEN_linux_resource_limits_WHEN_it_changes_THEN_component_runs_with_new_resource_limits () throws Exception {
645+ // Skip test if no proper access available (required for cgroup access)
646+ assumeTrue ("root" .equals (SystemUtils .USER_NAME ), "Test requires root access for cgroup management" );
647+
644648 String componentName = "echo_service" ;
645649 // Run with no resource limit
646650 ConfigPlatformResolver .initKernelWithMultiPlatformConfig (kernel ,
@@ -818,20 +822,38 @@ void GIVEN_service_starts_up_WHEN_startup_times_out_THEN_timeout_error_code_pers
818822 }
819823
820824 private void assertResourceLimits (String componentName , long memory , double cpus ) throws Exception {
821- byte [] buf1 = Files .readAllBytes (Cgroup .Memory .getComponentMemoryLimitPath (componentName ));
822- assertThat (memory , equalTo (Long .parseLong (new String (buf1 , StandardCharsets .UTF_8 ).trim ())));
823-
824- byte [] buf2 = Files .readAllBytes (Cgroup .CPU .getComponentCpuQuotaPath (componentName ));
825- byte [] buf3 = Files .readAllBytes (Cgroup .CPU .getComponentCpuPeriodPath (componentName ));
826-
827- int quota = Integer .parseInt (new String (buf2 , StandardCharsets .UTF_8 ).trim ());
828- int period = Integer .parseInt (new String (buf3 , StandardCharsets .UTF_8 ).trim ());
825+ int quota ;
826+ int period ;
827+
828+ if (isCgroupV2Supported ()) {
829+ byte [] buf1 = Files .readAllBytes (CgroupV2 .Memory .getComponentMemoryLimitPath (componentName ));
830+ assertThat (memory , equalTo (Long .parseLong (new String (buf1 , StandardCharsets .UTF_8 ).trim ())));
831+
832+ byte [] buf2 = Files .readAllBytes (CgroupV2 .CPU .getComponentCpuLimitPath (componentName ));
833+ String cpuMax = new String (buf2 , StandardCharsets .UTF_8 ).trim ();
834+ String [] parts = cpuMax .split (" " );
835+ quota = Integer .parseInt (parts [0 ]);
836+ period = Integer .parseInt (parts [1 ]);
837+ } else {
838+ byte [] buf1 = Files .readAllBytes (CgroupV1 .Memory .getComponentMemoryLimitPath (componentName ));
839+ assertThat (memory , equalTo (Long .parseLong (new String (buf1 , StandardCharsets .UTF_8 ).trim ())));
840+
841+ byte [] buf2 = Files .readAllBytes (CgroupV1 .CPU .getComponentCpuQuotaPath (componentName ));
842+ byte [] buf3 = Files .readAllBytes (CgroupV1 .CPU .getComponentCpuPeriodPath (componentName ));
843+
844+ quota = Integer .parseInt (new String (buf2 , StandardCharsets .UTF_8 ).trim ());
845+ period = Integer .parseInt (new String (buf3 , StandardCharsets .UTF_8 ).trim ());
846+ }
847+
829848 int expectedQuota = (int ) (cpus * period );
830849 assertThat (expectedQuota , equalTo (quota ));
831850 }
832851
852+ @ Test
853+ @ EnabledOnOs ({OS .LINUX })
833854 void GIVEN_running_service_WHEN_pause_resume_requested_THEN_pause_resume_Service_and_freeze_thaw_cgroup (
834855 ExtensionContext context ) throws Exception {
856+ assumeTrue ("root" .equals (SystemUtils .USER_NAME ), "Test requires root access for cgroup management" );
835857 ignoreExceptionOfType (context , FileSystemException .class );
836858 ConfigPlatformResolver .initKernelWithMultiPlatformConfig (kernel ,
837859 getClass ().getResource ("long_running_services.yaml" ));
@@ -852,21 +874,17 @@ void GIVEN_running_service_WHEN_pause_resume_requested_THEN_pause_resume_Service
852874
853875 component .pause ();
854876 assertTrue (component .isPaused ());
855- assertThat (getCgroupFreezerState (component .getServiceName ()),
856- anyOf (is (LinuxSystemResourceController .CgroupFreezerState .FROZEN ),
857- is (LinuxSystemResourceController .CgroupFreezerState .FREEZING )));
877+
878+ // check if component is frozen
879+ CgroupManager freezerManager = isCgroupV2Supported () ? CgroupV2 .Freezer : CgroupV1 .Freezer ;
880+ assertTrue (freezerManager .isComponentFrozen (component .getServiceName ()));
858881
859882 component .resume ();
860883 assertFalse (component .isPaused ());
861- assertThat (getCgroupFreezerState (component .getServiceName ()),
862- is (LinuxSystemResourceController .CgroupFreezerState .THAWED ));
884+ assertFalse (freezerManager .isComponentFrozen (component .getServiceName ()));
863885 }
864886
865- // To be used on linux only
866- private LinuxSystemResourceController .CgroupFreezerState getCgroupFreezerState (String serviceName )
867- throws IOException {
868- return LinuxSystemResourceController .CgroupFreezerState
869- .valueOf (new String (Files .readAllBytes (Cgroup .Freezer .getCgroupFreezerStateFilePath (serviceName ))
870- , StandardCharsets .UTF_8 ).trim ());
887+ private boolean isCgroupV2Supported () {
888+ return Files .exists (Paths .get ("/sys/fs/cgroup/cgroup.controllers" ));
871889 }
872890}
0 commit comments