diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ast_jpeg_decoder_test.cpp | 283 | ||||
-rw-r--r-- | src/ast_video_puller_test.cpp | 65 | ||||
-rw-r--r-- | src/base64.cpp | 290 | ||||
-rw-r--r-- | src/crow_getroutes_test.cpp | 58 | ||||
-rw-r--r-- | src/crow_test.cpp | 1508 | ||||
-rw-r--r-- | src/getvideo_main.cpp | 94 | ||||
-rw-r--r-- | src/gtest_main.cpp | 7 | ||||
-rw-r--r-- | src/kvm_websocket_test.cpp | 191 | ||||
-rw-r--r-- | src/msan_test.cpp | 8 | ||||
-rw-r--r-- | src/openbmc_jtag_rest_test.cpp | 92 | ||||
-rw-r--r-- | src/security_headers_middleware_test.cpp | 126 | ||||
-rw-r--r-- | src/token_authorization_middleware_test.cpp | 527 | ||||
-rw-r--r-- | src/webassets_test.cpp | 234 | ||||
-rw-r--r-- | src/webserver_main.cpp | 105 |
14 files changed, 1899 insertions, 1689 deletions
diff --git a/src/ast_jpeg_decoder_test.cpp b/src/ast_jpeg_decoder_test.cpp index 277ba2cc8b..1552f46f76 100644 --- a/src/ast_jpeg_decoder_test.cpp +++ b/src/ast_jpeg_decoder_test.cpp @@ -1,4 +1,5 @@ #include "ast_jpeg_decoder.hpp" + #include <gmock/gmock.h> #include <gtest/gtest.h> @@ -10,150 +11,160 @@ using namespace testing; MATCHER_P2(IsBetween, a, b, std::string(negation ? "isn't" : "is") + " between " + - PrintToString(a) + " and " + PrintToString(b)) { - return a <= arg && arg <= b; + PrintToString(a) + " and " + PrintToString(b)) +{ + return a <= arg && arg <= b; }; -TEST(AstJpegDecoder, AllBlue) { - ast_video::RawVideoBuffer out; - - // This binary blog was created on the aspeed hardware using a blue screen - // consisting of the color 0x8EFFFA in a web browser window - FILE *fp = fopen("test_resources/aspeedbluescreen.bin", "rb"); - EXPECT_NE(fp, nullptr); - size_t bufferlen = - fread(out.buffer.data(), sizeof(decltype(out.buffer)::value_type), - out.buffer.size(), fp); - fclose(fp); - - ASSERT_GT(bufferlen, 0); - - out.ySelector = 0; - out.uvSelector = 0; - out.mode = ast_video::YuvMode::YUV444; - out.width = 800; - out.height = 600; - - ast_video::AstJpegDecoder d; - d.decode(out.buffer, out.width, out.height, out.mode, out.ySelector, - out.uvSelector); - - int tolerance = 16; - - // All pixels should be blue (0x8EFFFA) to within a tolerance (due to jpeg - // compression artifacts and quanitization) - for (int i = 0; i < out.width * out.height; i++) { - ast_video::RGB &pixel = d.outBuffer[i]; - EXPECT_GT(pixel.r, 0x8E - tolerance); - EXPECT_LT(pixel.r, 0x8E + tolerance); - EXPECT_GT(pixel.g, 0xFF - tolerance); - EXPECT_LT(pixel.g, 0xFF + tolerance); - EXPECT_GT(pixel.b, 0xF1 - tolerance); - EXPECT_LT(pixel.b, 0xF1 + tolerance); - } +TEST(AstJpegDecoder, AllBlue) +{ + ast_video::RawVideoBuffer out; + + // This binary blog was created on the aspeed hardware using a blue screen + // consisting of the color 0x8EFFFA in a web browser window + FILE *fp = fopen("test_resources/aspeedbluescreen.bin", "rb"); + EXPECT_NE(fp, nullptr); + size_t bufferlen = + fread(out.buffer.data(), sizeof(decltype(out.buffer)::value_type), + out.buffer.size(), fp); + fclose(fp); + + ASSERT_GT(bufferlen, 0); + + out.ySelector = 0; + out.uvSelector = 0; + out.mode = ast_video::YuvMode::YUV444; + out.width = 800; + out.height = 600; + + ast_video::AstJpegDecoder d; + d.decode(out.buffer, out.width, out.height, out.mode, out.ySelector, + out.uvSelector); + + int tolerance = 16; + + // All pixels should be blue (0x8EFFFA) to within a tolerance (due to jpeg + // compression artifacts and quanitization) + for (int i = 0; i < out.width * out.height; i++) + { + ast_video::RGB &pixel = d.outBuffer[i]; + EXPECT_GT(pixel.r, 0x8E - tolerance); + EXPECT_LT(pixel.r, 0x8E + tolerance); + EXPECT_GT(pixel.g, 0xFF - tolerance); + EXPECT_LT(pixel.g, 0xFF + tolerance); + EXPECT_GT(pixel.b, 0xF1 - tolerance); + EXPECT_LT(pixel.b, 0xF1 + tolerance); + } } -TEST(AstJpegDecoder, AllBlack) { - ast_video::RawVideoBuffer out; - - // This binary blog was created on the aspeed hardware using a black screen - FILE *fp = fopen("test_resources/aspeedblackscreen.bin", "rb"); - EXPECT_NE(fp, nullptr); - size_t bufferlen = fread(out.buffer.data(), sizeof(char), - out.buffer.size() * sizeof(long), fp); - fclose(fp); - - ASSERT_GT(bufferlen, 0); - - out.ySelector = 0; - out.uvSelector = 0; - out.mode = ast_video::YuvMode::YUV444; - out.width = 800; - out.height = 600; - - ast_video::AstJpegDecoder d; - d.decode(out.buffer, out.width, out.height, out.mode, out.ySelector, - out.uvSelector); - - // All pixels should be blue (0x8EFFFA) to within a tolerance (due to jpeg - // compression artifacts and quanitization) - for (int x = 0; x < out.width; x++) { - for (int y = 0; y < out.height; y++) { - ast_video::RGB pixel = d.outBuffer[x + (y * out.width)]; - ASSERT_EQ(pixel.r, 0x00) << "X:" << x << " Y: " << y; - ASSERT_EQ(pixel.g, 0x00) << "X:" << x << " Y: " << y; - ASSERT_EQ(pixel.b, 0x00) << "X:" << x << " Y: " << y; +TEST(AstJpegDecoder, AllBlack) +{ + ast_video::RawVideoBuffer out; + + // This binary blog was created on the aspeed hardware using a black screen + FILE *fp = fopen("test_resources/aspeedblackscreen.bin", "rb"); + EXPECT_NE(fp, nullptr); + size_t bufferlen = fread(out.buffer.data(), sizeof(char), + out.buffer.size() * sizeof(long), fp); + fclose(fp); + + ASSERT_GT(bufferlen, 0); + + out.ySelector = 0; + out.uvSelector = 0; + out.mode = ast_video::YuvMode::YUV444; + out.width = 800; + out.height = 600; + + ast_video::AstJpegDecoder d; + d.decode(out.buffer, out.width, out.height, out.mode, out.ySelector, + out.uvSelector); + + // All pixels should be blue (0x8EFFFA) to within a tolerance (due to jpeg + // compression artifacts and quanitization) + for (int x = 0; x < out.width; x++) + { + for (int y = 0; y < out.height; y++) + { + ast_video::RGB pixel = d.outBuffer[x + (y * out.width)]; + ASSERT_EQ(pixel.r, 0x00) << "X:" << x << " Y: " << y; + ASSERT_EQ(pixel.g, 0x00) << "X:" << x << " Y: " << y; + ASSERT_EQ(pixel.b, 0x00) << "X:" << x << " Y: " << y; + } } - } } -TEST(AstJpegDecoder, TestColors) { - ast_video::RawVideoBuffer out; - - // This binary blog was created on the aspeed hardware using a blue screen - // consisting of the color 0x8EFFFA in a web browser window - FILE *fp = fopen("test_resources/ubuntu_444_800x600_0chrom_0lum.bin", "rb"); - EXPECT_NE(fp, nullptr); - size_t bufferlen = fread(out.buffer.data(), sizeof(char), - out.buffer.size() * sizeof(long), fp); - fclose(fp); - - ASSERT_GT(bufferlen, 0); - - out.ySelector = 0; - out.uvSelector = 0; - out.mode = ast_video::YuvMode::YUV444; - out.width = 800; - out.height = 600; - - ast_video::AstJpegDecoder d; - d.decode(out.buffer, out.width, out.height, out.mode, out.ySelector, - out.uvSelector); - - int tolerance = 16; - /* - for (int i = 0; i < out.width * out.height; i++) { - ast_video::RGB &pixel = d.outBuffer[i]; - EXPECT_GT(pixel.r, 0x8E - tolerance); - EXPECT_LT(pixel.r, 0x8E + tolerance); - EXPECT_GT(pixel.g, 0xFF - tolerance); - EXPECT_LT(pixel.g, 0xFF + tolerance); - EXPECT_GT(pixel.b, 0xF1 - tolerance); - EXPECT_LT(pixel.b, 0xF1 + tolerance); - } - */ +TEST(AstJpegDecoder, TestColors) +{ + ast_video::RawVideoBuffer out; + + // This binary blog was created on the aspeed hardware using a blue screen + // consisting of the color 0x8EFFFA in a web browser window + FILE *fp = fopen("test_resources/ubuntu_444_800x600_0chrom_0lum.bin", "rb"); + EXPECT_NE(fp, nullptr); + size_t bufferlen = fread(out.buffer.data(), sizeof(char), + out.buffer.size() * sizeof(long), fp); + fclose(fp); + + ASSERT_GT(bufferlen, 0); + + out.ySelector = 0; + out.uvSelector = 0; + out.mode = ast_video::YuvMode::YUV444; + out.width = 800; + out.height = 600; + + ast_video::AstJpegDecoder d; + d.decode(out.buffer, out.width, out.height, out.mode, out.ySelector, + out.uvSelector); + + int tolerance = 16; + /* + for (int i = 0; i < out.width * out.height; i++) { + ast_video::RGB &pixel = d.outBuffer[i]; + EXPECT_GT(pixel.r, 0x8E - tolerance); + EXPECT_LT(pixel.r, 0x8E + tolerance); + EXPECT_GT(pixel.g, 0xFF - tolerance); + EXPECT_LT(pixel.g, 0xFF + tolerance); + EXPECT_GT(pixel.b, 0xF1 - tolerance); + EXPECT_LT(pixel.b, 0xF1 + tolerance); + } + */ } // Tests the buffers around the screen aren't written to -TEST(AstJpegDecoder, BufferLimits) { - ast_video::RawVideoBuffer out; - - // This binary blog was created on the aspeed hardware using a black screen - FILE *fp = fopen("test_resources/aspeedblackscreen.bin", "rb"); - EXPECT_NE(fp, nullptr); - size_t bufferlen = fread(out.buffer.data(), sizeof(char), - out.buffer.size() * sizeof(long), fp); - fclose(fp); - - ASSERT_GT(bufferlen, 0); - - out.ySelector = 0; - out.uvSelector = 0; - out.mode = ast_video::YuvMode::YUV444; - out.width = 800; - out.height = 600; - - ast_video::AstJpegDecoder d; - d.decode(out.buffer, out.width, out.height, out.mode, out.ySelector, - out.uvSelector); - // reserved pixel should be default value - for (auto &pixel : d.outBuffer) { - EXPECT_EQ(pixel.reserved, 0xAA); - } - // All pixels beyond the buffer should be zero - for (int i = out.width * out.height; i < d.outBuffer.size(); i++) { - EXPECT_EQ(d.outBuffer[i].r, 0x00) << "index:" << i; - EXPECT_EQ(d.outBuffer[i].b, 0x00) << "index:" << i; - EXPECT_EQ(d.outBuffer[i].g, 0x00) << "index:" << i; - } +TEST(AstJpegDecoder, BufferLimits) +{ + ast_video::RawVideoBuffer out; + + // This binary blog was created on the aspeed hardware using a black screen + FILE *fp = fopen("test_resources/aspeedblackscreen.bin", "rb"); + EXPECT_NE(fp, nullptr); + size_t bufferlen = fread(out.buffer.data(), sizeof(char), + out.buffer.size() * sizeof(long), fp); + fclose(fp); + + ASSERT_GT(bufferlen, 0); + + out.ySelector = 0; + out.uvSelector = 0; + out.mode = ast_video::YuvMode::YUV444; + out.width = 800; + out.height = 600; + + ast_video::AstJpegDecoder d; + d.decode(out.buffer, out.width, out.height, out.mode, out.ySelector, + out.uvSelector); + // reserved pixel should be default value + for (auto &pixel : d.outBuffer) + { + EXPECT_EQ(pixel.reserved, 0xAA); + } + // All pixels beyond the buffer should be zero + for (int i = out.width * out.height; i < d.outBuffer.size(); i++) + { + EXPECT_EQ(d.outBuffer[i].r, 0x00) << "index:" << i; + EXPECT_EQ(d.outBuffer[i].b, 0x00) << "index:" << i; + EXPECT_EQ(d.outBuffer[i].g, 0x00) << "index:" << i; + } }
\ No newline at end of file diff --git a/src/ast_video_puller_test.cpp b/src/ast_video_puller_test.cpp index 58adda9697..4fa3dccc68 100644 --- a/src/ast_video_puller_test.cpp +++ b/src/ast_video_puller_test.cpp @@ -2,6 +2,7 @@ #include <stdio.h> #include <stdlib.h> #include <unistd.h> + #include <ast_jpeg_decoder.hpp> #include <ast_video_puller.hpp> #include <chrono> @@ -10,38 +11,46 @@ #include <iostream> #include <thread> #include <vector> + #include <gmock/gmock.h> #include <gtest/gtest.h> -TEST(AstvideoPuller, BasicRead) { - ast_video::RawVideoBuffer out; - bool have_hardware = false; - if (access("/dev/video", F_OK) != -1) { - ast_video::SimpleVideoPuller p; - p.initialize(); - out = p.readVideo(); - } else { - FILE *fp = fopen("test_resources/ubuntu_444_800x600_0chrom_0lum.bin", "rb"); - if (fp) { - size_t newLen = fread(out.buffer.data(), sizeof(char), - out.buffer.size() * sizeof(long), fp); - if (ferror(fp) != 0) { - fputs("Error reading file", stderr); - } - fclose(fp); - out.buffer.resize(newLen); - out.mode = ast_video::YuvMode::YUV444; - out.width = 800; - out.height = 600; - out.ySelector = 0; - out.uvSelector = 0; +TEST(AstvideoPuller, BasicRead) +{ + ast_video::RawVideoBuffer out; + bool have_hardware = false; + if (access("/dev/video", F_OK) != -1) + { + ast_video::SimpleVideoPuller p; + p.initialize(); + out = p.readVideo(); + } + else + { + FILE *fp = + fopen("test_resources/ubuntu_444_800x600_0chrom_0lum.bin", "rb"); + if (fp) + { + size_t newLen = fread(out.buffer.data(), sizeof(char), + out.buffer.size() * sizeof(long), fp); + if (ferror(fp) != 0) + { + fputs("Error reading file", stderr); + } + fclose(fp); + out.buffer.resize(newLen); + out.mode = ast_video::YuvMode::YUV444; + out.width = 800; + out.height = 600; + out.ySelector = 0; + out.uvSelector = 0; + } } - } - FILE *fp = fopen("/tmp/screendata.bin", "wb"); - fwrite(out.buffer.data(), sizeof(char), out.buffer.size(), fp); + FILE *fp = fopen("/tmp/screendata.bin", "wb"); + fwrite(out.buffer.data(), sizeof(char), out.buffer.size(), fp); - ast_video::AstJpegDecoder d; - d.decode(out.buffer, out.width, out.height, out.mode, out.ySelector, - out.uvSelector); + ast_video::AstJpegDecoder d; + d.decode(out.buffer, out.width, out.height, out.mode, out.ySelector, + out.uvSelector); } diff --git a/src/base64.cpp b/src/base64.cpp index 0013c28ac3..851ef72a42 100644 --- a/src/base64.cpp +++ b/src/base64.cpp @@ -1,143 +1,165 @@ #include <base64.hpp> -namespace base64 { -bool base64_encode(const std::string &input, std::string &output) { - // This is left as a raw array (and not a range checked std::array) under the - // suspicion that the optimizer is not smart enough to remove the range checks - // that would be done below if at were called. As is, this array is 64 bytes - // long, which should be greater than the max of 0b00111111 when indexed - // NOLINT calls below are to silence clang-tidy about this - // TODO(ed) this requires further investigation if a more safe method could be - // used without performance impact. - static const char encoding_data[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - size_t input_length = input.size(); - - // allocate space for output string - output.clear(); - output.reserve(((input_length + 2) / 3) * 4); - - // for each 3-bytes sequence from the input, extract 4 6-bits sequences and - // encode using - // encoding_data lookup table. - // if input do not contains enough chars to complete 3-byte sequence,use pad - // char '=' - for (size_t i = 0; i < input_length; i++) { - int base64code0 = 0; - int base64code1 = 0; - int base64code2 = 0; - int base64code3 = 0; - - base64code0 = (input[i] >> 2) & 0x3f; // 1-byte 6 bits - - output += encoding_data[base64code0]; // NOLINT - base64code1 = (input[i] << 4) & 0x3f; // 1-byte 2 bits + - - if (++i < input_length) { - base64code1 |= (input[i] >> 4) & 0x0f; // 2-byte 4 bits - output += encoding_data[base64code1]; // NOLINT - base64code2 = (input[i] << 2) & 0x3f; // 2-byte 4 bits + - - if (++i < input_length) { - base64code2 |= (input[i] >> 6) & 0x03; // 3-byte 2 bits - base64code3 = input[i] & 0x3f; // 3-byte 6 bits - output += encoding_data[base64code2]; // NOLINT - output += encoding_data[base64code3]; // NOLINT - } else { - output += encoding_data[base64code2]; // NOLINT - output += '='; - } - } else { - output += encoding_data[base64code1]; // NOLINT - output += '='; - output += '='; +namespace base64 +{ +bool base64_encode(const std::string &input, std::string &output) +{ + // This is left as a raw array (and not a range checked std::array) under + // the suspicion that the optimizer is not smart enough to remove the range + // checks that would be done below if at were called. As is, this array is + // 64 bytes long, which should be greater than the max of 0b00111111 when + // indexed NOLINT calls below are to silence clang-tidy about this + // TODO(ed) this requires further investigation if a more safe method could + // be used without performance impact. + static const char encoding_data[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + size_t input_length = input.size(); + + // allocate space for output string + output.clear(); + output.reserve(((input_length + 2) / 3) * 4); + + // for each 3-bytes sequence from the input, extract 4 6-bits sequences and + // encode using + // encoding_data lookup table. + // if input do not contains enough chars to complete 3-byte sequence,use pad + // char '=' + for (size_t i = 0; i < input_length; i++) + { + int base64code0 = 0; + int base64code1 = 0; + int base64code2 = 0; + int base64code3 = 0; + + base64code0 = (input[i] >> 2) & 0x3f; // 1-byte 6 bits + + output += encoding_data[base64code0]; // NOLINT + base64code1 = (input[i] << 4) & 0x3f; // 1-byte 2 bits + + + if (++i < input_length) + { + base64code1 |= (input[i] >> 4) & 0x0f; // 2-byte 4 bits + output += encoding_data[base64code1]; // NOLINT + base64code2 = (input[i] << 2) & 0x3f; // 2-byte 4 bits + + + if (++i < input_length) + { + base64code2 |= (input[i] >> 6) & 0x03; // 3-byte 2 bits + base64code3 = input[i] & 0x3f; // 3-byte 6 bits + output += encoding_data[base64code2]; // NOLINT + output += encoding_data[base64code3]; // NOLINT + } + else + { + output += encoding_data[base64code2]; // NOLINT + output += '='; + } + } + else + { + output += encoding_data[base64code1]; // NOLINT + output += '='; + output += '='; + } } - } - return true; + return true; } -bool base64_decode(const std::string &input, std::string &output) { - static const char nop = -1; - // See note on encoding_data[] in above function - static const char decoding_data[] = { - nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, - nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, - nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, 62, nop, - nop, nop, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, nop, nop, - nop, nop, nop, nop, nop, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, nop, nop, nop, nop, nop, nop, 26, 27, 28, 29, 30, 31, 32, 33, - 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, - nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, - nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, - nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, - nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, - nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, - nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, - nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, - nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, - nop}; - - size_t input_length = input.size(); - - // allocate space for output string - output.clear(); - output.reserve(((input_length + 2) / 3) * 4); - - // for each 4-bytes sequence from the input, extract 4 6-bits sequences by - // droping first two bits - // and regenerate into 3 8-bits sequences - - for (size_t i = 0; i < input_length; i++) { - char base64code0; - char base64code1; - char base64code2 = 0; // initialized to 0 to suppress warnings - char base64code3; - - base64code0 = decoding_data[static_cast<int>(input[i])]; // NOLINT - if (base64code0 == nop) { // non base64 character - return false; +bool base64_decode(const std::string &input, std::string &output) +{ + static const char nop = -1; + // See note on encoding_data[] in above function + static const char decoding_data[] = { + nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, + nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, + nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, + nop, 62, nop, nop, nop, 63, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, nop, nop, nop, nop, nop, nop, nop, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, nop, nop, nop, nop, nop, nop, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, nop, nop, nop, + nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, + nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, + nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, + nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, + nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, + nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, + nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, + nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, + nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, + nop, nop, nop, nop}; + + size_t input_length = input.size(); + + // allocate space for output string + output.clear(); + output.reserve(((input_length + 2) / 3) * 4); + + // for each 4-bytes sequence from the input, extract 4 6-bits sequences by + // droping first two bits + // and regenerate into 3 8-bits sequences + + for (size_t i = 0; i < input_length; i++) + { + char base64code0; + char base64code1; + char base64code2 = 0; // initialized to 0 to suppress warnings + char base64code3; + + base64code0 = decoding_data[static_cast<int>(input[i])]; // NOLINT + if (base64code0 == nop) + { // non base64 character + return false; + } + if (!(++i < input_length)) + { // we need at least two input bytes for first + // byte output + return false; + } + base64code1 = decoding_data[static_cast<int>(input[i])]; // NOLINT + if (base64code1 == nop) + { // non base64 character + return false; + } + output += + static_cast<char>((base64code0 << 2) | ((base64code1 >> 4) & 0x3)); + + if (++i < input_length) + { + char c = input[i]; + if (c == '=') + { // padding , end of input + return (base64code1 & 0x0f) == 0; + } + base64code2 = decoding_data[static_cast<int>(input[i])]; // NOLINT + if (base64code2 == nop) + { // non base64 character + return false; + } + output += static_cast<char>(((base64code1 << 4) & 0xf0) | + ((base64code2 >> 2) & 0x0f)); + } + + if (++i < input_length) + { + char c = input[i]; + if (c == '=') + { // padding , end of input + return (base64code2 & 0x03) == 0; + } + base64code3 = decoding_data[static_cast<int>(input[i])]; // NOLINT + if (base64code3 == nop) + { // non base64 character + return false; + } + output += + static_cast<char>((((base64code2 << 6) & 0xc0) | base64code3)); + } } - if (!(++i < input_length)) { // we need at least two input bytes for first - // byte output - return false; - } - base64code1 = decoding_data[static_cast<int>(input[i])]; // NOLINT - if (base64code1 == nop) { // non base64 character - return false; - } - output += - static_cast<char>((base64code0 << 2) | ((base64code1 >> 4) & 0x3)); - - if (++i < input_length) { - char c = input[i]; - if (c == '=') { // padding , end of input - return (base64code1 & 0x0f) == 0; - } - base64code2 = decoding_data[static_cast<int>(input[i])]; // NOLINT - if (base64code2 == nop) { // non base64 character - return false; - } - output += static_cast<char>(((base64code1 << 4) & 0xf0) | - ((base64code2 >> 2) & 0x0f)); - } - - if (++i < input_length) { - char c = input[i]; - if (c == '=') { // padding , end of input - return (base64code2 & 0x03) == 0; - } - base64code3 = decoding_data[static_cast<int>(input[i])]; // NOLINT - if (base64code3 == nop) { // non base64 character - return false; - } - output += static_cast<char>((((base64code2 << 6) & 0xc0) | base64code3)); - } - } - return true; + return true; } -} // namespace base64 +} // namespace base64 diff --git a/src/crow_getroutes_test.cpp b/src/crow_getroutes_test.cpp index 29052a9a21..e76d221479 100644 --- a/src/crow_getroutes_test.cpp +++ b/src/crow_getroutes_test.cpp @@ -1,43 +1,47 @@ #include <crow/app.h> + #include "gmock/gmock.h" #include "gtest/gtest.h" using namespace crow; using namespace std; -TEST(GetRoutes, TestEmptyRoutes) { - SimpleApp app; - decltype(app)::server_t server(&app, "127.0.0.1", 45451); +TEST(GetRoutes, TestEmptyRoutes) +{ + SimpleApp app; + decltype(app)::server_t server(&app, "127.0.0.1", 45451); - EXPECT_THAT(app.getRoutes(), testing::IsEmpty()); + EXPECT_THAT(app.getRoutes(), testing::IsEmpty()); } // Tests that static urls are correctly passed -TEST(GetRoutes, TestOneRoute) { - SimpleApp app; - decltype(app)::server_t server(&app, "127.0.0.1", 45451); - BMCWEB_ROUTE(app, "/")([]() { return boost::beast::http::status::ok; }); +TEST(GetRoutes, TestOneRoute) +{ + SimpleApp app; + decltype(app)::server_t server(&app, "127.0.0.1", 45451); + BMCWEB_ROUTE(app, "/")([]() { return boost::beast::http::status::ok; }); - EXPECT_THAT(app.getRoutes(), - testing::ElementsAre(testing::Pointee(std::string("/")))); + EXPECT_THAT(app.getRoutes(), + testing::ElementsAre(testing::Pointee(std::string("/")))); } // Tests that static urls are correctly passed -TEST(GetRoutes, TestlotsOfRoutes) { - SimpleApp app; - decltype(app)::server_t server(&app, "127.0.0.1", 45451); - BMCWEB_ROUTE(app, "/")([]() { return boost::beast::http::status::ok; }); - BMCWEB_ROUTE(app, "/foo")([]() { return boost::beast::http::status::ok; }); - BMCWEB_ROUTE(app, "/bar")([]() { return boost::beast::http::status::ok; }); - BMCWEB_ROUTE(app, "/baz")([]() { return boost::beast::http::status::ok; }); - BMCWEB_ROUTE(app, "/boo")([]() { return boost::beast::http::status::ok; }); - BMCWEB_ROUTE(app, "/moo")([]() { return boost::beast::http::status::ok; }); - - EXPECT_THAT(app.getRoutes(), testing::UnorderedElementsAre( - testing::Pointee(std::string("/")), - testing::Pointee(std::string("/foo")), - testing::Pointee(std::string("/bar")), - testing::Pointee(std::string("/baz")), - testing::Pointee(std::string("/boo")), - testing::Pointee(std::string("/moo")))); +TEST(GetRoutes, TestlotsOfRoutes) +{ + SimpleApp app; + decltype(app)::server_t server(&app, "127.0.0.1", 45451); + BMCWEB_ROUTE(app, "/")([]() { return boost::beast::http::status::ok; }); + BMCWEB_ROUTE(app, "/foo")([]() { return boost::beast::http::status::ok; }); + BMCWEB_ROUTE(app, "/bar")([]() { return boost::beast::http::status::ok; }); + BMCWEB_ROUTE(app, "/baz")([]() { return boost::beast::http::status::ok; }); + BMCWEB_ROUTE(app, "/boo")([]() { return boost::beast::http::status::ok; }); + BMCWEB_ROUTE(app, "/moo")([]() { return boost::beast::http::status::ok; }); + + EXPECT_THAT(app.getRoutes(), testing::UnorderedElementsAre( + testing::Pointee(std::string("/")), + testing::Pointee(std::string("/foo")), + testing::Pointee(std::string("/bar")), + testing::Pointee(std::string("/baz")), + testing::Pointee(std::string("/boo")), + testing::Pointee(std::string("/moo")))); }
\ No newline at end of file diff --git a/src/crow_test.cpp b/src/crow_test.cpp index cd668171db..96b90b0ed2 100644 --- a/src/crow_test.cpp +++ b/src/crow_test.cpp @@ -1,7 +1,9 @@ -#include "crow.h" #include <iostream> #include <sstream> #include <vector> + +#include "crow.h" + #include "gtest/gtest.h" #undef BMCWEB_LOG_LEVEL #define BMCWEB_LOG_LEVEL 0 @@ -10,864 +12,934 @@ using namespace std; using namespace crow; bool failed__ = false; -void error_print() { cerr << endl; } +void error_print() +{ + cerr << endl; +} template <typename A, typename... Args> -void error_print(const A& a, Args... args) { - cerr << a; - error_print(args...); +void error_print(const A& a, Args... args) +{ + cerr << a; + error_print(args...); } -template <typename... Args> -void fail(Args... args) { - error_print(args...); - failed__ = true; +template <typename... Args> void fail(Args... args) +{ + error_print(args...); + failed__ = true; } -#define ASSERT_EQUAL(a, b) \ - if ((a) != (b)) \ - fail(__FILE__ ":", __LINE__, ": Assert fail: expected ", (a), " actual ", \ - (b), ", " #a " == " #b ", at " __FILE__ ":", __LINE__) -#define ASSERT_NOTEQUAL(a, b) \ - if ((a) == (b)) \ - fail(__FILE__ ":", __LINE__, ": Assert fail: not expected ", (a), \ - ", " #a " != " #b ", at " __FILE__ ":", __LINE__) - -#define DISABLE_TEST(x) \ - struct test##x { \ - void test(); \ - } x##_; \ - void test##x::test() +#define ASSERT_EQUAL(a, b) \ + if ((a) != (b)) \ + fail(__FILE__ ":", __LINE__, ": Assert fail: expected ", (a), " actual ", \ + (b), ", " #a " == " #b ", at " __FILE__ ":", __LINE__) +#define ASSERT_NOTEQUAL(a, b) \ + if ((a) == (b)) \ + fail(__FILE__ ":", __LINE__, ": Assert fail: not expected ", (a), \ + ", " #a " != " #b ", at " __FILE__ ":", __LINE__) + +#define DISABLE_TEST(x) \ + struct test##x \ + { \ + void test(); \ + } x##_; \ + void test##x::test() #define LOCALHOST_ADDRESS "127.0.0.1" -TEST(Crow, Rule) { - TaggedRule<> r("/http/"); - r.name("abc"); +TEST(Crow, Rule) +{ + TaggedRule<> r("/http/"); + r.name("abc"); - // empty handler - fail to validate - try { - r.validate(); - fail("empty handler should fail to validate"); - } catch (runtime_error& e) { - } + // empty handler - fail to validate + try + { + r.validate(); + fail("empty handler should fail to validate"); + } + catch (runtime_error& e) + { + } - int x = 0; + int x = 0; - // registering handler - r([&x] { - x = 1; - return ""; - }); + // registering handler + r([&x] { + x = 1; + return ""; + }); - r.validate(); + r.validate(); - Response res; + Response res; - // executing handler - ASSERT_EQUAL(0, x); - boost::beast::http::request<boost::beast::http::string_body> req{}; - r.handle(Request(req), res, RoutingParams()); - ASSERT_EQUAL(1, x); + // executing handler + ASSERT_EQUAL(0, x); + boost::beast::http::request<boost::beast::http::string_body> req{}; + r.handle(Request(req), res, RoutingParams()); + ASSERT_EQUAL(1, x); - // registering handler with Request argument - r([&x](const crow::Request&) { - x = 2; - return ""; - }); + // registering handler with Request argument + r([&x](const crow::Request&) { + x = 2; + return ""; + }); - r.validate(); + r.validate(); - // executing handler - ASSERT_EQUAL(1, x); - r.handle(Request(req), res, RoutingParams()); - ASSERT_EQUAL(2, x); + // executing handler + ASSERT_EQUAL(1, x); + r.handle(Request(req), res, RoutingParams()); + ASSERT_EQUAL(2, x); } -TEST(Crow, ParameterTagging) { - static_assert(black_magic::isValid("<int><int><int>"), "valid url"); - static_assert(!black_magic::isValid("<int><int<<int>"), "invalid url"); - static_assert(!black_magic::isValid("nt>"), "invalid url"); - ASSERT_EQUAL(1, black_magic::get_parameter_tag("<int>")); - ASSERT_EQUAL(2, black_magic::get_parameter_tag("<uint>")); - ASSERT_EQUAL(3, black_magic::get_parameter_tag("<float>")); - ASSERT_EQUAL(3, black_magic::get_parameter_tag("<double>")); - ASSERT_EQUAL(4, black_magic::get_parameter_tag("<str>")); - ASSERT_EQUAL(4, black_magic::get_parameter_tag("<string>")); - ASSERT_EQUAL(5, black_magic::get_parameter_tag("<path>")); - ASSERT_EQUAL(6 * 6 + 6 + 1, - black_magic::get_parameter_tag("<int><int><int>")); - ASSERT_EQUAL(6 * 6 + 6 + 2, - black_magic::get_parameter_tag("<uint><int><int>")); - ASSERT_EQUAL(6 * 6 + 6 * 3 + 2, - black_magic::get_parameter_tag("<uint><double><int>")); - - // url definition parsed in compile time, build into *one number*, and given - // to template argument - static_assert( - std::is_same<black_magic::S<uint64_t, double, int64_t>, - black_magic::Arguments<6 * 6 + 6 * 3 + 2>::type>::value, - "tag to type container"); +TEST(Crow, ParameterTagging) +{ + static_assert(black_magic::isValid("<int><int><int>"), "valid url"); + static_assert(!black_magic::isValid("<int><int<<int>"), "invalid url"); + static_assert(!black_magic::isValid("nt>"), "invalid url"); + ASSERT_EQUAL(1, black_magic::get_parameter_tag("<int>")); + ASSERT_EQUAL(2, black_magic::get_parameter_tag("<uint>")); + ASSERT_EQUAL(3, black_magic::get_parameter_tag("<float>")); + ASSERT_EQUAL(3, black_magic::get_parameter_tag("<double>")); + ASSERT_EQUAL(4, black_magic::get_parameter_tag("<str>")); + ASSERT_EQUAL(4, black_magic::get_parameter_tag("<string>")); + ASSERT_EQUAL(5, black_magic::get_parameter_tag("<path>")); + ASSERT_EQUAL(6 * 6 + 6 + 1, + black_magic::get_parameter_tag("<int><int><int>")); + ASSERT_EQUAL(6 * 6 + 6 + 2, + black_magic::get_parameter_tag("<uint><int><int>")); + ASSERT_EQUAL(6 * 6 + 6 * 3 + 2, + black_magic::get_parameter_tag("<uint><double><int>")); + + // url definition parsed in compile time, build into *one number*, and given + // to template argument + static_assert( + std::is_same<black_magic::S<uint64_t, double, int64_t>, + black_magic::Arguments<6 * 6 + 6 * 3 + 2>::type>::value, + "tag to type container"); } -TEST(Crow, PathRouting) { - SimpleApp app; +TEST(Crow, PathRouting) +{ + SimpleApp app; - BMCWEB_ROUTE(app, "/file") - ([] { return "file"; }); + BMCWEB_ROUTE(app, "/file") + ([] { return "file"; }); - BMCWEB_ROUTE(app, "/path/") - ([] { return "path"; }); + BMCWEB_ROUTE(app, "/path/") + ([] { return "path"; }); - { - boost::beast::http::request<boost::beast::http::string_body> r{}; - Request req{r}; - Response res; + { + boost::beast::http::request<boost::beast::http::string_body> r{}; + Request req{r}; + Response res; - req.url = "/file"; + req.url = "/file"; - app.handle(req, res); + app.handle(req, res); - ASSERT_EQUAL(200, res.resultInt()); - } - { - boost::beast::http::request<boost::beast::http::string_body> r{}; - Request req{r}; - Response res; + ASSERT_EQUAL(200, res.resultInt()); + } + { + boost::beast::http::request<boost::beast::http::string_body> r{}; + Request req{r}; + Response res; - req.url = "/file/"; + req.url = "/file/"; - app.handle(req, res); - ASSERT_EQUAL(404, res.resultInt()); - } - { - boost::beast::http::request<boost::beast::http::string_body> r{}; - Request req{r}; - Response res; + app.handle(req, res); + ASSERT_EQUAL(404, res.resultInt()); + } + { + boost::beast::http::request<boost::beast::http::string_body> r{}; + Request req{r}; + Response res; - req.url = "/path"; + req.url = "/path"; - app.handle(req, res); - ASSERT_NOTEQUAL(404, res.resultInt()); - } - { - boost::beast::http::request<boost::beast::http::string_body> r{}; - Request req{r}; - Response res; + app.handle(req, res); + ASSERT_NOTEQUAL(404, res.resultInt()); + } + { + boost::beast::http::request<boost::beast::http::string_body> r{}; + Request req{r}; + Response res; - req.url = "/path/"; + req.url = "/path/"; - app.handle(req, res); - ASSERT_EQUAL(200, res.resultInt()); - } + app.handle(req, res); + ASSERT_EQUAL(200, res.resultInt()); + } } -TEST(Crow, RoutingTest) { - SimpleApp app; - int A{}; - uint32_t b{}; - double C{}; - string D{}; - string E{}; - - BMCWEB_ROUTE(app, "/0/<uint>") - ([&](uint32_t b) { - b = b; - return "OK"; - }); - - BMCWEB_ROUTE(app, "/1/<int>/<uint>") - ([&](int a, uint32_t b) { - A = a; - b = b; - return "OK"; - }); - - BMCWEB_ROUTE(app, "/4/<int>/<uint>/<double>/<string>") - ([&](int a, uint32_t b, double c, string d) { - A = a; - b = b; - C = c; - D = d; - return "OK"; - }); - - BMCWEB_ROUTE(app, "/5/<int>/<uint>/<double>/<string>/<path>") - ([&](int a, uint32_t b, double c, string d, string e) { - A = a; - b = b; - C = c; - D = d; - E = e; - return "OK"; - }); - - app.validate(); - // app.debugPrint(); - { - boost::beast::http::request<boost::beast::http::string_body> r{}; - Request req{r}; - Response res; +TEST(Crow, RoutingTest) +{ + SimpleApp app; + int A{}; + uint32_t b{}; + double C{}; + string D{}; + string E{}; + + BMCWEB_ROUTE(app, "/0/<uint>") + ([&](uint32_t b) { + b = b; + return "OK"; + }); + + BMCWEB_ROUTE(app, "/1/<int>/<uint>") + ([&](int a, uint32_t b) { + A = a; + b = b; + return "OK"; + }); + + BMCWEB_ROUTE(app, "/4/<int>/<uint>/<double>/<string>") + ([&](int a, uint32_t b, double c, string d) { + A = a; + b = b; + C = c; + D = d; + return "OK"; + }); + + BMCWEB_ROUTE(app, "/5/<int>/<uint>/<double>/<string>/<path>") + ([&](int a, uint32_t b, double c, string d, string e) { + A = a; + b = b; + C = c; + D = d; + E = e; + return "OK"; + }); - req.url = "/-1"; + app.validate(); + // app.debugPrint(); + { + boost::beast::http::request<boost::beast::http::string_body> r{}; + Request req{r}; + Response res; - app.handle(req, res); + req.url = "/-1"; - ASSERT_EQUAL(404, res.resultInt()); - } + app.handle(req, res); - { - boost::beast::http::request<boost::beast::http::string_body> r{}; - Request req{r}; - Response res; + ASSERT_EQUAL(404, res.resultInt()); + } - req.url = "/0/1001999"; + { + boost::beast::http::request<boost::beast::http::string_body> r{}; + Request req{r}; + Response res; - app.handle(req, res); + req.url = "/0/1001999"; - ASSERT_EQUAL(200, res.resultInt()); + app.handle(req, res); - ASSERT_EQUAL(1001999, b); - } + ASSERT_EQUAL(200, res.resultInt()); - { - boost::beast::http::request<boost::beast::http::string_body> r{}; - Request req{r}; - Response res; + ASSERT_EQUAL(1001999, b); + } - req.url = "/1/-100/1999"; + { + boost::beast::http::request<boost::beast::http::string_body> r{}; + Request req{r}; + Response res; - app.handle(req, res); + req.url = "/1/-100/1999"; - ASSERT_EQUAL(200, res.resultInt()); + app.handle(req, res); - ASSERT_EQUAL(-100, A); - ASSERT_EQUAL(1999, b); - } - { - boost::beast::http::request<boost::beast::http::string_body> r{}; - Request req{r}; - Response res; + ASSERT_EQUAL(200, res.resultInt()); - req.url = "/4/5000/3/-2.71828/hellhere"; + ASSERT_EQUAL(-100, A); + ASSERT_EQUAL(1999, b); + } + { + boost::beast::http::request<boost::beast::http::string_body> r{}; + Request req{r}; + Response res; - app.handle(req, res); + req.url = "/4/5000/3/-2.71828/hellhere"; - ASSERT_EQUAL(200, res.resultInt()); + app.handle(req, res); - ASSERT_EQUAL(5000, A); - ASSERT_EQUAL(3, b); - ASSERT_EQUAL(-2.71828, C); - ASSERT_EQUAL("hellhere", D); - } - { - boost::beast::http::request<boost::beast::http::string_body> r{}; - Request req{r}; - Response res; + ASSERT_EQUAL(200, res.resultInt()); - req.url = "/5/-5/999/3.141592/hello_there/a/b/c/d"; + ASSERT_EQUAL(5000, A); + ASSERT_EQUAL(3, b); + ASSERT_EQUAL(-2.71828, C); + ASSERT_EQUAL("hellhere", D); + } + { + boost::beast::http::request<boost::beast::http::string_body> r{}; + Request req{r}; + Response res; - app.handle(req, res); + req.url = "/5/-5/999/3.141592/hello_there/a/b/c/d"; - ASSERT_EQUAL(200, res.resultInt()); + app.handle(req, res); - ASSERT_EQUAL(-5, A); - ASSERT_EQUAL(999, b); - ASSERT_EQUAL(3.141592, C); - ASSERT_EQUAL("hello_there", D); - ASSERT_EQUAL("a/b/c/d", E); - } + ASSERT_EQUAL(200, res.resultInt()); + + ASSERT_EQUAL(-5, A); + ASSERT_EQUAL(999, b); + ASSERT_EQUAL(3.141592, C); + ASSERT_EQUAL("hello_there", D); + ASSERT_EQUAL("a/b/c/d", E); + } } -TEST(Crow, simple_response_RoutingParams) { - ASSERT_EQUAL(100, - Response(boost::beast::http::status::continue_).resultInt()); - ASSERT_EQUAL(200, Response("Hello there").resultInt()); - ASSERT_EQUAL(500, Response(boost::beast::http::status::internal_server_error, - "Internal Error?") - .resultInt()); - - RoutingParams rp; - rp.intParams.push_back(1); - rp.intParams.push_back(5); - rp.uintParams.push_back(2); - rp.doubleParams.push_back(3); - rp.stringParams.push_back("hello"); - ASSERT_EQUAL(1, rp.get<int64_t>(0)); - ASSERT_EQUAL(5, rp.get<int64_t>(1)); - ASSERT_EQUAL(2, rp.get<uint64_t>(0)); - ASSERT_EQUAL(3, rp.get<double>(0)); - ASSERT_EQUAL("hello", rp.get<string>(0)); +TEST(Crow, simple_response_RoutingParams) +{ + ASSERT_EQUAL(100, + Response(boost::beast::http::status::continue_).resultInt()); + ASSERT_EQUAL(200, Response("Hello there").resultInt()); + ASSERT_EQUAL(500, + Response(boost::beast::http::status::internal_server_error, + "Internal Error?") + .resultInt()); + + RoutingParams rp; + rp.intParams.push_back(1); + rp.intParams.push_back(5); + rp.uintParams.push_back(2); + rp.doubleParams.push_back(3); + rp.stringParams.push_back("hello"); + ASSERT_EQUAL(1, rp.get<int64_t>(0)); + ASSERT_EQUAL(5, rp.get<int64_t>(1)); + ASSERT_EQUAL(2, rp.get<uint64_t>(0)); + ASSERT_EQUAL(3, rp.get<double>(0)); + ASSERT_EQUAL("hello", rp.get<string>(0)); } -TEST(Crow, handler_with_response) { - SimpleApp app; - BMCWEB_ROUTE(app, "/")([](const crow::Request&, crow::Response&) {}); +TEST(Crow, handler_with_response) +{ + SimpleApp app; + BMCWEB_ROUTE(app, "/")([](const crow::Request&, crow::Response&) {}); } -TEST(Crow, http_method) { - SimpleApp app; - - BMCWEB_ROUTE(app, "/").methods("POST"_method, - "GET"_method)([](const Request& req) { - if (req.method() == "GET"_method) - return "2"; - else - return "1"; - }); - - BMCWEB_ROUTE(app, "/get_only") - .methods("GET"_method)([](const Request& /*req*/) { return "get"; }); - BMCWEB_ROUTE(app, "/post_only") - .methods("POST"_method)([](const Request& /*req*/) { return "post"; }); - - // cannot have multiple handlers for the same url - // BMCWEB_ROUTE(app, "/") - //.methods("GET"_method) - //([]{ return "2"; }); - - { - boost::beast::http::request<boost::beast::http::string_body> r{}; - Request req{r}; - Response res; +TEST(Crow, http_method) +{ + SimpleApp app; - req.url = "/"; - app.handle(req, res); + BMCWEB_ROUTE(app, "/").methods("POST"_method, + "GET"_method)([](const Request& req) { + if (req.method() == "GET"_method) + return "2"; + else + return "1"; + }); - ASSERT_EQUAL("2", res.body()); - } - { - boost::beast::http::request<boost::beast::http::string_body> r{}; - Request req{r}; - Response res; + BMCWEB_ROUTE(app, "/get_only") + .methods("GET"_method)([](const Request& /*req*/) { return "get"; }); + BMCWEB_ROUTE(app, "/post_only") + .methods("POST"_method)([](const Request& /*req*/) { return "post"; }); - req.url = "/"; - r.method("POST"_method); - app.handle(req, res); + // cannot have multiple handlers for the same url + // BMCWEB_ROUTE(app, "/") + //.methods("GET"_method) + //([]{ return "2"; }); - ASSERT_EQUAL("1", res.body()); - } + { + boost::beast::http::request<boost::beast::http::string_body> r{}; + Request req{r}; + Response res; - { - boost::beast::http::request<boost::beast::http::string_body> r{}; - Request req{r}; - Response res; + req.url = "/"; + app.handle(req, res); + + ASSERT_EQUAL("2", res.body()); + } + { + boost::beast::http::request<boost::beast::http::string_body> r{}; + Request req{r}; + Response res; - req.url = "/get_only"; - app.handle(req, res); + req.url = "/"; + r.method("POST"_method); + app.handle(req, res); - ASSERT_EQUAL("get", res.body()); - } + ASSERT_EQUAL("1", res.body()); + } - { - boost::beast::http::request<boost::beast::http::string_body> r{}; - Request req{r}; - Response res; + { + boost::beast::http::request<boost::beast::http::string_body> r{}; + Request req{r}; + Response res; - req.url = "/get_only"; - r.method("POST"_method); - app.handle(req, res); + req.url = "/get_only"; + app.handle(req, res); - ASSERT_NOTEQUAL("get", res.body()); - } -} + ASSERT_EQUAL("get", res.body()); + } -TEST(Crow, server_handling_error_request) { - static char buf[2048]; - SimpleApp app; - BMCWEB_ROUTE(app, "/")([] { return "A"; }); - Server<SimpleApp> server(&app, LOCALHOST_ADDRESS, 45451); - auto _ = async(launch::async, [&] { server.run(); }); - std::string sendmsg = "POX"; - asio::io_service is; - { - asio::ip::tcp::socket c(is); - c.connect(asio::ip::tcp::endpoint( - asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451)); - - c.send(asio::buffer(sendmsg)); - - try { - c.receive(asio::buffer(buf, 2048)); - fail(); - } catch (std::exception& e) { - // std::cerr << e.what() << std::endl; - } - } - server.stop(); + { + boost::beast::http::request<boost::beast::http::string_body> r{}; + Request req{r}; + Response res; + + req.url = "/get_only"; + r.method("POST"_method); + app.handle(req, res); + + ASSERT_NOTEQUAL("get", res.body()); + } } -TEST(Crow, multi_server) { - static char buf[2048]; - SimpleApp app1, app2; - BMCWEB_ROUTE(app1, "/").methods("GET"_method, - "POST"_method)([] { return "A"; }); - BMCWEB_ROUTE(app2, "/").methods("GET"_method, - "POST"_method)([] { return "B"; }); +TEST(Crow, server_handling_error_request) +{ + static char buf[2048]; + SimpleApp app; + BMCWEB_ROUTE(app, "/")([] { return "A"; }); + Server<SimpleApp> server(&app, LOCALHOST_ADDRESS, 45451); + auto _ = async(launch::async, [&] { server.run(); }); + std::string sendmsg = "POX"; + asio::io_service is; + { + asio::ip::tcp::socket c(is); + c.connect(asio::ip::tcp::endpoint( + asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451)); - Server<SimpleApp> server1(&app1, LOCALHOST_ADDRESS, 45451); - Server<SimpleApp> server2(&app2, LOCALHOST_ADDRESS, 45452); + c.send(asio::buffer(sendmsg)); - auto _ = async(launch::async, [&] { server1.run(); }); - auto _2 = async(launch::async, [&] { server2.run(); }); + try + { + c.receive(asio::buffer(buf, 2048)); + fail(); + } + catch (std::exception& e) + { + // std::cerr << e.what() << std::endl; + } + } + server.stop(); +} - std::string sendmsg = - "POST /\r\nContent-Length:3\r\nX-HeaderTest: 123\r\n\r\nA=b\r\n"; - asio::io_service is; - { - asio::ip::tcp::socket c(is); - c.connect(asio::ip::tcp::endpoint( - asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451)); +TEST(Crow, multi_server) +{ + static char buf[2048]; + SimpleApp app1, app2; + BMCWEB_ROUTE(app1, "/").methods("GET"_method, + "POST"_method)([] { return "A"; }); + BMCWEB_ROUTE(app2, "/").methods("GET"_method, + "POST"_method)([] { return "B"; }); - c.send(asio::buffer(sendmsg)); + Server<SimpleApp> server1(&app1, LOCALHOST_ADDRESS, 45451); + Server<SimpleApp> server2(&app2, LOCALHOST_ADDRESS, 45452); - size_t recved = c.receive(asio::buffer(buf, 2048)); - ASSERT_EQUAL('A', buf[recved - 1]); - } + auto _ = async(launch::async, [&] { server1.run(); }); + auto _2 = async(launch::async, [&] { server2.run(); }); - { - asio::ip::tcp::socket c(is); - c.connect(asio::ip::tcp::endpoint( - asio::ip::address::from_string(LOCALHOST_ADDRESS), 45452)); + std::string sendmsg = + "POST /\r\nContent-Length:3\r\nX-HeaderTest: 123\r\n\r\nA=b\r\n"; + asio::io_service is; + { + asio::ip::tcp::socket c(is); + c.connect(asio::ip::tcp::endpoint( + asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451)); + + c.send(asio::buffer(sendmsg)); - for (auto ch : sendmsg) { - char buf[1] = {ch}; - c.send(asio::buffer(buf)); + size_t recved = c.receive(asio::buffer(buf, 2048)); + ASSERT_EQUAL('A', buf[recved - 1]); } - size_t recved = c.receive(asio::buffer(buf, 2048)); - ASSERT_EQUAL('b', buf[recved - 1]); - } + { + asio::ip::tcp::socket c(is); + c.connect(asio::ip::tcp::endpoint( + asio::ip::address::from_string(LOCALHOST_ADDRESS), 45452)); + + for (auto ch : sendmsg) + { + char buf[1] = {ch}; + c.send(asio::buffer(buf)); + } + + size_t recved = c.receive(asio::buffer(buf, 2048)); + ASSERT_EQUAL('b', buf[recved - 1]); + } - server1.stop(); - server2.stop(); + server1.stop(); + server2.stop(); } -TEST(Crow, black_magic) { - using namespace black_magic; - static_assert( - std::is_same<void, LastElementType<int, char, void>::type>::value, - "LastElementType"); - static_assert( - std::is_same< - char, PopBack<int, char, void>::rebind<LastElementType>::type>::value, - "pop_back"); - static_assert( - std::is_same<int, PopBack<int, char, void>::rebind<PopBack>::rebind< - LastElementType>::type>::value, - "pop_back"); +TEST(Crow, black_magic) +{ + using namespace black_magic; + static_assert( + std::is_same<void, LastElementType<int, char, void>::type>::value, + "LastElementType"); + static_assert( + std::is_same<char, PopBack<int, char, + void>::rebind<LastElementType>::type>::value, + "pop_back"); + static_assert( + std::is_same<int, PopBack<int, char, void>::rebind<PopBack>::rebind< + LastElementType>::type>::value, + "pop_back"); } -struct NullMiddleware { - struct Context {}; +struct NullMiddleware +{ + struct Context + { + }; - template <typename AllContext> - void beforeHandle(Request&, Response&, Context&, AllContext&) {} + template <typename AllContext> + void beforeHandle(Request&, Response&, Context&, AllContext&) + { + } - template <typename AllContext> - void afterHandle(Request&, Response&, Context&, AllContext&) {} + template <typename AllContext> + void afterHandle(Request&, Response&, Context&, AllContext&) + { + } }; -struct NullSimpleMiddleware { - struct Context {}; +struct NullSimpleMiddleware +{ + struct Context + { + }; - void beforeHandle(Request& /*req*/, Response& /*res*/, Context& /*ctx*/) {} + void beforeHandle(Request& /*req*/, Response& /*res*/, Context& /*ctx*/) + { + } - void afterHandle(Request& /*req*/, Response& /*res*/, Context& /*ctx*/) {} + void afterHandle(Request& /*req*/, Response& /*res*/, Context& /*ctx*/) + { + } }; -TEST(Crow, middleware_simple) { - App<NullMiddleware, NullSimpleMiddleware> app; - decltype(app)::server_t server(&app, LOCALHOST_ADDRESS, 45451); - BMCWEB_ROUTE(app, "/") - ([&](const crow::Request& req) { - app.getContext<NullMiddleware>(req); - app.getContext<NullSimpleMiddleware>(req); - return ""; - }); +TEST(Crow, middleware_simple) +{ + App<NullMiddleware, NullSimpleMiddleware> app; + decltype(app)::server_t server(&app, LOCALHOST_ADDRESS, 45451); + BMCWEB_ROUTE(app, "/") + ([&](const crow::Request& req) { + app.getContext<NullMiddleware>(req); + app.getContext<NullSimpleMiddleware>(req); + return ""; + }); } -struct IntSettingMiddleware { - struct Context { - int val; - }; +struct IntSettingMiddleware +{ + struct Context + { + int val; + }; - template <typename AllContext> - void beforeHandle(Request&, Response&, Context& ctx, AllContext&) { - ctx.val = 1; - } + template <typename AllContext> + void beforeHandle(Request&, Response&, Context& ctx, AllContext&) + { + ctx.val = 1; + } - template <typename AllContext> - void afterHandle(Request&, Response&, Context& ctx, AllContext&) { - ctx.val = 2; - } + template <typename AllContext> + void afterHandle(Request&, Response&, Context& ctx, AllContext&) + { + ctx.val = 2; + } }; std::vector<std::string> test_middleware_context_vector; -struct FirstMW { - struct Context { - std::vector<string> v; - }; +struct FirstMW +{ + struct Context + { + std::vector<string> v; + }; - void beforeHandle(Request& /*req*/, Response& /*res*/, Context& ctx) { - ctx.v.push_back("1 before"); - } + void beforeHandle(Request& /*req*/, Response& /*res*/, Context& ctx) + { + ctx.v.push_back("1 before"); + } - void afterHandle(Request& /*req*/, Response& /*res*/, Context& ctx) { - ctx.v.push_back("1 after"); - test_middleware_context_vector = ctx.v; - } + void afterHandle(Request& /*req*/, Response& /*res*/, Context& ctx) + { + ctx.v.push_back("1 after"); + test_middleware_context_vector = ctx.v; + } }; -struct SecondMW { - struct Context {}; - template <typename AllContext> - void beforeHandle(Request& req, Response& res, Context&, - AllContext& all_ctx) { - all_ctx.template get<FirstMW>().v.push_back("2 before"); - if (req.url == "/break") res.end(); - } - - template <typename AllContext> - void afterHandle(Request&, Response&, Context&, AllContext& all_ctx) { - all_ctx.template get<FirstMW>().v.push_back("2 after"); - } +struct SecondMW +{ + struct Context + { + }; + template <typename AllContext> + void beforeHandle(Request& req, Response& res, Context&, + AllContext& all_ctx) + { + all_ctx.template get<FirstMW>().v.push_back("2 before"); + if (req.url == "/break") + res.end(); + } + + template <typename AllContext> + void afterHandle(Request&, Response&, Context&, AllContext& all_ctx) + { + all_ctx.template get<FirstMW>().v.push_back("2 after"); + } }; -struct ThirdMW { - struct Context {}; - template <typename AllContext> - void beforeHandle(Request&, Response&, Context&, AllContext& all_ctx) { - all_ctx.template get<FirstMW>().v.push_back("3 before"); - } - - template <typename AllContext> - void afterHandle(Request&, Response&, Context&, AllContext& all_ctx) { - all_ctx.template get<FirstMW>().v.push_back("3 after"); - } +struct ThirdMW +{ + struct Context + { + }; + template <typename AllContext> + void beforeHandle(Request&, Response&, Context&, AllContext& all_ctx) + { + all_ctx.template get<FirstMW>().v.push_back("3 before"); + } + + template <typename AllContext> + void afterHandle(Request&, Response&, Context&, AllContext& all_ctx) + { + all_ctx.template get<FirstMW>().v.push_back("3 after"); + } }; -TEST(Crow, middlewareContext) { - static char buf[2048]; - // SecondMW depends on FirstMW (it uses all_ctx.get<FirstMW>) - // so it leads to compile error if we remove FirstMW from definition - // App<IntSettingMiddleware, SecondMW> app; - // or change the order of FirstMW and SecondMW - // App<IntSettingMiddleware, SecondMW, FirstMW> app; +TEST(Crow, middlewareContext) +{ + static char buf[2048]; + // SecondMW depends on FirstMW (it uses all_ctx.get<FirstMW>) + // so it leads to compile error if we remove FirstMW from definition + // App<IntSettingMiddleware, SecondMW> app; + // or change the order of FirstMW and SecondMW + // App<IntSettingMiddleware, SecondMW, FirstMW> app; + + App<IntSettingMiddleware, FirstMW, SecondMW, ThirdMW> app; + + int x{}; + BMCWEB_ROUTE(app, "/") + ([&](const Request& req) { + { + auto& ctx = app.getContext<IntSettingMiddleware>(req); + x = ctx.val; + } + { + auto& ctx = app.getContext<FirstMW>(req); + ctx.v.push_back("handle"); + } + + return ""; + }); + BMCWEB_ROUTE(app, "/break") + ([&](const Request& req) { + { + auto& ctx = app.getContext<FirstMW>(req); + ctx.v.push_back("handle"); + } - App<IntSettingMiddleware, FirstMW, SecondMW, ThirdMW> app; + return ""; + }); - int x{}; - BMCWEB_ROUTE(app, "/") - ([&](const Request& req) { + decltype(app)::server_t server(&app, LOCALHOST_ADDRESS, 45451); + auto _ = async(launch::async, [&] { server.run(); }); + std::string sendmsg = "GET /\r\n\r\n"; + asio::io_service is; { - auto& ctx = app.getContext<IntSettingMiddleware>(req); - x = ctx.val; + asio::ip::tcp::socket c(is); + c.connect(asio::ip::tcp::endpoint( + asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451)); + + c.send(asio::buffer(sendmsg)); + + c.receive(asio::buffer(buf, 2048)); + c.close(); } { - auto& ctx = app.getContext<FirstMW>(req); - ctx.v.push_back("handle"); + auto& out = test_middleware_context_vector; + ASSERT_EQUAL(1, x); + ASSERT_EQUAL(7, out.size()); + ASSERT_EQUAL("1 before", out[0]); + ASSERT_EQUAL("2 before", out[1]); + ASSERT_EQUAL("3 before", out[2]); + ASSERT_EQUAL("handle", out[3]); + ASSERT_EQUAL("3 after", out[4]); + ASSERT_EQUAL("2 after", out[5]); + ASSERT_EQUAL("1 after", out[6]); } + std::string sendmsg2 = "GET /break\r\n\r\n"; + { + asio::ip::tcp::socket c(is); + c.connect(asio::ip::tcp::endpoint( + asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451)); + + c.send(asio::buffer(sendmsg2)); - return ""; - }); - BMCWEB_ROUTE(app, "/break") - ([&](const Request& req) { + c.receive(asio::buffer(buf, 2048)); + c.close(); + } { - auto& ctx = app.getContext<FirstMW>(req); - ctx.v.push_back("handle"); + auto& out = test_middleware_context_vector; + ASSERT_EQUAL(4, out.size()); + ASSERT_EQUAL("1 before", out[0]); + ASSERT_EQUAL("2 before", out[1]); + ASSERT_EQUAL("2 after", out[2]); + ASSERT_EQUAL("1 after", out[3]); } + server.stop(); +} - return ""; - }); +TEST(Crow, bug_quick_repeated_request) +{ + static char buf[2048]; - decltype(app)::server_t server(&app, LOCALHOST_ADDRESS, 45451); - auto _ = async(launch::async, [&] { server.run(); }); - std::string sendmsg = "GET /\r\n\r\n"; - asio::io_service is; - { - asio::ip::tcp::socket c(is); - c.connect(asio::ip::tcp::endpoint( - asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451)); + SimpleApp app; - c.send(asio::buffer(sendmsg)); + BMCWEB_ROUTE(app, "/")([&] { return "hello"; }); - c.receive(asio::buffer(buf, 2048)); - c.close(); - } - { - auto& out = test_middleware_context_vector; - ASSERT_EQUAL(1, x); - ASSERT_EQUAL(7, out.size()); - ASSERT_EQUAL("1 before", out[0]); - ASSERT_EQUAL("2 before", out[1]); - ASSERT_EQUAL("3 before", out[2]); - ASSERT_EQUAL("handle", out[3]); - ASSERT_EQUAL("3 after", out[4]); - ASSERT_EQUAL("2 after", out[5]); - ASSERT_EQUAL("1 after", out[6]); - } - std::string sendmsg2 = "GET /break\r\n\r\n"; - { - asio::ip::tcp::socket c(is); - c.connect(asio::ip::tcp::endpoint( - asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451)); - - c.send(asio::buffer(sendmsg2)); - - c.receive(asio::buffer(buf, 2048)); - c.close(); - } - { - auto& out = test_middleware_context_vector; - ASSERT_EQUAL(4, out.size()); - ASSERT_EQUAL("1 before", out[0]); - ASSERT_EQUAL("2 before", out[1]); - ASSERT_EQUAL("2 after", out[2]); - ASSERT_EQUAL("1 after", out[3]); - } - server.stop(); + decltype(app)::server_t server(&app, LOCALHOST_ADDRESS, 45451); + auto _ = async(launch::async, [&] { server.run(); }); + std::string sendmsg = "GET / HTTP/1.1\r\nHost: localhost\r\n\r\n"; + asio::io_service is; + { + std::vector<std::future<void>> v; + for (int i = 0; i < 5; i++) + { + v.push_back(async(launch::async, [&] { + asio::ip::tcp::socket c(is); + c.connect(asio::ip::tcp::endpoint( + asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451)); + + for (int j = 0; j < 5; j++) + { + c.send(asio::buffer(sendmsg)); + + size_t received = c.receive(asio::buffer(buf, 2048)); + ASSERT_EQUAL("hello", std::string(buf + received - 5, + buf + received)); + } + c.close(); + })); + } + } + server.stop(); } -TEST(Crow, bug_quick_repeated_request) { - static char buf[2048]; +TEST(Crow, simple_url_params) +{ + static char buf[2048]; + + SimpleApp app; + + QueryString lastUrlParams; + + BMCWEB_ROUTE(app, "/params") + ([&lastUrlParams](const crow::Request& req) { + lastUrlParams = std::move(req.urlParams); + return "OK"; + }); - SimpleApp app; + /// params?h=1&foo=bar&lol&count[]=1&count[]=4&pew=5.2 - BMCWEB_ROUTE(app, "/")([&] { return "hello"; }); + decltype(app)::server_t server(&app, LOCALHOST_ADDRESS, 45451); + auto _ = async(launch::async, [&] { server.run(); }); + asio::io_service is; + std::string sendmsg; - decltype(app)::server_t server(&app, LOCALHOST_ADDRESS, 45451); - auto _ = async(launch::async, [&] { server.run(); }); - std::string sendmsg = "GET / HTTP/1.1\r\nHost: localhost\r\n\r\n"; - asio::io_service is; - { - std::vector<std::future<void>> v; - for (int i = 0; i < 5; i++) { - v.push_back(async(launch::async, [&] { + // check empty params + sendmsg = "GET /params\r\n\r\n"; + { asio::ip::tcp::socket c(is); c.connect(asio::ip::tcp::endpoint( asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451)); + c.send(asio::buffer(sendmsg)); + c.receive(asio::buffer(buf, 2048)); + c.close(); - for (int j = 0; j < 5; j++) { - c.send(asio::buffer(sendmsg)); + stringstream ss; + ss << lastUrlParams; - size_t received = c.receive(asio::buffer(buf, 2048)); - ASSERT_EQUAL("hello", - std::string(buf + received - 5, buf + received)); - } + ASSERT_EQUAL("[ ]", ss.str()); + } + // check single presence + sendmsg = "GET /params?foobar\r\n\r\n"; + { + asio::ip::tcp::socket c(is); + c.connect(asio::ip::tcp::endpoint( + asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451)); + c.send(asio::buffer(sendmsg)); + c.receive(asio::buffer(buf, 2048)); + c.close(); + + ASSERT_TRUE(lastUrlParams.get("missing") == nullptr); + ASSERT_TRUE(lastUrlParams.get("foobar") != nullptr); + ASSERT_TRUE(lastUrlParams.getList("missing").empty()); + } + // check multiple presence + sendmsg = "GET /params?foo&bar&baz\r\n\r\n"; + { + asio::ip::tcp::socket c(is); + c.connect(asio::ip::tcp::endpoint( + asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451)); + c.send(asio::buffer(sendmsg)); + c.receive(asio::buffer(buf, 2048)); c.close(); - })); + + ASSERT_TRUE(lastUrlParams.get("missing") == nullptr); + ASSERT_TRUE(lastUrlParams.get("foo") != nullptr); + ASSERT_TRUE(lastUrlParams.get("bar") != nullptr); + ASSERT_TRUE(lastUrlParams.get("baz") != nullptr); } - } - server.stop(); -} + // check single value + sendmsg = "GET /params?hello=world\r\n\r\n"; + { + asio::ip::tcp::socket c(is); + c.connect(asio::ip::tcp::endpoint( + asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451)); + c.send(asio::buffer(sendmsg)); + c.receive(asio::buffer(buf, 2048)); + c.close(); -TEST(Crow, simple_url_params) { - static char buf[2048]; - - SimpleApp app; - - QueryString lastUrlParams; - - BMCWEB_ROUTE(app, "/params") - ([&lastUrlParams](const crow::Request& req) { - lastUrlParams = std::move(req.urlParams); - return "OK"; - }); - - /// params?h=1&foo=bar&lol&count[]=1&count[]=4&pew=5.2 - - decltype(app)::server_t server(&app, LOCALHOST_ADDRESS, 45451); - auto _ = async(launch::async, [&] { server.run(); }); - asio::io_service is; - std::string sendmsg; - - // check empty params - sendmsg = "GET /params\r\n\r\n"; - { - asio::ip::tcp::socket c(is); - c.connect(asio::ip::tcp::endpoint( - asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451)); - c.send(asio::buffer(sendmsg)); - c.receive(asio::buffer(buf, 2048)); - c.close(); - - stringstream ss; - ss << lastUrlParams; - - ASSERT_EQUAL("[ ]", ss.str()); - } - // check single presence - sendmsg = "GET /params?foobar\r\n\r\n"; - { - asio::ip::tcp::socket c(is); - c.connect(asio::ip::tcp::endpoint( - asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451)); - c.send(asio::buffer(sendmsg)); - c.receive(asio::buffer(buf, 2048)); - c.close(); - - ASSERT_TRUE(lastUrlParams.get("missing") == nullptr); - ASSERT_TRUE(lastUrlParams.get("foobar") != nullptr); - ASSERT_TRUE(lastUrlParams.getList("missing").empty()); - } - // check multiple presence - sendmsg = "GET /params?foo&bar&baz\r\n\r\n"; - { - asio::ip::tcp::socket c(is); - c.connect(asio::ip::tcp::endpoint( - asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451)); - c.send(asio::buffer(sendmsg)); - c.receive(asio::buffer(buf, 2048)); - c.close(); - - ASSERT_TRUE(lastUrlParams.get("missing") == nullptr); - ASSERT_TRUE(lastUrlParams.get("foo") != nullptr); - ASSERT_TRUE(lastUrlParams.get("bar") != nullptr); - ASSERT_TRUE(lastUrlParams.get("baz") != nullptr); - } - // check single value - sendmsg = "GET /params?hello=world\r\n\r\n"; - { - asio::ip::tcp::socket c(is); - c.connect(asio::ip::tcp::endpoint( - asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451)); - c.send(asio::buffer(sendmsg)); - c.receive(asio::buffer(buf, 2048)); - c.close(); - - ASSERT_EQUAL(string(lastUrlParams.get("hello")), "world"); - } - // check multiple value - sendmsg = "GET /params?hello=world&left=right&up=down\r\n\r\n"; - { - asio::ip::tcp::socket c(is); - c.connect(asio::ip::tcp::endpoint( - asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451)); - c.send(asio::buffer(sendmsg)); - c.receive(asio::buffer(buf, 2048)); - c.close(); - - ASSERT_EQUAL(string(lastUrlParams.get("hello")), "world"); - ASSERT_EQUAL(string(lastUrlParams.get("left")), "right"); - ASSERT_EQUAL(string(lastUrlParams.get("up")), "down"); - } - // check multiple value, multiple types - sendmsg = "GET /params?int=100&double=123.45&boolean=1\r\n\r\n"; - { - asio::ip::tcp::socket c(is); - c.connect(asio::ip::tcp::endpoint( - asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451)); - c.send(asio::buffer(sendmsg)); - c.receive(asio::buffer(buf, 2048)); - c.close(); - - ASSERT_EQUAL(boost::lexical_cast<int>(lastUrlParams.get("int")), 100); - ASSERT_EQUAL(boost::lexical_cast<double>(lastUrlParams.get("double")), - 123.45); - ASSERT_EQUAL(boost::lexical_cast<bool>(lastUrlParams.get("boolean")), true); - } - // check single array value - sendmsg = "GET /params?tmnt[]=leonardo\r\n\r\n"; - { - asio::ip::tcp::socket c(is); - - c.connect(asio::ip::tcp::endpoint( - asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451)); - c.send(asio::buffer(sendmsg)); - c.receive(asio::buffer(buf, 2048)); - c.close(); - - ASSERT_TRUE(lastUrlParams.get("tmnt") == nullptr); - ASSERT_EQUAL(lastUrlParams.getList("tmnt").size(), 1); - ASSERT_EQUAL(string(lastUrlParams.getList("tmnt")[0]), "leonardo"); - } - // check multiple array value - sendmsg = - "GET /params?tmnt[]=leonardo&tmnt[]=donatello&tmnt[]=raphael\r\n\r\n"; - { - asio::ip::tcp::socket c(is); - - c.connect(asio::ip::tcp::endpoint( - asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451)); - c.send(asio::buffer(sendmsg)); - c.receive(asio::buffer(buf, 2048)); - c.close(); - - ASSERT_EQUAL(lastUrlParams.getList("tmnt").size(), 3); - ASSERT_EQUAL(string(lastUrlParams.getList("tmnt")[0]), "leonardo"); - ASSERT_EQUAL(string(lastUrlParams.getList("tmnt")[1]), "donatello"); - ASSERT_EQUAL(string(lastUrlParams.getList("tmnt")[2]), "raphael"); - } - server.stop(); + ASSERT_EQUAL(string(lastUrlParams.get("hello")), "world"); + } + // check multiple value + sendmsg = "GET /params?hello=world&left=right&up=down\r\n\r\n"; + { + asio::ip::tcp::socket c(is); + c.connect(asio::ip::tcp::endpoint( + asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451)); + c.send(asio::buffer(sendmsg)); + c.receive(asio::buffer(buf, 2048)); + c.close(); + + ASSERT_EQUAL(string(lastUrlParams.get("hello")), "world"); + ASSERT_EQUAL(string(lastUrlParams.get("left")), "right"); + ASSERT_EQUAL(string(lastUrlParams.get("up")), "down"); + } + // check multiple value, multiple types + sendmsg = "GET /params?int=100&double=123.45&boolean=1\r\n\r\n"; + { + asio::ip::tcp::socket c(is); + c.connect(asio::ip::tcp::endpoint( + asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451)); + c.send(asio::buffer(sendmsg)); + c.receive(asio::buffer(buf, 2048)); + c.close(); + + ASSERT_EQUAL(boost::lexical_cast<int>(lastUrlParams.get("int")), 100); + ASSERT_EQUAL(boost::lexical_cast<double>(lastUrlParams.get("double")), + 123.45); + ASSERT_EQUAL(boost::lexical_cast<bool>(lastUrlParams.get("boolean")), + true); + } + // check single array value + sendmsg = "GET /params?tmnt[]=leonardo\r\n\r\n"; + { + asio::ip::tcp::socket c(is); + + c.connect(asio::ip::tcp::endpoint( + asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451)); + c.send(asio::buffer(sendmsg)); + c.receive(asio::buffer(buf, 2048)); + c.close(); + + ASSERT_TRUE(lastUrlParams.get("tmnt") == nullptr); + ASSERT_EQUAL(lastUrlParams.getList("tmnt").size(), 1); + ASSERT_EQUAL(string(lastUrlParams.getList("tmnt")[0]), "leonardo"); + } + // check multiple array value + sendmsg = + "GET /params?tmnt[]=leonardo&tmnt[]=donatello&tmnt[]=raphael\r\n\r\n"; + { + asio::ip::tcp::socket c(is); + + c.connect(asio::ip::tcp::endpoint( + asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451)); + c.send(asio::buffer(sendmsg)); + c.receive(asio::buffer(buf, 2048)); + c.close(); + + ASSERT_EQUAL(lastUrlParams.getList("tmnt").size(), 3); + ASSERT_EQUAL(string(lastUrlParams.getList("tmnt")[0]), "leonardo"); + ASSERT_EQUAL(string(lastUrlParams.getList("tmnt")[1]), "donatello"); + ASSERT_EQUAL(string(lastUrlParams.getList("tmnt")[2]), "raphael"); + } + server.stop(); } -TEST(Crow, routeDynamic) { - SimpleApp app; - int x = 1; - app.routeDynamic("/")([&] { - x = 2; - return ""; - }); - - app.routeDynamic("/set4")([&](const Request&) { - x = 4; - return ""; - }); - app.routeDynamic("/set5")([&](const Request&, Response& res) { - x = 5; - res.end(); - }); - - app.routeDynamic("/set_int/<int>")([&](int y) { - x = y; - return ""; - }); - - try { - app.routeDynamic("/invalid_test/<double>/<path>")([]() { return ""; }); - fail(); - } catch (std::exception&) { - } - - // app is in an invalid state when routeDynamic throws an exception. - try { - app.validate(); - fail(); - } catch (std::exception&) { - } +TEST(Crow, routeDynamic) +{ + SimpleApp app; + int x = 1; + app.routeDynamic("/")([&] { + x = 2; + return ""; + }); + + app.routeDynamic("/set4")([&](const Request&) { + x = 4; + return ""; + }); + app.routeDynamic("/set5")([&](const Request&, Response& res) { + x = 5; + res.end(); + }); + + app.routeDynamic("/set_int/<int>")([&](int y) { + x = y; + return ""; + }); + + try + { + app.routeDynamic("/invalid_test/<double>/<path>")([]() { return ""; }); + fail(); + } + catch (std::exception&) + { + } - { - boost::beast::http::request<boost::beast::http::string_body> r{}; - Request req{r}; - Response res; - req.url = "/"; - app.handle(req, res); - ASSERT_EQUAL(x, 2); - } - { - boost::beast::http::request<boost::beast::http::string_body> r{}; - Request req{r}; - Response res; - req.url = "/set_int/42"; - app.handle(req, res); - ASSERT_EQUAL(x, 42); - } - { - boost::beast::http::request<boost::beast::http::string_body> r{}; - Request req{r}; - Response res; - req.url = "/set5"; - app.handle(req, res); - ASSERT_EQUAL(x, 5); - } - { - boost::beast::http::request<boost::beast::http::string_body> r{}; - Request req{r}; - Response res; - req.url = "/set4"; - app.handle(req, res); - ASSERT_EQUAL(x, 4); - } + // app is in an invalid state when routeDynamic throws an exception. + try + { + app.validate(); + fail(); + } + catch (std::exception&) + { + } + + { + boost::beast::http::request<boost::beast::http::string_body> r{}; + Request req{r}; + Response res; + req.url = "/"; + app.handle(req, res); + ASSERT_EQUAL(x, 2); + } + { + boost::beast::http::request<boost::beast::http::string_body> r{}; + Request req{r}; + Response res; + req.url = "/set_int/42"; + app.handle(req, res); + ASSERT_EQUAL(x, 42); + } + { + boost::beast::http::request<boost::beast::http::string_body> r{}; + Request req{r}; + Response res; + req.url = "/set5"; + app.handle(req, res); + ASSERT_EQUAL(x, 5); + } + { + boost::beast::http::request<boost::beast::http::string_body> r{}; + Request req{r}; + Response res; + req.url = "/set4"; + app.handle(req, res); + ASSERT_EQUAL(x, 4); + } } diff --git a/src/getvideo_main.cpp b/src/getvideo_main.cpp index 7055d35dfc..8d5f7afd3b 100644 --- a/src/getvideo_main.cpp +++ b/src/getvideo_main.cpp @@ -1,15 +1,15 @@ #include <fcntl.h> #include <unistd.h> + #include <chrono> +#include <cstdio> +#include <cstdlib> #include <fstream> #include <iomanip> #include <iostream> #include <thread> #include <vector> -#include <cstdio> -#include <cstdlib> - //#define BUILD_CIMG #ifdef BUILD_CIMG #define cimg_display 0 @@ -19,52 +19,60 @@ #include <ast_jpeg_decoder.hpp> #include <ast_video_puller.hpp> -int main() { - ast_video::RawVideoBuffer out; - bool have_hardware = false; - if (access("/dev/video", F_OK) != -1) { - ast_video::SimpleVideoPuller p; - p.initialize(); - out = p.readVideo(); - } else { - FILE *fp = fopen("/home/ed/screendata.bin", "rb"); - if (fp != nullptr) { - size_t newLen = fread(out.buffer.data(), sizeof(char), - out.buffer.size() * sizeof(long), fp); - if (ferror(fp) != 0) { - fputs("Error reading file", stderr); - } - fclose(fp); - out.buffer.resize(newLen); - out.mode = ast_video::YuvMode::YUV444; - out.width = 800; - out.height = 600; - out.ySelector = 0; - out.uvSelector = 0; +int main() +{ + ast_video::RawVideoBuffer out; + bool have_hardware = false; + if (access("/dev/video", F_OK) != -1) + { + ast_video::SimpleVideoPuller p; + p.initialize(); + out = p.readVideo(); + } + else + { + FILE *fp = fopen("/home/ed/screendata.bin", "rb"); + if (fp != nullptr) + { + size_t newLen = fread(out.buffer.data(), sizeof(char), + out.buffer.size() * sizeof(long), fp); + if (ferror(fp) != 0) + { + fputs("Error reading file", stderr); + } + fclose(fp); + out.buffer.resize(newLen); + out.mode = ast_video::YuvMode::YUV444; + out.width = 800; + out.height = 600; + out.ySelector = 0; + out.uvSelector = 0; + } } - } - FILE *fp = fopen("/tmp/screendata.bin", "wb"); - fwrite(out.buffer.data(), sizeof(char), out.buffer.size(), fp); + FILE *fp = fopen("/tmp/screendata.bin", "wb"); + fwrite(out.buffer.data(), sizeof(char), out.buffer.size(), fp); - ast_video::AstJpegDecoder d; - d.decode(out.buffer, out.width, out.height, out.mode, out.ySelector, - out.uvSelector); + ast_video::AstJpegDecoder d; + d.decode(out.buffer, out.width, out.height, out.mode, out.ySelector, + out.uvSelector); #ifdef BUILD_CIMG - cimg_library::CImg<unsigned char> image(out.width, out.height, 1, - 3 /*numchannels*/); - for (int y = 0; y < out.height; y++) { - for (int x = 0; x < out.width; x++) { - auto pixel = d.outBuffer[x + (y * out.width)]; - image(x, y, 0) = pixel.r; - image(x, y, 1) = pixel.g; - image(x, y, 2) = pixel.b; + cimg_library::CImg<unsigned char> image(out.width, out.height, 1, + 3 /*numchannels*/); + for (int y = 0; y < out.height; y++) + { + for (int x = 0; x < out.width; x++) + { + auto pixel = d.outBuffer[x + (y * out.width)]; + image(x, y, 0) = pixel.r; + image(x, y, 1) = pixel.g; + image(x, y, 2) = pixel.b; + } } - } - image.save("/tmp/file2.bmp"); + image.save("/tmp/file2.bmp"); #endif - std::cout << "Done!\n"; + std::cout << "Done!\n"; - return 1; + return 1; } diff --git a/src/gtest_main.cpp b/src/gtest_main.cpp index eec00675a3..77e70aac1d 100644 --- a/src/gtest_main.cpp +++ b/src/gtest_main.cpp @@ -1,7 +1,8 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -int main(int argc, char **argv) { - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); +int main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); }
\ No newline at end of file diff --git a/src/kvm_websocket_test.cpp b/src/kvm_websocket_test.cpp index b5e1bdcffd..1ddaad9b35 100644 --- a/src/kvm_websocket_test.cpp +++ b/src/kvm_websocket_test.cpp @@ -1,9 +1,12 @@ +#include "gzip_helper.hpp" +#include "web_kvm.hpp" + #include <iostream> #include <sstream> #include <vector> -#include "gzip_helper.hpp" -#include "web_kvm.hpp" + #include "crow.h" + #include <gmock/gmock.h> #include <gtest/gtest.h> @@ -11,93 +14,101 @@ using namespace crow; using namespace testing; // Tests static files are loaded correctly -TEST(Kvm, BasicRfb) { - return; // TODO(ed) Make hte code below work again - SimpleApp app; - - crow::kvm::requestRoutes(app); - app.bindaddr("127.0.0.1").port(45451); - BMCWEB_ROUTE(app, "/")([]() { return boost::beast::http::status::ok; }); - auto _ = async(std::launch::async, [&] { app.run(); }); - auto routes = app.getRoutes(); - asio::io_service is; - - { - // Retry a couple of times waiting for the server to come up - // TODO(ed) This is really unfortunate, and should use some form of mock - asio::ip::tcp::socket c(is); - for (int i = 0; i < 200; i++) { - try { - c.connect(asio::ip::tcp::endpoint( - asio::ip::address::from_string("127.0.0.1"), 45451)); - c.close(); - break; - } catch (std::exception e) { - // do nothing. We expect this to fail while the server is starting up - } +TEST(Kvm, BasicRfb) +{ + return; // TODO(ed) Make hte code below work again + SimpleApp app; + + crow::kvm::requestRoutes(app); + app.bindaddr("127.0.0.1").port(45451); + BMCWEB_ROUTE(app, "/")([]() { return boost::beast::http::status::ok; }); + auto _ = async(std::launch::async, [&] { app.run(); }); + auto routes = app.getRoutes(); + asio::io_service is; + + { + // Retry a couple of times waiting for the server to come up + // TODO(ed) This is really unfortunate, and should use some form of + // mock + asio::ip::tcp::socket c(is); + for (int i = 0; i < 200; i++) + { + try + { + c.connect(asio::ip::tcp::endpoint( + asio::ip::address::from_string("127.0.0.1"), 45451)); + c.close(); + break; + } + catch (std::exception e) + { + // do nothing. We expect this to fail while the server is + // starting up + } + } + } + + // Get the websocket + std::string sendmsg = ("GET /kvmws HTTP/1.1\r\n" + "Host: localhost:45451\r\n" + "Connection: Upgrade\r\n" + "Upgrade: websocket\r\n" + "Sec-WebSocket-Version: 13\r\n" + "Sec-WebSocket-Key: aLeGkmLPZmdv5tTyEpJ3jQ==\r\n" + "Sec-WebSocket-Extensions: permessage-deflate; " + "client_max_window_bits\r\n" + "Sec-WebSocket-Protocol: binary\r\n" + "\r\n"); + + asio::ip::tcp::socket socket(is); + socket.connect(asio::ip::tcp::endpoint( + asio::ip::address::from_string("127.0.0.1"), 45451)); + socket.send(asio::buffer(sendmsg)); + + // Read the Response status line. The Response streambuf will automatically + // grow to accommodate the entire line. The growth may be limited by passing + // a maximum size to the streambuf constructor. + boost::asio::streambuf response; + boost::asio::read_until(socket, response, "\r\n"); + + // Check that Response is OK. + std::istream response_stream(&response); + std::string http_response; + std::getline(response_stream, http_response); + + EXPECT_EQ(http_response, "HTTP/1.1 101 Switching Protocols\r"); + + // Read the Response headers, which are terminated by a blank line. + boost::asio::read_until(socket, response, "\r\n\r\n"); + + // Process the Response headers. + std::string header; + std::vector<std::string> headers; + while (std::getline(response_stream, header) && header != "\r") + { + headers.push_back(header); } - } - - // Get the websocket - std::string sendmsg = - ("GET /kvmws HTTP/1.1\r\n" - "Host: localhost:45451\r\n" - "Connection: Upgrade\r\n" - "Upgrade: websocket\r\n" - "Sec-WebSocket-Version: 13\r\n" - "Sec-WebSocket-Key: aLeGkmLPZmdv5tTyEpJ3jQ==\r\n" - "Sec-WebSocket-Extensions: permessage-deflate; " - "client_max_window_bits\r\n" - "Sec-WebSocket-Protocol: binary\r\n" - "\r\n"); - - asio::ip::tcp::socket socket(is); - socket.connect(asio::ip::tcp::endpoint( - asio::ip::address::from_string("127.0.0.1"), 45451)); - socket.send(asio::buffer(sendmsg)); - - // Read the Response status line. The Response streambuf will automatically - // grow to accommodate the entire line. The growth may be limited by passing - // a maximum size to the streambuf constructor. - boost::asio::streambuf response; - boost::asio::read_until(socket, response, "\r\n"); - - // Check that Response is OK. - std::istream response_stream(&response); - std::string http_response; - std::getline(response_stream, http_response); - - EXPECT_EQ(http_response, "HTTP/1.1 101 Switching Protocols\r"); - - // Read the Response headers, which are terminated by a blank line. - boost::asio::read_until(socket, response, "\r\n\r\n"); - - // Process the Response headers. - std::string header; - std::vector<std::string> headers; - while (std::getline(response_stream, header) && header != "\r") { - headers.push_back(header); - } - - EXPECT_THAT(headers, Contains("Upgrade: websocket\r")); - EXPECT_THAT(headers, Contains("Connection: Upgrade\r")); - EXPECT_THAT(headers, Contains("Sec-WebSocket-Protocol: binary\r")); - // TODO(ed) This is the result that it gives today. Need to check websocket - // docs and make - // sure that this calclution is actually being done to spec - EXPECT_THAT(headers, - Contains("Sec-WebSocket-Accept: /CnDM3l79rIxniLNyxMryXbtLEU=\r")); - std::array<char, 13> rfb_open_string; - - // - // socket.receive(rfb_open_string.data(), rfb_open_string.size()); - boost::asio::read(socket, boost::asio::buffer(rfb_open_string)); - auto open_string = - std::string(std::begin(rfb_open_string), std::end(rfb_open_string)); - // Todo(ed) find out what the two characters at the end of the websocket - // stream are - open_string = open_string.substr(2); - EXPECT_EQ(open_string, "RFB 003.008"); - - app.stop(); + + EXPECT_THAT(headers, Contains("Upgrade: websocket\r")); + EXPECT_THAT(headers, Contains("Connection: Upgrade\r")); + EXPECT_THAT(headers, Contains("Sec-WebSocket-Protocol: binary\r")); + // TODO(ed) This is the result that it gives today. Need to check websocket + // docs and make + // sure that this calclution is actually being done to spec + EXPECT_THAT( + headers, + Contains("Sec-WebSocket-Accept: /CnDM3l79rIxniLNyxMryXbtLEU=\r")); + std::array<char, 13> rfb_open_string; + + // + // socket.receive(rfb_open_string.data(), rfb_open_string.size()); + boost::asio::read(socket, boost::asio::buffer(rfb_open_string)); + auto open_string = + std::string(std::begin(rfb_open_string), std::end(rfb_open_string)); + // Todo(ed) find out what the two characters at the end of the websocket + // stream are + open_string = open_string.substr(2); + EXPECT_EQ(open_string, "RFB 003.008"); + + app.stop(); }
\ No newline at end of file diff --git a/src/msan_test.cpp b/src/msan_test.cpp index 9fcb9d530c..7e42e48659 100644 --- a/src/msan_test.cpp +++ b/src/msan_test.cpp @@ -1,7 +1,9 @@ #include <string> + #include "gtest/gtest.h" -TEST(MemorySanitizer, TestIsWorking) { - std::string foo("foo"); - EXPECT_STREQ("foo", foo.c_str()); +TEST(MemorySanitizer, TestIsWorking) +{ + std::string foo("foo"); + EXPECT_STREQ("foo", foo.c_str()); } diff --git a/src/openbmc_jtag_rest_test.cpp b/src/openbmc_jtag_rest_test.cpp index 7e40d6ddee..42504d3895 100644 --- a/src/openbmc_jtag_rest_test.cpp +++ b/src/openbmc_jtag_rest_test.cpp @@ -1,51 +1,53 @@ #include "openbmc_dbus_rest.hpp" + #include "gmock/gmock.h" #include "gtest/gtest.h" -TEST(OpenBmcDbusTest, TestArgSplit) { - // test the basic types - EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("x"), - ::testing::ElementsAre("x")); - EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("y"), - ::testing::ElementsAre("y")); - EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("b"), - ::testing::ElementsAre("b")); - EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("n"), - ::testing::ElementsAre("n")); - EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("q"), - ::testing::ElementsAre("q")); - EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("i"), - ::testing::ElementsAre("i")); - EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("u"), - ::testing::ElementsAre("u")); - EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("x"), - ::testing::ElementsAre("x")); - EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("t"), - ::testing::ElementsAre("t")); - EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("d"), - ::testing::ElementsAre("d")); - EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("h"), - ::testing::ElementsAre("h")); - // test arrays - EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("ai"), - ::testing::ElementsAre("ai")); - EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("ax"), - ::testing::ElementsAre("ax")); - // test tuples - EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("(sss)"), - ::testing::ElementsAre("(sss)")); - EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("(sss)b"), - ::testing::ElementsAre("(sss)", "b")); - EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("b(sss)"), - ::testing::ElementsAre("b", "(sss)")); +TEST(OpenBmcDbusTest, TestArgSplit) +{ + // test the basic types + EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("x"), + ::testing::ElementsAre("x")); + EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("y"), + ::testing::ElementsAre("y")); + EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("b"), + ::testing::ElementsAre("b")); + EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("n"), + ::testing::ElementsAre("n")); + EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("q"), + ::testing::ElementsAre("q")); + EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("i"), + ::testing::ElementsAre("i")); + EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("u"), + ::testing::ElementsAre("u")); + EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("x"), + ::testing::ElementsAre("x")); + EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("t"), + ::testing::ElementsAre("t")); + EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("d"), + ::testing::ElementsAre("d")); + EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("h"), + ::testing::ElementsAre("h")); + // test arrays + EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("ai"), + ::testing::ElementsAre("ai")); + EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("ax"), + ::testing::ElementsAre("ax")); + // test tuples + EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("(sss)"), + ::testing::ElementsAre("(sss)")); + EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("(sss)b"), + ::testing::ElementsAre("(sss)", "b")); + EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("b(sss)"), + ::testing::ElementsAre("b", "(sss)")); - // Test nested types - EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("a{si}b"), - ::testing::ElementsAre("a{si}", "b")); - EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("a(sss)b"), - ::testing::ElementsAre("a(sss)", "b")); - EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("aa{si}b"), - ::testing::ElementsAre("aa{si}", "b")); - EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("i{si}b"), - ::testing::ElementsAre("b", "aa{si}")); + // Test nested types + EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("a{si}b"), + ::testing::ElementsAre("a{si}", "b")); + EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("a(sss)b"), + ::testing::ElementsAre("a(sss)", "b")); + EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("aa{si}b"), + ::testing::ElementsAre("aa{si}", "b")); + EXPECT_THAT(crow::openbmc_mapper::dbus_arg_split("i{si}b"), + ::testing::ElementsAre("b", "aa{si}")); } diff --git a/src/security_headers_middleware_test.cpp b/src/security_headers_middleware_test.cpp index e7008cb165..2af15c6d07 100644 --- a/src/security_headers_middleware_test.cpp +++ b/src/security_headers_middleware_test.cpp @@ -1,5 +1,7 @@ -#include <security_headers_middleware.hpp> #include <crow/app.h> + +#include <security_headers_middleware.hpp> + #include <gmock/gmock.h> #include <gtest/gtest.h> @@ -7,68 +9,78 @@ using namespace crow; using namespace std; // Tests that the security headers are added correctly -TEST(SecurityHeaders, TestHeadersExist) { - App<SecurityHeadersMiddleware> app; - app.bindaddr("127.0.0.1").port(45451); - BMCWEB_ROUTE(app, "/")([]() { return boost::beast::http::status::ok; }); - auto _ = async(launch::async, [&] { app.run(); }); +TEST(SecurityHeaders, TestHeadersExist) +{ + App<SecurityHeadersMiddleware> app; + app.bindaddr("127.0.0.1").port(45451); + BMCWEB_ROUTE(app, "/")([]() { return boost::beast::http::status::ok; }); + auto _ = async(launch::async, [&] { app.run(); }); - asio::io_service is; - std::array<char, 2048> buf; - std::string sendmsg; + asio::io_service is; + std::array<char, 2048> buf; + std::string sendmsg; - { - // Retry a couple of times waiting for the server to come up - // TODO(ed) This is really unfortunate, and should use some form of mock - asio::ip::tcp::socket c(is); - for (int i = 0; i < 200; i++) { - try { - c.connect(asio::ip::tcp::endpoint( - asio::ip::address::from_string("127.0.0.1"), 45451)); - c.close(); - break; - } catch (std::exception e) { - // do nothing. We expect this to fail while the server is starting up - } + { + // Retry a couple of times waiting for the server to come up + // TODO(ed) This is really unfortunate, and should use some form of + // mock + asio::ip::tcp::socket c(is); + for (int i = 0; i < 200; i++) + { + try + { + c.connect(asio::ip::tcp::endpoint( + asio::ip::address::from_string("127.0.0.1"), 45451)); + c.close(); + break; + } + catch (std::exception e) + { + // do nothing. We expect this to fail while the server is + // starting up + } + } } - } - // Test correct login credentials - sendmsg = "GET /\r\n\r\n"; + // Test correct login credentials + sendmsg = "GET /\r\n\r\n"; - asio::ip::tcp::socket c(is); - c.connect(asio::ip::tcp::endpoint(asio::ip::address::from_string("127.0.0.1"), - 45451)); - c.send(asio::buffer(sendmsg)); - c.receive(asio::buffer(buf)); - c.close(); - auto return_code = std::string(&buf[9], &buf[12]); - EXPECT_EQ("200", return_code); - std::string response(std::begin(buf), std::end(buf)); + asio::ip::tcp::socket c(is); + c.connect(asio::ip::tcp::endpoint( + asio::ip::address::from_string("127.0.0.1"), 45451)); + c.send(asio::buffer(sendmsg)); + c.receive(asio::buffer(buf)); + c.close(); + auto return_code = std::string(&buf[9], &buf[12]); + EXPECT_EQ("200", return_code); + std::string response(std::begin(buf), std::end(buf)); - // This is a routine to split strings until a blank is hit - // TODO(ed) this should really use the HTTP parser - std::vector<std::string> headers; - std::string::size_type pos = 0; - std::string::size_type prev = 0; - while ((pos = response.find("\r\n", prev)) != std::string::npos) { - auto this_string = response.substr(prev, pos - prev); - if (this_string == "") { - break; + // This is a routine to split strings until a blank is hit + // TODO(ed) this should really use the HTTP parser + std::vector<std::string> headers; + std::string::size_type pos = 0; + std::string::size_type prev = 0; + while ((pos = response.find("\r\n", prev)) != std::string::npos) + { + auto this_string = response.substr(prev, pos - prev); + if (this_string == "") + { + break; + } + headers.push_back(this_string); + prev = pos + 2; } - headers.push_back(this_string); - prev = pos + 2; - } - headers.push_back(response.substr(prev)); + headers.push_back(response.substr(prev)); - EXPECT_EQ(headers[0], "HTTP/1.1 200 OK"); - EXPECT_THAT(headers, ::testing::Contains("Strict-Transport-Security: " - "max-age=31536000; " - "includeSubdomains; preload")); - EXPECT_THAT(headers, ::testing::Contains("X-UA-Compatible: IE=11")); - EXPECT_THAT(headers, ::testing::Contains("X-Frame-Options: DENY")); - EXPECT_THAT(headers, ::testing::Contains("X-XSS-Protection: 1; mode=block")); - EXPECT_THAT(headers, ::testing::Contains( - "X-Content-Security-Policy: default-src 'self'")); - app.stop(); + EXPECT_EQ(headers[0], "HTTP/1.1 200 OK"); + EXPECT_THAT(headers, ::testing::Contains("Strict-Transport-Security: " + "max-age=31536000; " + "includeSubdomains; preload")); + EXPECT_THAT(headers, ::testing::Contains("X-UA-Compatible: IE=11")); + EXPECT_THAT(headers, ::testing::Contains("X-Frame-Options: DENY")); + EXPECT_THAT(headers, + ::testing::Contains("X-XSS-Protection: 1; mode=block")); + EXPECT_THAT(headers, ::testing::Contains( + "X-Content-Security-Policy: default-src 'self'")); + app.stop(); } diff --git a/src/token_authorization_middleware_test.cpp b/src/token_authorization_middleware_test.cpp index ab735b3a52..812a6d193e 100644 --- a/src/token_authorization_middleware_test.cpp +++ b/src/token_authorization_middleware_test.cpp @@ -1,287 +1,322 @@ #include "token_authorization_middleware.hpp" +#include "webserver_common.hpp" + #include <condition_variable> #include <future> #include <mutex> -#include "webserver_common.hpp" + #include "gmock/gmock.h" #include "gtest/gtest.h" using namespace crow; -class TokenAuth : public ::testing::Test { - public: - TokenAuth() - : lk(std::unique_lock<std::mutex>(m)), - io(std::make_shared<boost::asio::io_service>()) {} - - std::mutex m; - std::condition_variable cv; - std::unique_lock<std::mutex> lk; - std::shared_ptr<boost::asio::io_service> io; - int testPort = 45451; +class TokenAuth : public ::testing::Test +{ + public: + TokenAuth() : + lk(std::unique_lock<std::mutex>(m)), + io(std::make_shared<boost::asio::io_service>()) + { + } + + std::mutex m; + std::condition_variable cv; + std::unique_lock<std::mutex> lk; + std::shared_ptr<boost::asio::io_service> io; + int testPort = 45451; }; -TEST_F(TokenAuth, SpecialResourcesAreAcceptedWithoutAuth) { - CrowApp app(io); - crow::token_authorization::requestRoutes(app); - BMCWEB_ROUTE(app, "/redfish/v1") - ([]() { return boost::beast::http::status::ok; }); - auto _ = std::async(std::launch::async, [&] { - app.port(testPort).run(); - cv.notify_one(); - io->run(); - }); - - asio::io_service is; - std::string sendmsg; - - static char buf[2048]; - - // Homepage should be passed with no credentials - sendmsg = "GET /\r\n\r\n"; - { - asio::ip::tcp::socket c(is); - c.connect(asio::ip::tcp::endpoint( - asio::ip::address::from_string("127.0.0.1"), 45451)); - c.send(asio::buffer(sendmsg)); - c.receive(asio::buffer(buf, 2048)); - c.close(); - EXPECT_EQ("200", std::string(buf + 9, buf + 12)); - } +TEST_F(TokenAuth, SpecialResourcesAreAcceptedWithoutAuth) +{ + CrowApp app(io); + crow::token_authorization::requestRoutes(app); + BMCWEB_ROUTE(app, "/redfish/v1") + ([]() { return boost::beast::http::status::ok; }); + auto _ = std::async(std::launch::async, [&] { + app.port(testPort).run(); + cv.notify_one(); + io->run(); + }); + + asio::io_service is; + std::string sendmsg; + + static char buf[2048]; + + // Homepage should be passed with no credentials + sendmsg = "GET /\r\n\r\n"; + { + asio::ip::tcp::socket c(is); + c.connect(asio::ip::tcp::endpoint( + asio::ip::address::from_string("127.0.0.1"), 45451)); + c.send(asio::buffer(sendmsg)); + c.receive(asio::buffer(buf, 2048)); + c.close(); + EXPECT_EQ("200", std::string(buf + 9, buf + 12)); + } - // static should be passed with no credentials - sendmsg = "GET /static/index.html\r\n\r\n"; - { - asio::ip::tcp::socket c(is); - c.connect(asio::ip::tcp::endpoint( - asio::ip::address::from_string("127.0.0.1"), 45451)); - c.send(asio::buffer(sendmsg)); - c.receive(asio::buffer(buf, 2048)); - c.close(); - EXPECT_EQ("404", std::string(buf + 9, buf + 12)); - } + // static should be passed with no credentials + sendmsg = "GET /static/index.html\r\n\r\n"; + { + asio::ip::tcp::socket c(is); + c.connect(asio::ip::tcp::endpoint( + asio::ip::address::from_string("127.0.0.1"), 45451)); + c.send(asio::buffer(sendmsg)); + c.receive(asio::buffer(buf, 2048)); + c.close(); + EXPECT_EQ("404", std::string(buf + 9, buf + 12)); + } - app.stop(); + app.stop(); } // Tests that Base64 basic strings work -TEST(TokenAuthentication, TestRejectedResource) { - App<crow::persistent_data::Middleware, crow::token_authorization::Middleware> - app; - app.bindaddr("127.0.0.1").port(45451); - BMCWEB_ROUTE(app, "/")([]() { return boost::beast::http::status::ok; }); - auto _ = async(std::launch::async, [&] { app.run(); }); - - asio::io_service is; - static char buf[2048]; - - // Other resources should not be passed - std::string sendmsg = "GET /foo\r\n\r\n"; - asio::ip::tcp::socket c(is); - for (int i = 0; i < 200; i++) { - try { - c.connect(asio::ip::tcp::endpoint( - asio::ip::address::from_string("127.0.0.1"), 45451)); - } catch (std::exception e) { - // do nothing +TEST(TokenAuthentication, TestRejectedResource) +{ + App<crow::persistent_data::Middleware, + crow::token_authorization::Middleware> + app; + app.bindaddr("127.0.0.1").port(45451); + BMCWEB_ROUTE(app, "/")([]() { return boost::beast::http::status::ok; }); + auto _ = async(std::launch::async, [&] { app.run(); }); + + asio::io_service is; + static char buf[2048]; + + // Other resources should not be passed + std::string sendmsg = "GET /foo\r\n\r\n"; + asio::ip::tcp::socket c(is); + for (int i = 0; i < 200; i++) + { + try + { + c.connect(asio::ip::tcp::endpoint( + asio::ip::address::from_string("127.0.0.1"), 45451)); + } + catch (std::exception e) + { + // do nothing + } } - } - c.send(asio::buffer(sendmsg)); - c.receive(asio::buffer(buf, 2048)); - c.close(); - EXPECT_EQ("401", std::string(buf + 9, buf + 12)); + c.send(asio::buffer(sendmsg)); + c.receive(asio::buffer(buf, 2048)); + c.close(); + EXPECT_EQ("401", std::string(buf + 9, buf + 12)); - app.stop(); + app.stop(); } // Tests that Base64 basic strings work -TEST(TokenAuthentication, TestGetLoginUrl) { - App<crow::persistent_data::Middleware, crow::token_authorization::Middleware> - app; - app.bindaddr("127.0.0.1").port(45451); - BMCWEB_ROUTE(app, "/")([]() { return boost::beast::http::status::ok; }); - auto _ = async(std::launch::async, [&] { app.run(); }); - - asio::io_service is; - static char buf[2048]; - - // Other resources should not be passed - std::string sendmsg = "GET /login\r\n\r\n"; - asio::ip::tcp::socket c(is); - for (int i = 0; i < 200; i++) { - try { - c.connect(asio::ip::tcp::endpoint( - asio::ip::address::from_string("127.0.0.1"), 45451)); - } catch (std::exception e) { - // do nothing +TEST(TokenAuthentication, TestGetLoginUrl) +{ + App<crow::persistent_data::Middleware, + crow::token_authorization::Middleware> + app; + app.bindaddr("127.0.0.1").port(45451); + BMCWEB_ROUTE(app, "/")([]() { return boost::beast::http::status::ok; }); + auto _ = async(std::launch::async, [&] { app.run(); }); + + asio::io_service is; + static char buf[2048]; + + // Other resources should not be passed + std::string sendmsg = "GET /login\r\n\r\n"; + asio::ip::tcp::socket c(is); + for (int i = 0; i < 200; i++) + { + try + { + c.connect(asio::ip::tcp::endpoint( + asio::ip::address::from_string("127.0.0.1"), 45451)); + } + catch (std::exception e) + { + // do nothing + } } - } - c.send(asio::buffer(sendmsg)); - c.receive(asio::buffer(buf, 2048)); - c.close(); - EXPECT_EQ("401", std::string(buf + 9, buf + 12)); + c.send(asio::buffer(sendmsg)); + c.receive(asio::buffer(buf, 2048)); + c.close(); + EXPECT_EQ("401", std::string(buf + 9, buf + 12)); - app.stop(); + app.stop(); } // Tests boundary conditions on login -TEST(TokenAuthentication, TestPostBadLoginUrl) { - App<crow::persistent_data::Middleware, crow::token_authorization::Middleware> - app; - app.bindaddr("127.0.0.1").port(45451); - BMCWEB_ROUTE(app, "/")([]() { return boost::beast::http::status::ok; }); - auto _ = async(std::launch::async, [&] { app.run(); }); - - asio::io_service is; - std::array<char, 2048> buf; - std::string sendmsg; - - auto send_to_localhost = [&is, &buf](std::string sendmsg) { - asio::ip::tcp::socket c(is); - c.connect(asio::ip::tcp::endpoint( - asio::ip::address::from_string("127.0.0.1"), 45451)); - c.send(asio::buffer(sendmsg)); - c.receive(asio::buffer(buf)); - c.close(); - }; - - { - // Retry a couple of times waiting for the server to come up - asio::ip::tcp::socket c(is); - for (int i = 0; i < 200; i++) { - try { +TEST(TokenAuthentication, TestPostBadLoginUrl) +{ + App<crow::persistent_data::Middleware, + crow::token_authorization::Middleware> + app; + app.bindaddr("127.0.0.1").port(45451); + BMCWEB_ROUTE(app, "/")([]() { return boost::beast::http::status::ok; }); + auto _ = async(std::launch::async, [&] { app.run(); }); + + asio::io_service is; + std::array<char, 2048> buf; + std::string sendmsg; + + auto send_to_localhost = [&is, &buf](std::string sendmsg) { + asio::ip::tcp::socket c(is); c.connect(asio::ip::tcp::endpoint( asio::ip::address::from_string("127.0.0.1"), 45451)); + c.send(asio::buffer(sendmsg)); + c.receive(asio::buffer(buf)); c.close(); - break; - } catch (std::exception e) { - // do nothing. We expect this to fail while the server is starting up - } + }; + + { + // Retry a couple of times waiting for the server to come up + asio::ip::tcp::socket c(is); + for (int i = 0; i < 200; i++) + { + try + { + c.connect(asio::ip::tcp::endpoint( + asio::ip::address::from_string("127.0.0.1"), 45451)); + c.close(); + break; + } + catch (std::exception e) + { + // do nothing. We expect this to fail while the server is + // starting up + } + } } - } - - // Test blank login credentials - sendmsg = "POST /login\r\nContent-Length:0\r\n\r\n\r\n"; - { - send_to_localhost(sendmsg); - auto return_code = std::string(&buf[9], &buf[12]); - EXPECT_EQ("400", return_code); - } - - // Test wrong login credentials - sendmsg = - "POST /login\r\nContent-Length:38\r\n\r\n{\"username\": \"foo\", " - "\"password\": \"bar\"}\r\n"; - { - send_to_localhost(sendmsg); - auto return_code = std::string(&buf[9], &buf[12]); - EXPECT_EQ("401", return_code); - // TODO(ed) need to test more here. Response string? - } - - // Test only sending a username - sendmsg = - "POST /login\r\nContent-Length:19\r\n\r\n{\"username\": \"foo\"}\r\n"; - { - send_to_localhost(sendmsg); - auto return_code = std::string(&buf[9], &buf[12]); - EXPECT_EQ("400", return_code); - } - - // Test only sending a password - sendmsg = - "POST /login\r\nContent-Length:19\r\n\r\n{\"password\": \"foo\"}\r\n"; - { - send_to_localhost(sendmsg); - auto return_code = std::string(&buf[9], &buf[12]); - EXPECT_EQ("400", return_code); - } - - app.stop(); -} -// Test class that allows login for a fixed password. -class KnownLoginAuthenticator { - public: - inline bool authenticate(const std::string& username, - const std::string& password) { - return (username == "dude") && (password == "foo"); - } -}; + // Test blank login credentials + sendmsg = "POST /login\r\nContent-Length:0\r\n\r\n\r\n"; + { + send_to_localhost(sendmsg); + auto return_code = std::string(&buf[9], &buf[12]); + EXPECT_EQ("400", return_code); + } -TEST(TokenAuthentication, TestSuccessfulLogin) { - App<crow::persistent_data::Middleware, crow::token_authorization::Middleware> - app; - app.bindaddr("127.0.0.1").port(45451); - BMCWEB_ROUTE(app, "/")([]() { return boost::beast::http::status::ok; }); - auto _ = async(std::launch::async, [&] { app.run(); }); + // Test wrong login credentials + sendmsg = "POST /login\r\nContent-Length:38\r\n\r\n{\"username\": \"foo\", " + "\"password\": \"bar\"}\r\n"; + { + send_to_localhost(sendmsg); + auto return_code = std::string(&buf[9], &buf[12]); + EXPECT_EQ("401", return_code); + // TODO(ed) need to test more here. Response string? + } - asio::io_service is; - std::array<char, 2048> buf; - std::string sendmsg; + // Test only sending a username + sendmsg = + "POST /login\r\nContent-Length:19\r\n\r\n{\"username\": \"foo\"}\r\n"; + { + send_to_localhost(sendmsg); + auto return_code = std::string(&buf[9], &buf[12]); + EXPECT_EQ("400", return_code); + } - auto send_to_localhost = [&is, &buf](std::string sendmsg) { - asio::ip::tcp::socket c(is); - c.connect(asio::ip::tcp::endpoint( - asio::ip::address::from_string("127.0.0.1"), 45451)); - c.send(asio::buffer(sendmsg)); - c.receive(asio::buffer(buf)); - c.close(); - }; + // Test only sending a password + sendmsg = + "POST /login\r\nContent-Length:19\r\n\r\n{\"password\": \"foo\"}\r\n"; + { + send_to_localhost(sendmsg); + auto return_code = std::string(&buf[9], &buf[12]); + EXPECT_EQ("400", return_code); + } - { - // Retry a couple of times waiting for the server to come up - asio::ip::tcp::socket c(is); - for (int i = 0; i < 200; i++) { - try { + app.stop(); +} + +// Test class that allows login for a fixed password. +class KnownLoginAuthenticator +{ + public: + inline bool authenticate(const std::string& username, + const std::string& password) + { + return (username == "dude") && (password == "foo"); + } +}; + +TEST(TokenAuthentication, TestSuccessfulLogin) +{ + App<crow::persistent_data::Middleware, + crow::token_authorization::Middleware> + app; + app.bindaddr("127.0.0.1").port(45451); + BMCWEB_ROUTE(app, "/")([]() { return boost::beast::http::status::ok; }); + auto _ = async(std::launch::async, [&] { app.run(); }); + + asio::io_service is; + std::array<char, 2048> buf; + std::string sendmsg; + + auto send_to_localhost = [&is, &buf](std::string sendmsg) { + asio::ip::tcp::socket c(is); c.connect(asio::ip::tcp::endpoint( asio::ip::address::from_string("127.0.0.1"), 45451)); + c.send(asio::buffer(sendmsg)); + c.receive(asio::buffer(buf)); c.close(); - break; - } catch (std::exception e) { - // do nothing. We expect this to fail while the server is starting up - } + }; + + { + // Retry a couple of times waiting for the server to come up + asio::ip::tcp::socket c(is); + for (int i = 0; i < 200; i++) + { + try + { + c.connect(asio::ip::tcp::endpoint( + asio::ip::address::from_string("127.0.0.1"), 45451)); + c.close(); + break; + } + catch (std::exception e) + { + // do nothing. We expect this to fail while the server is + // starting up + } + } } - } - - // Test correct login credentials - sendmsg = - "POST /login\r\nContent-Length:40\r\n\r\n{\"username\": \"dude\", " - "\"password\": \"foo\"}\r\n"; - { - send_to_localhost(sendmsg); - std::string response(std::begin(buf), std::end(buf)); - // This is a routine to split strings until a newline is hit - // TODO(ed) this should really use the HTTP parser - std::vector<std::string> headers; - std::string::size_type pos = 0; - std::string::size_type prev = 0; - int content_length = 0; - std::string content_encoding(""); - while ((pos = response.find("\r\n", prev)) != std::string::npos) { - auto this_string = response.substr(prev, pos - prev); - if (this_string == "") { - prev = pos + 2; - break; - } - - headers.push_back(this_string); - prev = pos + 2; + + // Test correct login credentials + sendmsg = + "POST /login\r\nContent-Length:40\r\n\r\n{\"username\": \"dude\", " + "\"password\": \"foo\"}\r\n"; + { + send_to_localhost(sendmsg); + std::string response(std::begin(buf), std::end(buf)); + // This is a routine to split strings until a newline is hit + // TODO(ed) this should really use the HTTP parser + std::vector<std::string> headers; + std::string::size_type pos = 0; + std::string::size_type prev = 0; + int content_length = 0; + std::string content_encoding(""); + while ((pos = response.find("\r\n", prev)) != std::string::npos) + { + auto this_string = response.substr(prev, pos - prev); + if (this_string == "") + { + prev = pos + 2; + break; + } + + headers.push_back(this_string); + prev = pos + 2; + } + EXPECT_EQ(headers[0], "HTTP/1.1 200 OK"); + EXPECT_THAT(headers, + testing::Contains("Content-Type: application/json")); + auto http_content = response.substr(prev); } - EXPECT_EQ(headers[0], "HTTP/1.1 200 OK"); - EXPECT_THAT(headers, testing::Contains("Content-Type: application/json")); - auto http_content = response.substr(prev); - } - - // Try to use those login credentials to access a resource - sendmsg = - "GET /\r\nAuthorization: token\r\n\r\n{\"username\": \"dude\", " - "\"password\": \"dude\"}\r\n"; - { - send_to_localhost(sendmsg); - auto return_code = std::string(&buf[9], &buf[12]); - EXPECT_EQ("200", return_code); - } - - app.stop(); + + // Try to use those login credentials to access a resource + sendmsg = "GET /\r\nAuthorization: token\r\n\r\n{\"username\": \"dude\", " + "\"password\": \"dude\"}\r\n"; + { + send_to_localhost(sendmsg); + auto return_code = std::string(&buf[9], &buf[12]); + EXPECT_EQ("200", return_code); + } + + app.stop(); }
\ No newline at end of file diff --git a/src/webassets_test.cpp b/src/webassets_test.cpp index 2633c9b65b..a3106f2796 100644 --- a/src/webassets_test.cpp +++ b/src/webassets_test.cpp @@ -1,135 +1,145 @@ #include <crow/app.h> -#include <gmock/gmock.h> -#include <gzip_helper.hpp> -#include <webassets.hpp> -#include <sstream> #include <boost/algorithm/string/predicate.hpp> #include <boost/lexical_cast.hpp> +#include <gzip_helper.hpp> +#include <sstream> +#include <webassets.hpp> + #include "gtest/gtest.h" +#include <gmock/gmock.h> using namespace crow; using namespace std; using namespace testing; // Tests static files are loaded correctly -TEST(Webassets, StaticFilesFixedRoutes) { - std::array<char, 2048> buf; - SimpleApp app; - webassets::requestRoutes(app); - Server<SimpleApp> server(&app, "127.0.0.1", 45451); - auto _ = async(launch::async, [&] { server.run(); }); - - // get the homepage - std::string sendmsg = "GET /\r\n\r\n"; - - asio::io_service is; - - asio::ip::tcp::socket c(is); - c.connect(asio::ip::tcp::endpoint(asio::ip::address::from_string("127.0.0.1"), - 45451)); - - c.send(asio::buffer(sendmsg)); - - c.receive(asio::buffer(buf, 2048)); - c.close(); - - std::string response(std::begin(buf), std::end(buf)); - // This is a routine to split strings until a newline is hit - // TODO(ed) this should really use the HTTP parser - std::vector<std::string> headers; - std::string::size_type pos = 0; - std::string::size_type prev = 0; - int content_length = 0; - std::string content_encoding(""); - while ((pos = response.find("\r\n", prev)) != std::string::npos) { - auto this_string = response.substr(prev, pos - prev); - if (this_string == "") { - prev = pos + 2; - break; +TEST(Webassets, StaticFilesFixedRoutes) +{ + std::array<char, 2048> buf; + SimpleApp app; + webassets::requestRoutes(app); + Server<SimpleApp> server(&app, "127.0.0.1", 45451); + auto _ = async(launch::async, [&] { server.run(); }); + + // get the homepage + std::string sendmsg = "GET /\r\n\r\n"; + + asio::io_service is; + + asio::ip::tcp::socket c(is); + c.connect(asio::ip::tcp::endpoint( + asio::ip::address::from_string("127.0.0.1"), 45451)); + + c.send(asio::buffer(sendmsg)); + + c.receive(asio::buffer(buf, 2048)); + c.close(); + + std::string response(std::begin(buf), std::end(buf)); + // This is a routine to split strings until a newline is hit + // TODO(ed) this should really use the HTTP parser + std::vector<std::string> headers; + std::string::size_type pos = 0; + std::string::size_type prev = 0; + int content_length = 0; + std::string content_encoding(""); + while ((pos = response.find("\r\n", prev)) != std::string::npos) + { + auto this_string = response.substr(prev, pos - prev); + if (this_string == "") + { + prev = pos + 2; + break; + } + + if (boost::starts_with(this_string, "Content-Length: ")) + { + content_length = boost::lexical_cast<int>(this_string.substr(16)); + // TODO(ed) This is an unfortunate test, but it's all we have at + // this point Realistically, the index.html will be more than 500 + // bytes. This test will need to be improved at some point + EXPECT_GT(content_length, 500); + } + if (boost::starts_with(this_string, "Content-Encoding: ")) + { + content_encoding = this_string.substr(18); + } + + headers.push_back(this_string); + prev = pos + 2; } - if (boost::starts_with(this_string, "Content-Length: ")) { - content_length = boost::lexical_cast<int>(this_string.substr(16)); - // TODO(ed) This is an unfortunate test, but it's all we have at this - // point - // Realistically, the index.html will be more than 500 bytes. This - // test will need to be improved at some point - EXPECT_GT(content_length, 500); - } - if (boost::starts_with(this_string, "Content-Encoding: ")) { - content_encoding = this_string.substr(18); + auto http_content = response.substr(prev); + // TODO(ed) ideally the server should support non-compressed gzip assets. + // Once this occurs, this line will be obsolete + std::string ungziped_content = http_content; + if (content_encoding == "gzip") + { + EXPECT_TRUE(gzipInflate(http_content, ungziped_content)); } - headers.push_back(this_string); - prev = pos + 2; - } - - auto http_content = response.substr(prev); - // TODO(ed) ideally the server should support non-compressed gzip assets. - // Once this occurs, this line will be obsolete - std::string ungziped_content = http_content; - if (content_encoding == "gzip") { - EXPECT_TRUE(gzipInflate(http_content, ungziped_content)); - } - - EXPECT_EQ(headers[0], "HTTP/1.1 200 OK"); - EXPECT_THAT(headers, - ::testing::Contains("Content-Type: text/html;charset=UTF-8")); + EXPECT_EQ(headers[0], "HTTP/1.1 200 OK"); + EXPECT_THAT(headers, + ::testing::Contains("Content-Type: text/html;charset=UTF-8")); - EXPECT_EQ(ungziped_content.substr(0, 21), "<!DOCTYPE html>\n<html"); + EXPECT_EQ(ungziped_content.substr(0, 21), "<!DOCTYPE html>\n<html"); - server.stop(); + server.stop(); } // Tests static files are loaded correctly -TEST(Webassets, EtagIsSane) { - std::array<char, 2048> buf; - SimpleApp app; - webassets::requestRoutes(app); - Server<SimpleApp> server(&app, "127.0.0.1", 45451); - auto _ = async(launch::async, [&] { server.run(); }); - - // get the homepage - std::string sendmsg = "GET /\r\n\r\n"; - - asio::io_service is; - - asio::ip::tcp::socket c(is); - c.connect(asio::ip::tcp::endpoint(asio::ip::address::from_string("127.0.0.1"), - 45451)); - - c.send(asio::buffer(sendmsg)); - - c.receive(asio::buffer(buf, 2048)); - c.close(); - - std::string response(std::begin(buf), std::end(buf)); - // This is a routine to split strings until a newline is hit - // TODO(ed) this should really use the HTTP parser - std::vector<std::string> headers; - std::string::size_type pos = 0; - std::string::size_type prev = 0; - int content_length = 0; - std::string content_encoding(""); - while ((pos = response.find("\r\n", prev)) != std::string::npos) { - auto this_string = response.substr(prev, pos - prev); - if (this_string == "") { - break; +TEST(Webassets, EtagIsSane) +{ + std::array<char, 2048> buf; + SimpleApp app; + webassets::requestRoutes(app); + Server<SimpleApp> server(&app, "127.0.0.1", 45451); + auto _ = async(launch::async, [&] { server.run(); }); + + // get the homepage + std::string sendmsg = "GET /\r\n\r\n"; + + asio::io_service is; + + asio::ip::tcp::socket c(is); + c.connect(asio::ip::tcp::endpoint( + asio::ip::address::from_string("127.0.0.1"), 45451)); + + c.send(asio::buffer(sendmsg)); + + c.receive(asio::buffer(buf, 2048)); + c.close(); + + std::string response(std::begin(buf), std::end(buf)); + // This is a routine to split strings until a newline is hit + // TODO(ed) this should really use the HTTP parser + std::vector<std::string> headers; + std::string::size_type pos = 0; + std::string::size_type prev = 0; + int content_length = 0; + std::string content_encoding(""); + while ((pos = response.find("\r\n", prev)) != std::string::npos) + { + auto this_string = response.substr(prev, pos - prev); + if (this_string == "") + { + break; + } + + if (boost::starts_with(this_string, "ETag: ")) + { + auto etag = this_string.substr(6); + // ETAG should not be blank + EXPECT_NE(etag, ""); + // SHa1 is 20 characters long + EXPECT_EQ(etag.size(), 40); + EXPECT_THAT(etag, MatchesRegex("^[a-f0-9]+$")); + } + + headers.push_back(this_string); + prev = pos + 2; } - if (boost::starts_with(this_string, "ETag: ")) { - auto etag = this_string.substr(6); - // ETAG should not be blank - EXPECT_NE(etag, ""); - // SHa1 is 20 characters long - EXPECT_EQ(etag.size(), 40); - EXPECT_THAT(etag, MatchesRegex("^[a-f0-9]+$")); - } - - headers.push_back(this_string); - prev = pos + 2; - } - - server.stop(); + server.stop(); } diff --git a/src/webserver_main.cpp b/src/webserver_main.cpp index 2f89ad4269..051b1fed61 100644 --- a/src/webserver_main.cpp +++ b/src/webserver_main.cpp @@ -1,8 +1,12 @@ +#include <crow/app.h> #include <systemd/sd-daemon.h> + #include <bmcweb/settings.hpp> +#include <boost/asio.hpp> #include <dbus_monitor.hpp> #include <dbus_singleton.hpp> #include <image_upload.hpp> +#include <memory> #include <openbmc_dbus_rest.hpp> #include <persistent_data_middleware.hpp> #include <redfish.hpp> @@ -12,84 +16,91 @@ #include <sdbusplus/server.hpp> #include <security_headers_middleware.hpp> #include <ssl_key_handler.hpp> +#include <string> #include <token_authorization_middleware.hpp> #include <web_kvm.hpp> #include <webassets.hpp> #include <webserver_common.hpp> -#include <memory> -#include <string> -#include <crow/app.h> -#include <boost/asio.hpp> constexpr int defaultPort = 18080; template <typename... Middlewares> -void setupSocket(crow::Crow<Middlewares...>& app) { - int listenFd = sd_listen_fds(0); - if (1 == listenFd) { - BMCWEB_LOG_INFO << "attempting systemd socket activation"; - if (sd_is_socket_inet(SD_LISTEN_FDS_START, AF_UNSPEC, SOCK_STREAM, 1, 0)) { - BMCWEB_LOG_INFO << "Starting webserver on socket handle " - << SD_LISTEN_FDS_START; - app.socket(SD_LISTEN_FDS_START); - } else { - BMCWEB_LOG_INFO << "bad incoming socket, starting webserver on port " - << defaultPort; - app.port(defaultPort); +void setupSocket(crow::Crow<Middlewares...>& app) +{ + int listenFd = sd_listen_fds(0); + if (1 == listenFd) + { + BMCWEB_LOG_INFO << "attempting systemd socket activation"; + if (sd_is_socket_inet(SD_LISTEN_FDS_START, AF_UNSPEC, SOCK_STREAM, 1, + 0)) + { + BMCWEB_LOG_INFO << "Starting webserver on socket handle " + << SD_LISTEN_FDS_START; + app.socket(SD_LISTEN_FDS_START); + } + else + { + BMCWEB_LOG_INFO + << "bad incoming socket, starting webserver on port " + << defaultPort; + app.port(defaultPort); + } + } + else + { + BMCWEB_LOG_INFO << "Starting webserver on port " << defaultPort; + app.port(defaultPort); } - } else { - BMCWEB_LOG_INFO << "Starting webserver on port " << defaultPort; - app.port(defaultPort); - } } -int main(int argc, char** argv) { - crow::logger::setLogLevel(crow::LogLevel::DEBUG); +int main(int argc, char** argv) +{ + crow::logger::setLogLevel(crow::LogLevel::DEBUG); - auto io = std::make_shared<boost::asio::io_service>(); - CrowApp app(io); + auto io = std::make_shared<boost::asio::io_service>(); + CrowApp app(io); #ifdef BMCWEB_ENABLE_SSL - std::string sslPemFile("server.pem"); - std::cout << "Building SSL Context\n"; + std::string sslPemFile("server.pem"); + std::cout << "Building SSL Context\n"; - ensuressl::ensureOpensslKeyPresentAndValid(sslPemFile); - std::cout << "SSL Enabled\n"; - auto sslContext = ensuressl::getSslContext(sslPemFile); - app.ssl(std::move(sslContext)); + ensuressl::ensureOpensslKeyPresentAndValid(sslPemFile); + std::cout << "SSL Enabled\n"; + auto sslContext = ensuressl::getSslContext(sslPemFile); + app.ssl(std::move(sslContext)); #endif - // Static assets need to be initialized before Authorization, because auth - // needs to build the whitelist from the static routes + // Static assets need to be initialized before Authorization, because auth + // needs to build the whitelist from the static routes #ifdef BMCWEB_ENABLE_STATIC_HOSTING - crow::webassets::requestRoutes(app); + crow::webassets::requestRoutes(app); #endif #ifdef BMCWEB_ENABLE_KVM - crow::kvm::requestRoutes(app); + crow::kvm::requestRoutes(app); #endif #ifdef BMCWEB_ENABLE_REDFISH - crow::redfish::requestRoutes(app); + crow::redfish::requestRoutes(app); #endif #ifdef BMCWEB_ENABLE_DBUS_REST - crow::dbus_monitor::requestRoutes(app); - crow::image_upload::requestRoutes(app); - crow::openbmc_mapper::requestRoutes(app); + crow::dbus_monitor::requestRoutes(app); + crow::image_upload::requestRoutes(app); + crow::openbmc_mapper::requestRoutes(app); #endif - crow::token_authorization::requestRoutes(app); + crow::token_authorization::requestRoutes(app); - BMCWEB_LOG_INFO << "bmcweb (" << __DATE__ << ": " << __TIME__ << ')'; - setupSocket(app); + BMCWEB_LOG_INFO << "bmcweb (" << __DATE__ << ": " << __TIME__ << ')'; + setupSocket(app); - crow::connections::systemBus = - std::make_shared<sdbusplus::asio::connection>(*io); - redfish::RedfishService redfish(app); + crow::connections::systemBus = + std::make_shared<sdbusplus::asio::connection>(*io); + redfish::RedfishService redfish(app); - app.run(); - io->run(); + app.run(); + io->run(); - crow::connections::systemBus.reset(); + crow::connections::systemBus.reset(); } |