ApmTest.VerifyDebugDump(Int|Float) more insightful with failures

Instead of showing individual byte differences, this CL detects
differences in the expected and actual byte streams of the evaluated
AEC dump and, if detected, parses the `audioproc::Event` proto lite
messages and calls EXPECT_EQ() for a subset of individual (sub-)fields.

Note that messages are parsed only if the byte streams of each message
pair do not match, so with no failures the test runs at no extra cost.
Plus, the the added funcionality can only be enabled for local
debugging by flipping the `kDumpWhenExpectMessageEqFails` flag - a
code change cannot land if the flag is set to true.

Note that `MessageDifferencer` (see [1]) could not be used because
it is not implemented for `MessageLite` protos.

[1] https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.util.message_differencer

Bug: b/241923537
Change-Id: I8e0eda3b1ecfe06945b6dad5ee8871f8200d76d7
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/270922
Reviewed-by: Jesus de Vicente Pena <devicentepena@webrtc.org>
Commit-Queue: Alessio Bazzica <alessiob@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#37765}
This commit is contained in:
Alessio Bazzica
2022-08-11 15:48:54 +02:00
committed by WebRTC LUCI CQ
parent b69b81944c
commit 85a126ec5d

View File

@ -50,6 +50,7 @@
#include "test/testsupport/file_utils.h"
RTC_PUSH_IGNORING_WUNDEF()
#include "modules/audio_processing/debug.pb.h"
#ifdef WEBRTC_ANDROID_PLATFORM_BUILD
#include "external/webrtc/webrtc/modules/audio_processing/test/unittest.pb.h"
#else
@ -335,6 +336,72 @@ std::string GetReferenceFilename() {
#endif
}
// Flag that can temporarily be enabled for local debugging to inspect
// `ApmTest.VerifyDebugDump(Int|Float)` failures. Do not upload code changes
// with this flag set to true.
constexpr bool kDumpWhenExpectMessageEqFails = false;
// Checks the debug constants values used in this file so that no code change is
// submitted with values temporarily used for local debugging.
TEST(ApmUnitTests, CheckDebugConstants) {
ASSERT_FALSE(kDumpWhenExpectMessageEqFails);
}
// Expects the equality of `actual` and `expected` by inspecting a hard-coded
// subset of `audioproc::Stream` fields.
void ExpectStreamFieldsEq(const audioproc::Stream& actual,
const audioproc::Stream& expected) {
EXPECT_EQ(actual.input_data(), expected.input_data());
EXPECT_EQ(actual.output_data(), expected.output_data());
EXPECT_EQ(actual.delay(), expected.delay());
EXPECT_EQ(actual.drift(), expected.drift());
EXPECT_EQ(actual.level(), expected.level());
EXPECT_EQ(actual.keypress(), expected.keypress());
}
// Expects the equality of `actual` and `expected` by inspecting a hard-coded
// subset of `audioproc::Event` fields.
void ExpectEventFieldsEq(const audioproc::Event& actual,
const audioproc::Event& expected) {
EXPECT_EQ(actual.type(), expected.type());
if (actual.type() != expected.type()) {
return;
}
switch (actual.type()) {
case audioproc::Event::STREAM:
ExpectStreamFieldsEq(actual.stream(), expected.stream());
break;
default:
// Not implemented.
break;
}
}
// Returns true if the `actual` and `expected` byte streams share the same size
// and contain the same data. If they differ and `kDumpWhenExpectMessageEqFails`
// is true, checks the equality of a subset of `audioproc::Event` (nested)
// fields.
bool ExpectMessageEq(rtc::ArrayView<const uint8_t> actual,
rtc::ArrayView<const uint8_t> expected) {
EXPECT_EQ(actual.size(), expected.size());
if (actual.size() != expected.size()) {
return false;
}
if (memcmp(actual.data(), expected.data(), actual.size()) == 0) {
// Same message. No need to parse.
return true;
}
if (kDumpWhenExpectMessageEqFails) {
// Parse differing messages and expect equality to produce detailed error
// messages.
audioproc::Event event_actual, event_expected;
RTC_DCHECK(event_actual.ParseFromArray(actual.data(), actual.size()));
RTC_DCHECK(event_expected.ParseFromArray(expected.data(), expected.size()));
ExpectEventFieldsEq(event_actual, event_expected);
}
return false;
}
class ApmTest : public ::testing::Test {
protected:
ApmTest();
@ -1525,8 +1592,13 @@ void ApmTest::VerifyDebugDumpTest(Format format) {
bytes_read_limited += limited_size;
EXPECT_EQ(ref_size, out_size);
EXPECT_GE(ref_size, limited_size);
EXPECT_EQ(0, memcmp(ref_bytes.get(), out_bytes.get(), ref_size));
EXPECT_EQ(0, memcmp(ref_bytes.get(), limited_bytes.get(), limited_size));
EXPECT_TRUE(ExpectMessageEq(/*actual=*/{out_bytes.get(), out_size},
/*expected=*/{ref_bytes.get(), ref_size}));
if (limited_size > 0) {
EXPECT_TRUE(
ExpectMessageEq(/*actual=*/{limited_bytes.get(), limited_size},
/*expected=*/{ref_bytes.get(), ref_size}));
}
ref_size = ReadMessageBytesFromFile(ref_file, &ref_bytes);
out_size = ReadMessageBytesFromFile(out_file, &out_bytes);
limited_size = ReadMessageBytesFromFile(limited_file, &limited_bytes);