Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@
import com.aws.greengrass.util.Coerce;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.SystemUtils;
import org.hamcrest.collection.IsMapContaining;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledOnOs;
import org.junit.jupiter.api.condition.OS;
Expand Down Expand Up @@ -85,6 +85,7 @@
import static org.hamcrest.Matchers.equalTo;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;

Expand Down Expand Up @@ -325,10 +326,10 @@ void GIVEN_deployment_with_large_config_WHEN_receives_deployment_THEN_deployment
assertThat(resultConfig, IsMapContaining.hasEntry("willBeNullKey", null));
}

@Disabled
@Test
@EnabledOnOs(OS.LINUX)
void GIVEN_deployment_with_system_resource_WHEN_receives_deployment_THEN_deployment_succeeds() throws Exception {
assumeTrue("root".equals(SystemUtils.USER_NAME), "Test requires root access for cgroup management");
CountDownLatch deploymentFinished = new CountDownLatch(1);
Consumer<GreengrassLogMessage> listener = m -> {
if (m.getMessage() != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,14 @@
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.vdurmont.semver4j.Semver;
import org.apache.commons.lang3.SystemUtils;
import org.hamcrest.Matchers;
import org.hamcrest.collection.IsMapContaining;
import org.hamcrest.collection.IsMapWithSize;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -126,6 +126,7 @@
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import static org.junit.jupiter.api.Assumptions.assumeTrue;

@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@SuppressWarnings("PMD.ExcessiveClassLength")
Expand Down Expand Up @@ -871,10 +872,10 @@ void GIVEN_services_running_WHEN_service_added_and_deleted_THEN_add_remove_servi
* Start a service running with a user, then deploy an update to change the user and ensure the correct user stops
* the process and starts the new one.
*/
@Disabled
@Test
@Order(9) // deploy before tests that break services
void GIVEN_a_deployment_with_runwith_config_WHEN_submitted_THEN_runwith_updated() throws Exception {
assumeTrue("root".equals(SystemUtils.USER_NAME), "Test requires root access for cgroup management");
((Map) kernel.getContext().getvIfExists(Kernel.SERVICE_TYPE_TO_CLASS_MAP_KEY).get())
.put("plugin", GreengrassService.class.getName());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,42 +9,41 @@
import com.aws.greengrass.lifecyclemanager.Kernel;
import com.aws.greengrass.testcommons.testutilities.GGExtension;
import com.aws.greengrass.testcommons.testutilities.TestUtils;
import com.aws.greengrass.util.platforms.unix.linux.Cgroup;
import com.aws.greengrass.util.platforms.unix.linux.LinuxSystemResourceController;
import com.aws.greengrass.util.platforms.unix.linux.CgroupManager;
import com.aws.greengrass.util.platforms.unix.linux.CgroupV1;
import com.aws.greengrass.util.platforms.unix.linux.CgroupV2;
import org.apache.commons.lang3.SystemUtils;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledOnOs;
import org.junit.jupiter.api.condition.OS;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.io.TempDir;
import org.mockito.junit.jupiter.MockitoExtension;
import software.amazon.awssdk.aws.greengrass.GreengrassCoreIPCClient;
import software.amazon.awssdk.aws.greengrass.model.PauseComponentRequest;
import software.amazon.awssdk.aws.greengrass.model.ResumeComponentRequest;
import software.amazon.awssdk.crt.io.SocketOptions;
import software.amazon.awssdk.eventstreamrpc.EventStreamRPCConnection;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystemException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

import static com.aws.greengrass.integrationtests.ipc.IPCTestUtils.prepareKernelFromConfigFile;
import static com.aws.greengrass.testcommons.testutilities.ExceptionLogProtector.ignoreExceptionOfType;
import static com.aws.greengrass.testcommons.testutilities.ExceptionLogProtector.ignoreExceptionUltimateCauseWithMessage;
import static com.aws.greengrass.testcommons.testutilities.ExceptionLogProtector.ignoreExceptionWithMessage;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.anyOf;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assumptions.assumeTrue;

@ExtendWith({GGExtension.class})
@ExtendWith({GGExtension.class, MockitoExtension.class})
class IPCHibernateTest {
private static final String TARGET_COMPONENT_NAME = "HibernateTarget";
private static final String CONTROLLER_COMPONENT_NAME = "HibernateController";
Expand Down Expand Up @@ -88,37 +87,35 @@ void beforeEach(ExtensionContext context) throws Exception {
greengrassCoreIPCClient = new GreengrassCoreIPCClient(clientConnection);
}

@Disabled
@SuppressWarnings({"PMD.CloseResource", "PMD.AvoidCatchingGenericException"})
@EnabledOnOs({OS.LINUX})
@Test
void GIVEN_LifeCycleEventStreamClient_WHEN_pause_resume_component_THEN_target_service_paused_and_resumed()
throws Exception {
// Skip test if not running as root (required for cgroup access)
assumeTrue("root".equals(SystemUtils.USER_NAME), "Test requires root access for cgroup management");

GenericExternalService component = (GenericExternalService) kernel.locate(TARGET_COMPONENT_NAME);

PauseComponentRequest pauseRequest = new PauseComponentRequest();
pauseRequest.setComponentName(TARGET_COMPONENT_NAME);
greengrassCoreIPCClient.pauseComponent(pauseRequest, Optional.empty()).getResponse().get(5, TimeUnit.SECONDS);

assertTrue(component.isPaused());
assertThat(getCgroupFreezerState(component.getServiceName()),
anyOf(is(LinuxSystemResourceController.CgroupFreezerState.FROZEN),
is(LinuxSystemResourceController.CgroupFreezerState.FREEZING)));

CgroupManager freezerManager = isCgroupV2Supported() ? CgroupV2.Freezer : CgroupV1.Freezer;
assertTrue(freezerManager.isComponentFrozen(TARGET_COMPONENT_NAME));

ResumeComponentRequest resumeRequest = new ResumeComponentRequest();
resumeRequest.setComponentName(TARGET_COMPONENT_NAME);
greengrassCoreIPCClient.resumeComponent(resumeRequest, Optional.empty()).getResponse().get(5, TimeUnit.SECONDS);

assertFalse(component.isPaused());
assertThat(getCgroupFreezerState(component.getServiceName()),
is(LinuxSystemResourceController.CgroupFreezerState.THAWED));
assertFalse(freezerManager.isComponentFrozen(TARGET_COMPONENT_NAME));
}

private LinuxSystemResourceController.CgroupFreezerState getCgroupFreezerState(String serviceName)
throws IOException {
return LinuxSystemResourceController.CgroupFreezerState.valueOf(
new String(Files.readAllBytes(Cgroup.Freezer.getCgroupFreezerStateFilePath(serviceName)),
StandardCharsets.UTF_8).trim());
private boolean isCgroupV2Supported() {
return Files.exists(Paths.get("/sys/fs/cgroup/cgroup.controllers"));
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -18,27 +18,31 @@
import com.aws.greengrass.logging.impl.GreengrassLogMessage;
import com.aws.greengrass.logging.impl.Slf4jLogAdapter;
import com.aws.greengrass.status.model.ComponentStatusDetails;
import com.aws.greengrass.testcommons.testutilities.GGExtension;
import com.aws.greengrass.testcommons.testutilities.NoOpPathOwnershipHandler;
import com.aws.greengrass.util.Pair;
import com.aws.greengrass.util.platforms.unix.linux.Cgroup;
import com.aws.greengrass.util.platforms.unix.linux.LinuxSystemResourceController;
import com.aws.greengrass.util.platforms.unix.linux.CgroupManager;
import com.aws.greengrass.util.platforms.unix.linux.CgroupV1;
import com.aws.greengrass.util.platforms.unix.linux.CgroupV2;
import org.apache.commons.lang3.SystemUtils;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledOnOs;
import org.junit.jupiter.api.condition.OS;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.junit.jupiter.MockitoExtension;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystemException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
Expand All @@ -64,7 +68,6 @@
import static com.aws.greengrass.testcommons.testutilities.TestUtils.createCloseableLogListener;
import static com.aws.greengrass.util.platforms.unix.UnixPlatform.STDOUT;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.anyOf;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
Expand All @@ -83,7 +86,7 @@
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;


@ExtendWith({GGExtension.class, MockitoExtension.class})
class GenericExternalServiceIntegTest extends BaseITCase {

private Kernel kernel;
Expand Down Expand Up @@ -581,7 +584,6 @@ void GIVEN_bootstrap_command_WHEN_runs_longer_than_5_sec_THEN_timeout_exception_
assertThrows(TimeoutException.class, serviceWithJustBootstrapAndShouldTimeout::bootstrap);
}

@Disabled
@EnabledOnOs({OS.LINUX, OS.MAC})
@ParameterizedTest
@MethodSource("posixTestUserConfig")
Expand Down Expand Up @@ -637,10 +639,12 @@ void GIVEN_posix_default_user_WHEN_runs_THEN_runs_with_default_user(String file,
}
}

@Disabled
@EnabledOnOs({OS.LINUX})
@Test
void GIVEN_linux_resource_limits_WHEN_it_changes_THEN_component_runs_with_new_resource_limits() throws Exception {
// Skip test if no proper access available (required for cgroup access)
assumeTrue("root".equals(SystemUtils.USER_NAME), "Test requires root access for cgroup management");

String componentName = "echo_service";
// Run with no resource limit
ConfigPlatformResolver.initKernelWithMultiPlatformConfig(kernel,
Expand Down Expand Up @@ -818,20 +822,38 @@ void GIVEN_service_starts_up_WHEN_startup_times_out_THEN_timeout_error_code_pers
}

private void assertResourceLimits(String componentName, long memory, double cpus) throws Exception {
byte[] buf1 = Files.readAllBytes(Cgroup.Memory.getComponentMemoryLimitPath(componentName));
assertThat(memory, equalTo(Long.parseLong(new String(buf1, StandardCharsets.UTF_8).trim())));

byte[] buf2 = Files.readAllBytes(Cgroup.CPU.getComponentCpuQuotaPath(componentName));
byte[] buf3 = Files.readAllBytes(Cgroup.CPU.getComponentCpuPeriodPath(componentName));

int quota = Integer.parseInt(new String(buf2, StandardCharsets.UTF_8).trim());
int period = Integer.parseInt(new String(buf3, StandardCharsets.UTF_8).trim());
int quota;
int period;

if (isCgroupV2Supported()) {
byte[] buf1 = Files.readAllBytes(CgroupV2.Memory.getComponentMemoryLimitPath(componentName));
assertThat(memory, equalTo(Long.parseLong(new String(buf1, StandardCharsets.UTF_8).trim())));

byte[] buf2 = Files.readAllBytes(CgroupV2.CPU.getComponentCpuLimitPath(componentName));
String cpuMax = new String(buf2, StandardCharsets.UTF_8).trim();
String[] parts = cpuMax.split(" ");
quota = Integer.parseInt(parts[0]);
period = Integer.parseInt(parts[1]);
} else {
byte[] buf1 = Files.readAllBytes(CgroupV1.Memory.getComponentMemoryLimitPath(componentName));
assertThat(memory, equalTo(Long.parseLong(new String(buf1, StandardCharsets.UTF_8).trim())));

byte[] buf2 = Files.readAllBytes(CgroupV1.CPU.getComponentCpuQuotaPath(componentName));
byte[] buf3 = Files.readAllBytes(CgroupV1.CPU.getComponentCpuPeriodPath(componentName));

quota = Integer.parseInt(new String(buf2, StandardCharsets.UTF_8).trim());
period = Integer.parseInt(new String(buf3, StandardCharsets.UTF_8).trim());
}

int expectedQuota = (int) (cpus * period);
assertThat(expectedQuota, equalTo(quota));
}

@Test
@EnabledOnOs({OS.LINUX})
void GIVEN_running_service_WHEN_pause_resume_requested_THEN_pause_resume_Service_and_freeze_thaw_cgroup(
ExtensionContext context) throws Exception {
assumeTrue("root".equals(SystemUtils.USER_NAME), "Test requires root access for cgroup management");
ignoreExceptionOfType(context, FileSystemException.class);
ConfigPlatformResolver.initKernelWithMultiPlatformConfig(kernel,
getClass().getResource("long_running_services.yaml"));
Expand All @@ -852,21 +874,17 @@ void GIVEN_running_service_WHEN_pause_resume_requested_THEN_pause_resume_Service

component.pause();
assertTrue(component.isPaused());
assertThat(getCgroupFreezerState(component.getServiceName()),
anyOf(is(LinuxSystemResourceController.CgroupFreezerState.FROZEN),
is(LinuxSystemResourceController.CgroupFreezerState.FREEZING)));

// check if component is frozen
CgroupManager freezerManager = isCgroupV2Supported() ? CgroupV2.Freezer : CgroupV1.Freezer;
assertTrue(freezerManager.isComponentFrozen(component.getServiceName()));

component.resume();
assertFalse(component.isPaused());
assertThat(getCgroupFreezerState(component.getServiceName()),
is(LinuxSystemResourceController.CgroupFreezerState.THAWED));
assertFalse(freezerManager.isComponentFrozen(component.getServiceName()));
}

// To be used on linux only
private LinuxSystemResourceController.CgroupFreezerState getCgroupFreezerState(String serviceName)
throws IOException {
return LinuxSystemResourceController.CgroupFreezerState
.valueOf(new String(Files.readAllBytes(Cgroup.Freezer.getCgroupFreezerStateFilePath(serviceName))
, StandardCharsets.UTF_8).trim());
private boolean isCgroupV2Supported() {
return Files.exists(Paths.get("/sys/fs/cgroup/cgroup.controllers"));
}
}
Loading
Loading