1 // SPDX-License-Identifier: Apache-2.0 2 // SPDX-FileCopyrightText: Copyright OpenBMC Authors 3 4 #include "utility.hpp" 5 6 #include <boost/system/result.hpp> 7 #include <boost/url/parse.hpp> 8 #include <boost/url/url.hpp> 9 #include <boost/url/url_view.hpp> 10 #include <nlohmann/json.hpp> 11 12 #include <algorithm> 13 #include <ctime> 14 #include <functional> 15 #include <string> 16 #include <string_view> 17 18 #include <gtest/gtest.h> 19 20 namespace crow::utility 21 { 22 namespace 23 { 24 25 TEST(Utility, Base64DecodeAuthString) 26 { 27 std::string authString("dXNlcm40bWU6cGFzc3cwcmQ="); 28 std::string result; 29 EXPECT_TRUE(base64Decode(authString, result)); 30 EXPECT_EQ(result, "usern4me:passw0rd"); 31 } 32 33 TEST(Utility, Base64DecodeUrlsafe) 34 { 35 std::string result; 36 EXPECT_TRUE(base64Decode<true>("-_abcde", result)); 37 EXPECT_EQ(result, "\xfb\xf6\x9b\x71\xd7"); 38 } 39 40 TEST(Utility, Base64DecodeNonAscii) 41 { 42 std::string junkString("\xff\xee\xdd\xcc\x01\x11\x22\x33"); 43 std::string result; 44 EXPECT_FALSE(base64Decode(junkString, result)); 45 } 46 47 TEST(Utility, Base64EncodeString) 48 { 49 using namespace std::string_literals; 50 std::string encoded; 51 52 encoded = base64encode(""); 53 EXPECT_EQ(encoded, ""); 54 55 encoded = base64encode("f"); 56 EXPECT_EQ(encoded, "Zg=="); 57 58 encoded = base64encode("f0"); 59 EXPECT_EQ(encoded, "ZjA="); 60 61 encoded = base64encode("f0\0"s); 62 EXPECT_EQ(encoded, "ZjAA"); 63 64 encoded = base64encode("f0\0 "s); 65 EXPECT_EQ(encoded, "ZjAAIA=="); 66 67 encoded = base64encode("f0\0 B"s); 68 EXPECT_EQ(encoded, "ZjAAIEI="); 69 70 encoded = base64encode("f0\0 Ba"s); 71 EXPECT_EQ(encoded, "ZjAAIEJh"); 72 73 encoded = base64encode("f0\0 Bar"s); 74 EXPECT_EQ(encoded, "ZjAAIEJhcg=="); 75 } 76 77 TEST(Utility, Base64Encoder) 78 { 79 using namespace std::string_literals; 80 std::string data = "f0\0 Bar"s; 81 for (size_t chunkSize = 1; chunkSize < 6; chunkSize++) 82 { 83 std::string_view testString(data); 84 std::string out; 85 Base64Encoder encoder; 86 while (!testString.empty()) 87 { 88 size_t thisChunk = std::min(testString.size(), chunkSize); 89 encoder.encode(testString.substr(0, thisChunk), out); 90 testString.remove_prefix(thisChunk); 91 } 92 93 encoder.finalize(out); 94 EXPECT_EQ(out, "ZjAAIEJhcg=="); 95 } 96 } 97 98 TEST(Utility, Base64EncodeDecodeString) 99 { 100 using namespace std::string_literals; 101 std::string data("Data fr\0m 90 reading a \nFile"s); 102 std::string encoded = base64encode(data); 103 std::string decoded; 104 EXPECT_TRUE(base64Decode(encoded, decoded)); 105 EXPECT_EQ(data, decoded); 106 } 107 108 TEST(Utility, CreateBasicAuthHeader) 109 { 110 std::string authHeader = createBasicAuthHeader("username", "password"); 111 EXPECT_EQ(authHeader, "Basic dXNlcm5hbWU6cGFzc3dvcmQ="); 112 } 113 114 TEST(Utility, readUrlSegments) 115 { 116 boost::system::result<boost::urls::url_view> parsed = 117 boost::urls::parse_relative_ref("/redfish/v1/Chassis"); 118 119 EXPECT_TRUE(readUrlSegments(*parsed, "redfish", "v1", "Chassis")); 120 121 EXPECT_FALSE(readUrlSegments(*parsed, "FOOBAR", "v1", "Chassis")); 122 123 EXPECT_FALSE(readUrlSegments(*parsed, "redfish", "v1")); 124 125 EXPECT_FALSE( 126 readUrlSegments(*parsed, "redfish", "v1", "Chassis", "FOOBAR")); 127 128 std::string out1; 129 std::string out2; 130 std::string out3; 131 EXPECT_TRUE(readUrlSegments(*parsed, "redfish", "v1", std::ref(out1))); 132 EXPECT_EQ(out1, "Chassis"); 133 134 out1 = out2 = out3 = ""; 135 EXPECT_TRUE(readUrlSegments(*parsed, std::ref(out1), std::ref(out2), 136 std::ref(out3))); 137 EXPECT_EQ(out1, "redfish"); 138 EXPECT_EQ(out2, "v1"); 139 EXPECT_EQ(out3, "Chassis"); 140 141 out1 = out2 = out3 = ""; 142 EXPECT_TRUE(readUrlSegments(*parsed, "redfish", std::ref(out1), "Chassis")); 143 EXPECT_EQ(out1, "v1"); 144 145 out1 = out2 = out3 = ""; 146 EXPECT_TRUE(readUrlSegments(*parsed, std::ref(out1), "v1", std::ref(out2))); 147 EXPECT_EQ(out1, "redfish"); 148 EXPECT_EQ(out2, "Chassis"); 149 150 EXPECT_FALSE(readUrlSegments(*parsed, "too", "short")); 151 152 EXPECT_FALSE(readUrlSegments(*parsed, "too", "long", "too", "long")); 153 154 EXPECT_FALSE( 155 readUrlSegments(*parsed, std::ref(out1), "v2", std::ref(out2))); 156 157 EXPECT_FALSE(readUrlSegments(*parsed, "redfish", std::ref(out1), 158 std::ref(out2), std::ref(out3))); 159 160 parsed = boost::urls::parse_relative_ref("/absolute/url"); 161 EXPECT_TRUE(readUrlSegments(*parsed, "absolute", "url")); 162 163 parsed = boost::urls::parse_relative_ref("not/absolute/url"); 164 EXPECT_FALSE(readUrlSegments(*parsed, "not", "absolute", "url")); 165 166 parsed = boost::urls::parse_relative_ref("/excellent/path"); 167 168 EXPECT_TRUE(readUrlSegments(*parsed, "excellent", "path", OrMorePaths())); 169 EXPECT_TRUE(readUrlSegments(*parsed, "excellent", OrMorePaths())); 170 EXPECT_TRUE(readUrlSegments(*parsed, OrMorePaths())); 171 } 172 173 TEST(Utility, readUrlSegmentsManager) 174 { 175 boost::urls::url_view url( 176 "/redfish/v1/Managers/bmc#/Oem/OpenBmc/Fan/FanZones/Left"); 177 std::string managerId; 178 std::string input; 179 EXPECT_TRUE( 180 readUrlSegments(url, "redfish", "v1", "Managers", std::ref(managerId), 181 "Oem", "OpenBmc", "Fan", "FanZones", std::ref(input))); 182 EXPECT_EQ(managerId, "bmc"); 183 EXPECT_EQ(input, "Left"); 184 } 185 186 TEST(Router, ParameterTagging) 187 { 188 EXPECT_EQ(1, getParameterTag("<str>")); 189 EXPECT_EQ(1, getParameterTag("<string>")); 190 EXPECT_EQ(1, getParameterTag("<path>")); 191 EXPECT_EQ(2, getParameterTag("<str>/<str>")); 192 EXPECT_EQ(2, getParameterTag("<string>/<string>")); 193 EXPECT_EQ(2, getParameterTag("<path>/<path>")); 194 } 195 196 TEST(URL, JsonEncoding) 197 { 198 std::string urlString = "/foo"; 199 EXPECT_EQ(nlohmann::json(boost::urls::url(urlString)), urlString); 200 EXPECT_EQ(nlohmann::json(boost::urls::url_view(urlString)), urlString); 201 } 202 203 TEST(AppendUrlFromPieces, PiecesAreAppendedViaDelimiters) 204 { 205 boost::urls::url url("/redfish/v1/foo"); 206 EXPECT_EQ(std::string_view(url.data(), url.size()), "/redfish/v1/foo"); 207 208 appendUrlPieces(url, "bar"); 209 EXPECT_EQ(std::string_view(url.data(), url.size()), "/redfish/v1/foo/bar"); 210 211 appendUrlPieces(url, "/", "bad&string"); 212 EXPECT_EQ(std::string_view(url.data(), url.size()), 213 "/redfish/v1/foo/bar/%2F/bad&string"); 214 } 215 216 } // namespace 217 } // namespace crow::utility 218