From fefa31eb471d8051ba84b02c90efbe15b2cf46b1 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Tue, 28 Jul 2015 12:02:41 -0700 Subject: [PATCH] Improve code coverage of tests --- libaegisub/audio/provider.cpp | 28 ++++----- libaegisub/common/calltip_provider.cpp | 2 +- .../include/libaegisub/audio/provider.h | 2 +- src/command/audio.cpp | 2 +- tests/tests/audio.cpp | 59 ++++++++++++++++++- tests/tests/calltip_provider.cpp | 7 ++- tests/tests/character_count.cpp | 4 ++ tests/tests/color.cpp | 7 +++ tests/tests/format.cpp | 1 + tests/tests/hotkey.cpp | 2 + tests/tests/ifind.cpp | 1 + tests/tests/time.cpp | 4 ++ 12 files changed, 96 insertions(+), 23 deletions(-) diff --git a/libaegisub/audio/provider.cpp b/libaegisub/audio/provider.cpp index 78d3facc2..961e5bf89 100644 --- a/libaegisub/audio/provider.cpp +++ b/libaegisub/audio/provider.cpp @@ -36,8 +36,8 @@ void AudioProvider::GetAudioWithVolume(void *buf, int64_t start, int64_t count, void AudioProvider::ZeroFill(void *buf, int64_t count) const { if (bytes_per_sample == 1) - // 8 bit formats are usually unsigned with bias 127 - memset(buf, 127, count * channels); + // 8 bit formats are usually unsigned with bias 128 + memset(buf, 128, count * channels); else // While everything else is signed memset(buf, 0, count * bytes_per_sample * channels); } @@ -100,13 +100,13 @@ public: }; } -void SaveAudioClip(AudioProvider *provider, fs::path const& path, int start_time, int end_time) { - auto start_sample = ((int64_t)start_time * provider->GetSampleRate() + 999) / 1000; - auto end_sample = ((int64_t)end_time * provider->GetSampleRate() + 999) / 1000; - if (start_sample >= provider->GetNumSamples() || start_sample >= end_sample) return; +void SaveAudioClip(AudioProvider const& provider, fs::path const& path, int start_time, int end_time) { + const auto max_samples = provider.GetNumSamples(); + const auto start_sample = std::min(max_samples, ((int64_t)start_time * provider.GetSampleRate() + 999) / 1000); + const auto end_sample = util::mid(start_sample, ((int64_t)end_time * provider.GetSampleRate() + 999) / 1000, max_samples); - size_t bytes_per_sample = provider->GetBytesPerSample() * provider->GetChannels(); - size_t bufsize = (end_sample - start_sample) * bytes_per_sample; + const size_t bytes_per_sample = provider.GetBytesPerSample() * provider.GetChannels(); + const size_t bufsize = (end_sample - start_sample) * bytes_per_sample; writer out{path}; out.write("RIFF"); @@ -115,11 +115,11 @@ void SaveAudioClip(AudioProvider *provider, fs::path const& path, int start_time out.write("WAVEfmt "); out.write(16); // Size of chunk out.write(1); // compression format (PCM) - out.write(provider->GetChannels()); - out.write(provider->GetSampleRate()); - out.write(provider->GetSampleRate() * provider->GetChannels() * provider->GetBytesPerSample()); - out.write(provider->GetChannels() * provider->GetBytesPerSample()); - out.write(provider->GetBytesPerSample() * 8); + out.write(provider.GetChannels()); + out.write(provider.GetSampleRate()); + out.write(provider.GetSampleRate() * provider.GetChannels() * provider.GetBytesPerSample()); + out.write(provider.GetChannels() * provider.GetBytesPerSample()); + out.write(provider.GetBytesPerSample() * 8); out.write("data"); out.write(bufsize); @@ -130,7 +130,7 @@ void SaveAudioClip(AudioProvider *provider, fs::path const& path, int start_time for (int64_t i = start_sample; i < end_sample; i += spr) { spr = std::min(spr, end_sample - i); buf.resize(spr * bytes_per_sample); - provider->GetAudio(&buf[0], i, spr); + provider.GetAudio(&buf[0], i, spr); out.write(buf); } } diff --git a/libaegisub/common/calltip_provider.cpp b/libaegisub/common/calltip_provider.cpp index 575d0a942..de693e637 100644 --- a/libaegisub/common/calltip_provider.cpp +++ b/libaegisub/common/calltip_provider.cpp @@ -193,7 +193,7 @@ Calltip GetCalltip(std::vector const& tokens, std::string co auto start = proto->args + tag_name_length + 2; // One for slash, one for open paren for (; commas > 0; --commas) { start = strchr(start, ','); - if (!start) return ret; // No calltip if there's too many args + if (!start) return ret; // No calltip if we're after the last arg ++start; } diff --git a/libaegisub/include/libaegisub/audio/provider.h b/libaegisub/include/libaegisub/audio/provider.h index 9e631bc40..debb560ce 100644 --- a/libaegisub/include/libaegisub/audio/provider.h +++ b/libaegisub/include/libaegisub/audio/provider.h @@ -91,5 +91,5 @@ std::unique_ptr CreateLockAudioProvider(std::unique_ptr CreateHDAudioProvider(std::unique_ptr source_provider, fs::path const& dir); std::unique_ptr CreateRAMAudioProvider(std::unique_ptr source_provider); -void SaveAudioClip(AudioProvider *provider, fs::path const& path, int start_time, int end_time); +void SaveAudioClip(AudioProvider const& provider, fs::path const& path, int start_time, int end_time); } diff --git a/src/command/audio.cpp b/src/command/audio.cpp index a6f700bac..d10491b07 100644 --- a/src/command/audio.cpp +++ b/src/command/audio.cpp @@ -184,7 +184,7 @@ struct audio_save_clip final : public Command { end = std::max(end, line->End); } - agi::SaveAudioClip(c->project->AudioProvider(), filename, start, end); + agi::SaveAudioClip(*c->project->AudioProvider(), filename, start, end); } }; diff --git a/tests/tests/audio.cpp b/tests/tests/audio.cpp index ba5b0d4cc..4e0853315 100644 --- a/tests/tests/audio.cpp +++ b/tests/tests/audio.cpp @@ -87,6 +87,20 @@ TEST(lagi_audio, before_sample_zero) { ASSERT_EQ(i - 8, buff[i]); } +TEST(lagi_audio, before_sample_zero_8bit) { + TestAudioProvider provider; + provider.bias = 128; + + uint8_t buff[16]; + memset(buff, sizeof(buff), 1); + provider.GetAudio(buff, -8, 16); + + for (int i = 0; i < 8; ++i) + ASSERT_EQ(128, buff[i]); + for (int i = 8; i < 16; ++i) + ASSERT_EQ(128 + i - 8, buff[i]); +} + TEST(lagi_audio, after_end) { TestAudioProvider<> provider(1); @@ -105,7 +119,7 @@ TEST(lagi_audio, save_audio_clip) { agi::fs::Remove(path); auto provider = agi::CreateDummyAudioProvider("dummy-audio:noise?", nullptr); - agi::SaveAudioClip(provider.get(), path, 60 * 60 * 1000, (60 * 60 + 10) * 1000); + agi::SaveAudioClip(*provider, path, 60 * 60 * 1000, (60 * 60 + 10) * 1000); { bfs::ifstream s(path); @@ -117,6 +131,45 @@ TEST(lagi_audio, save_audio_clip) { agi::fs::Remove(path); } +TEST(lagi_audio, save_audio_clip_out_of_audio_range) { + const auto path = agi::Path().Decode("?temp/save_clip"); + agi::fs::Remove(path); + + const auto provider = agi::CreateDummyAudioProvider("dummy-audio:noise?", nullptr); + const auto end_time = 150 * 60 * 1000; + + // Start time after end of clip: empty file + agi::SaveAudioClip(*provider, path, end_time, end_time + 1); + { + bfs::ifstream s(path); + ASSERT_TRUE(s.good()); + s.seekg(0, std::ios::end); + EXPECT_EQ(44, s.tellg()); + } + agi::fs::Remove(path); + + // Start time >= end time: empty file + agi::SaveAudioClip(*provider, path, end_time - 1, end_time - 1); + { + bfs::ifstream s(path); + ASSERT_TRUE(s.good()); + s.seekg(0, std::ios::end); + EXPECT_EQ(44, s.tellg()); + } + agi::fs::Remove(path); + + // Start time during clip, end time after end of clip: save only the part that exists + agi::SaveAudioClip(*provider, path, end_time - 1000, end_time + 1000); + { + bfs::ifstream s(path); + ASSERT_TRUE(s.good()); + s.seekg(0, std::ios::end); + // 1 second of 44.1 kHz samples per second of 16-bit mono, plus 44 bytes of header + EXPECT_EQ(44100 * 2 + 44, s.tellg()); + } + agi::fs::Remove(path); +} + TEST(lagi_audio, get_with_volume) { TestAudioProvider<> provider; uint16_t buff[4]; @@ -309,7 +362,7 @@ TEST(lagi_audio, pcm_simple) { auto path = agi::Path().Decode("?temp/pcm_simple"); { TestAudioProvider<> provider; - agi::SaveAudioClip(&provider, path, 0, 1000); + agi::SaveAudioClip(provider, path, 0, 1000); } auto provider = agi::CreatePCMAudioProvider(path, nullptr); @@ -333,7 +386,7 @@ TEST(lagi_audio, pcm_truncated) { auto path = agi::Path().Decode("?temp/pcm_truncated"); { TestAudioProvider<> provider; - agi::SaveAudioClip(&provider, path, 0, 1000); + agi::SaveAudioClip(provider, path, 0, 1000); } char file[1000]; diff --git a/tests/tests/calltip_provider.cpp b/tests/tests/calltip_provider.cpp index 1431799aa..a56d23f9e 100644 --- a/tests/tests/calltip_provider.cpp +++ b/tests/tests/calltip_provider.cpp @@ -68,10 +68,11 @@ TEST(lagi_calltip, overloads) { } TEST(lagi_calltip, too_many_args) { - expect_tip("{\\pos(100,100,100)}hello", 2, bad_tip); + expect_tip("{\\pos(100,100,100)}hello", 15, bad_tip); + expect_tip("{\\pos(100,100,100)}hello", 3, Calltip{"\\pos(X,Y)", 5, 6, 2}); } TEST(lagi_calltip, unknown_tag) { - expect_tip("{\\foo(100,100,100)}hello", 2, bad_tip); - expect_tip("{\\toolong(100,100,100)}hello", 2, bad_tip); + expect_tip("{\\foo(100,100,100)}hello", 3, bad_tip); + expect_tip("{\\toolong(100,100,100)}hello", 3, bad_tip); } diff --git a/tests/tests/character_count.cpp b/tests/tests/character_count.cpp index 2ccfd5e8c..36d3e948b 100644 --- a/tests/tests/character_count.cpp +++ b/tests/tests/character_count.cpp @@ -51,6 +51,10 @@ TEST(lagi_character_count, ignore_blocks_and_punctuation) { EXPECT_EQ(5, agi::CharacterCount("{asdf}hello.", agi::IGNORE_PUNCTUATION | agi::IGNORE_BLOCKS)); } +TEST(lagi_character_count, ignore_blocks_unclosed) { + EXPECT_EQ(6, agi::CharacterCount("{hello", agi::IGNORE_BLOCKS)); +} + TEST(lagi_character_count, line_length) { EXPECT_EQ(5, agi::MaxLineLength("hello", agi::IGNORE_NONE)); EXPECT_EQ(5, agi::MaxLineLength("hello\\Nasdf", agi::IGNORE_NONE)); diff --git a/tests/tests/color.cpp b/tests/tests/color.cpp index 32118973d..57d08a612 100644 --- a/tests/tests/color.cpp +++ b/tests/tests/color.cpp @@ -43,6 +43,13 @@ TEST(lagi_color, hex) { EXPECT_EQ("#102030", agi::Color(16, 32, 48).GetHexFormatted()); } +TEST(lagi_color, hex_rgba) { + EXPECT_EQ("#00000000", agi::Color(0, 0, 0, 0).GetHexFormatted(true)); + EXPECT_EQ("#FFFFFFFF", agi::Color(255, 255, 255, 255).GetHexFormatted(true)); + EXPECT_EQ("#FF007F20", agi::Color(255, 0, 127, 32).GetHexFormatted(true)); + EXPECT_EQ("#10203040", agi::Color(16, 32, 48, 64).GetHexFormatted(true)); +} + TEST(lagi_color, rgb) { EXPECT_EQ(agi::Color(0, 0, 0), agi::Color("rgb(0, 0, 0)")); EXPECT_EQ(agi::Color(255, 255, 255), agi::Color("rgb(255, 255, 255)")); diff --git a/tests/tests/format.cpp b/tests/tests/format.cpp index a0495094a..5a7065909 100644 --- a/tests/tests/format.cpp +++ b/tests/tests/format.cpp @@ -94,6 +94,7 @@ TEST(lagi_format, length_modifiers) { TEST(lagi_format, precision_width) { EXPECT_EQ("05", agi::format("%02X", 5)); EXPECT_EQ(" -10", agi::format("%10d", -10)); + EXPECT_EQ("-10 ", agi::format("%-10d", -10)); EXPECT_EQ("0010", agi::format("%04d", 10)); EXPECT_EQ(" 1234.1235", agi::format("%10.4f", 1234.1234567890)); EXPECT_EQ("10", agi::format("%.f", 10.1)); diff --git a/tests/tests/hotkey.cpp b/tests/tests/hotkey.cpp index de0dc9d08..91c7bafb6 100644 --- a/tests/tests/hotkey.cpp +++ b/tests/tests/hotkey.cpp @@ -216,4 +216,6 @@ TEST(lagi_hotkey, old_format_is_backed_up_before_migrating) { tmp.read(buff, sizeof(buff)); ASSERT_TRUE(memcmp(buff, simple_valid, sizeof(buff)) == 0); } + + agi::fs::Remove("data/hotkey_tmp.3_1"); } diff --git a/tests/tests/ifind.cpp b/tests/tests/ifind.cpp index 541089627..e165b9bbe 100644 --- a/tests/tests/ifind.cpp +++ b/tests/tests/ifind.cpp @@ -39,6 +39,7 @@ TEST(lagi_ifind, basic_match) { EXPECT_IFIND(" a ", "a", 1, 2); EXPECT_IFIND(" a ", "A", 1, 2); + EXPECT_IFIND(" A ", "a", 1, 2); EXPECT_NO_MATCH(" a ", "b"); } diff --git a/tests/tests/time.cpp b/tests/tests/time.cpp index 74ea7558f..a9fcc8753 100644 --- a/tests/tests/time.cpp +++ b/tests/tests/time.cpp @@ -58,6 +58,10 @@ TEST(lagi_time, comma_decimal) { EXPECT_STREQ("1:23:45.67", Time("1:23:45,67").GetAssFormatted().c_str()); } +TEST(lagi_time, extra_garbage_is_ignored) { + EXPECT_STREQ("1:23:45.67", Time("1a:b2c3d:e4f5g.!6&7").GetAssFormatted().c_str()); +} + TEST(lagi_time, component_getters) { Time t("1:23:45.67"); EXPECT_EQ(1, t.GetTimeHours());