28 explicit ScopedTestFd(
int fd) : fd_(fd) {}
35 bool IsValid()
const {
return fd_ >= 0; }
56 EXPECT_TRUE(slot1.IsValid());
57 EXPECT_FALSE(slot1.IsImplicit());
58 EXPECT_TRUE(slot1.IsExplicit());
59 EXPECT_EQ(10u, slot1.GetExplicitValue());
62 EXPECT_TRUE(slot2.IsValid());
63 EXPECT_FALSE(slot2.IsImplicit());
64 EXPECT_TRUE(slot2.IsExplicit());
65 EXPECT_EQ(42u, slot2.GetExplicitValue());
68 slot2 = std::move(slot1);
69 EXPECT_FALSE(slot1.IsValid());
70 EXPECT_TRUE(slot2.IsValid());
71 EXPECT_TRUE(slot2.IsExplicit());
72 ASSERT_EQ(10u, slot2.GetExplicitValue());
74 slot1 = std::move(slot0);
76 EXPECT_TRUE(slot1.IsValid());
77 EXPECT_TRUE(slot1.IsImplicit());
78 EXPECT_FALSE(slot1.IsExplicit());
116 EXPECT_EQ(
"foo", config.
path);
124 EXPECT_EQ(
"foo", config.
path);
132 EXPECT_EQ(
"foo", config.
path);
139 "-one-flag --jobserver-auth=fifo:foo", &config, &error));
147 EXPECT_EQ(
"semaphore_name", config.
path);
170 "--jobserver-auth=10,42 --jobserver-fds=12,44 "
171 "--jobserver-auth=fifo:/tmp/fifo",
174 EXPECT_EQ(
"/tmp/fifo", config.
path);
180 EXPECT_EQ(
"Invalid file descriptor pair [10,]", error);
192 EXPECT_EQ(error,
"Pipe-based protocol is not supported!");
199 "--jobserver-auth=semaphore_name", &config, &error));
201 EXPECT_EQ(
"semaphore_name", config.
path);
208 EXPECT_EQ(error,
"FIFO mode is not supported on Windows!");
214 "--jobserver-auth=semaphore_name", &config, &error));
215 EXPECT_EQ(error,
"Semaphore mode is not supported on Posix!");
223 EXPECT_EQ(
"foo", config.
path);
232 std::unique_ptr<Jobserver::Client> client =
234 EXPECT_FALSE(client.get());
235 EXPECT_EQ(
"Unsupported jobserver mode", error);
243 struct ScopedSemaphoreHandle {
244 ScopedSemaphoreHandle(HANDLE handle) : handle_(handle) {}
245 ~ScopedSemaphoreHandle() {
247 ::CloseHandle(handle_);
249 HANDLE get()
const {
return handle_; }
252 HANDLE handle_ = NULL;
257 const size_t kExplicitCount = 10;
258 const char kSemaphoreName[] =
"ninja_test_jobserver_semaphore";
259 ScopedSemaphoreHandle handle(
260 ::CreateSemaphoreA(NULL,
static_cast<DWORD
>(kExplicitCount),
261 static_cast<DWORD
>(kExplicitCount), kSemaphoreName));
262 ASSERT_TRUE(handle.get()) << GetLastErrorString();
267 config.
path = kSemaphoreName;
270 std::unique_ptr<Jobserver::Client> client =
272 EXPECT_TRUE(client.get()) << error;
273 EXPECT_TRUE(error.empty()) << error;
276 std::vector<Jobserver::Slot> slots;
279 slot = client->TryAcquire();
282 slots.push_back(std::move(slot));
285 for (
size_t n = 0; n < kExplicitCount; ++n) {
286 slot = client->TryAcquire();
289 slots.push_back(std::move(slot));
293 slot = client->TryAcquire();
297 while (!slots.empty()) {
298 client->Release(std::move(slots.back()));
302 slot = client->TryAcquire();
305 slots.push_back(std::move(slot));
307 for (
size_t n = 0; n < kExplicitCount; ++n) {
308 slot = client->TryAcquire();
311 slots.push_back(std::move(slot));
315 slot = client->TryAcquire();
325 int ret = mknod(fifo_path.c_str(), S_IFIFO | 0666, 0);
326 ASSERT_EQ(0, ret) <<
"Could not create FIFO at: " << fifo_path;
328 const size_t kSlotCount = 5;
330 ScopedTestFd write_fd(::open(fifo_path.c_str(), O_RDWR));
331 ASSERT_TRUE(write_fd.IsValid()) <<
"Cannot open FIFO at: " << strerror(errno);
332 for (
size_t n = 0; n < kSlotCount; ++n) {
333 uint8_t slot_byte =
static_cast<uint8_t
>(
'0' + n);
334 ssize_t ret = ::write(write_fd.fd_, &slot_byte, 1);
343 config.
path = fifo_path;
346 std::unique_ptr<Jobserver::Client> client =
348 EXPECT_TRUE(client.get());
349 EXPECT_TRUE(error.empty()) << error;
352 std::vector<Jobserver::Slot> slots;
355 slots.push_back(client->TryAcquire());
356 ASSERT_TRUE(slots.back().IsValid());
357 EXPECT_TRUE(slots.back().IsImplicit());
360 for (
size_t n = 0; n < kSlotCount; ++n) {
362 ASSERT_TRUE(slot.
IsValid()) <<
"Slot #" << n + 1;
364 slots.push_back(std::move(slot));
378 int fd = ::open(file_path.c_str(), O_CREAT | O_RDWR, 0660);
379 ASSERT_GE(fd, 0) <<
"Could not create file: " << strerror(errno);
385 config.
path = file_path;
388 std::unique_ptr<Jobserver::Client> client =
390 EXPECT_FALSE(client.get());
391 EXPECT_FALSE(error.empty());
392 EXPECT_EQ(
"Not a fifo path: " + file_path, error);
398 EXPECT_FALSE(client.get());
399 EXPECT_FALSE(error.empty());
400 EXPECT_EQ(
"Empty fifo path", error);
static std::unique_ptr< Client > Create(const Config &, std::string *error)
Create a new Client instance from a given configuration.
TEST(Jobserver, SlotTest)
A Jobserver::Config models how to access or implement a GNU jobserver implementation.
std::string path
For kModeFifo, this is the path to the Unix FIFO to use.
Mode mode
Implementation mode for the pool.
A Jobserver::Slot models a single job slot that can be acquired from.
uint8_t GetExplicitValue() const
Return value of an explicit slot.
bool IsExplicit() const
Return true if this instance represents an explicit job slot.
static Slot CreateImplicit()
Create instance for the implicit value.
static Slot CreateExplicit(uint8_t value)
Create instance for explicit byte value.
bool IsImplicit() const
Return true if this instance represents an implicit job slot.
bool IsValid() const
Return true if this instance is valid, i.e.
Jobserver provides types related to managing a pool of "job slots" using the GNU Make jobserver ptoco...
static bool ParseNativeMakeFlagsValue(const char *makeflags_env, Config *config, std::string *error)
A variant of ParseMakeFlagsValue() that will return an error if the parsed result is not compatible w...
static bool ParseMakeFlagsValue(const char *makeflags_env, Config *config, std::string *error)
Parse the value of a MAKEFLAGS environment variable.
void CreateAndEnter(const std::string &name)
Create a temporary directory and chdir into it.
std::string temp_dir_name_
The subdirectory name for our dir, or empty if it hasn't been set up.