Software APIs
status_report_unittest.cc
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
5 #include <iostream>
6 #include <vector>
7 
8 #include "gtest/gtest.h"
9 #include "sw/device/lib/base/status.h"
10 #include "sw/device/lib/base/status_report_unittest_c.h"
11 
12 namespace status_list_unittest {
13 namespace {
14 
15 // Stack trace stored as a vector for easy access.
16 std::vector<status_t> StatusList;
17 
18 // Implement the stack tracing facility.
19 extern "C" void status_report(status_t code) { StatusList.push_back(code); }
20 
21 const status_t kExpectedList[] = {
22  // The first entry of the list should correspond to the entry pushed by
23  // status_report(OK_STATUS(300));
24  // at line 38 to make sure that the report can handle OK statuses as well.
25  status_create(absl_status_t::kOk, 0, "", 654321),
26  // The next entry of the list should correspond to the TRY() at line 19:
27  // TRY(sudo_god());
28  // where the module ID is "psy" and the error is PERMISSION_DENIED().
29  status_create(absl_status_t::kPermissionDenied,
30  MAKE_MODULE_ID('p', 's', 'y'), "", 21),
31  // The think() function does not use TRY() and instead returns ABORTED()
32  // so it creates no entry.
33  // The next entry is created by the TRY() at line 34:
34  // TRY(think());
35  // where the module ID is "unt" and the error is ABORTED().
36  status_create(absl_status_t::kAborted, MAKE_MODULE_ID('u', 'n', 't'), "",
37  41),
38  // The last entry is the one we push in the test: this is the error
39  // returned by status_report_unittest_c() that comes from think()
40  // at line 27 with error code ABORTED() and module ID "thk".
41  status_create(absl_status_t::kAborted, MAKE_MODULE_ID('t', 'h', 'k'), "",
42  29),
43 };
44 
45 std::string status_to_string(status_t status) {
46  int32_t arg;
47  const char *message;
48  char mod_id[4];
49  std::stringstream oss;
50  if (status_extract(status, &message, &arg, mod_id)) {
51  mod_id[3] = 0;
52  oss << message << "(" << arg << ") in " << mod_id;
53  } else {
54  oss << "Ok(" << arg << ")";
55  }
56  return oss.str();
57 }
58 
59 TEST(StackTrace, Trace) {
60  // The unit test exercises the TRY() macro that only works in C code.
61  status_t status = status_report_unittest_c();
62 
63  // We push the status on the stack just to make checking below easier
64  status_report(status);
65 
66  EXPECT_EQ(StatusList.size(), ARRAYSIZE(kExpectedList));
67 
68  for (size_t i = 0; i < StatusList.size(); i++) {
69  EXPECT_EQ(StatusList[i].value, kExpectedList[i].value)
70  << "GOT " << status_to_string(StatusList[i]) << ", EXPECTED "
71  << status_to_string(kExpectedList[i]);
72  }
73 }
74 
75 } // namespace
76 } // namespace status_list_unittest