• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 The Abseil Authors.
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 "absl/base/internal/strerror.h"
16 
17 #include <atomic>
18 #include <cerrno>
19 #include <cstdio>
20 #include <cstring>
21 #include <string>
22 #include <thread>  // NOLINT(build/c++11)
23 #include <vector>
24 
25 #include "gmock/gmock.h"
26 #include "gtest/gtest.h"
27 #include "absl/strings/match.h"
28 
29 namespace {
30 using ::testing::AnyOf;
31 using ::testing::Eq;
32 
TEST(StrErrorTest,ValidErrorCode)33 TEST(StrErrorTest, ValidErrorCode) {
34   errno = ERANGE;
35   EXPECT_THAT(absl::base_internal::StrError(EDOM), Eq(strerror(EDOM)));
36   EXPECT_THAT(errno, Eq(ERANGE));
37 }
38 
TEST(StrErrorTest,InvalidErrorCode)39 TEST(StrErrorTest, InvalidErrorCode) {
40   errno = ERANGE;
41   EXPECT_THAT(absl::base_internal::StrError(-1),
42               AnyOf(Eq("No error information"), Eq("Unknown error -1")));
43   EXPECT_THAT(errno, Eq(ERANGE));
44 }
45 
TEST(StrErrorTest,MultipleThreads)46 TEST(StrErrorTest, MultipleThreads) {
47   // In this test, we will start up 2 threads and have each one call
48   // StrError 1000 times, each time with a different errnum.  We
49   // expect that StrError(errnum) will return a string equal to the
50   // one returned by strerror(errnum), if the code is known.  Since
51   // strerror is known to be thread-hostile, collect all the expected
52   // strings up front.
53   const int kNumCodes = 1000;
54   std::vector<std::string> expected_strings(kNumCodes);
55   for (int i = 0; i < kNumCodes; ++i) {
56     expected_strings[i] = strerror(i);
57   }
58 
59   std::atomic_int counter(0);
60   auto thread_fun = [&]() {
61     for (int i = 0; i < kNumCodes; ++i) {
62       ++counter;
63       errno = ERANGE;
64       const std::string value = absl::base_internal::StrError(i);
65       // Only the GNU implementation is guaranteed to provide the
66       // string "Unknown error nnn". POSIX doesn't say anything.
67       if (!absl::StartsWith(value, "Unknown error ")) {
68         EXPECT_THAT(absl::base_internal::StrError(i), Eq(expected_strings[i]));
69       }
70       EXPECT_THAT(errno, Eq(ERANGE));
71     }
72   };
73 
74   const int kNumThreads = 100;
75   std::vector<std::thread> threads;
76   for (int i = 0; i < kNumThreads; ++i) {
77     threads.push_back(std::thread(thread_fun));
78   }
79   for (auto& thread : threads) {
80     thread.join();
81   }
82 
83   EXPECT_THAT(counter, Eq(kNumThreads * kNumCodes));
84 }
85 
86 }  // namespace
87