1 // Copyright 2019 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "sandboxed_api/util/strerror.h"
16
17 #include <atomic>
18 #include <cerrno>
19 #include <cstring>
20 #include <string>
21 #include <thread> // NOLINT(build/c++11)
22 #include <vector>
23
24 #include "gmock/gmock.h"
25 #include "gtest/gtest.h"
26 #include "absl/strings/match.h"
27
28 namespace sapi {
29 namespace {
30
31 using ::testing::Eq;
32 using ::testing::StrEq;
33
TEST(StrErrorTest,ValidErrorCode)34 TEST(StrErrorTest, ValidErrorCode) {
35 errno = EAGAIN;
36 EXPECT_THAT(StrError(EINTR), StrEq(strerror(EINTR)));
37 EXPECT_THAT(errno, Eq(EAGAIN));
38 }
39
TEST(StrErrorTest,InvalidErrorCode)40 TEST(StrErrorTest, InvalidErrorCode) {
41 errno = EBUSY;
42 EXPECT_THAT(StrError(-1), StrEq("Unknown error -1"));
43 EXPECT_THAT(errno, Eq(EBUSY));
44 }
45
TEST(StrErrorTest,MultipleThreads)46 TEST(StrErrorTest, MultipleThreads) {
47 // In this test, we will start up 2 threads and have each one call StrError
48 // 1000 times, each time with a different errnum. We expect that
49 // StrError(errnum) will return a string equal to the one returned by
50 // strerror(errnum), if the code is known. Since strerror is known to be
51 // thread-hostile, collect all the expected strings up front.
52 constexpr int kNumCodes = 1000;
53 std::vector<std::string> expected_strings(kNumCodes);
54 for (int i = 0; i < kNumCodes; ++i) {
55 expected_strings[i] = strerror(i);
56 }
57
58 std::atomic<int> counter{0};
59 auto thread_fun = [&counter, &expected_strings]() {
60 for (int i = 0; i < kNumCodes; ++i) {
61 ++counter;
62 std::string value = StrError(i);
63 if (!absl::StartsWith(value, "Unknown error ")) {
64 EXPECT_THAT(StrError(i), StrEq(expected_strings[i]));
65 }
66 }
67 };
68
69 constexpr int kNumThreads = 100;
70 std::vector<std::thread> threads;
71 for (int i = 0; i < kNumThreads; ++i) {
72 threads.push_back(std::thread(thread_fun));
73 }
74 for (auto& thread : threads) {
75 thread.join();
76 }
77
78 EXPECT_THAT(counter, Eq(kNumThreads * kNumCodes));
79 }
80
81 } // namespace
82 } // namespace sapi
83