diff --git a/src/crypto-test.cc b/src/crypto-test.cc index d3e91ce..b80f5b6 100644 --- a/src/crypto-test.cc +++ b/src/crypto-test.cc @@ -45,13 +45,13 @@ namespace { TEST(DigestTest, Sha1) { auto sha1 = Digest::SHA1(); - EXPECT_EQ("da 39 a3 ee 5e 6b 4b 0d 32 55 bf ef 95 60 18 90 af d8 07 09", + EXPECT_EQ("da39a3ee5e6b4b0d3255bfef95601890afd80709", ToHex(sha1->Finalize())); sha1 = Digest::SHA1(); sha1->Update("hello"); sha1->Update(" world"); - EXPECT_EQ("2a ae 6c 35 c9 4f cf b4 15 db e9 5f 40 8b 9c e9 1e e8 46 ed", + EXPECT_EQ("2aae6c35c94fcfb415dbe95f408b9ce91ee846ed", ToHex(sha1->Finalize())); } diff --git a/src/h264-test.cc b/src/h264-test.cc index 1cf5638..df04dd6 100644 --- a/src/h264-test.cc +++ b/src/h264-test.cc @@ -70,7 +70,7 @@ TEST(H264Test, DecodeOnly) { re2::StringPiece test_input(reinterpret_cast(kAnnexBTestInput), sizeof(kAnnexBTestInput)); internal::NalUnitFunction fn = [&nal_units_hexed](re2::StringPiece nal_unit) { - nal_units_hexed.push_back(ToHex(nal_unit)); + nal_units_hexed.push_back(ToHex(nal_unit, true)); return IterationControl::kContinue; }; std::string error_message; @@ -91,7 +91,7 @@ TEST(H264Test, SampleDataFromAnnexBExtraData) { GetH264SampleEntry(test_input, 1280, 720, &sample_entry, &error_message)) << error_message; - EXPECT_EQ(kTestOutput, ToHex(sample_entry)); + EXPECT_EQ(kTestOutput, ToHex(sample_entry, true)); } TEST(H264Test, SampleDataFromAvcDecoderConfigExtraData) { @@ -104,7 +104,7 @@ TEST(H264Test, SampleDataFromAvcDecoderConfigExtraData) { GetH264SampleEntry(test_input, 1280, 720, &sample_entry, &error_message)) << error_message; - EXPECT_EQ(kTestOutput, ToHex(sample_entry)); + EXPECT_EQ(kTestOutput, ToHex(sample_entry, true)); } } // namespace diff --git a/src/h264.cc b/src/h264.cc index 411677a..6369869 100644 --- a/src/h264.cc +++ b/src/h264.cc @@ -92,8 +92,8 @@ bool DecodeH264AnnexB(re2::StringPiece data, NalUnitFunction process_nal_unit, static const RE2 kStartCode("(\\x00{2,}\\x01)"); if (!RE2::Consume(&data, kStartCode)) { - *error_message = - StrCat("stream does not start with Annex B start code: ", ToHex(data)); + *error_message = StrCat("stream does not start with Annex B start code: ", + ToHex(data, true)); return false; } diff --git a/src/mp4-test.cc b/src/mp4-test.cc index f192302..93c8763 100644 --- a/src/mp4-test.cc +++ b/src/mp4-test.cc @@ -52,15 +52,18 @@ using moonfire_nvr::internal::Mp4SampleTablePieces; namespace moonfire_nvr { namespace { -std::string ToHex(const FileSlice *slice) { +std::string ToHex(const FileSlice *slice, bool pad) { EvBuffer buf; std::string error_message; size_t size = slice->size(); CHECK(slice->AddRange(ByteRange(0, size), &buf, &error_message)) << error_message; CHECK_EQ(size, evbuffer_get_length(buf.get())); - return ::moonfire_nvr::ToHex(re2::StringPiece( - reinterpret_cast(evbuffer_pullup(buf.get(), size)), size)); + return ::moonfire_nvr::ToHex( + re2::StringPiece( + reinterpret_cast(evbuffer_pullup(buf.get(), size)), + size), + pad); } TEST(Mp4SampleTablePiecesTest, Stts) { @@ -81,7 +84,7 @@ TEST(Mp4SampleTablePiecesTest, Stts) { "00 00 00 01 00 00 00 02 " "00 00 00 01 00 00 00 03 " "00 00 00 01 00 00 00 04"; - EXPECT_EQ(kExpectedEntries, ToHex(pieces.stts_entries())); + EXPECT_EQ(kExpectedEntries, ToHex(pieces.stts_entries(), true)); } TEST(Mp4SampleTablePiecesTest, SttsAfterSyncSample) { @@ -102,7 +105,7 @@ TEST(Mp4SampleTablePiecesTest, SttsAfterSyncSample) { "00 00 00 01 00 00 00 02 " "00 00 00 01 00 00 00 03 " "00 00 00 01 00 00 00 04"; - EXPECT_EQ(kExpectedEntries, ToHex(pieces.stts_entries())); + EXPECT_EQ(kExpectedEntries, ToHex(pieces.stts_entries(), true)); } TEST(Mp4SampleTablePiecesTest, Stss) { @@ -117,7 +120,7 @@ TEST(Mp4SampleTablePiecesTest, Stss) { << error_message; EXPECT_EQ(2, pieces.stss_entry_count()); const char kExpectedSampleNumbers[] = "00 00 00 0a 00 00 00 0c"; - EXPECT_EQ(kExpectedSampleNumbers, ToHex(pieces.stss_entries())); + EXPECT_EQ(kExpectedSampleNumbers, ToHex(pieces.stss_entries(), true)); } TEST(Mp4SampleTablePiecesTest, Stsc) { @@ -132,7 +135,7 @@ TEST(Mp4SampleTablePiecesTest, Stsc) { << error_message; EXPECT_EQ(1, pieces.stsc_entry_count()); const char kExpectedEntries[] = "00 00 00 0a 00 00 00 04 00 00 00 02"; - EXPECT_EQ(kExpectedEntries, ToHex(pieces.stsc_entries())); + EXPECT_EQ(kExpectedEntries, ToHex(pieces.stsc_entries(), true)); } TEST(Mp4SampleTablePiecesTest, Stsz) { @@ -150,7 +153,7 @@ TEST(Mp4SampleTablePiecesTest, Stsz) { << error_message; EXPECT_EQ(3, pieces.stsz_entry_count()); const char kExpectedEntries[] = "00 00 00 04 00 00 00 06 00 00 00 08"; - EXPECT_EQ(kExpectedEntries, ToHex(pieces.stsz_entries())); + EXPECT_EQ(kExpectedEntries, ToHex(pieces.stsz_entries(), true)); } class IntegrationTest : public testing::Test { diff --git a/src/recording-test.cc b/src/recording-test.cc index f8f5cfe..cc57665 100644 --- a/src/recording-test.cc +++ b/src/recording-test.cc @@ -60,7 +60,7 @@ TEST(SampleIndexTest, EncodeExample) { encoder.AddSample(11, 15, false); encoder.AddSample(10, 12, false); encoder.AddSample(10, 1050, true); - ASSERT_EQ("29 d0 0f 02 14 08 0a 02 05 01 64", ToHex(encoder.data())); + ASSERT_EQ("29 d0 0f 02 14 08 0a 02 05 01 64", ToHex(encoder.data(), true)); } TEST(SampleIndexTest, RoundTrip) { @@ -150,8 +150,7 @@ TEST(SampleFileWriterTest, Simple) { EXPECT_TRUE(writer.Write(write_1, &error_message)) << error_message; EXPECT_TRUE(writer.Write(write_2, &error_message)) << error_message; EXPECT_TRUE(writer.Close(&sha1, &error_message)) << error_message; - EXPECT_EQ("6b c3 73 25 b3 6f b5 fd 20 5e 57 28 44 29 e7 57 64 33 86 18", - ToHex(sha1)); + EXPECT_EQ("6bc37325b36fb5fd205e57284429e75764338618", ToHex(sha1)); } TEST(SampleFileWriterTest, PartialWriteIsRetried) { @@ -181,8 +180,7 @@ TEST(SampleFileWriterTest, PartialWriteIsRetried) { EXPECT_TRUE(writer.Write(write_1, &error_message)) << error_message; EXPECT_TRUE(writer.Write(write_2, &error_message)) << error_message; EXPECT_TRUE(writer.Close(&sha1, &error_message)) << error_message; - EXPECT_EQ("6b c3 73 25 b3 6f b5 fd 20 5e 57 28 44 29 e7 57 64 33 86 18", - ToHex(sha1)); + EXPECT_EQ("6bc37325b36fb5fd205e57284429e75764338618", ToHex(sha1)); } TEST(SampleFileWriterTest, PartialWriteIsTruncated) { @@ -212,8 +210,7 @@ TEST(SampleFileWriterTest, PartialWriteIsTruncated) { EXPECT_TRUE(writer.Write(write_1, &error_message)) << error_message; EXPECT_FALSE(writer.Write(write_2, &error_message)) << error_message; EXPECT_TRUE(writer.Close(&sha1, &error_message)) << error_message; - EXPECT_EQ("b1 cc ee 33 9b 93 55 87 c0 99 97 a9 ec 8b b2 37 4e 02 b5 d0", - ToHex(sha1)); + EXPECT_EQ("b1ccee339b935587c09997a9ec8bb2374e02b5d0", ToHex(sha1)); } TEST(SampleFileWriterTest, PartialWriteTruncateFailureCausesCloseToFail) { diff --git a/src/sqlite-test.cc b/src/sqlite-test.cc index a36d318..4dad0e5 100644 --- a/src/sqlite-test.cc +++ b/src/sqlite-test.cc @@ -87,7 +87,7 @@ TEST_F(SqliteTest, BindAndColumn) { &error_message); ASSERT_TRUE(select_stmt != nullptr) << error_message; ASSERT_EQ(SQLITE_ROW, select_stmt->Step()); - EXPECT_EQ(ToHex(blob_piece), ToHex(select_stmt->ColumnBlob(0))); + EXPECT_EQ(ToHex(blob_piece, true), ToHex(select_stmt->ColumnBlob(0), true)); EXPECT_EQ(kText, select_stmt->ColumnText(1).as_string()); EXPECT_EQ(kInt64, select_stmt->ColumnInt64(2)); ASSERT_EQ(SQLITE_DONE, select_stmt->Step()); diff --git a/src/string-test.cc b/src/string-test.cc index 94223ed..099421f 100644 --- a/src/string-test.cc +++ b/src/string-test.cc @@ -93,8 +93,10 @@ TEST(EscapeTest, Simple) { } TEST(ToHexTest, Simple) { - EXPECT_EQ("", ToHex("")); - EXPECT_EQ("12 34 de ad be ef", ToHex("\x12\x34\xde\xad\xbe\xef")); + EXPECT_EQ("", ToHex("", false)); + EXPECT_EQ("", ToHex("", true)); + EXPECT_EQ("1234deadbeef", ToHex("\x12\x34\xde\xad\xbe\xef", false)); + EXPECT_EQ("12 34 de ad be ef", ToHex("\x12\x34\xde\xad\xbe\xef", true)); } } // namespace diff --git a/src/string.cc b/src/string.cc index 408794c..dbb7f75 100644 --- a/src/string.cc +++ b/src/string.cc @@ -112,11 +112,11 @@ std::string EscapeHtml(const std::string &input) { return output; } -std::string ToHex(re2::StringPiece in) { +std::string ToHex(re2::StringPiece in, bool pad) { std::string out; - out.reserve(in.size() * 3 + 1); + out.reserve(in.size() * (2 + pad) + pad); for (int i = 0; i < in.size(); ++i) { - if (i > 0) out.push_back(' '); + if (pad && i > 0) out.push_back(' '); uint8_t byte = in[i]; out.push_back(HexDigit(byte >> 4)); out.push_back(HexDigit(byte & 0x0F)); diff --git a/src/string.h b/src/string.h index f039e2e..99dd9f7 100644 --- a/src/string.h +++ b/src/string.h @@ -118,9 +118,9 @@ bool IsWord(const std::string &str); // HTML-escape the given UTF-8-encoded string. std::string EscapeHtml(const std::string &input); -// Return a hex string for debugging. -// For example, ToHex("\xde\xad\xbe\xef") returns "de ad be ef". -std::string ToHex(re2::StringPiece in); +// Return a hex-encoded version of |in|, optionally padding between bytes. +// For example, ToHex("\xde\xad\xbe\xef", true) returns "de ad be ef". +std::string ToHex(re2::StringPiece in, bool pad = false); // Wrapper around ::strtol that returns true iff valid and corrects // constness.