/Users/deen/code/yugabyte-db/src/yb/util/result-test.cc
Line | Count | Source (jump to first uncovered line) |
1 | | // |
2 | | // Copyright (c) YugaByte, Inc. |
3 | | // |
4 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
5 | | // in compliance with the License. You may obtain a copy of the License at |
6 | | // |
7 | | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
10 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
11 | | // or implied. See the License for the specific language governing permissions and limitations |
12 | | // under the License. |
13 | | // |
14 | | // |
15 | | |
16 | | #include "yb/util/result.h" |
17 | | #include "yb/util/test_util.h" |
18 | | |
19 | | namespace yb { |
20 | | namespace test { |
21 | | |
22 | | class ResultTest : public YBTest { |
23 | | }; |
24 | | |
25 | | namespace { |
26 | | |
27 | | template<class TValue> |
28 | 16 | void CheckResultIsStatus(const yb::Result<TValue>& result) { |
29 | 16 | ASSERT_FALSE(result.ok()); |
30 | 16 | ASSERT_FALSE(result); |
31 | 16 | ASSERT_TRUE(!result); |
32 | 16 | ASSERT_TRUE(result.status().IsRuntimeError()); |
33 | 16 | } result-test.cc:_ZN2yb4test12_GLOBAL__N_119CheckResultIsStatusIiEEvRKNS_6ResultIT_EE Line | Count | Source | 28 | 8 | void CheckResultIsStatus(const yb::Result<TValue>& result) { | 29 | 8 | ASSERT_FALSE(result.ok()); | 30 | 8 | ASSERT_FALSE(result); | 31 | 8 | ASSERT_TRUE(!result); | 32 | 8 | ASSERT_TRUE(result.status().IsRuntimeError()); | 33 | 8 | } |
result-test.cc:_ZN2yb4test12_GLOBAL__N_119CheckResultIsStatusINSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEEEvRKNS_6ResultIT_EE Line | Count | Source | 28 | 8 | void CheckResultIsStatus(const yb::Result<TValue>& result) { | 29 | 8 | ASSERT_FALSE(result.ok()); | 30 | 8 | ASSERT_FALSE(result); | 31 | 8 | ASSERT_TRUE(!result); | 32 | 8 | ASSERT_TRUE(result.status().IsRuntimeError()); | 33 | 8 | } |
|
34 | | |
35 | 8 | void CheckResultIsStatus(const yb::Result<bool>& result) { |
36 | 8 | ASSERT_FALSE(result.ok()); |
37 | 8 | ASSERT_TRUE(result.status().IsRuntimeError()); |
38 | 8 | } |
39 | | |
40 | | template<class TValue> |
41 | 16 | void CheckResultIsValue(const yb::Result<TValue>& result, const TValue& value) { |
42 | 16 | ASSERT_TRUE(result.ok()); |
43 | 16 | ASSERT_TRUE(result ? true : false); |
44 | 16 | ASSERT_FALSE(!result); |
45 | 16 | CHECK_EQ(*result, value); |
46 | 16 | } result-test.cc:_ZN2yb4test12_GLOBAL__N_118CheckResultIsValueIiEEvRKNS_6ResultIT_EERKS4_ Line | Count | Source | 41 | 8 | void CheckResultIsValue(const yb::Result<TValue>& result, const TValue& value) { | 42 | 8 | ASSERT_TRUE(result.ok()); | 43 | 8 | ASSERT_TRUE(result ? true : false); | 44 | 8 | ASSERT_FALSE(!result); | 45 | 8 | CHECK_EQ(*result, value); | 46 | 8 | } |
result-test.cc:_ZN2yb4test12_GLOBAL__N_118CheckResultIsValueINSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEEEvRKNS_6ResultIT_EERKSB_ Line | Count | Source | 41 | 8 | void CheckResultIsValue(const yb::Result<TValue>& result, const TValue& value) { | 42 | 8 | ASSERT_TRUE(result.ok()); | 43 | 8 | ASSERT_TRUE(result ? true : false); | 44 | 8 | ASSERT_FALSE(!result); | 45 | 8 | CHECK_EQ(*result, value); | 46 | 8 | } |
|
47 | | |
48 | 8 | void CheckResultIsValue(const yb::Result<bool>& result, bool value) { |
49 | 8 | ASSERT_TRUE(result.ok()); |
50 | 8 | CHECK_EQ(result.get(), value); |
51 | 8 | } |
52 | | |
53 | | template<class TValue, class Checker> |
54 | 6 | void CheckFromResult(const yb::Result<TValue>& result, const Checker& checker) { |
55 | 6 | typedef yb::Result<TValue> Result; |
56 | | |
57 | 6 | Result result3(result); // Copy from result |
58 | 6 | checker(result3); |
59 | | |
60 | 6 | Result result4(std::move(result)); // Move from result |
61 | 6 | checker(result4); |
62 | | |
63 | 6 | result3 = result4; // Assign from result |
64 | 6 | checker(result3); |
65 | | |
66 | 6 | result3 = std::move(result4); // Move assign from result |
67 | 6 | checker(result3); |
68 | 6 | } result-test.cc:_ZN2yb4test12_GLOBAL__N_115CheckFromResultIiZNS1_11CheckStatusIiEEvvEUlRKT_E_EEvRKNS_6ResultIS4_EERKT0_ Line | Count | Source | 54 | 1 | void CheckFromResult(const yb::Result<TValue>& result, const Checker& checker) { | 55 | 1 | typedef yb::Result<TValue> Result; | 56 | | | 57 | 1 | Result result3(result); // Copy from result | 58 | 1 | checker(result3); | 59 | | | 60 | 1 | Result result4(std::move(result)); // Move from result | 61 | 1 | checker(result4); | 62 | | | 63 | 1 | result3 = result4; // Assign from result | 64 | 1 | checker(result3); | 65 | | | 66 | 1 | result3 = std::move(result4); // Move assign from result | 67 | 1 | checker(result3); | 68 | 1 | } |
result-test.cc:_ZN2yb4test12_GLOBAL__N_115CheckFromResultINSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEZNS1_11CheckStatusIS9_EEvvEUlRKT_E_EEvRKNS_6ResultISB_EERKT0_ Line | Count | Source | 54 | 1 | void CheckFromResult(const yb::Result<TValue>& result, const Checker& checker) { | 55 | 1 | typedef yb::Result<TValue> Result; | 56 | | | 57 | 1 | Result result3(result); // Copy from result | 58 | 1 | checker(result3); | 59 | | | 60 | 1 | Result result4(std::move(result)); // Move from result | 61 | 1 | checker(result4); | 62 | | | 63 | 1 | result3 = result4; // Assign from result | 64 | 1 | checker(result3); | 65 | | | 66 | 1 | result3 = std::move(result4); // Move assign from result | 67 | 1 | checker(result3); | 68 | 1 | } |
result-test.cc:_ZN2yb4test12_GLOBAL__N_115CheckFromResultIbZNS1_11CheckStatusIbEEvvEUlRKT_E_EEvRKNS_6ResultIS4_EERKT0_ Line | Count | Source | 54 | 1 | void CheckFromResult(const yb::Result<TValue>& result, const Checker& checker) { | 55 | 1 | typedef yb::Result<TValue> Result; | 56 | | | 57 | 1 | Result result3(result); // Copy from result | 58 | 1 | checker(result3); | 59 | | | 60 | 1 | Result result4(std::move(result)); // Move from result | 61 | 1 | checker(result4); | 62 | | | 63 | 1 | result3 = result4; // Assign from result | 64 | 1 | checker(result3); | 65 | | | 66 | 1 | result3 = std::move(result4); // Move assign from result | 67 | 1 | checker(result3); | 68 | 1 | } |
result-test.cc:_ZN2yb4test12_GLOBAL__N_115CheckFromResultIiZNS1_10CheckValueIiEEvT_EUlRKS4_E_EEvRKNS_6ResultIS4_EERKT0_ Line | Count | Source | 54 | 1 | void CheckFromResult(const yb::Result<TValue>& result, const Checker& checker) { | 55 | 1 | typedef yb::Result<TValue> Result; | 56 | | | 57 | 1 | Result result3(result); // Copy from result | 58 | 1 | checker(result3); | 59 | | | 60 | 1 | Result result4(std::move(result)); // Move from result | 61 | 1 | checker(result4); | 62 | | | 63 | 1 | result3 = result4; // Assign from result | 64 | 1 | checker(result3); | 65 | | | 66 | 1 | result3 = std::move(result4); // Move assign from result | 67 | 1 | checker(result3); | 68 | 1 | } |
result-test.cc:_ZN2yb4test12_GLOBAL__N_115CheckFromResultINSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEZNS1_10CheckValueIS9_EEvT_EUlRKSB_E_EEvRKNS_6ResultISB_EERKT0_ Line | Count | Source | 54 | 1 | void CheckFromResult(const yb::Result<TValue>& result, const Checker& checker) { | 55 | 1 | typedef yb::Result<TValue> Result; | 56 | | | 57 | 1 | Result result3(result); // Copy from result | 58 | 1 | checker(result3); | 59 | | | 60 | 1 | Result result4(std::move(result)); // Move from result | 61 | 1 | checker(result4); | 62 | | | 63 | 1 | result3 = result4; // Assign from result | 64 | 1 | checker(result3); | 65 | | | 66 | 1 | result3 = std::move(result4); // Move assign from result | 67 | 1 | checker(result3); | 68 | 1 | } |
result-test.cc:_ZN2yb4test12_GLOBAL__N_115CheckFromResultIbZNS1_10CheckValueIbEEvT_EUlRKS4_E_EEvRKNS_6ResultIS4_EERKT0_ Line | Count | Source | 54 | 1 | void CheckFromResult(const yb::Result<TValue>& result, const Checker& checker) { | 55 | 1 | typedef yb::Result<TValue> Result; | 56 | | | 57 | 1 | Result result3(result); // Copy from result | 58 | 1 | checker(result3); | 59 | | | 60 | 1 | Result result4(std::move(result)); // Move from result | 61 | 1 | checker(result4); | 62 | | | 63 | 1 | result3 = result4; // Assign from result | 64 | 1 | checker(result3); | 65 | | | 66 | 1 | result3 = std::move(result4); // Move assign from result | 67 | 1 | checker(result3); | 68 | 1 | } |
|
69 | | |
70 | | template<class TValue> |
71 | 3 | void CheckStatus() { |
72 | 3 | typedef yb::Result<TValue> Result; |
73 | 3 | Status status = STATUS(RuntimeError, ""); |
74 | 3 | Status status2 = status; |
75 | 3 | Status status3 = status; |
76 | | |
77 | 3 | Result result(status); // Copy from status |
78 | 3 | CheckResultIsStatus(result); |
79 | | |
80 | 3 | Result result2(std::move(status2)); // Move from status |
81 | 3 | CheckResultIsStatus(result2); |
82 | | |
83 | 3 | result = status; // Assign from status |
84 | 3 | CheckResultIsStatus(result); |
85 | | |
86 | 3 | result = std::move(status3); // Move assign from status |
87 | 3 | CheckResultIsStatus(result); |
88 | | |
89 | 12 | CheckFromResult(result, [](const auto& result) { CheckResultIsStatus(result); }); result-test.cc:_ZZN2yb4test12_GLOBAL__N_111CheckStatusIiEEvvENKUlRKT_E_clINS_6ResultIiEEEEDaS5_ Line | Count | Source | 89 | 4 | CheckFromResult(result, [](const auto& result) { CheckResultIsStatus(result); }); |
result-test.cc:_ZZN2yb4test12_GLOBAL__N_111CheckStatusINSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEEEvvENKUlRKT_E_clINS_6ResultIS9_EEEEDaSC_ Line | Count | Source | 89 | 4 | CheckFromResult(result, [](const auto& result) { CheckResultIsStatus(result); }); |
result-test.cc:_ZZN2yb4test12_GLOBAL__N_111CheckStatusIbEEvvENKUlRKT_E_clINS_6ResultIbEEEEDaS5_ Line | Count | Source | 89 | 4 | CheckFromResult(result, [](const auto& result) { CheckResultIsStatus(result); }); |
|
90 | 3 | } result-test.cc:_ZN2yb4test12_GLOBAL__N_111CheckStatusIiEEvv Line | Count | Source | 71 | 1 | void CheckStatus() { | 72 | 1 | typedef yb::Result<TValue> Result; | 73 | 1 | Status status = STATUS(RuntimeError, ""); | 74 | 1 | Status status2 = status; | 75 | 1 | Status status3 = status; | 76 | | | 77 | 1 | Result result(status); // Copy from status | 78 | 1 | CheckResultIsStatus(result); | 79 | | | 80 | 1 | Result result2(std::move(status2)); // Move from status | 81 | 1 | CheckResultIsStatus(result2); | 82 | | | 83 | 1 | result = status; // Assign from status | 84 | 1 | CheckResultIsStatus(result); | 85 | | | 86 | 1 | result = std::move(status3); // Move assign from status | 87 | 1 | CheckResultIsStatus(result); | 88 | | | 89 | 1 | CheckFromResult(result, [](const auto& result) { CheckResultIsStatus(result); }); | 90 | 1 | } |
result-test.cc:_ZN2yb4test12_GLOBAL__N_111CheckStatusINSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEEEvv Line | Count | Source | 71 | 1 | void CheckStatus() { | 72 | 1 | typedef yb::Result<TValue> Result; | 73 | 1 | Status status = STATUS(RuntimeError, ""); | 74 | 1 | Status status2 = status; | 75 | 1 | Status status3 = status; | 76 | | | 77 | 1 | Result result(status); // Copy from status | 78 | 1 | CheckResultIsStatus(result); | 79 | | | 80 | 1 | Result result2(std::move(status2)); // Move from status | 81 | 1 | CheckResultIsStatus(result2); | 82 | | | 83 | 1 | result = status; // Assign from status | 84 | 1 | CheckResultIsStatus(result); | 85 | | | 86 | 1 | result = std::move(status3); // Move assign from status | 87 | 1 | CheckResultIsStatus(result); | 88 | | | 89 | 1 | CheckFromResult(result, [](const auto& result) { CheckResultIsStatus(result); }); | 90 | 1 | } |
result-test.cc:_ZN2yb4test12_GLOBAL__N_111CheckStatusIbEEvv Line | Count | Source | 71 | 1 | void CheckStatus() { | 72 | 1 | typedef yb::Result<TValue> Result; | 73 | 1 | Status status = STATUS(RuntimeError, ""); | 74 | 1 | Status status2 = status; | 75 | 1 | Status status3 = status; | 76 | | | 77 | 1 | Result result(status); // Copy from status | 78 | 1 | CheckResultIsStatus(result); | 79 | | | 80 | 1 | Result result2(std::move(status2)); // Move from status | 81 | 1 | CheckResultIsStatus(result2); | 82 | | | 83 | 1 | result = status; // Assign from status | 84 | 1 | CheckResultIsStatus(result); | 85 | | | 86 | 1 | result = std::move(status3); // Move assign from status | 87 | 1 | CheckResultIsStatus(result); | 88 | | | 89 | 1 | CheckFromResult(result, [](const auto& result) { CheckResultIsStatus(result); }); | 90 | 1 | } |
|
91 | | |
92 | | template<class TValue> |
93 | 3 | void CheckValue(TValue value) { |
94 | 3 | typedef yb::Result<TValue> Result; |
95 | | |
96 | 3 | static_assert(sizeof(Result) == sizeof(void*) + std::max(sizeof(TValue), sizeof(void*)), |
97 | 3 | "Invalid Result size"); |
98 | | |
99 | 3 | auto value2 = value; |
100 | 3 | auto value3 = value; |
101 | | |
102 | 3 | Result result(value); // Copy from value |
103 | 3 | CheckResultIsValue(result, value); |
104 | | |
105 | 3 | Result result2(std::move(value2)); // Move from value |
106 | 3 | CheckResultIsValue(result2, value); |
107 | | |
108 | 3 | result = value; // Assign from value |
109 | 3 | CheckResultIsValue(result, value); |
110 | | |
111 | 3 | result = std::move(value3); // Move assign from value |
112 | 3 | CheckResultIsValue(result, value); |
113 | | |
114 | 12 | CheckFromResult(result, [value](const auto& res) { CheckResultIsValue(res, value); }); result-test.cc:_ZZN2yb4test12_GLOBAL__N_110CheckValueIiEEvT_ENKUlRKS3_E_clINS_6ResultIiEEEEDaS5_ Line | Count | Source | 114 | 4 | CheckFromResult(result, [value](const auto& res) { CheckResultIsValue(res, value); }); |
result-test.cc:_ZZN2yb4test12_GLOBAL__N_110CheckValueINSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEEEvT_ENKUlRKSA_E_clINS_6ResultIS9_EEEEDaSC_ Line | Count | Source | 114 | 4 | CheckFromResult(result, [value](const auto& res) { CheckResultIsValue(res, value); }); |
result-test.cc:_ZZN2yb4test12_GLOBAL__N_110CheckValueIbEEvT_ENKUlRKS3_E_clINS_6ResultIbEEEEDaS5_ Line | Count | Source | 114 | 4 | CheckFromResult(result, [value](const auto& res) { CheckResultIsValue(res, value); }); |
|
115 | 3 | } result-test.cc:_ZN2yb4test12_GLOBAL__N_110CheckValueIiEEvT_ Line | Count | Source | 93 | 1 | void CheckValue(TValue value) { | 94 | 1 | typedef yb::Result<TValue> Result; | 95 | | | 96 | 1 | static_assert(sizeof(Result) == sizeof(void*) + std::max(sizeof(TValue), sizeof(void*)), | 97 | 1 | "Invalid Result size"); | 98 | | | 99 | 1 | auto value2 = value; | 100 | 1 | auto value3 = value; | 101 | | | 102 | 1 | Result result(value); // Copy from value | 103 | 1 | CheckResultIsValue(result, value); | 104 | | | 105 | 1 | Result result2(std::move(value2)); // Move from value | 106 | 1 | CheckResultIsValue(result2, value); | 107 | | | 108 | 1 | result = value; // Assign from value | 109 | 1 | CheckResultIsValue(result, value); | 110 | | | 111 | 1 | result = std::move(value3); // Move assign from value | 112 | 1 | CheckResultIsValue(result, value); | 113 | | | 114 | 1 | CheckFromResult(result, [value](const auto& res) { CheckResultIsValue(res, value); }); | 115 | 1 | } |
result-test.cc:_ZN2yb4test12_GLOBAL__N_110CheckValueINSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEEEvT_ Line | Count | Source | 93 | 1 | void CheckValue(TValue value) { | 94 | 1 | typedef yb::Result<TValue> Result; | 95 | | | 96 | 1 | static_assert(sizeof(Result) == sizeof(void*) + std::max(sizeof(TValue), sizeof(void*)), | 97 | 1 | "Invalid Result size"); | 98 | | | 99 | 1 | auto value2 = value; | 100 | 1 | auto value3 = value; | 101 | | | 102 | 1 | Result result(value); // Copy from value | 103 | 1 | CheckResultIsValue(result, value); | 104 | | | 105 | 1 | Result result2(std::move(value2)); // Move from value | 106 | 1 | CheckResultIsValue(result2, value); | 107 | | | 108 | 1 | result = value; // Assign from value | 109 | 1 | CheckResultIsValue(result, value); | 110 | | | 111 | 1 | result = std::move(value3); // Move assign from value | 112 | 1 | CheckResultIsValue(result, value); | 113 | | | 114 | 1 | CheckFromResult(result, [value](const auto& res) { CheckResultIsValue(res, value); }); | 115 | 1 | } |
result-test.cc:_ZN2yb4test12_GLOBAL__N_110CheckValueIbEEvT_ Line | Count | Source | 93 | 1 | void CheckValue(TValue value) { | 94 | 1 | typedef yb::Result<TValue> Result; | 95 | | | 96 | 1 | static_assert(sizeof(Result) == sizeof(void*) + std::max(sizeof(TValue), sizeof(void*)), | 97 | 1 | "Invalid Result size"); | 98 | | | 99 | 1 | auto value2 = value; | 100 | 1 | auto value3 = value; | 101 | | | 102 | 1 | Result result(value); // Copy from value | 103 | 1 | CheckResultIsValue(result, value); | 104 | | | 105 | 1 | Result result2(std::move(value2)); // Move from value | 106 | 1 | CheckResultIsValue(result2, value); | 107 | | | 108 | 1 | result = value; // Assign from value | 109 | 1 | CheckResultIsValue(result, value); | 110 | | | 111 | 1 | result = std::move(value3); // Move assign from value | 112 | 1 | CheckResultIsValue(result, value); | 113 | | | 114 | 1 | CheckFromResult(result, [value](const auto& res) { CheckResultIsValue(res, value); }); | 115 | 1 | } |
|
116 | | |
117 | 5 | Result<std::string&> GetStringReference() { |
118 | 5 | static std::string result = "shared string"; |
119 | 5 | return result; |
120 | 5 | } |
121 | | |
122 | 1 | Result<std::string&> GetBadStringReference() { |
123 | 1 | return STATUS(RuntimeError, "Just for test"); |
124 | 1 | } |
125 | | |
126 | 2 | Result<const std::string&> GetConstStringReference() { |
127 | 2 | return GetStringReference(); |
128 | 2 | } |
129 | | |
130 | | } // namespace |
131 | | |
132 | 1 | TEST_F(ResultTest, Status) { |
133 | 1 | CheckStatus<int>(); |
134 | 1 | CheckStatus<std::string>(); |
135 | 1 | CheckStatus<bool>(); |
136 | 1 | } |
137 | | |
138 | 1 | TEST_F(ResultTest, Result) { |
139 | 1 | const std::string kString = "Hello World!"; |
140 | 1 | CheckValue(42); |
141 | 1 | CheckValue(std::string(kString)); |
142 | 1 | CheckValue(true); |
143 | 1 | yb::Result<std::string> result(kString); |
144 | 1 | ASSERT_TRUE(result.ok()); |
145 | 1 | ASSERT_EQ(result->size(), kString.size()); // Check of operator-> |
146 | 1 | } |
147 | | |
148 | 1 | TEST_F(ResultTest, NonCopyable) { |
149 | 1 | Result<std::unique_ptr<int>> ptr = std::make_unique<int>(42); |
150 | 1 | Result<std::unique_ptr<int>> ptr2(std::move(ptr)); |
151 | 1 | ASSERT_OK(ptr2); |
152 | | |
153 | 1 | std::unique_ptr<int>& unique = *ptr2; |
154 | 1 | ASSERT_EQ(42, *unique); |
155 | 1 | } |
156 | | |
157 | 1 | TEST_F(ResultTest, Reference) { |
158 | 1 | LOG(INFO) << GetStringReference(); |
159 | 1 | LOG(INFO) << GetConstStringReference(); |
160 | 1 | auto result = GetStringReference(); |
161 | 1 | auto const_result = GetConstStringReference(); |
162 | | |
163 | 1 | static_assert(sizeof(result) == 2 * sizeof(void*), "Invalid Result size"); |
164 | | |
165 | 1 | ASSERT_OK(result); |
166 | 1 | Result<std::string&> result2(result); |
167 | 1 | const_result = result; |
168 | 1 | const_result = std::move(result); |
169 | 1 | result = GetBadStringReference(); |
170 | 1 | ASSERT_NOK(result); |
171 | 1 | auto status = std::move(result.status()); |
172 | 1 | ASSERT_NOK(status); |
173 | 1 | result = GetStringReference(); |
174 | 1 | ASSERT_OK(result); |
175 | 1 | } |
176 | | |
177 | 3 | Result<std::unique_ptr<int>> ReturnVariable() { |
178 | 3 | std::unique_ptr<int> result; |
179 | 3 | result = std::make_unique<int>(42); |
180 | 3 | return result; |
181 | 3 | } |
182 | | |
183 | | // Test that we could return non-copyable variable of type T from function with return type |
184 | | // Result<T>. |
185 | 1 | TEST_F(ResultTest, ReturnVariable) { |
186 | 1 | auto ptr = ASSERT_RESULT(ReturnVariable()); |
187 | 1 | ASSERT_EQ(42, *ptr); |
188 | 1 | } |
189 | | |
190 | 1 | Result<std::unique_ptr<int>> ReturnBadVariable() { |
191 | 1 | return STATUS(RuntimeError, "Just for test"); |
192 | 1 | } |
193 | | |
194 | 2 | Status test_function(int* num_func_calls, std::unique_ptr<int> ptr) { |
195 | 2 | ++(*CHECK_NOTNULL(num_func_calls)); |
196 | 2 | LOG(INFO) << "Called test_function() (call number " << *num_func_calls << ") with arg=" << *ptr; |
197 | 2 | EXPECT_EQ(42, *ptr); |
198 | 2 | return *num_func_calls == 1 ? |
199 | 1 | Status::OK() : STATUS(InternalError, "test_function() returned a error"); |
200 | 2 | } |
201 | | |
202 | | template<typename F, typename GetResult> |
203 | 3 | Status GetStatus(int* num_func_calls, F f, GetResult get_result) { |
204 | 3 | RETURN_NOT_OK(f(num_func_calls, VERIFY_RESULT(get_result()))); |
205 | 1 | return Status::OK(); |
206 | 3 | } |
207 | | |
208 | 1 | TEST_F(ResultTest, VerifyResultMacro) { |
209 | 1 | int num_func_calls = 0; |
210 | | // Good way - no returns from the macros. |
211 | 1 | Status s = GetStatus(&num_func_calls, test_function, ReturnVariable); |
212 | 1 | LOG(INFO) << "GetStatus() returned status=" << s; |
213 | 1 | ASSERT_EQ(1, num_func_calls); |
214 | 1 | ASSERT_TRUE(s.ok()); |
215 | | |
216 | | // Bad way 1 - exit from VERIFY_RESULT(). |
217 | 1 | s = GetStatus(&num_func_calls, test_function, ReturnBadVariable); |
218 | 1 | LOG(INFO) << "GetStatus() returned status=" << s; |
219 | 1 | ASSERT_EQ(1, num_func_calls); |
220 | 1 | ASSERT_TRUE(s.IsRuntimeError()); |
221 | | |
222 | | // Bad way 2 - exit from RETURN_NOT_OK(). |
223 | 1 | s = GetStatus(&num_func_calls, test_function, ReturnVariable); |
224 | 1 | LOG(INFO) << "GetStatus() returned status=" << s; |
225 | 1 | ASSERT_EQ(2, num_func_calls); |
226 | 1 | ASSERT_TRUE(s.IsInternalError()); |
227 | 1 | } |
228 | | |
229 | | struct NonCopyableNonMovable { |
230 | | NonCopyableNonMovable() = default; |
231 | | NonCopyableNonMovable(const NonCopyableNonMovable&) = delete; |
232 | | NonCopyableNonMovable& operator=(const NonCopyableNonMovable&) = delete; |
233 | | }; |
234 | | |
235 | | class MoveCounter { |
236 | | public: |
237 | | MoveCounter() = default; |
238 | | MoveCounter(const MoveCounter&) = delete; |
239 | | |
240 | 2 | MoveCounter(const MoveCounter&&) { |
241 | 2 | ++counter_; |
242 | 2 | } |
243 | | |
244 | | MoveCounter& operator=(const MoveCounter&) = delete; |
245 | | |
246 | 0 | MoveCounter& operator=(MoveCounter&&) { |
247 | 0 | ++counter_; |
248 | 0 | return *this; |
249 | 0 | } |
250 | | |
251 | 1 | static size_t counter() { |
252 | 1 | return counter_; |
253 | 1 | } |
254 | | |
255 | | private: |
256 | | static size_t counter_; |
257 | | }; |
258 | | |
259 | | size_t MoveCounter::counter_ = 0; |
260 | | |
261 | | // Next function won't compile in case VERIFY_RESULT will try to create copy of Result's data |
262 | 1 | Status VerifyResultMacroReferenceNoCopyHelper() { |
263 | 1 | static const NonCopyableNonMovable data; |
264 | 1 | const auto& r ATTRIBUTE_UNUSED = VERIFY_RESULT_REF(Result<const NonCopyableNonMovable&>(data)); |
265 | 1 | return Status::OK(); |
266 | 1 | } |
267 | | |
268 | 1 | Status VerifyResultMacroMoveCountHelper() { |
269 | 1 | const auto result ATTRIBUTE_UNUSED = VERIFY_RESULT(Result<MoveCounter>(MoveCounter())); |
270 | 1 | return Status::OK(); |
271 | 1 | } |
272 | | |
273 | 1 | TEST_F(ResultTest, VerifyResultMacroReferenceNoCopy) { |
274 | 1 | ASSERT_OK(VerifyResultMacroReferenceNoCopyHelper()); |
275 | 1 | } |
276 | | |
277 | 1 | TEST_F(ResultTest, VerifyResultMacroMoveCount) { |
278 | 1 | ASSERT_OK(VerifyResultMacroMoveCountHelper()); |
279 | 1 | ASSERT_EQ(2, MoveCounter::counter()); |
280 | 1 | } |
281 | | |
282 | | } // namespace test |
283 | | } // namespace yb |