1 /*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "utils/base/status.h"
18
19 #include "utils/base/logging.h"
20 #include "utils/base/status_macros.h"
21 #include "gtest/gtest.h"
22
23 namespace libtextclassifier3 {
24 namespace {
25
TEST(StatusTest,PrintsAbortedStatus)26 TEST(StatusTest, PrintsAbortedStatus) {
27 logging::LoggingStringStream stream;
28 stream << Status::UNKNOWN;
29 EXPECT_EQ(Status::UNKNOWN.error_code(), 2);
30 EXPECT_EQ(Status::UNKNOWN.CanonicalCode(), StatusCode::UNKNOWN);
31 EXPECT_EQ(Status::UNKNOWN.error_message(), "");
32 EXPECT_EQ(stream.message, "2");
33 }
34
TEST(StatusTest,PrintsOKStatus)35 TEST(StatusTest, PrintsOKStatus) {
36 logging::LoggingStringStream stream;
37 stream << Status::OK;
38 EXPECT_EQ(Status::OK.error_code(), 0);
39 EXPECT_EQ(Status::OK.CanonicalCode(), StatusCode::OK);
40 EXPECT_EQ(Status::OK.error_message(), "");
41 EXPECT_EQ(stream.message, "0");
42 }
43
TEST(StatusTest,UnknownStatusHasRightAttributes)44 TEST(StatusTest, UnknownStatusHasRightAttributes) {
45 EXPECT_EQ(Status::UNKNOWN.error_code(), 2);
46 EXPECT_EQ(Status::UNKNOWN.CanonicalCode(), StatusCode::UNKNOWN);
47 EXPECT_EQ(Status::UNKNOWN.error_message(), "");
48 }
49
TEST(StatusTest,OkStatusHasRightAttributes)50 TEST(StatusTest, OkStatusHasRightAttributes) {
51 EXPECT_EQ(Status::OK.error_code(), 0);
52 EXPECT_EQ(Status::OK.CanonicalCode(), StatusCode::OK);
53 EXPECT_EQ(Status::OK.error_message(), "");
54 }
55
TEST(StatusTest,CustomStatusHasRightAttributes)56 TEST(StatusTest, CustomStatusHasRightAttributes) {
57 Status status(StatusCode::INVALID_ARGUMENT, "You can't put this here!");
58 EXPECT_EQ(status.error_code(), 3);
59 EXPECT_EQ(status.CanonicalCode(), StatusCode::INVALID_ARGUMENT);
60 EXPECT_EQ(status.error_message(), "You can't put this here!");
61 }
62
TEST(StatusTest,AssignmentPreservesMembers)63 TEST(StatusTest, AssignmentPreservesMembers) {
64 Status status(StatusCode::INVALID_ARGUMENT, "You can't put this here!");
65
66 Status status2 = status;
67
68 EXPECT_EQ(status2.error_code(), 3);
69 EXPECT_EQ(status2.CanonicalCode(), StatusCode::INVALID_ARGUMENT);
70 EXPECT_EQ(status2.error_message(), "You can't put this here!");
71 }
72
TEST(StatusTest,ReturnIfErrorOkStatus)73 TEST(StatusTest, ReturnIfErrorOkStatus) {
74 bool returned_due_to_error = true;
75 auto lambda = [&returned_due_to_error](const Status& s) {
76 TC3_RETURN_IF_ERROR(s);
77 returned_due_to_error = false;
78 return Status::OK;
79 };
80
81 // OK should allow execution to continue and the returned status should also
82 // be OK.
83 Status status = lambda(Status());
84 EXPECT_EQ(status.error_code(), 0);
85 EXPECT_EQ(status.CanonicalCode(), StatusCode::OK);
86 EXPECT_EQ(status.error_message(), "");
87 EXPECT_FALSE(returned_due_to_error);
88 }
89
TEST(StatusTest,ReturnIfErrorInvalidArgumentStatus)90 TEST(StatusTest, ReturnIfErrorInvalidArgumentStatus) {
91 bool returned_due_to_error = true;
92 auto lambda = [&returned_due_to_error](const Status& s) {
93 TC3_RETURN_IF_ERROR(s);
94 returned_due_to_error = false;
95 return Status::OK;
96 };
97
98 // INVALID_ARGUMENT should cause an early return.
99 Status invalid_arg_status(StatusCode::INVALID_ARGUMENT, "You can't do that!");
100 Status status = lambda(invalid_arg_status);
101 EXPECT_EQ(status.error_code(), 3);
102 EXPECT_EQ(status.CanonicalCode(), StatusCode::INVALID_ARGUMENT);
103 EXPECT_EQ(status.error_message(), "You can't do that!");
104 EXPECT_TRUE(returned_due_to_error);
105 }
106
TEST(StatusTest,ReturnIfErrorUnknownStatus)107 TEST(StatusTest, ReturnIfErrorUnknownStatus) {
108 bool returned_due_to_error = true;
109 auto lambda = [&returned_due_to_error](const Status& s) {
110 TC3_RETURN_IF_ERROR(s);
111 returned_due_to_error = false;
112 return Status::OK;
113 };
114
115 // UNKNOWN should cause an early return.
116 Status unknown_status(StatusCode::UNKNOWN,
117 "We also know there are known unknowns.");
118 libtextclassifier3::Status status = lambda(unknown_status);
119 EXPECT_EQ(status.error_code(), 2);
120 EXPECT_EQ(status.CanonicalCode(), StatusCode::UNKNOWN);
121 EXPECT_EQ(status.error_message(), "We also know there are known unknowns.");
122 EXPECT_TRUE(returned_due_to_error);
123 }
124
TEST(StatusTest,ReturnIfErrorOnlyInvokesExpressionOnce)125 TEST(StatusTest, ReturnIfErrorOnlyInvokesExpressionOnce) {
126 int num_invocations = 0;
127 auto ok_internal_expr = [&num_invocations]() {
128 ++num_invocations;
129 return Status::OK;
130 };
131 auto ok_lambda = [&ok_internal_expr]() {
132 TC3_RETURN_IF_ERROR(ok_internal_expr());
133 return Status::OK;
134 };
135
136 libtextclassifier3::Status status = ok_lambda();
137 EXPECT_EQ(status.CanonicalCode(), StatusCode::OK);
138 EXPECT_EQ(num_invocations, 1);
139
140 num_invocations = 0;
141 auto error_internal_expr = [&num_invocations]() {
142 ++num_invocations;
143 return Status::UNKNOWN;
144 };
145 auto error_lambda = [&error_internal_expr]() {
146 TC3_RETURN_IF_ERROR(error_internal_expr());
147 return Status::OK;
148 };
149
150 status = error_lambda();
151 EXPECT_EQ(status.CanonicalCode(), StatusCode::UNKNOWN);
152 EXPECT_EQ(num_invocations, 1);
153 }
154
155 } // namespace
156 } // namespace libtextclassifier3
157