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