TEST(CacheTest, LRUEviction) { Cache<int, std::string> cache(2); cache.put(1, "a"); cache.put(2, "b"); cache.put(3, "c"); EXPECT_NONE(cache.get(1)); // 'Get' makes '2' the most-recently used (MRU) item. cache.get(2); cache.put(4, "d"); EXPECT_NONE(cache.get(3)); EXPECT_SOME_EQ("b", cache.get(2)); EXPECT_SOME_EQ("d", cache.get(4)); // 'Put' also makes '2' MRU. cache.put(2, "x"); cache.put(5, "e"); EXPECT_NONE(cache.get(4)); EXPECT_SOME_EQ("x", cache.get(2)); EXPECT_SOME_EQ("e", cache.get(5)); // 'Erase' the LRU. cache.erase(2); cache.put(6, "f"); cache.put(7, "g"); EXPECT_NONE(cache.get(5)); }
TEST(AgentValidationTest, ContainerID) { ContainerID containerId; Option<Error> error; // No empty IDs. containerId.set_value(""); error = validation::container::validateContainerId(containerId); EXPECT_SOME(error); // No slashes. containerId.set_value("/"); error = validation::container::validateContainerId(containerId); EXPECT_SOME(error); containerId.set_value("\\"); error = validation::container::validateContainerId(containerId); EXPECT_SOME(error); // No spaces. containerId.set_value("redis backup"); error = validation::container::validateContainerId(containerId); EXPECT_SOME(error); // No periods. containerId.set_value("redis.backup"); error = validation::container::validateContainerId(containerId); EXPECT_SOME(error); // Cannot be '.'. containerId.set_value("."); error = validation::container::validateContainerId(containerId); EXPECT_SOME(error); // Cannot be '..'. containerId.set_value(".."); error = validation::container::validateContainerId(containerId); EXPECT_SOME(error); // Valid. containerId.set_value("redis"); error = validation::container::validateContainerId(containerId); EXPECT_NONE(error); // Valid with invalid parent (empty `ContainerID.value`). containerId.set_value("backup"); containerId.mutable_parent(); error = validation::container::validateContainerId(containerId); EXPECT_SOME(error); // Valid with valid parent. containerId.set_value("backup"); containerId.mutable_parent()->set_value("redis"); error = validation::container::validateContainerId(containerId); EXPECT_NONE(error); }
// Tests that the common validation code for the // `Secret` message works as expected. TEST(AgentValidationTest, Secret) { // Test a secret of VALUE type. { Secret secret; secret.set_type(Secret::VALUE); Option<Error> error = validateSecret(secret); EXPECT_SOME(error); EXPECT_EQ( "Secret of type VALUE must have the 'value' field set", error->message); secret.mutable_value()->set_data("SECRET_VALUE"); secret.mutable_reference()->set_name("SECRET_NAME"); error = validateSecret(secret); EXPECT_SOME(error); EXPECT_EQ( "Secret of type VALUE must not have the 'reference' field set", error->message); // Test the valid case. secret.clear_reference(); error = validateSecret(secret); EXPECT_NONE(error); } // Test a secret of REFERENCE type. { Secret secret; secret.set_type(Secret::REFERENCE); Option<Error> error = validateSecret(secret); EXPECT_SOME(error); EXPECT_EQ( "Secret of type REFERENCE must have the 'reference' field set", error->message); secret.mutable_reference()->set_name("SECRET_NAME"); secret.mutable_value()->set_data("SECRET_VALUE"); error = validateSecret(secret); EXPECT_SOME(error); EXPECT_EQ( "Secret 'SECRET_NAME' of type REFERENCE " "must not have the 'value' field set", error->message); // Test the valid case. secret.clear_value(); error = validateSecret(secret); EXPECT_NONE(error); } }
TEST_F(ZooKeeperTest, LeaderDetectorTimeoutHandling) { Duration timeout = Seconds(10); Group group(server->connectString(), timeout, "/test/"); LeaderDetector detector(&group); AWAIT_READY(group.join("member 1")); Future<Option<Group::Membership> > leader = detector.detect(); AWAIT_READY(leader); EXPECT_SOME(leader.get()); leader = detector.detect(leader.get()); Future<Nothing> reconnecting = FUTURE_DISPATCH( group.process->self(), &GroupProcess::reconnecting); server->shutdownNetwork(); AWAIT_READY(reconnecting); Clock::pause(); // Settle to make sure 'reconnecting' schedules the timeout before // we advance. Clock::settle(); Clock::advance(timeout); // The detect operation times out. AWAIT_READY(leader); EXPECT_NONE(leader.get()); }
TEST(QoSPipelineTest, FiltersNotProperlyFed) { uint64_t WINDOWS_SIZE = 10; uint64_t CONTENTION_COOLDOWN = 10; double_t RELATIVE_THRESHOLD = 0.5; Try<mesos::FixtureResourceUsage> usages = JsonUsage::ReadJson("tests/fixtures/pipeline/insufficient_metrics.json"); if (usages.isError()) { LOG(ERROR) << "JsonSource failed: " << usages.error() << std::endl; } ResourceUsage usage; usage.CopyFrom(usages.get().resource_usage(0)); QoSControllerPipeline* pipeline = new CpuQoSPipeline<RollingChangePointDetector>( QoSPipelineConf( ChangePointDetectionState::createForRollingDetector( WINDOWS_SIZE, CONTENTION_COOLDOWN, RELATIVE_THRESHOLD), ema::DEFAULT_ALPHA, false, true)); Result<QoSCorrections> corrections = pipeline->run(usage); EXPECT_NONE(corrections); delete pipeline; }
TEST_F(ZooKeeperTest, LeaderDetectorCancellationHandling) { Duration timeout = Seconds(10); Group group(server->connectString(), timeout, "/test/"); LeaderDetector detector(&group); AWAIT_READY(group.join("member 1")); Future<Option<Group::Membership> > leader = detector.detect(); AWAIT_READY(leader); EXPECT_SOME(leader.get()); // Cancel the member and join another. Future<bool> cancelled = group.cancel(leader.get().get()); AWAIT_READY(cancelled); EXPECT_TRUE(cancelled.get()); leader = detector.detect(leader.get()); AWAIT_READY(leader); EXPECT_NONE(leader.get()); AWAIT_READY(group.join("member 2")); // Detect a new leader. leader = detector.detect(leader.get()); AWAIT_READY(leader); EXPECT_SOME(leader.get()); }
TEST(AgentCallValidationTest, RemoveNestedContainer) { // Missing `remove_nested_container`. agent::Call call; call.set_type(agent::Call::REMOVE_NESTED_CONTAINER); Option<Error> error = validation::agent::call::validate(call); EXPECT_SOME(error); // Expecting a `container_id.parent`. ContainerID containerId; containerId.set_value(UUID::random().toString()); agent::Call::RemoveNestedContainer* removeNestedContainer = call.mutable_remove_nested_container(); removeNestedContainer->mutable_container_id()->CopyFrom(containerId); error = validation::agent::call::validate(call); EXPECT_SOME(error); // Test the valid case. ContainerID parentContainerId; parentContainerId.set_value(UUID::random().toString()); removeNestedContainer->mutable_container_id()->mutable_parent()->CopyFrom( containerId); error = validation::agent::call::validate(call); EXPECT_NONE(error); }
TEST(QoSPipelineTest, FiltersNotProperlyFed) { uint64_t WINDOWS_SIZE = 10; uint64_t CONTENTION_COOLDOWN = 10; double_t FRATIONAL_THRESHOLD = 0.5; Try<mesos::FixtureResourceUsage> usages = JsonUsage::ReadJson("tests/fixtures/pipeline/insufficient_metrics.json"); if (usages.isError()) { LOG(ERROR) << "JsonSource failed: " << usages.error() << std::endl; } ResourceUsage usage; usage.CopyFrom(usages.get().resource_usage(0)); SerenityConfig conf; conf["Detector"] = createAssuranceDetectorCfg( WINDOWS_SIZE, CONTENTION_COOLDOWN, FRATIONAL_THRESHOLD); conf.set(ENABLED_VISUALISATION, false); conf.set(VALVE_OPENED, true); QoSControllerPipeline* pipeline = new CpuQoSPipeline(conf); Result<QoSCorrections> corrections = pipeline->run(usage); EXPECT_NONE(corrections); delete pipeline; }
TEST(QoSPipelineTest, NoCorrections) { uint64_t WINDOWS_SIZE = 10; uint64_t CONTENTION_COOLDOWN = 10; double_t RELATIVE_THRESHOLD = 0.5; MockSlaveUsage mockSlaveUsage(QOS_PIPELINE_FIXTURE1); QoSControllerPipeline* pipeline = new CpuQoSPipeline<RollingChangePointDetector>( QoSPipelineConf( ChangePointDetectionState::createForRollingDetector( WINDOWS_SIZE, CONTENTION_COOLDOWN, RELATIVE_THRESHOLD), ema::DEFAULT_ALPHA, false, true)); // First iteration. Result<QoSCorrections> corrections = pipeline->run(mockSlaveUsage.usage().get()); EXPECT_NONE(corrections); // Second iteration. corrections = pipeline->run(mockSlaveUsage.usage().get()); EXPECT_SOME(corrections); EXPECT_TRUE(corrections.get().empty()); delete pipeline; }
TEST(QoSPipelineTest, NoCorrections) { uint64_t WINDOWS_SIZE = 10; uint64_t CONTENTION_COOLDOWN = 10; double_t FRATIONAL_THRESHOLD = 0.5; MockSlaveUsage mockSlaveUsage(QOS_PIPELINE_FIXTURE1); SerenityConfig conf; conf["Detector"] = createAssuranceDetectorCfg( WINDOWS_SIZE, CONTENTION_COOLDOWN, FRATIONAL_THRESHOLD); conf.set(ENABLED_VISUALISATION, false); conf.set(VALVE_OPENED, true); QoSControllerPipeline* pipeline = new CpuQoSPipeline(conf); // First iteration. Result<QoSCorrections> corrections = pipeline->run(mockSlaveUsage.usage().get()); EXPECT_NONE(corrections); // Second iteration. corrections = pipeline->run(mockSlaveUsage.usage().get()); EXPECT_SOME(corrections); EXPECT_TRUE(corrections.get().empty()); delete pipeline; }
TEST(CacheTest, Erase) { Cache<int, std::string> cache(2); cache.put(1, "a"); cache.put(2, "b"); EXPECT_NONE(cache.erase(44)); EXPECT_SOME_EQ("b", cache.erase(2)); EXPECT_EQ(1, cache.size()); EXPECT_NONE(cache.erase(2)); EXPECT_EQ(1, cache.size()); EXPECT_SOME_EQ("a", cache.erase(1)); EXPECT_EQ(0, cache.size()); }
TEST(Stout, Some) { Option<int> o1 = Some(42); EXPECT_SOME(o1); EXPECT_EQ(42, o1.get()); Result<int> r1 = Some(42); EXPECT_SOME(r1); EXPECT_EQ(42, r1.get()); Try<Option<int> > t1 = Some(42); ASSERT_SOME(t1); EXPECT_SOME(t1.get()); EXPECT_EQ(42, t1.get().get()); t1 = None(); ASSERT_SOME(t1); EXPECT_NONE(t1.get()); Try<Result<int> > t2 = Some(42); ASSERT_SOME(t2); EXPECT_SOME(t2.get()); EXPECT_EQ(42, t2.get().get()); Option<Result<int> > o2 = Some(42); ASSERT_SOME(o2); EXPECT_SOME(o2.get()); EXPECT_EQ(42, o2.get().get()); Option<Result<int> > o3 = Some(Some(42)); ASSERT_SOME(o3); EXPECT_SOME(o3.get()); EXPECT_EQ(42, o3.get().get()); Result<Option<int> > r2 = Some(42); ASSERT_SOME(r2); EXPECT_SOME(r2.get()); EXPECT_EQ(42, r2.get().get()); Result<Option<int> > r3 = Some(Some(42)); ASSERT_SOME(r3); EXPECT_SOME(r3.get()); EXPECT_EQ(42, r3.get().get()); Option<std::string> o4 = Some("hello"); EXPECT_SOME(o4); EXPECT_EQ("hello", o4.get()); Result<std::string> r4 = Some("world"); EXPECT_SOME(r4); EXPECT_EQ("world", r4.get()); std::map<std::string, Option<std::string> > values; values["no-debug"] = None(); values["debug"] = None(); values["debug"] = Some("true"); values["debug"] = Some("false"); values["name"] = Some("frank"); }
TEST(EstimatorPipelineTest, FiltersNotProperlyFed) { Try<mesos::FixtureResourceUsage> usages = JsonUsage::ReadJson("tests/fixtures/pipeline/insufficient_metrics.json"); if (usages.isError()) { LOG(ERROR) << "JsonSource failed: " << usages.error() << std::endl; ASSERT_FALSE(usages.isError()); // test failure. } ResourceUsage usage; usage.CopyFrom(usages.get().resource_usage(0)); ResourceEstimatorPipeline* pipeline = new CpuEstimatorPipeline(); Result<Resources> slack = pipeline->run(usage); EXPECT_NONE(slack); delete pipeline; }
// No user should return an authentication failure. TYPED_TEST(CRAMMD5Authentication, Failed2) { // Launch a dummy process (somebody to send the AuthenticateMessage). UPID pid = spawn(new ProcessBase(), true); Credential credential1; credential1.set_principal("benh"); credential1.set_secret("secret"); Credentials credentials; Credential* credential2 = credentials.add_credentials(); credential2->set_principal("vinod"); credential2->set_secret(credential1.secret()); Future<Message> message = FUTURE_MESSAGE(Eq(AuthenticateMessage().GetTypeName()), _, _); Try<Authenticatee*> authenticatee = TypeParam::TypeAuthenticatee::create(); CHECK_SOME(authenticatee); Future<bool> client = authenticatee.get()->authenticate(pid, UPID(), credential1); AWAIT_READY(message); Try<Authenticator*> authenticator = TypeParam::TypeAuthenticator::create(); CHECK_SOME(authenticator); EXPECT_SOME(authenticator.get()->initialize(credentials)); Future<Option<string>> server = authenticator.get()->authenticate(message.get().from); AWAIT_EQ(false, client); AWAIT_READY(server); EXPECT_NONE(server.get()); terminate(pid); delete authenticator.get(); delete authenticatee.get(); }
// Ensures the containerizer responds correctly (returns None) // to a request to wait on an unknown container. TEST_F(ComposingContainerizerTest, WaitUnknownContainer) { vector<Containerizer*> containerizers; MockContainerizer* mockContainerizer1 = new MockContainerizer(); MockContainerizer* mockContainerizer2 = new MockContainerizer(); containerizers.push_back(mockContainerizer1); containerizers.push_back(mockContainerizer2); ComposingContainerizer containerizer(containerizers); ContainerID containerId; containerId.set_value(UUID::random().toString()); Future<Option<ContainerTermination>> wait = containerizer.wait(containerId); AWAIT_READY(wait); EXPECT_NONE(wait.get()); }
TEST_F(AppcSpecTest, ValidateLayout) { string image = os::getcwd(); JSON::Value manifest = JSON::parse( "{" " \"acKind\": \"ImageManifest\"," " \"acVersion\": \"0.6.1\"," " \"name\": \"foo.com/bar\"" "}").get(); ASSERT_SOME(os::write(path::join(image, "manifest"), stringify(manifest))); // Missing rootfs. EXPECT_SOME(spec::validateLayout(image)); ASSERT_SOME(os::mkdir(path::join(image, "rootfs", "tmp"))); ASSERT_SOME(os::write(path::join(image, "rootfs", "tmp", "test"), "test")); EXPECT_NONE(spec::validateLayout(image)); }
TEST(QoSIpcPipelineTest, AssuranceFractionalDetectorTwoDropCorrectionsWithEma) { QoSPipelineConf conf; ChangePointDetectionState cpdState; // Detector configuration: // How far we look back in samples. cpdState.windowSize = 10; // How many iterations detector will wait with creating another // contention. cpdState.contentionCooldown = 4; // Defines how much (relatively to base point) value must drop to trigger // contention. // Most detectors will use that. cpdState.fractionalThreshold = 0.3; // Defines how to convert difference in values to CPU. // This option helps RollingFractionalDetector to estimate severity of // drop. cpdState.severityLevel = 1; cpdState.nearFraction = 0.1; conf.cpdState = cpdState; conf.emaAlpha = 0.9; conf.visualisation = false; // Let's start with QoS pipeline disabled. conf.valveOpened = true; MockSlaveUsage mockSlaveUsage(QOS_PIPELINE_FIXTURE2); QoSControllerPipeline* pipeline = new CpuQoSPipeline<AssuranceFractionalDetector>(conf); // First iteration. Result<QoSCorrections> corrections = pipeline->run(mockSlaveUsage.usage().get()); EXPECT_NONE(corrections); ResourceUsage usage = mockSlaveUsage.usage().get(); const int32_t LOAD_ITERATIONS = 17; LoadGenerator loadGen( [](double_t iter) { return 1; }, new ZeroNoise(), LOAD_ITERATIONS); for (; loadGen.end(); loadGen++) { // Test scenario: After 10 iterations create drop in IPC // for executor num 3. double_t ipcFor3Executor = (*loadGen)(); if (loadGen.iteration >= 11) { ipcFor3Executor /= 2.0; } usage.mutable_executors(PR_4CPUS)->CopyFrom( generateIPC(usage.executors(PR_4CPUS), ipcFor3Executor, (*loadGen).timestamp)); usage.mutable_executors(PR_2CPUS)->CopyFrom( generateIPC(usage.executors(PR_2CPUS), (*loadGen)(), (*loadGen).timestamp)); // Third iteration (repeated). corrections = pipeline->run(usage); // Assurance Detector will wait for signal to be returned to the // established state. if (loadGen.iteration == 11 || loadGen.iteration == 16) { EXPECT_SOME(corrections); ASSERT_EQ(slave::QoSCorrection_Type_KILL, corrections.get().front().type()); // Make sure that we do not kill PR tasks! EXPECT_NE("serenityPR", corrections.get().front().kill().executor_id().value()); EXPECT_NE("serenityPR2", corrections.get().front().kill().executor_id().value()); } else { EXPECT_SOME(corrections); EXPECT_TRUE(corrections.get().empty()); } } delete pipeline; }
TEST(QoSIpcPipelineTest, AssuranceDetectorTwoDropCorrectionsWithEma) { uint64_t WINDOWS_SIZE = 10; uint64_t CONTENTION_COOLDOWN = 4; double_t FRATIONAL_THRESHOLD = 0.3; double_t SEVERITY_LEVEL = 1; double_t NEAR_LEVEL = 0.1; MockSlaveUsage mockSlaveUsage(QOS_PIPELINE_FIXTURE2); SerenityConfig conf; conf["Detector"] = createAssuranceDetectorCfg( WINDOWS_SIZE, CONTENTION_COOLDOWN, FRATIONAL_THRESHOLD, SEVERITY_LEVEL, NEAR_LEVEL); conf.set(ema::ALPHA, 0.9); conf.set(ENABLED_VISUALISATION, false); conf.set(VALVE_OPENED, true); QoSControllerPipeline* pipeline = new CpuQoSPipeline(conf); // First iteration. Result<QoSCorrections> corrections = pipeline->run(mockSlaveUsage.usage().get()); EXPECT_NONE(corrections); ResourceUsage usage = mockSlaveUsage.usage().get(); const int32_t LOAD_ITERATIONS = 17; LoadGenerator loadGen( [](double_t iter) { return 1; }, new ZeroNoise(), LOAD_ITERATIONS); for (; loadGen.end(); loadGen++) { // Test scenario: After 10 iterations create drop in IPC // for executor num 3. double_t ipcFor3Executor = (*loadGen)(); if (loadGen.iteration >= 11) { ipcFor3Executor /= 2.0; } usage.mutable_executors(PR_4CPUS)->CopyFrom( generateIPC(usage.executors(PR_4CPUS), ipcFor3Executor, (*loadGen).timestamp)); usage.mutable_executors(PR_2CPUS)->CopyFrom( generateIPC(usage.executors(PR_2CPUS), (*loadGen)(), (*loadGen).timestamp)); // Third iteration (repeated). corrections = pipeline->run(usage); // Assurance Detector will wait for signal to be returned to the // established state. if (loadGen.iteration == 11 || loadGen.iteration == 16) { EXPECT_SOME(corrections); ASSERT_EQ(slave::QoSCorrection_Type_KILL, corrections.get().front().type()); // Make sure that we do not kill PR tasks! EXPECT_NE("serenityPR", corrections.get().front().kill().executor_id().value()); EXPECT_NE("serenityPR2", corrections.get().front().kill().executor_id().value()); } else { EXPECT_SOME(corrections); EXPECT_TRUE(corrections.get().empty()); } } delete pipeline; }
// Tests that the common validation code for the // `Environment` message works as expected. TEST(AgentValidationTest, Environment) { // Validate a variable of SECRET type. { Environment environment; Environment::Variable* variable = environment.mutable_variables()->Add(); variable->set_type(mesos::Environment::Variable::SECRET); variable->set_name("ENV_VAR_KEY"); Option<Error> error = validateEnvironment(environment); EXPECT_SOME(error); EXPECT_EQ( "Environment variable 'ENV_VAR_KEY' of type " "'SECRET' must have a secret set", error->message); Secret secret; secret.set_type(Secret::VALUE); secret.mutable_value()->set_data("SECRET_VALUE"); variable->mutable_secret()->CopyFrom(secret); variable->set_value("ENV_VAR_VALUE"); error = validateEnvironment(environment); EXPECT_SOME(error); EXPECT_EQ( "Environment variable 'ENV_VAR_KEY' of type 'SECRET' " "must not have a value set", error->message); variable->clear_value(); char invalid_secret[5] = {'a', 'b', '\0', 'c', 'd'}; variable->mutable_secret()->mutable_value()->set_data( std::string(invalid_secret, 5)); error = validateEnvironment(environment); EXPECT_SOME(error); EXPECT_EQ( "Environment variable 'ENV_VAR_KEY' specifies a secret containing " "null bytes, which is not allowed in the environment", error->message); // Test the valid case. variable->mutable_secret()->mutable_value()->set_data("SECRET_VALUE"); error = validateEnvironment(environment); EXPECT_NONE(error); } // Validate a variable of VALUE type. { // The default type for an environment variable // should be VALUE, so we do not set the type here. Environment environment; Environment::Variable* variable = environment.mutable_variables()->Add(); variable->set_name("ENV_VAR_KEY"); Option<Error> error = validateEnvironment(environment); EXPECT_SOME(error); EXPECT_EQ( "Environment variable 'ENV_VAR_KEY' of type 'VALUE' " "must have a value set", error->message); variable->set_value("ENV_VAR_VALUE"); Secret secret; secret.set_type(Secret::VALUE); secret.mutable_value()->set_data("SECRET_VALUE"); variable->mutable_secret()->CopyFrom(secret); error = validateEnvironment(environment); EXPECT_SOME(error); EXPECT_EQ( "Environment variable 'ENV_VAR_KEY' of type 'VALUE' " "must not have a secret set", error->message); // Test the valid case. variable->clear_secret(); error = validateEnvironment(environment); EXPECT_NONE(error); } // Validate a variable of UNKNOWN type. { Environment environment; Environment::Variable* variable = environment.mutable_variables()->Add(); variable->set_type(mesos::Environment::Variable::UNKNOWN); variable->set_name("ENV_VAR_KEY"); variable->set_value("ENV_VAR_VALUE"); Option<Error> error = validateEnvironment(environment); EXPECT_SOME(error); EXPECT_EQ( "Environment variable of type 'UNKNOWN' is not allowed", error->message); } }
TEST(AgentCallValidationTest, LaunchNestedContainerSession) { // Missing `launch_nested_container_session`. agent::Call call; call.set_type(agent::Call::LAUNCH_NESTED_CONTAINER_SESSION); Option<Error> error = validation::agent::call::validate(call); EXPECT_SOME(error); // `container_id` is not valid. ContainerID badContainerId; badContainerId.set_value("no spaces allowed"); agent::Call::LaunchNestedContainerSession* launch = call.mutable_launch_nested_container_session(); launch->mutable_container_id()->CopyFrom(badContainerId); error = validation::agent::call::validate(call); EXPECT_SOME(error); // Valid `container_id` but missing `container_id.parent`. ContainerID containerId; containerId.set_value(UUID::random().toString()); launch->mutable_container_id()->CopyFrom(containerId); error = validation::agent::call::validate(call); EXPECT_SOME(error); // Valid `container_id.parent` but invalid `command.environment`. Set // an invalid environment variable to check that the common validation // code for the command's environment is being executed. ContainerID parentContainerId; parentContainerId.set_value(UUID::random().toString()); launch->mutable_container_id()->mutable_parent()->CopyFrom(parentContainerId); launch->mutable_command()->CopyFrom(createCommandInfo("exit 0")); Environment::Variable* variable = launch ->mutable_command() ->mutable_environment() ->mutable_variables() ->Add(); variable->set_name("ENV_VAR_KEY"); variable->set_type(mesos::Environment::Variable::VALUE); error = validation::agent::call::validate(call); EXPECT_SOME(error); EXPECT_EQ( "'launch_nested_container_session.command' is invalid: Environment " "variable 'ENV_VAR_KEY' of type 'VALUE' must have a value set", error->message); // Test the valid case. variable->set_value("env_var_value"); error = validation::agent::call::validate(call); EXPECT_NONE(error); // Any number of parents is valid. ContainerID grandparentContainerId; grandparentContainerId.set_value(UUID::random().toString()); launch->mutable_container_id()->mutable_parent()->mutable_parent()->CopyFrom( grandparentContainerId); error = validation::agent::call::validate(call); EXPECT_NONE(error); }
TEST(QoSIpcPipelineTest, RollingDetectorOneDropCorrectionsWithEma) { uint64_t WINDOWS_SIZE = 10; uint64_t CONTENTION_COOLDOWN = 10; double_t RELATIVE_THRESHOLD = 0.3; MockSlaveUsage mockSlaveUsage(QOS_PIPELINE_FIXTURE2); QoSControllerPipeline* pipeline = new CpuQoSPipeline<RollingChangePointDetector>( QoSPipelineConf( ChangePointDetectionState::createForRollingDetector( WINDOWS_SIZE, CONTENTION_COOLDOWN, RELATIVE_THRESHOLD), 0.2, // Alpha = 1 means no smoothing. 0.2 means high smoothing. false, true)); // First iteration. Result<QoSCorrections> corrections = pipeline->run(mockSlaveUsage.usage().get()); EXPECT_NONE(corrections); ResourceUsage usage = mockSlaveUsage.usage().get(); const int32_t LOAD_ITERATIONS = 16; LoadGenerator loadGen( [](double_t iter) { return 1; }, new ZeroNoise(), LOAD_ITERATIONS); for (; loadGen.end(); loadGen++) { // Test scenario: After 10 iterations create drop in // IPC for executor num 3. double_t ipcFor3Executor = (*loadGen)(); if (loadGen.iteration >= 11) { ipcFor3Executor /= 2.0; } usage.mutable_executors(PR_4CPUS)->CopyFrom( generateIPC(usage.executors(PR_4CPUS), ipcFor3Executor, (*loadGen).timestamp)); usage.mutable_executors(PR_2CPUS)->CopyFrom( generateIPC(usage.executors(PR_2CPUS), (*loadGen)(), (*loadGen).timestamp)); // Third iteration (repeated). corrections = pipeline->run(usage); if (loadGen.iteration >= 15) { EXPECT_SOME(corrections); ASSERT_EQ(slave::QoSCorrection_Type_KILL, corrections.get().front().type()); // Make sure that we do not kill PR tasks! EXPECT_NE("serenityPR", corrections.get().front().kill().executor_id().value()); EXPECT_NE("serenityPR2", corrections.get().front().kill().executor_id().value()); } else { EXPECT_SOME(corrections); EXPECT_TRUE(corrections.get().empty()); } } delete pipeline; }
TEST(QoSIpsPipelineTest, RollingFractionalDetectorOneDropCorrectionsWithEma) { QoSPipelineConf conf; ChangePointDetectionState cpdState; // Detector configuration: // How far we look back in samples. cpdState.windowSize = 10; // How many iterations detector will wait with creating another // contention. cpdState.contentionCooldown = 10; // Defines how much (relatively to base point) value must drop to trigger // contention. // Most detectors will use that. cpdState.fractionalThreshold = 0.5; // Defines how many instructions can be done per one CPU in one second. // This option helps RollingFractionalDetector to estimate severity of // drop. cpdState.severityLevel = 1000000000; // 1 Billion. conf.cpdState = cpdState; conf.emaAlpha = 0.4; conf.visualisation = false; // Let's start with QoS pipeline disabled. conf.valveOpened = true; MockSlaveUsage mockSlaveUsage(QOS_PIPELINE_FIXTURE3); QoSControllerPipeline* pipeline = new IpsQoSPipeline<RollingFractionalDetector>(conf); // First iteration. Result<QoSCorrections> corrections = pipeline->run(mockSlaveUsage.usage().get()); EXPECT_NONE(corrections); // Second iteration is used for manually configured load. ResourceUsage usage = mockSlaveUsage.usage().get(); const int32_t LOAD_ITERATIONS = 14; LoadGenerator loadGen( [](double_t iter) { return 3000000000; }, new ZeroNoise(), LOAD_ITERATIONS); for (; loadGen.end(); loadGen++) { // Test scenario: After 10 iterations create drop in IPS for executor num 3. double ipsFor3Executor = (*loadGen)(); if (loadGen.iteration >= 11) { ipsFor3Executor /= 3.0; } usage.mutable_executors(PR_4CPUS)->CopyFrom( generateIPS(usage.executors(PR_4CPUS), ipsFor3Executor, (*loadGen).timestamp)); usage.mutable_executors(PR_2CPUS)->CopyFrom( generateIPS(usage.executors(PR_2CPUS), (*loadGen)(), (*loadGen).timestamp)); // Third iteration (repeated). corrections = pipeline->run(usage); if (loadGen.iteration >= 13) { EXPECT_SOME(corrections); ASSERT_EQ(slave::QoSCorrection_Type_KILL, corrections.get().front().type()); // Make sure that we do not kill PR tasks! EXPECT_NE("serenityPR", corrections.get().front().kill().executor_id().value()); EXPECT_NE("serenityPR2", corrections.get().front().kill().executor_id().value()); } else { EXPECT_SOME(corrections); EXPECT_TRUE(corrections.get().empty()); } } delete pipeline; }