mirror of
https://github.com/aaru-dps/libaaruformat.git
synced 2026-04-05 21:51:03 +00:00
Merge pull request #31 from RomTholos/test/flac-error-handling
Add FLAC error handling regression tests
This commit is contained in:
141
tests/flac.cpp
141
tests/flac.cpp
@@ -19,6 +19,7 @@
|
||||
#include <climits>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
#include <aaruformat.h>
|
||||
|
||||
@@ -57,6 +58,146 @@ protected:
|
||||
// shared user data
|
||||
};
|
||||
|
||||
// --- Regression tests for fix/flac-error-handling (TEST-R01) ---
|
||||
// The fix changed decode/encode to return 0 (not -1 or crash) on error,
|
||||
// added NULL checks, and fixed a decoder leak on init failure.
|
||||
|
||||
TEST(flacErrors, decode_garbage_returns_zero)
|
||||
{
|
||||
// Random garbage is not valid FLAC — decoder must return 0, not crash or return -1
|
||||
uint8_t garbage[4096];
|
||||
memset(garbage, 0xAB, sizeof(garbage));
|
||||
|
||||
const size_t out_size = 65536;
|
||||
auto *out = static_cast<uint8_t *>(malloc(out_size));
|
||||
ASSERT_NE(out, nullptr);
|
||||
|
||||
size_t result = aaruf_flac_decode_redbook_buffer(out, out_size, garbage, sizeof(garbage));
|
||||
|
||||
EXPECT_EQ(result, 0U);
|
||||
free(out);
|
||||
}
|
||||
|
||||
TEST(flacErrors, decode_truncated_flac_returns_zero)
|
||||
{
|
||||
// Valid FLAC header but truncated mid-stream
|
||||
// fLaC magic = 0x664C6143
|
||||
uint8_t truncated[64];
|
||||
truncated[0] = 'f';
|
||||
truncated[1] = 'L';
|
||||
truncated[2] = 'a';
|
||||
truncated[3] = 'C';
|
||||
// Fill rest with zeros (incomplete metadata block)
|
||||
memset(truncated + 4, 0, sizeof(truncated) - 4);
|
||||
|
||||
auto *out = static_cast<uint8_t *>(malloc(4096));
|
||||
ASSERT_NE(out, nullptr);
|
||||
|
||||
size_t result = aaruf_flac_decode_redbook_buffer(out, 4096, truncated, sizeof(truncated));
|
||||
|
||||
EXPECT_EQ(result, 0U);
|
||||
free(out);
|
||||
}
|
||||
|
||||
TEST(flacErrors, decode_empty_input_returns_zero)
|
||||
{
|
||||
auto *out = static_cast<uint8_t *>(malloc(4096));
|
||||
ASSERT_NE(out, nullptr);
|
||||
|
||||
size_t result = aaruf_flac_decode_redbook_buffer(out, 4096, NULL, 0);
|
||||
|
||||
EXPECT_EQ(result, 0U);
|
||||
free(out);
|
||||
}
|
||||
|
||||
TEST(flacErrors, decode_zero_length_returns_zero)
|
||||
{
|
||||
uint8_t src[1] = {0};
|
||||
auto *out = static_cast<uint8_t *>(malloc(4096));
|
||||
ASSERT_NE(out, nullptr);
|
||||
|
||||
size_t result = aaruf_flac_decode_redbook_buffer(out, 4096, src, 0);
|
||||
|
||||
EXPECT_EQ(result, 0U);
|
||||
free(out);
|
||||
}
|
||||
|
||||
TEST(flacErrors, encode_zero_length_no_crash)
|
||||
{
|
||||
// Zero-length encode with NULL source: FLAC encoder still produces a valid
|
||||
// stream header (STREAMINFO + footer), so result > 0 is expected.
|
||||
// The key assertion: no crash, no leak, no ASan error.
|
||||
uint8_t out[4096];
|
||||
size_t result = aaruf_flac_encode_redbook_buffer(out, sizeof(out), NULL, 0, 4608, 1, 0,
|
||||
"partial_tukey(0/1.0/1.0)", 12, 0, 1, false, 0, 8, NULL, 0);
|
||||
|
||||
// FLAC emits a valid (empty) stream — header bytes only
|
||||
EXPECT_GT(result, 0U);
|
||||
EXPECT_LT(result, 256U); // sanity: just header, no audio data
|
||||
}
|
||||
|
||||
TEST(flacErrors, encode_garbage_roundtrip_fails_cleanly)
|
||||
{
|
||||
// Non-PCM data that is technically processable by FLAC (correct length for samples)
|
||||
// but should still produce a valid FLAC stream that roundtrips.
|
||||
// The key test here: even random data shouldn't crash or leak.
|
||||
const size_t src_size = 2352 * 4; // 4 CD sectors worth of "audio"
|
||||
auto *src = static_cast<uint8_t *>(malloc(src_size));
|
||||
memset(src, 0xDE, src_size);
|
||||
|
||||
auto *cmp = static_cast<uint8_t *>(malloc(src_size * 2));
|
||||
size_t cmp_result =
|
||||
aaruf_flac_encode_redbook_buffer(cmp, src_size * 2, src, src_size, 4608, 1, 0,
|
||||
"partial_tukey(0/1.0/1.0)", 12, 0, 1, false, 0, 8, NULL, 0);
|
||||
|
||||
// Encoding random data should succeed (FLAC handles any 16-bit PCM)
|
||||
EXPECT_GT(cmp_result, 0U);
|
||||
|
||||
if(cmp_result > 0)
|
||||
{
|
||||
// Verify roundtrip: decode what we just encoded
|
||||
auto *decoded = static_cast<uint8_t *>(malloc(src_size));
|
||||
size_t dec_result = aaruf_flac_decode_redbook_buffer(decoded, src_size, cmp, cmp_result);
|
||||
|
||||
EXPECT_EQ(dec_result, src_size);
|
||||
if(dec_result == src_size) EXPECT_EQ(memcmp(src, decoded, src_size), 0);
|
||||
|
||||
free(decoded);
|
||||
}
|
||||
|
||||
free(src);
|
||||
free(cmp);
|
||||
}
|
||||
|
||||
TEST(flacErrors, decode_dst_too_small_returns_zero)
|
||||
{
|
||||
// Encode valid audio data, then try to decode into a buffer that's too small.
|
||||
// This should not crash or overwrite past the buffer.
|
||||
const size_t src_size = 2352 * 4;
|
||||
auto *src = static_cast<uint8_t *>(malloc(src_size));
|
||||
memset(src, 0x00, src_size); // silence — compresses well
|
||||
|
||||
auto *cmp = static_cast<uint8_t *>(malloc(src_size));
|
||||
size_t cmp_result =
|
||||
aaruf_flac_encode_redbook_buffer(cmp, src_size, src, src_size, 4608, 1, 0, "partial_tukey(0/1.0/1.0)", 12, 0,
|
||||
1, false, 0, 8, NULL, 0);
|
||||
ASSERT_GT(cmp_result, 0U) << "Failed to encode test data";
|
||||
|
||||
// Decode into a buffer that's way too small
|
||||
uint8_t tiny[64];
|
||||
size_t dec_result = aaruf_flac_decode_redbook_buffer(tiny, sizeof(tiny), cmp, cmp_result);
|
||||
|
||||
// The decoder writes into the callback buffer capped by dst_len,
|
||||
// but FLAC may still report success. The important thing is no crash
|
||||
// and the returned size doesn't exceed our buffer.
|
||||
EXPECT_LE(dec_result, sizeof(tiny));
|
||||
|
||||
free(src);
|
||||
free(cmp);
|
||||
}
|
||||
|
||||
// --- Original tests below ---
|
||||
|
||||
TEST_F(flacFixture, flac)
|
||||
{
|
||||
auto *outBuf = static_cast<uint8_t *>(malloc(9633792));
|
||||
|
||||
Reference in New Issue
Block a user