diff options
| author | Joel Klinghed <the_jk@spawned.biz> | 2021-11-17 22:34:57 +0100 |
|---|---|---|
| committer | Joel Klinghed <the_jk@spawned.biz> | 2021-11-17 22:34:57 +0100 |
| commit | 6232d13f5321b87ddf12a1aa36b4545da45f173d (patch) | |
| tree | 23f3316470a14136debd9d02f9e920ca2b06f4cc /test/test_fcgi_protocol.cc | |
Travel3: Simple image and video display site
Reads the images and videos from filesystem and builds a site in
memroy.
Diffstat (limited to 'test/test_fcgi_protocol.cc')
| -rw-r--r-- | test/test_fcgi_protocol.cc | 678 |
1 files changed, 678 insertions, 0 deletions
diff --git a/test/test_fcgi_protocol.cc b/test/test_fcgi_protocol.cc new file mode 100644 index 0000000..b72b6f3 --- /dev/null +++ b/test/test_fcgi_protocol.cc @@ -0,0 +1,678 @@ +#include "common.hh" + +#include "fcgi_protocol.hh" +#include "str_buffer.hh" + +#include <gtest/gtest.h> + +namespace { + +constexpr const auto kSanity = std::string_view( + "\1" // version = 1 + "\1" // begin_request = 1 + "\0\1" // request_id = 1 + "\x10\xfe" // content_length = 4350 + "\xf0" // padding_length = 240 + "\0", // reserved = 0 + 8); + +constexpr const auto kMax = std::string_view( + "\1" // version = 1 + "\xa" // get_values_result = 10 + "\xff\xff" // request_id = 0xffff + "\xff\xff" // content_length = 0xffff + "\xff" // padding_length = 0xff + "\0", // reserved = 0 + 8); + +constexpr const auto kBeginRequest = std::string_view( + "\1" // version = 1 + "\1" // begin_request = 1 + "\0\1" // request_id = 1 + "\0\x8" // content_length = 8 + "\0" // padding_length = 0 + "\0" // reserved = 0 + "\0\1" // role = 1 + "\1" // flags = 1 + "\0\0\0\0\0", // reserved + 16); + +constexpr const auto kPairShortShort = std::string_view( + "\1" // version = 1 + "\x4" // Params + "\0\0" // request id = 0 + "\0\x5" // content length = 5 + "\x3" // padding length = 3 + "\0" // reserved + "\x3" // name length = 3 + "\0" // value length = 0 + "foo" // name + "" // value + "\0\0\0", // padding + 16); + +#define LONG_NAME \ + "0123456789012345678901234567890123456789012345678901234567890123456789" \ + "0123456789012345678901234567890123456789012345678901234567" + +#define LONG_VALUE \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + +constexpr const auto kPairShortLong = std::string_view( + "\1" // version = 1 + "\x4" // Params + "\0\0" // request id = 0 + "\1\x88" // content length = 392 + "\0" // padding length = 0 + "\0" // reserved + "\x3" // name length = 3 + "\x80\0\1\x80" // value length = 384 + "foo" // name + LONG_VALUE + "", // padding + 400); + +constexpr const auto kPairLongShort = std::string_view( + "\1" // version = 1 + "\x4" // Params + "\0\0" // request id = 0 + "\0\x85" // content length = 133 + "\x3" // padding length = 3 + "\0" // reserved + "\x80\0\0\x80" // name length = 128 + "\0" // value length = 0 + LONG_NAME + "" // value + "\0\0\0", // padding + 144); + +constexpr const auto kPairLongLong = std::string_view( + "\1" // version = 1 + "\x4" // Params + "\0\0" // request id = 0 + "\2\x8" // content length = 520 + "\0" // padding length = 0 + "\0" // reserved + "\x80\0\0\x80" // name length = 128 + "\x80\0\1\x80" // value length = 384 + LONG_NAME + LONG_VALUE + "", // padding + 528); + +constexpr const auto kStream1 = std::string_view( + "\1" // version = 1 + "\x4" // Params + "\0\1" // request id = 1 + "\0\x8" // content length = 8 + "\0" // padding length = 0 + "\0" // reserved + "\x3" // name length = 3 + "\0" // value length = 0 + "foo" // name + "" // value + "\x3" // name length = 3 + "\x3" // value length = 3 + "b", // name[0..1] + 16); + +constexpr const auto kStream2 = std::string_view( + "\1" // version = 1 + "\x4" // Params + "\0\1" // request id = 1 + "\0\x5" // content length = 5 + "\x3" // padding length = 3 + "\0" // reserved + "ar" // name[2..3] + "zum" // value + "\0\0\0", // padding + 16); + +constexpr const auto kStream3 = std::string_view( + "\1" // version = 1 + "\x4" // Params + "\0\1" // request id = 1 + "\0\x5" // content length = 5 + "\x3" // padding length = 3 + "\0" // reserved + "\0" // name length = 0 + "\x3" // value length = 3 + "" // name + "aaa" // value + "\0\0\0", // padding + 16); + +constexpr const auto kStream4 = std::string_view( + "\1" // version = 1 + "\x4" // Params + "\0\1" // request id = 1 + "\0\0" // content length = 0 + "\0" // padding length = 0 + "\0" // reserved + "", // padding + 8); + +constexpr const auto kPairInvalid = std::string_view( + "\1" // version = 1 + "\x4" // Params + "\0\0" // request id = 0 + "\0\x8" // content length = 8 + "\0" // padding length = 0 + "\0" // reserved + "\x3" // name length = 3 + "\x10" // value length = 16 + "foo" // name + "bar" // value (13 bytes to short) + "", // padding + 16); + +constexpr const auto kPairInvalidWithPadding = std::string_view( + "\1" // version = 1 + "\x4" // Params + "\0\0" // request id = 0 + "\0\x6" // content length = 6 + "\x2" // padding length = 2 + "\0" // reserved + "\x2" // name length = 2 + "\x8" // value length = 8 + "aa" // name + "bb" // value (13 bytes to short) + "\0\0", // padding + 16); + +} // namespace + +TEST(fcgi_protocol, empty) { + auto buf = make_strbuffer(std::string_view()); + EXPECT_FALSE(fcgi::Record::parse(buf.get())); +} + +TEST(fcgi_protocol, incomplete) { + for (size_t i = 1; i < kSanity.size(); ++i) { + auto buf = make_strbuffer(kSanity.substr(0, i)); + EXPECT_FALSE(fcgi::Record::parse(buf.get())); + } +} + +TEST(fcgi_protocol, bad) { + auto buf = make_strbuffer(std::string_view( + "\xff\xff\xff\xff\xff\xff\xff\xff")); + auto rec = fcgi::Record::parse(buf.get()); + ASSERT_TRUE(rec); + EXPECT_FALSE(rec->good()); +} + +TEST(fcgi_protocol, unknown) { + auto buf = make_strbuffer(std::string_view( + "\1\xff\xff\xff\xff\xff\xff\xff")); + auto rec = fcgi::Record::parse(buf.get()); + ASSERT_TRUE(rec); + EXPECT_TRUE(rec->good()); + EXPECT_EQ(0xff, rec->type()); +} + +TEST(fcgi_protocol, sanity) { + auto buf = make_strbuffer(kSanity); + auto rec = fcgi::Record::parse(buf.get()); + ASSERT_TRUE(rec); + EXPECT_TRUE(rec->good()); + EXPECT_EQ(fcgi::RecordType::BeginRequest, rec->type()); + EXPECT_EQ(1, rec->request_id()); + EXPECT_EQ(4350, rec->content_length()); + EXPECT_EQ(240, rec->padding_length()); + EXPECT_TRUE(buf->empty()); +} + +TEST(fcgi_protocol, max) { + auto buf = make_strbuffer(kMax); + auto rec = fcgi::Record::parse(buf.get()); + ASSERT_TRUE(rec); + EXPECT_TRUE(rec->good()); + EXPECT_EQ(fcgi::RecordType::GetValuesResult, rec->type()); + EXPECT_EQ(0xffff, rec->request_id()); + EXPECT_EQ(0xffff, rec->content_length()); + EXPECT_EQ(0xff, rec->padding_length()); + EXPECT_TRUE(buf->empty()); +} + +TEST(fcgi_protocol, builder_sanity) { + auto str = std::make_shared<std::string>(); + auto buf = make_strbuffer(str); + auto builder = fcgi::RecordBuilder::create(fcgi::RecordType::BeginRequest, + 1, + 4350, + 240); + EXPECT_TRUE(builder->build(buf.get())); + EXPECT_EQ(kSanity, *str); + EXPECT_EQ(kSanity.size() + 4350 + 240, builder->size()); + auto rec = fcgi::Record::parse(buf.get()); + ASSERT_TRUE(rec); + EXPECT_TRUE(rec->good()); + EXPECT_EQ(fcgi::RecordType::BeginRequest, rec->type()); + EXPECT_EQ(1, rec->request_id()); + EXPECT_EQ(4350, rec->content_length()); + EXPECT_EQ(240, rec->padding_length()); + EXPECT_TRUE(buf->empty()); +} + +TEST(fcgi_protocol, builder_with_body) { + auto str = std::make_shared<std::string>(); + auto buf = make_strbuffer(str); + auto builder = fcgi::RecordBuilder::create(fcgi::RecordType::BeginRequest, + 1, + 6, + 2); + EXPECT_TRUE(builder->build(buf.get())); + Buffer::write(buf.get(), "foobar", 6); + EXPECT_TRUE(builder->padding(buf.get())); + + auto rec = fcgi::Record::parse(buf.get()); + ASSERT_TRUE(rec); + EXPECT_TRUE(rec->good()); + EXPECT_EQ(fcgi::RecordType::BeginRequest, rec->type()); + EXPECT_EQ(1, rec->request_id()); + EXPECT_EQ(6, rec->content_length()); + EXPECT_EQ(2, rec->padding_length()); + + char tmp[7]; + std::fill_n(tmp, sizeof(tmp), 0); + EXPECT_EQ(6, Buffer::read(buf.get(), tmp, 6)); + EXPECT_STREQ("foobar", tmp); + + std::fill_n(tmp, sizeof(tmp), 0); + EXPECT_EQ(2, Buffer::read(buf.get(), tmp, 2)); + + EXPECT_TRUE(buf->empty()); +} + +TEST(fcgi_protocol, builder_max) { + auto str = std::make_shared<std::string>(); + auto buf = make_strbuffer(str); + auto builder = fcgi::RecordBuilder::create(fcgi::RecordType::GetValuesResult, + 0xffff, + 0xffff, + 0xff); + EXPECT_TRUE(builder->build(buf.get())); + EXPECT_EQ(kMax, *str); + EXPECT_EQ(kMax.size() + 0xffff + 0xff, builder->size()); + auto rec = fcgi::Record::parse(buf.get()); + ASSERT_TRUE(rec); + EXPECT_TRUE(rec->good()); + EXPECT_EQ(fcgi::RecordType::GetValuesResult, rec->type()); + EXPECT_EQ(0xffff, rec->request_id()); + EXPECT_EQ(0xffff, rec->content_length()); + EXPECT_EQ(0xff, rec->padding_length()); + EXPECT_TRUE(buf->empty()); +} + +TEST(fcgi_protocol, builder_incomplete) { + auto buf = Buffer::fixed(7); + auto builder = fcgi::RecordBuilder::create(fcgi::RecordType::BeginRequest, + 1, + 0); + EXPECT_FALSE(builder->build(buf.get())); + EXPECT_EQ(8, builder->size()); +} + +TEST(fcgi_protocol, builder_unknown_type) { + auto str = std::make_shared<std::string>(); + auto buf = make_strbuffer(str); + auto builder = fcgi::RecordBuilder::create_unknown_type(0xff); + EXPECT_TRUE(builder->build(buf.get())); + EXPECT_EQ(std::string_view("\1\xb\0\0\0\x8\0\0" "\xff\0\0\0\0\0\0\0", 16), + *str); + EXPECT_EQ(16, builder->size()); +} + +TEST(fcgi_protocol, builder_begin_request) { + auto str = std::make_shared<std::string>(); + auto buf = make_strbuffer(str); + auto builder = fcgi::RecordBuilder::create_begin_request( + 1, fcgi::Role::Responder, 0); + EXPECT_TRUE(builder->build(buf.get())); + EXPECT_EQ(std::string_view("\1\1\0\1\0\x8\0\0" "\0\1\0\0\0\0\0\0", 16), *str); + EXPECT_EQ(16, builder->size()); +} + +TEST(fcgi_protocol, builder_end_request) { + auto str = std::make_shared<std::string>(); + auto buf = make_strbuffer(str); + auto builder = fcgi::RecordBuilder::create_end_request( + 1, 0xbeef, fcgi::ProtocolStatus::RequestComplete); + EXPECT_TRUE(builder->build(buf.get())); + EXPECT_EQ(std::string_view("\1\3\0\1\0\x8\0\0" "\0\0\xbe\xef\0\0\0\0", 16), + *str); + EXPECT_EQ(16, builder->size()); +} + +TEST(fcgi_protocol, pair_short_short) { + auto buf = make_strbuffer(kPairShortShort); + auto rec = fcgi::Record::parse(buf.get()); + ASSERT_TRUE(rec); + auto stream = fcgi::RecordStream::create_single(rec.get()); + EXPECT_FALSE(stream->end_of_record()); + EXPECT_FALSE(stream->end_of_stream()); + auto pair = fcgi::Pair::start(stream.get(), buf.get()); + ASSERT_TRUE(pair); + EXPECT_TRUE(pair->good()); + EXPECT_EQ("foo", pair->name()); + EXPECT_EQ("", pair->value()); + EXPECT_FALSE(pair->next(stream.get(), buf.get())); + EXPECT_TRUE(stream->end_of_record()); + EXPECT_TRUE(stream->end_of_stream()); + EXPECT_TRUE(buf->empty()); +} + +TEST(fcgi_protocol, pair_short_short_incomplete) { + for (size_t i = 8; i < kPairShortShort.size() - 1; ++i) { + auto buf = make_strbuffer(kPairShortShort.substr(0, i)); + auto rec = fcgi::Record::parse(buf.get()); + ASSERT_TRUE(rec); + auto stream = fcgi::RecordStream::create_single(rec.get()); + EXPECT_FALSE(stream->end_of_record()); + EXPECT_FALSE(stream->end_of_stream()); + auto pair = fcgi::Pair::start(stream.get(), buf.get()); + EXPECT_FALSE(pair); + } +} + +TEST(fcgi_protocol, pair_short_long) { + auto buf = make_strbuffer(kPairShortLong); + auto rec = fcgi::Record::parse(buf.get()); + ASSERT_TRUE(rec); + auto stream = fcgi::RecordStream::create_single(rec.get()); + EXPECT_FALSE(stream->end_of_record()); + EXPECT_FALSE(stream->end_of_stream()); + auto pair = fcgi::Pair::start(stream.get(), buf.get()); + ASSERT_TRUE(pair); + EXPECT_TRUE(pair->good()); + EXPECT_EQ("foo", pair->name()); + EXPECT_EQ(LONG_VALUE, pair->value()); + EXPECT_FALSE(pair->next(stream.get(), buf.get())); + EXPECT_TRUE(stream->end_of_record()); + EXPECT_TRUE(stream->end_of_stream()); + EXPECT_TRUE(buf->empty()); +} + +TEST(fcgi_protocol, pair_long_short) { + auto buf = make_strbuffer(kPairLongShort); + auto rec = fcgi::Record::parse(buf.get()); + ASSERT_TRUE(rec); + auto stream = fcgi::RecordStream::create_single(rec.get()); + EXPECT_FALSE(stream->end_of_record()); + EXPECT_FALSE(stream->end_of_stream()); + auto pair = fcgi::Pair::start(stream.get(), buf.get()); + ASSERT_TRUE(pair); + EXPECT_TRUE(pair->good()); + EXPECT_EQ(LONG_NAME, pair->name()); + EXPECT_EQ("", pair->value()); + EXPECT_FALSE(pair->next(stream.get(), buf.get())); + EXPECT_TRUE(stream->end_of_record()); + EXPECT_TRUE(stream->end_of_stream()); + EXPECT_TRUE(buf->empty()); +} + +TEST(fcgi_protocol, pair_long_long) { + auto buf = make_strbuffer(kPairLongLong); + auto rec = fcgi::Record::parse(buf.get()); + ASSERT_TRUE(rec); + auto stream = fcgi::RecordStream::create_single(rec.get()); + EXPECT_FALSE(stream->end_of_record()); + EXPECT_FALSE(stream->end_of_stream()); + auto pair = fcgi::Pair::start(stream.get(), buf.get()); + ASSERT_TRUE(pair); + EXPECT_TRUE(pair->good()); + EXPECT_EQ(LONG_NAME, pair->name()); + EXPECT_EQ(LONG_VALUE, pair->value()); + EXPECT_FALSE(pair->next(stream.get(), buf.get())); + EXPECT_TRUE(stream->end_of_record()); + EXPECT_TRUE(stream->end_of_stream()); + EXPECT_TRUE(buf->empty()); +} + +TEST(fcgi_protocol, pair_stream) { + auto str = std::make_shared<std::string>(kStream1); + auto buf = make_strbuffer(str); + auto rec = fcgi::Record::parse(buf.get()); + ASSERT_TRUE(rec); + auto stream = fcgi::RecordStream::create_stream(rec.get()); + auto pair = fcgi::Pair::start(stream.get(), buf.get()); + ASSERT_TRUE(pair); + EXPECT_TRUE(pair->good()); + EXPECT_EQ("foo", pair->name()); + EXPECT_EQ("", pair->value()); + EXPECT_FALSE(pair->next(stream.get(), buf.get())); + EXPECT_TRUE(stream->end_of_record()); + EXPECT_FALSE(stream->end_of_stream()); + + str->append(kStream2); + rec = fcgi::Record::parse(buf.get()); + ASSERT_TRUE(rec); + stream->add(rec.get()); + ASSERT_TRUE(pair->next(stream.get(), buf.get())); + EXPECT_TRUE(pair->good()); + EXPECT_EQ("bar", pair->name()); + EXPECT_EQ("zum", pair->value()); + EXPECT_FALSE(pair->next(stream.get(), buf.get())); + EXPECT_TRUE(stream->end_of_record()); + EXPECT_FALSE(stream->end_of_stream()); + + str->append(kStream3); + rec = fcgi::Record::parse(buf.get()); + ASSERT_TRUE(rec); + stream->add(rec.get()); + ASSERT_TRUE(pair->next(stream.get(), buf.get())); + EXPECT_TRUE(pair->good()); + EXPECT_EQ("", pair->name()); + EXPECT_EQ("aaa", pair->value()); + EXPECT_FALSE(pair->next(stream.get(), buf.get())); + EXPECT_TRUE(stream->end_of_record()); + EXPECT_FALSE(stream->end_of_stream()); + + str->append(kStream4); + rec = fcgi::Record::parse(buf.get()); + ASSERT_TRUE(rec); + stream->add(rec.get()); + EXPECT_FALSE(pair->next(stream.get(), buf.get())); + EXPECT_TRUE(stream->end_of_record()); + EXPECT_TRUE(stream->end_of_stream()); + EXPECT_TRUE(buf->empty()); +} + +TEST(fcgi_protocol, pair_stream_incomplete) { + for (size_t i = 8; i < kStream2.size() - 1; ++i) { + auto str = std::make_shared<std::string>(kStream1); + auto buf = make_strbuffer(str); + auto rec = fcgi::Record::parse(buf.get()); + ASSERT_TRUE(rec); + auto stream = fcgi::RecordStream::create_stream(rec.get()); + auto pair = fcgi::Pair::start(stream.get(), buf.get()); + ASSERT_TRUE(pair); + EXPECT_TRUE(pair->good()); + EXPECT_FALSE(pair->next(stream.get(), buf.get())); + + str->append(kStream2.substr(0, i)); + rec = fcgi::Record::parse(buf.get()); + ASSERT_TRUE(rec); + stream->add(rec.get()); + EXPECT_FALSE(pair->next(stream.get(), buf.get())); + } +} + +TEST(fcgi_protocol, pair_stream_all_avail) { + auto buf = make_strbuffer(std::string(kStream1) + + std::string(kStream2) + + std::string(kStream3) + + std::string(kStream4)); + auto rec = fcgi::Record::parse(buf.get()); + ASSERT_TRUE(rec); + auto stream = fcgi::RecordStream::create_stream(rec.get()); + auto pair = fcgi::Pair::start(stream.get(), buf.get()); + ASSERT_TRUE(pair); + EXPECT_TRUE(pair->good()); + EXPECT_EQ("foo", pair->name()); + EXPECT_EQ("", pair->value()); + EXPECT_FALSE(pair->next(stream.get(), buf.get())); + EXPECT_TRUE(stream->end_of_record()); + EXPECT_FALSE(stream->end_of_stream()); + + rec = fcgi::Record::parse(buf.get()); + ASSERT_TRUE(rec); + stream->add(rec.get()); + ASSERT_TRUE(pair->next(stream.get(), buf.get())); + EXPECT_TRUE(pair->good()); + EXPECT_EQ("bar", pair->name()); + EXPECT_EQ("zum", pair->value()); + EXPECT_FALSE(pair->next(stream.get(), buf.get())); + EXPECT_TRUE(stream->end_of_record()); + EXPECT_FALSE(stream->end_of_stream()); + + rec = fcgi::Record::parse(buf.get()); + ASSERT_TRUE(rec); + stream->add(rec.get()); + ASSERT_TRUE(pair->next(stream.get(), buf.get())); + EXPECT_TRUE(pair->good()); + EXPECT_EQ("", pair->name()); + EXPECT_EQ("aaa", pair->value()); + EXPECT_FALSE(pair->next(stream.get(), buf.get())); + EXPECT_TRUE(stream->end_of_record()); + EXPECT_FALSE(stream->end_of_stream()); + + rec = fcgi::Record::parse(buf.get()); + ASSERT_TRUE(rec); + stream->add(rec.get()); + EXPECT_FALSE(pair->next(stream.get(), buf.get())); + EXPECT_TRUE(stream->end_of_record()); + EXPECT_TRUE(stream->end_of_stream()); + EXPECT_TRUE(buf->empty()); +} + +TEST(fcgi_protocol, pair_invalid) { + auto buf = make_strbuffer(kPairInvalid); + auto rec = fcgi::Record::parse(buf.get()); + ASSERT_TRUE(rec); + auto stream = fcgi::RecordStream::create_single(rec.get()); + EXPECT_FALSE(stream->end_of_record()); + EXPECT_FALSE(stream->end_of_stream()); + auto pair = fcgi::Pair::start(stream.get(), buf.get()); + ASSERT_TRUE(pair); + EXPECT_FALSE(pair->good()); + EXPECT_TRUE(stream->end_of_record()); + EXPECT_FALSE(stream->end_of_stream()); + EXPECT_TRUE(buf->empty()); +} + +TEST(fcgi_protocol, pair_invalid_with_padding) { + auto buf = make_strbuffer(kPairInvalidWithPadding); + auto rec = fcgi::Record::parse(buf.get()); + ASSERT_TRUE(rec); + auto stream = fcgi::RecordStream::create_single(rec.get()); + EXPECT_FALSE(stream->end_of_record()); + EXPECT_FALSE(stream->end_of_stream()); + auto pair = fcgi::Pair::start(stream.get(), buf.get()); + ASSERT_TRUE(pair); + EXPECT_FALSE(pair->good()); + EXPECT_TRUE(stream->end_of_record()); + EXPECT_FALSE(stream->end_of_stream()); + EXPECT_TRUE(buf->empty()); +} + +TEST(fcgi_protocol, pair_stream_invalid) { + auto buf = make_strbuffer(std::string(kPairShortShort) + + std::string(kPairInvalid) + + std::string(kStream4)); + auto rec = fcgi::Record::parse(buf.get()); + ASSERT_TRUE(rec); + auto stream = fcgi::RecordStream::create_stream(rec.get()); + auto pair = fcgi::Pair::start(stream.get(), buf.get()); + ASSERT_TRUE(pair); + EXPECT_TRUE(pair->good()); + EXPECT_FALSE(pair->next(stream.get(), buf.get())); + rec = fcgi::Record::parse(buf.get()); + ASSERT_TRUE(rec); + stream->add(rec.get()); + EXPECT_FALSE(pair->next(stream.get(), buf.get())); + rec = fcgi::Record::parse(buf.get()); + ASSERT_TRUE(rec); + stream->add(rec.get()); + EXPECT_TRUE(pair->next(stream.get(), buf.get())); + EXPECT_FALSE(pair->good()); +} + +TEST(fcgi_protocol, pair_builder) { + auto str = std::make_shared<std::string>(); + auto buf = make_strbuffer(str); + auto builder = fcgi::PairBuilder::create(); + builder->add("foo", ""); + EXPECT_EQ(5, builder->size()); + builder->add("foo", LONG_VALUE); + EXPECT_EQ(397, builder->size()); + builder->add(LONG_NAME, ""); + EXPECT_EQ(530, builder->size()); + builder->add(LONG_NAME, LONG_VALUE); + EXPECT_EQ(1050, builder->size()); + ASSERT_TRUE(builder->build(buf.get())); + EXPECT_EQ(std::string_view( + // ShortShort + "\x3" // name length = 3 + "\0" // value length = 0 + "foo" // name + "" // value + + // ShortLong + "\x3" // name length = 3 + "\x80\0\1\x80" // value length = 384 + "foo" // name + LONG_VALUE + + // LongShort + "\x80\0\0\x80" // name length = 128 + "\0" // value length = 0 + LONG_NAME + "" // value + + // LongLong + "\x80\0\0\x80" // name length = 128 + "\x80\0\1\x80" // value length = 384 + LONG_NAME + LONG_VALUE, + 1050), *str); +} + +TEST(fcgi_protocol, begin_request_body) { + auto buf = make_strbuffer(kBeginRequest); + auto req = fcgi::Record::parse(buf.get()); + ASSERT_TRUE(req); + EXPECT_TRUE(req->good()); + EXPECT_EQ(fcgi::RecordType::BeginRequest, req->type()); + auto body = fcgi::BeginRequestBody::parse(req.get(), buf.get()); + ASSERT_TRUE(body); + EXPECT_TRUE(body->good()); + EXPECT_EQ(1, body->role()); + EXPECT_EQ(1, body->flags()); + EXPECT_TRUE(buf->empty()); +} + +TEST(fcgi_protocol, begin_request_body_incomplete) { + for (size_t i = 8; i < kBeginRequest.size() - 1; ++i) { + auto buf = make_strbuffer(kBeginRequest.substr(0, i)); + auto req = fcgi::Record::parse(buf.get()); + ASSERT_TRUE(req); + auto body = fcgi::BeginRequestBody::parse(req.get(), buf.get()); + EXPECT_FALSE(body); + } +} + +TEST(fcgi_protocol, empty_stream) { + auto buf = make_strbuffer(kStream4); + auto req = fcgi::Record::parse(buf.get()); + ASSERT_TRUE(req); + auto stream = fcgi::RecordStream::create_stream(req.get()); + EXPECT_TRUE(stream->end_of_record()); + EXPECT_TRUE(stream->end_of_stream()); +} |
