How to write C++ unit tests for HTTP? (Host OS new line vs rn issue.) - Stack Overflow

I'm writing some C++ unit tests with Catch2 for a library which includes a dependency on a HTTP pa

I'm writing some C++ unit tests with Catch2 for a library which includes a dependency on a HTTP parser. (In this particular case, llhttp.)

As part of my unit tests, I have a directory containing test data. For example, one of the most simple tests contains the following file which specifies an input to the test.

POST /api/example HTTP/1.1
Host: example
Content-Type: application/json

{
  "body": "BODY"
}

This is a set of HTTP headers, and a JSON Content body, which is intended to be used as input to test the parsing logic.

However, the line endings are variable depending on the OS.

I saved the file from a Linux OS. Therefore the line endings are \n. (New line, no carriage return.)

This is incompatiable with HTTP, as the standard requires \r\n. (Carriage return, followed by new line.)

I'm looking for some advice on how best to proceed here.

While I could write a function to convert the data read from file into a std::string containing the correct line ending characters, this has some isses.

  • Firstly I have to write the function, and I can't immediatly think of an elegant implementation. This feels a bit like a code smell, maybe this isn't the best approach.
  • Possibly more importantly, this function is unlikely to be cross platform compatiable. If someone re-saves the same file from a Windows system, the logic will be broken. (Unless I were to implement something more complex which first scans the file to detect the line ending format.)

Something about this doesn't feel quite right. Perhaps someone has some advice on the best way to proceed?


To illustrate why I don't think I have a good solution to this problem, here's the current implementation I am using.

std::ifstream ifile("http_data.txt", std::ios::binary);

std::string line; // input
std::ostringstream oss; // output
while(std::getline(ifile, line)) // line ending agonstic
{
    oss.write(line.c_str(), line.size());
    oss.write("\r\n", 2); // line ending specific
}

In short - I don't think my approach is particuarly good. Is there a smarter way to do this?

I'm writing some C++ unit tests with Catch2 for a library which includes a dependency on a HTTP parser. (In this particular case, llhttp.)

As part of my unit tests, I have a directory containing test data. For example, one of the most simple tests contains the following file which specifies an input to the test.

POST /api/example HTTP/1.1
Host: example
Content-Type: application/json

{
  "body": "BODY"
}

This is a set of HTTP headers, and a JSON Content body, which is intended to be used as input to test the parsing logic.

However, the line endings are variable depending on the OS.

I saved the file from a Linux OS. Therefore the line endings are \n. (New line, no carriage return.)

This is incompatiable with HTTP, as the standard requires \r\n. (Carriage return, followed by new line.)

I'm looking for some advice on how best to proceed here.

While I could write a function to convert the data read from file into a std::string containing the correct line ending characters, this has some isses.

  • Firstly I have to write the function, and I can't immediatly think of an elegant implementation. This feels a bit like a code smell, maybe this isn't the best approach.
  • Possibly more importantly, this function is unlikely to be cross platform compatiable. If someone re-saves the same file from a Windows system, the logic will be broken. (Unless I were to implement something more complex which first scans the file to detect the line ending format.)

Something about this doesn't feel quite right. Perhaps someone has some advice on the best way to proceed?


To illustrate why I don't think I have a good solution to this problem, here's the current implementation I am using.

std::ifstream ifile("http_data.txt", std::ios::binary);

std::string line; // input
std::ostringstream oss; // output
while(std::getline(ifile, line)) // line ending agonstic
{
    oss.write(line.c_str(), line.size());
    oss.write("\r\n", 2); // line ending specific
}

In short - I don't think my approach is particuarly good. Is there a smarter way to do this?

Share asked Mar 3 at 22:23 user2138149user2138149 17.7k30 gold badges150 silver badges296 bronze badges 3
  • 3 On Linux, I'd use Vim and do a :set ff=dos then save the file. That wil use \r\n line endings. – Eljay Commented Mar 3 at 22:38
  • 3 You also have shell commands dos2unix and unix2dos. – edrezen Commented Mar 3 at 22:41
  • excellent tips, thank you both – user2138149 Commented Mar 4 at 21:02
Add a comment  | 

1 Answer 1

Reset to default 0

For such small input files, I would not care about input line ending and performance.

std::ifstream ifile("http_data.txt", std::ios::binary);
std::string data(std::istreambuf_iterator<char>{ifile}, {});
boost::replace_all(data, "\r\n", "\n");
boost::replace_all(data, "\n", "\r\n");
// data = std::regex_replace(data, std::regex("\r\n"), "\n"); // not tested
// data = std::regex_replace(data, std::regex("\n"), "\r\n"); // not tested
// Regex replace can be single: ([^\r])\n with \1\r\n, not tested

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745069377a4609452.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信