Software APIs
status_debug_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 <array>
6 
7 #include "gmock/gmock.h"
8 #include "gtest/gtest.h"
9 #include "sw/device/lib/crypto/impl/status.h"
10 
11 // NOTE: This test does not verify hardening measures; it only checks that the
12 // "normal" contract of the functions is upheld.
13 
14 namespace status_unittest {
15 namespace {
16 
17 TEST(Status, OkIsNonHardenedOk) { EXPECT_EQ(status_ok(OTCRYPTO_OK), true); }
18 
19 TEST(Status, ErrorMacrosNotOk) {
20  // Error macros should evaluate to non-OK statuses.
21  EXPECT_EQ(status_ok(OTCRYPTO_BAD_ARGS), false);
22  EXPECT_EQ(status_ok(OTCRYPTO_RECOV_ERR), false);
23  EXPECT_EQ(status_ok(OTCRYPTO_FATAL_ERR), false);
24  EXPECT_EQ(status_ok(OTCRYPTO_ASYNC_INCOMPLETE), false);
25 }
26 
27 TEST(Status, ErrorMacrosNotHardenedOk) {
28  // Error macros should evaluate to non-OK statuses.
29  EXPECT_EQ(status_ok(OTCRYPTO_BAD_ARGS), false);
30  EXPECT_EQ(status_ok(OTCRYPTO_RECOV_ERR), false);
31  EXPECT_EQ(status_ok(OTCRYPTO_FATAL_ERR), false);
32  EXPECT_EQ(status_ok(OTCRYPTO_ASYNC_INCOMPLETE), false);
33 }
34 
35 TEST(Status, ErrorMacrosHaveExpectedValues) {
36  // Error macros should evaluate to specific Abseil error codes.
37  EXPECT_EQ(status_err(OTCRYPTO_BAD_ARGS), kInvalidArgument);
38  EXPECT_EQ(status_err(OTCRYPTO_RECOV_ERR), kAborted);
39  EXPECT_EQ(status_err(OTCRYPTO_FATAL_ERR), kFailedPrecondition);
40  EXPECT_EQ(status_err(OTCRYPTO_ASYNC_INCOMPLETE), kUnavailable);
41  EXPECT_EQ(status_err(OTCRYPTO_NOT_IMPLEMENTED), kUnimplemented);
42 }
43 
44 __attribute__((noinline)) otcrypto_status_t try_interpret(status_t status) {
45  HARDENED_TRY(status);
46  return OTCRYPTO_OK;
47 }
48 
49 TEST(Status, TryInterpretOk) {
50  // Hardened OK should result in an OK status.
51  EXPECT_EQ(status_ok(try_interpret(OTCRYPTO_OK)), true);
52 }
53 
54 TEST(Status, TryInterpretNonHardenedOk) {
55  // Non-hardened OK should result in an error.
56  EXPECT_EQ(status_ok(try_interpret(OK_STATUS())), false);
57 }
58 
59 constexpr char kTestModId[3] = {'X', 'Y', 'Z'};
60 #define MODULE_ID MAKE_MODULE_ID(kTestModId[0], kTestModId[1], kTestModId[2])
61 
62 TEST(Status, ExtractStatusFieldsBadArgs) {
63  const char *code = NULL;
64  char mod_id[3] = {0};
65  int32_t line = 0;
66  const char expected_code[] = "InvalidArgument";
67  int32_t expected_line = __LINE__ + 1;
68  EXPECT_EQ(status_extract(OTCRYPTO_BAD_ARGS, &code, &line, mod_id), true);
69 
70  // Check the fields to ensure that the format of cryptolib errors matches the
71  // error format from the main status library.
72  EXPECT_EQ(memcmp(code, expected_code, ARRAYSIZE(expected_code)), 0);
73  EXPECT_THAT(mod_id, testing::ElementsAreArray(kTestModId));
74  EXPECT_EQ(line, expected_line);
75 }
76 
77 TEST(Status, ExtractStatusFieldsRecovErr) {
78  const char *code = NULL;
79  char mod_id[3] = {0};
80  int32_t line = 0;
81  const char expected_code[] = "Aborted";
82  int32_t expected_line = __LINE__ + 1;
83  EXPECT_EQ(status_extract(OTCRYPTO_RECOV_ERR, &code, &line, mod_id), true);
84 
85  // Check the fields to ensure that the format of cryptolib errors matches the
86  // error format from the main status library.
87  EXPECT_EQ(memcmp(code, expected_code, ARRAYSIZE(expected_code)), 0);
88  EXPECT_THAT(mod_id, testing::ElementsAreArray(kTestModId));
89  EXPECT_EQ(line, expected_line);
90 }
91 
92 TEST(Status, ExtractStatusFieldsFatalErr) {
93  const char *code = NULL;
94  char mod_id[3] = {0};
95  int32_t line = 0;
96  const char expected_code[] = "FailedPrecondition";
97  int32_t expected_line = __LINE__ + 1;
98  EXPECT_EQ(status_extract(OTCRYPTO_FATAL_ERR, &code, &line, mod_id), true);
99 
100  // Check the fields to ensure that the format of cryptolib errors matches the
101  // error format from the main status library.
102  EXPECT_EQ(memcmp(code, expected_code, ARRAYSIZE(expected_code)), 0);
103  EXPECT_THAT(mod_id, testing::ElementsAreArray(kTestModId));
104  EXPECT_EQ(line, expected_line);
105 }
106 
107 TEST(Status, ExtractStatusFieldsAsyncIncomplete) {
108  const char *code = NULL;
109  char mod_id[3] = {0};
110  int32_t line = 0;
111  const char expected_code[] = "Unavailable";
112  int32_t expected_line = __LINE__ + 1;
113  EXPECT_EQ(status_extract(OTCRYPTO_ASYNC_INCOMPLETE, &code, &line, mod_id),
114  true);
115 
116  // Check the fields to ensure that the format of cryptolib errors matches the
117  // error format from the main status library.
118  EXPECT_EQ(memcmp(code, expected_code, ARRAYSIZE(expected_code)), 0);
119  EXPECT_THAT(mod_id, testing::ElementsAreArray(kTestModId));
120  EXPECT_EQ(line, expected_line);
121 }
122 
123 } // namespace
124 } // namespace status_unittest