Beispiel #1
0
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);
  }
}
Beispiel #4
0
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());
}
Beispiel #5
0
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;
}
Beispiel #6
0
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);
}
Beispiel #8
0
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;
}
Beispiel #9
0
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;
}
Beispiel #10
0
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;
}
Beispiel #11
0
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());
}
Beispiel #12
0
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());
}
Beispiel #16
0
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));
}
Beispiel #17
0
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;
}
Beispiel #18
0
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);
}
Beispiel #21
0
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;
}
Beispiel #22
0
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;
}