Repository: mesos Updated Branches: refs/heads/master 6e5212e4c -> 66157a6ce
Added validation for CREATE offer operation. Review: https://reviews.apache.org/r/30513 Project: http://git-wip-us.apache.org/repos/asf/mesos/repo Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/66157a6c Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/66157a6c Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/66157a6c Branch: refs/heads/master Commit: 66157a6ce2d82f446fd3b59b252d8b473f5b2006 Parents: 6e5212e Author: Jie Yu <[email protected]> Authored: Fri Jan 30 14:42:03 2015 -0800 Committer: Jie Yu <[email protected]> Committed: Wed Feb 4 12:07:15 2015 -0800 ---------------------------------------------------------------------- src/Makefile.am | 1 + src/master/validation.cpp | 40 ++- src/master/validation.hpp | 6 +- src/tests/master_validation_tests.cpp | 156 ++++++++++ src/tests/resource_offers_tests.cpp | 440 ----------------------------- 5 files changed, 201 insertions(+), 442 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mesos/blob/66157a6c/src/Makefile.am ---------------------------------------------------------------------- diff --git a/src/Makefile.am b/src/Makefile.am index 5b1885d..93537d1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1279,6 +1279,7 @@ mesos_tests_SOURCES = \ tests/master_contender_detector_tests.cpp \ tests/master_slave_reconciliation_tests.cpp \ tests/master_tests.cpp \ + tests/master_validation_tests.cpp \ tests/mesos.cpp \ tests/metrics_tests.cpp \ tests/module.cpp \ http://git-wip-us.apache.org/repos/asf/mesos/blob/66157a6c/src/master/validation.cpp ---------------------------------------------------------------------- diff --git a/src/master/validation.cpp b/src/master/validation.cpp index 8804ba6..550782e 100644 --- a/src/master/validation.cpp +++ b/src/master/validation.cpp @@ -121,6 +121,22 @@ Option<Error> validateUniquePersistenceID( } +// Validates that all the given resources are persistent volumes. +Option<Error> validatePersistentVolume( + const RepeatedPtrField<Resource>& volumes) +{ + foreach (const Resource& volume, volumes) { + if (!volume.has_disk()) { + return Error("Resource " + stringify(volume) + " does not have DiskInfo"); + } else if (!volume.disk().has_persistence()) { + return Error("'persistence' is not set in DiskInfo"); + } + } + + return None(); +} + + Option<Error> validate(const RepeatedPtrField<Resource>& resources) { Option<Error> error = Resources::validate(resources); @@ -516,7 +532,29 @@ Option<Error> validate( namespace operation { -// TODO(jieyu): Added validate functions for Offer operations. +Option<Error> validate( + const Offer::Operation::Create& create, + const Resources& checkpointedResources) +{ + Option<Error> error = resource::validate(create.volumes()); + if (error.isSome()) { + return Error("Invalid resources: " + error.get().message); + } + + error = resource::validatePersistentVolume(create.volumes()); + if (error.isSome()) { + return Error("Not a persistent volume: " + error.get().message); + } + + error = resource::validateUniquePersistenceID( + checkpointedResources + create.volumes()); + + if (error.isSome()) { + return error; + } + + return None(); +} } // namespace operation { http://git-wip-us.apache.org/repos/asf/mesos/blob/66157a6c/src/master/validation.hpp ---------------------------------------------------------------------- diff --git a/src/master/validation.hpp b/src/master/validation.hpp index 642c375..81dc7ee 100644 --- a/src/master/validation.hpp +++ b/src/master/validation.hpp @@ -81,7 +81,11 @@ Option<Error> validate( namespace operation { -// TODO(jieyu): Added validate functions for Offer operations. +// Validates the CREATE operation. We need slave's checkpointed +// resources so that we can validate persistence ID uniqueness. +Option<Error> validate( + const Offer::Operation::Create& create, + const Resources& checkpointedResources); } // namespace operation { http://git-wip-us.apache.org/repos/asf/mesos/blob/66157a6c/src/tests/master_validation_tests.cpp ---------------------------------------------------------------------- diff --git a/src/tests/master_validation_tests.cpp b/src/tests/master_validation_tests.cpp new file mode 100644 index 0000000..1277311 --- /dev/null +++ b/src/tests/master_validation_tests.cpp @@ -0,0 +1,156 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <google/protobuf/repeated_field.h> + +#include <gtest/gtest.h> + +#include <mesos/mesos.hpp> +#include <mesos/resources.hpp> + +#include <stout/gtest.hpp> + +#include "master/validation.hpp" + +#include "tests/mesos.hpp" + +using namespace mesos; +using namespace mesos::internal::tests; +using namespace mesos::internal::master::validation; + +using google::protobuf::RepeatedPtrField; + + +class ResourceValidationTest : public ::testing::Test +{ +protected: + RepeatedPtrField<Resource> CreateResources(const Resource& resource) + { + RepeatedPtrField<Resource> resources; + resources.Add()->CopyFrom(resource); + return resources; + } +}; + + +TEST_F(ResourceValidationTest, PersistentVolume) +{ + Resource volume = Resources::parse("disk", "128", "role1").get(); + volume.mutable_disk()->CopyFrom(createDiskInfo("id1", "path1")); + + EXPECT_NONE(resource::validate(CreateResources(volume))); +} + + +TEST_F(ResourceValidationTest, UnreservedDiskInfo) +{ + Resource volume = Resources::parse("disk", "128", "*").get(); + volume.mutable_disk()->CopyFrom(createDiskInfo("id1", "path1")); + + EXPECT_SOME(resource::validate(CreateResources(volume))); +} + + +TEST_F(ResourceValidationTest, InvalidPersistenceID) +{ + Resource volume = Resources::parse("disk", "128", "role1").get(); + volume.mutable_disk()->CopyFrom(createDiskInfo("id1/", "path1")); + + EXPECT_SOME(resource::validate(CreateResources(volume))); +} + + +TEST_F(ResourceValidationTest, PersistentVolumeWithoutVolumeInfo) +{ + Resource volume = Resources::parse("disk", "128", "role1").get(); + volume.mutable_disk()->CopyFrom(createDiskInfo("id1", None())); + + EXPECT_SOME(resource::validate(CreateResources(volume))); +} + + +TEST_F(ResourceValidationTest, ReadOnlyPersistentVolume) +{ + Resource volume = Resources::parse("disk", "128", "role1").get(); + volume.mutable_disk()->CopyFrom(createDiskInfo("id1", "path1", Volume::RO)); + + EXPECT_SOME(resource::validate(CreateResources(volume))); +} + + +TEST_F(ResourceValidationTest, PersistentVolumeWithHostPath) +{ + Resource volume = Resources::parse("disk", "128", "role1").get(); + volume.mutable_disk()->CopyFrom( + createDiskInfo("id1", "path1", Volume::RW, "foo")); + + EXPECT_SOME(resource::validate(CreateResources(volume))); +} + + +TEST_F(ResourceValidationTest, NonPersistentVolume) +{ + Resource volume = Resources::parse("disk", "128", "role1").get(); + volume.mutable_disk()->CopyFrom(createDiskInfo(None(), "path1")); + + EXPECT_SOME(resource::validate(CreateResources(volume))); +} + + +class CreateOperationValidationTest : public ::testing::Test {}; + + +// This test verifies that all resources specified in the CREATE +// operation are persistent volumes. +TEST_F(CreateOperationValidationTest, PersistentVolumes) +{ + Resource volume = Resources::parse("disk", "128", "role1").get(); + volume.mutable_disk()->CopyFrom(createDiskInfo("id1", "path1")); + + Offer::Operation::Create create; + create.add_volumes()->CopyFrom(volume); + + EXPECT_NONE(operation::validate(create, Resources())); + + Resource cpus = Resources::parse("cpus", "2", "*").get(); + + create.add_volumes()->CopyFrom(cpus); + + EXPECT_SOME(operation::validate(create, Resources())); +} + + +TEST_F(CreateOperationValidationTest, DuplicatedPersistenceID) +{ + Resource volume1 = Resources::parse("disk", "128", "role1").get(); + volume1.mutable_disk()->CopyFrom(createDiskInfo("id1", "path1")); + + Offer::Operation::Create create; + create.add_volumes()->CopyFrom(volume1); + + EXPECT_NONE(operation::validate(create, Resources())); + + Resource volume2 = Resources::parse("disk", "64", "role1").get(); + volume2.mutable_disk()->CopyFrom(createDiskInfo("id1", "path1")); + + EXPECT_SOME(operation::validate(create, volume1)); + + create.add_volumes()->CopyFrom(volume2); + + EXPECT_SOME(operation::validate(create, Resources())); +} http://git-wip-us.apache.org/repos/asf/mesos/blob/66157a6c/src/tests/resource_offers_tests.cpp ---------------------------------------------------------------------- diff --git a/src/tests/resource_offers_tests.cpp b/src/tests/resource_offers_tests.cpp index 24a7eab..3e529ba 100644 --- a/src/tests/resource_offers_tests.cpp +++ b/src/tests/resource_offers_tests.cpp @@ -553,446 +553,6 @@ TEST_F(TaskValidationTest, ExecutorInfoDiffersOnDifferentSlaves) } -// TODO(jieyu): Disable all persistent volume related tests for now. -// Those tests should be moved to OfferOperationValidationTest. -TEST_F(TaskValidationTest, DISABLED_UnreservedDiskInfo) -{ - Try<PID<Master>> master = StartMaster(); - ASSERT_SOME(master); - - Try<PID<Slave>> slave = StartSlave(); - ASSERT_SOME(slave); - - MockScheduler sched; - MesosSchedulerDriver driver( - &sched, DEFAULT_FRAMEWORK_INFO, master.get(), DEFAULT_CREDENTIAL); - - EXPECT_CALL(sched, registered(&driver, _, _)) - .Times(1); - - Future<vector<Offer>> offers; - EXPECT_CALL(sched, resourceOffers(&driver, _)) - .WillOnce(FutureArg<1>(&offers)) - .WillRepeatedly(Return()); // Ignore subsequent offers. - - driver.start(); - - AWAIT_READY(offers); - EXPECT_NE(0u, offers.get().size()); - - // Create a persistent volume with "*" role. - Resource diskResource = Resources::parse("disk", "128", "*").get(); - diskResource.mutable_disk()->CopyFrom(createDiskInfo("1", "1")); - - // Include other resources in task resources. - Resources taskResources = - Resources::parse("cpus:1;mem:128").get() + diskResource; - - Offer offer = offers.get()[0]; - TaskInfo task = - createTask(offer.slave_id(), taskResources, "", DEFAULT_EXECUTOR_ID); - - vector<TaskInfo> tasks; - tasks.push_back(task); - - Future<TaskStatus> status; - EXPECT_CALL(sched, statusUpdate(&driver, _)) - .WillOnce(FutureArg<1>(&status)); - - driver.launchTasks(offer.id(), tasks); - - AWAIT_READY(status); - EXPECT_EQ(task.task_id(), status.get().task_id()); - EXPECT_EQ(TASK_ERROR, status.get().state()); - EXPECT_EQ(TaskStatus::REASON_TASK_INVALID, status.get().reason()); - EXPECT_TRUE(status.get().has_message()); - EXPECT_TRUE(strings::contains( - status.get().message(), - "Persistent disk volume is disallowed for '*' role")); - - driver.stop(); - driver.join(); - - Shutdown(); -} - - -TEST_F(TaskValidationTest, DISABLED_InvalidPersistenceID) -{ - Try<PID<Master>> master = StartMaster(); - ASSERT_SOME(master); - - Try<PID<Slave>> slave = StartSlave(); - ASSERT_SOME(slave); - - MockScheduler sched; - MesosSchedulerDriver driver( - &sched, DEFAULT_FRAMEWORK_INFO, master.get(), DEFAULT_CREDENTIAL); - - EXPECT_CALL(sched, registered(&driver, _, _)) - .Times(1); - - Future<vector<Offer>> offers; - EXPECT_CALL(sched, resourceOffers(&driver, _)) - .WillOnce(FutureArg<1>(&offers)) - .WillRepeatedly(Return()); // Ignore subsequent offers. - - driver.start(); - - AWAIT_READY(offers); - EXPECT_NE(0u, offers.get().size()); - - // Create a persistent volume with an invalid persistence id. - Resource diskResource = Resources::parse("disk", "128", "role1").get(); - diskResource.mutable_disk()->CopyFrom(createDiskInfo("1/", "1")); - - // Include other resources in task resources. - Resources taskResources = - Resources::parse("cpus:1;mem:128").get() + diskResource; - - Offer offer = offers.get()[0]; - TaskInfo task = - createTask(offer.slave_id(), taskResources, "", DEFAULT_EXECUTOR_ID); - - vector<TaskInfo> tasks; - tasks.push_back(task); - - Future<TaskStatus> status; - EXPECT_CALL(sched, statusUpdate(&driver, _)) - .WillOnce(FutureArg<1>(&status)); - - driver.launchTasks(offer.id(), tasks); - - AWAIT_READY(status); - EXPECT_EQ(task.task_id(), status.get().task_id()); - EXPECT_EQ(TASK_ERROR, status.get().state()); - EXPECT_EQ(TaskStatus::REASON_TASK_INVALID, status.get().reason()); - EXPECT_TRUE(status.get().has_message()); - EXPECT_TRUE(strings::contains( - status.get().message(), - "Persistence ID '1/' contains invalid characters")); - - driver.stop(); - driver.join(); - - Shutdown(); -} - - -TEST_F(TaskValidationTest, DISABLED_PersistentDiskInfoWithoutVolume) -{ - Try<PID<Master>> master = StartMaster(); - ASSERT_SOME(master); - - Try<PID<Slave>> slave = StartSlave(); - ASSERT_SOME(slave); - - MockScheduler sched; - MesosSchedulerDriver driver( - &sched, DEFAULT_FRAMEWORK_INFO, master.get(), DEFAULT_CREDENTIAL); - - EXPECT_CALL(sched, registered(&driver, _, _)) - .Times(1); - - Future<vector<Offer>> offers; - EXPECT_CALL(sched, resourceOffers(&driver, _)) - .WillOnce(FutureArg<1>(&offers)) - .WillRepeatedly(Return()); // Ignore subsequent offers. - - driver.start(); - - AWAIT_READY(offers); - EXPECT_NE(0u, offers.get().size()); - - // Create a persistent volume no volume information. - Resource diskResource = Resources::parse("disk", "128", "role1").get(); - diskResource.mutable_disk()->CopyFrom(createDiskInfo("1", None())); - - // Include other resources in task resources. - Resources taskResources = - Resources::parse("cpus:1;mem:128").get() + diskResource; - - Offer offer = offers.get()[0]; - TaskInfo task = - createTask(offer.slave_id(), taskResources, "", DEFAULT_EXECUTOR_ID); - - vector<TaskInfo> tasks; - tasks.push_back(task); - - Future<TaskStatus> status; - EXPECT_CALL(sched, statusUpdate(&driver, _)) - .WillOnce(FutureArg<1>(&status)); - - driver.launchTasks(offer.id(), tasks); - - AWAIT_READY(status); - EXPECT_EQ(task.task_id(), status.get().task_id()); - EXPECT_EQ(TASK_ERROR, status.get().state()); - EXPECT_EQ(TaskStatus::REASON_TASK_INVALID, status.get().reason()); - EXPECT_TRUE(status.get().has_message()); - EXPECT_TRUE(strings::contains( - status.get().message(), - "Persistent disk should specify a volume")); - - driver.stop(); - driver.join(); - - Shutdown(); -} - - -TEST_F(TaskValidationTest, DISABLED_PersistentDiskInfoWithReadOnlyVolume) -{ - Try<PID<Master>> master = StartMaster(); - ASSERT_SOME(master); - - Try<PID<Slave>> slave = StartSlave(); - ASSERT_SOME(slave); - - MockScheduler sched; - MesosSchedulerDriver driver( - &sched, DEFAULT_FRAMEWORK_INFO, master.get(), DEFAULT_CREDENTIAL); - - EXPECT_CALL(sched, registered(&driver, _, _)) - .Times(1); - - Future<vector<Offer>> offers; - EXPECT_CALL(sched, resourceOffers(&driver, _)) - .WillOnce(FutureArg<1>(&offers)) - .WillRepeatedly(Return()); // Ignore subsequent offers. - - driver.start(); - - AWAIT_READY(offers); - EXPECT_NE(0u, offers.get().size()); - - // Create a read-only persistent volume. - Resource diskResource = Resources::parse("disk", "128", "role1").get(); - diskResource.mutable_disk()->CopyFrom(createDiskInfo("1", "1", Volume::RO)); - - // Include other resources in task resources. - Resources taskResources = - Resources::parse("cpus:1;mem:128").get() + diskResource; - - Offer offer = offers.get()[0]; - TaskInfo task = - createTask(offer.slave_id(), taskResources, "", DEFAULT_EXECUTOR_ID); - - vector<TaskInfo> tasks; - tasks.push_back(task); - - Future<TaskStatus> status; - EXPECT_CALL(sched, statusUpdate(&driver, _)) - .WillOnce(FutureArg<1>(&status)); - - driver.launchTasks(offer.id(), tasks); - - AWAIT_READY(status); - EXPECT_EQ(task.task_id(), status.get().task_id()); - EXPECT_EQ(TASK_ERROR, status.get().state()); - EXPECT_EQ(TaskStatus::REASON_TASK_INVALID, status.get().reason()); - EXPECT_TRUE(status.get().has_message()); - EXPECT_TRUE(strings::contains( - status.get().message(), - "Read-only volume is not supported for DiskInfo")); - - driver.stop(); - driver.join(); - - Shutdown(); -} - - -TEST_F(TaskValidationTest, DISABLED_PersistentDiskInfoWithHostPath) -{ - Try<PID<Master>> master = StartMaster(); - ASSERT_SOME(master); - - Try<PID<Slave>> slave = StartSlave(); - ASSERT_SOME(slave); - - MockScheduler sched; - MesosSchedulerDriver driver( - &sched, DEFAULT_FRAMEWORK_INFO, master.get(), DEFAULT_CREDENTIAL); - - EXPECT_CALL(sched, registered(&driver, _, _)) - .Times(1); - - Future<vector<Offer>> offers; - EXPECT_CALL(sched, resourceOffers(&driver, _)) - .WillOnce(FutureArg<1>(&offers)) - .WillRepeatedly(Return()); // Ignore subsequent offers. - - driver.start(); - - AWAIT_READY(offers); - EXPECT_NE(0u, offers.get().size()); - - // Create a persistent volume with host path. - Resource diskResource = Resources::parse("disk", "128", "role1").get(); - diskResource.mutable_disk()->CopyFrom( - createDiskInfo("1", "1", Volume::RW, "foo")); - - // Include other resources in task resources. - Resources taskResources = - Resources::parse("cpus:1;mem:128").get() + diskResource; - - Offer offer = offers.get()[0]; - TaskInfo task = - createTask(offer.slave_id(), taskResources, "", DEFAULT_EXECUTOR_ID); - - vector<TaskInfo> tasks; - tasks.push_back(task); - - Future<TaskStatus> status; - EXPECT_CALL(sched, statusUpdate(&driver, _)) - .WillOnce(FutureArg<1>(&status)); - - driver.launchTasks(offer.id(), tasks); - - AWAIT_READY(status); - EXPECT_EQ(task.task_id(), status.get().task_id()); - EXPECT_EQ(TASK_ERROR, status.get().state()); - EXPECT_EQ(TaskStatus::REASON_TASK_INVALID, status.get().reason()); - EXPECT_TRUE(status.get().has_message()); - EXPECT_TRUE(strings::contains( - status.get().message(), - "Volume in DiskInfo should not have 'host_path' set")); - - driver.stop(); - driver.join(); - - Shutdown(); -} - - -TEST_F(TaskValidationTest, DISABLED_NonPersistentDiskInfoWithVolume) -{ - Try<PID<Master>> master = StartMaster(); - ASSERT_SOME(master); - - Try<PID<Slave>> slave = StartSlave(); - ASSERT_SOME(slave); - - MockScheduler sched; - MesosSchedulerDriver driver( - &sched, DEFAULT_FRAMEWORK_INFO, master.get(), DEFAULT_CREDENTIAL); - - EXPECT_CALL(sched, registered(&driver, _, _)) - .Times(1); - - Future<vector<Offer>> offers; - EXPECT_CALL(sched, resourceOffers(&driver, _)) - .WillOnce(FutureArg<1>(&offers)) - .WillRepeatedly(Return()); // Ignore subsequent offers. - - driver.start(); - - AWAIT_READY(offers); - EXPECT_NE(0u, offers.get().size()); - - // Create a non-persistent volume. - Resource diskResource = Resources::parse("disk", "128", "role1").get(); - diskResource.mutable_disk()->CopyFrom(createDiskInfo(None(), "1")); - - // Include other resources in task resources. - Resources taskResources = - Resources::parse("cpus:1;mem:128").get() + diskResource; - - Offer offer = offers.get()[0]; - TaskInfo task = - createTask(offer.slave_id(), taskResources, "", DEFAULT_EXECUTOR_ID); - - vector<TaskInfo> tasks; - tasks.push_back(task); - - Future<TaskStatus> status; - EXPECT_CALL(sched, statusUpdate(&driver, _)) - .WillOnce(FutureArg<1>(&status)); - - driver.launchTasks(offer.id(), tasks); - - AWAIT_READY(status); - EXPECT_EQ(task.task_id(), status.get().task_id()); - EXPECT_EQ(TASK_ERROR, status.get().state()); - EXPECT_EQ(TaskStatus::REASON_TASK_INVALID, status.get().reason()); - EXPECT_TRUE(status.get().has_message()); - EXPECT_TRUE(strings::contains( - status.get().message(), - "Non-persistent volume is not supported")); - - driver.stop(); - driver.join(); - - Shutdown(); -} - - -TEST_F(TaskValidationTest, DISABLED_DuplicatedPersistenceIDWithinTask) -{ - Try<PID<Master>> master = StartMaster(); - ASSERT_SOME(master); - - Try<PID<Slave>> slave = StartSlave(); - ASSERT_SOME(slave); - - MockScheduler sched; - MesosSchedulerDriver driver( - &sched, DEFAULT_FRAMEWORK_INFO, master.get(), DEFAULT_CREDENTIAL); - - EXPECT_CALL(sched, registered(&driver, _, _)) - .Times(1); - - Future<vector<Offer>> offers; - EXPECT_CALL(sched, resourceOffers(&driver, _)) - .WillOnce(FutureArg<1>(&offers)) - .WillRepeatedly(Return()); // Ignore subsequent offers. - - driver.start(); - - AWAIT_READY(offers); - EXPECT_NE(0u, offers.get().size()); - - // Create two persistent volumes with the same id. - Resource diskResource1 = Resources::parse("disk", "128", "role1").get(); - diskResource1.mutable_disk()->CopyFrom(createDiskInfo("1", "1")); - - Resource diskResource2 = Resources::parse("disk", "64", "role1").get(); - diskResource2.mutable_disk()->CopyFrom(createDiskInfo("1", "1")); - - // Include other resources in task resources. - Resources taskResources = - Resources::parse("cpus:1;mem:128").get() + diskResource1 + diskResource2; - - Offer offer = offers.get()[0]; - TaskInfo task = - createTask(offer.slave_id(), taskResources, "", DEFAULT_EXECUTOR_ID); - - vector<TaskInfo> tasks; - tasks.push_back(task); - - Future<TaskStatus> status; - EXPECT_CALL(sched, statusUpdate(&driver, _)) - .WillOnce(FutureArg<1>(&status)); - - driver.launchTasks(offer.id(), tasks); - - AWAIT_READY(status); - EXPECT_EQ(task.task_id(), status.get().task_id()); - EXPECT_EQ(TASK_ERROR, status.get().state()); - EXPECT_EQ(TaskStatus::REASON_TASK_INVALID, status.get().reason()); - EXPECT_TRUE(status.get().has_message()); - EXPECT_TRUE(strings::contains( - status.get().message(), - "Task uses duplicated persistence ID 1")); - - driver.stop(); - driver.join(); - - Shutdown(); -} - - // This test ensures that a persistent volume that is larger than the // offered disk resources results in a failed task. TEST_F(TaskValidationTest, DISABLED_AcquirePersistentDiskTooBig)
