Files
lms/src/libs/metadata/test/Lyrics.cpp
T

378 lines
14 KiB
C++

/*
* Copyright (C) 2024 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#include <gtest/gtest.h>
#include "metadata/Lyrics.hpp"
namespace lms::metadata::tests
{
using namespace std::chrono_literals;
TEST(Lyrics, synchronized)
{
std::istringstream is{ R"([id: dqsxdkbu]
[ar: Lady Gaga]
[al: Lady Gaga]
[ti: Die With A Smile]
[la: eng]
[length: 04:12]
[offset: -34]
[00:03.30]Ooh, ooh
[00:06.75]
[00:09.16]I, I just woke up from a dream)" };
const Lyrics lyrics{ parseLyrics(is) };
EXPECT_EQ(lyrics.displayArtist, "Lady Gaga");
EXPECT_EQ(lyrics.displayAlbum, "Lady Gaga");
EXPECT_EQ(lyrics.displayTitle, "Die With A Smile");
EXPECT_EQ(lyrics.language, "eng");
EXPECT_EQ(lyrics.offset, -34ms);
EXPECT_EQ(lyrics.unsynchronizedLines.size(), 0);
ASSERT_EQ(lyrics.synchronizedLines.size(), 3);
ASSERT_TRUE(lyrics.synchronizedLines.contains(3s + 300ms));
EXPECT_EQ(lyrics.synchronizedLines.find(3s + 300ms)->second, "Ooh, ooh");
ASSERT_TRUE(lyrics.synchronizedLines.contains(6s + 750ms));
EXPECT_EQ(lyrics.synchronizedLines.find(6s + 750ms)->second, "");
ASSERT_TRUE(lyrics.synchronizedLines.contains(9s + 160ms));
EXPECT_EQ(lyrics.synchronizedLines.find(9s + 160ms)->second, "I, I just woke up from a dream");
}
TEST(Lyrics, tagInMidleOfLyrics)
{
std::istringstream is{ R"([00:03.30]Ooh, ooh
[id: dqsxdkbu]
[00:09.16]I, I just woke up from a dream)" };
const Lyrics lyrics{ parseLyrics(is) };
EXPECT_EQ(lyrics.unsynchronizedLines.size(), 0);
ASSERT_EQ(lyrics.synchronizedLines.size(), 2);
ASSERT_TRUE(lyrics.synchronizedLines.contains(3s + 300ms));
EXPECT_EQ(lyrics.synchronizedLines.find(3s + 300ms)->second, "Ooh, ooh");
ASSERT_TRUE(lyrics.synchronizedLines.contains(9s + 160ms));
EXPECT_EQ(lyrics.synchronizedLines.find(9s + 160ms)->second, "I, I just woke up from a dream");
}
TEST(Lyrics, tagsWithSpaces)
{
std::istringstream is{ R"([al: dqsxdkbu ]
[00:09.16]I, I just woke up from a dream)" };
const Lyrics lyrics{ parseLyrics(is) };
EXPECT_EQ(lyrics.unsynchronizedLines.size(), 0);
ASSERT_EQ(lyrics.synchronizedLines.size(), 1);
EXPECT_EQ(lyrics.displayAlbum, "dqsxdkbu");
ASSERT_TRUE(lyrics.synchronizedLines.contains(9s + 160ms));
EXPECT_EQ(lyrics.synchronizedLines.find(9s + 160ms)->second, "I, I just woke up from a dream");
}
TEST(Lyrics, tagIDsWithSpaces)
{
std::istringstream is{ R"([ al : dqsxdkbu ]
[00:09.16]I, I just woke up from a dream)" };
const Lyrics lyrics{ parseLyrics(is) };
EXPECT_EQ(lyrics.unsynchronizedLines.size(), 0);
ASSERT_EQ(lyrics.synchronizedLines.size(), 1);
EXPECT_EQ(lyrics.displayAlbum, "dqsxdkbu");
ASSERT_TRUE(lyrics.synchronizedLines.contains(9s + 160ms));
EXPECT_EQ(lyrics.synchronizedLines.find(9s + 160ms)->second, "I, I just woke up from a dream");
}
TEST(Lyrics, tagAtTheEndOfLyrics)
{
std::istringstream is{ R"([00:03.30]Ooh, ooh
[00:09.16]I, I just woke up from a dream
[id: dqsxdkbu])" };
const Lyrics lyrics{ parseLyrics(is) };
EXPECT_EQ(lyrics.unsynchronizedLines.size(), 0);
ASSERT_EQ(lyrics.synchronizedLines.size(), 2);
ASSERT_TRUE(lyrics.synchronizedLines.contains(3s + 300ms));
EXPECT_EQ(lyrics.synchronizedLines.find(3s + 300ms)->second, "Ooh, ooh");
ASSERT_TRUE(lyrics.synchronizedLines.contains(9s + 160ms));
EXPECT_EQ(lyrics.synchronizedLines.find(9s + 160ms)->second, "I, I just woke up from a dream");
}
TEST(Lyrics, skipEmptyBeginLines)
{
std::istringstream is{ R"(
[00:03.30]Ooh, ooh)" };
const Lyrics lyrics{ parseLyrics(is) };
EXPECT_EQ(lyrics.unsynchronizedLines.size(), 0);
ASSERT_EQ(lyrics.synchronizedLines.size(), 1);
ASSERT_TRUE(lyrics.synchronizedLines.contains(3s + 300ms));
EXPECT_EQ(lyrics.synchronizedLines.find(3s + 300ms)->second, "Ooh, ooh");
}
TEST(Lyrics, skipEmptyEndLines)
{
std::istringstream is{ R"([00:03.30]Ooh, ooh
)" };
const Lyrics lyrics{ parseLyrics(is) };
EXPECT_EQ(lyrics.unsynchronizedLines.size(), 0);
ASSERT_EQ(lyrics.synchronizedLines.size(), 1);
ASSERT_TRUE(lyrics.synchronizedLines.contains(3s + 300ms));
EXPECT_EQ(lyrics.synchronizedLines.find(3s + 300ms)->second, "Ooh, ooh");
}
TEST(Lyrics, skipLeadingUnsynchronizedLyrics)
{
std::istringstream is{ R"(
Some unsynchronized lyrics
[00:03.30]Ooh, ooh)" };
const Lyrics lyrics{ parseLyrics(is) };
EXPECT_EQ(lyrics.unsynchronizedLines.size(), 0);
ASSERT_EQ(lyrics.synchronizedLines.size(), 1);
ASSERT_TRUE(lyrics.synchronizedLines.contains(3s + 300ms));
EXPECT_EQ(lyrics.synchronizedLines.find(3s + 300ms)->second, "Ooh, ooh");
}
TEST(Lyrics, skipComments)
{
std::istringstream is{ R"(###
[00:03.30]Ooh, ooh
## just dance
[00:09.16]I, I just woke up from a dream
##end)" };
const Lyrics lyrics{ parseLyrics(is) };
EXPECT_EQ(lyrics.unsynchronizedLines.size(), 0);
ASSERT_EQ(lyrics.synchronizedLines.size(), 2);
ASSERT_TRUE(lyrics.synchronizedLines.contains(3s + 300ms));
EXPECT_EQ(lyrics.synchronizedLines.find(3s + 300ms)->second, "Ooh, ooh");
ASSERT_TRUE(lyrics.synchronizedLines.contains(9s + 160ms));
EXPECT_EQ(lyrics.synchronizedLines.find(9s + 160ms)->second, "I, I just woke up from a dream");
}
TEST(Lyrics, synchronized_notags)
{
std::istringstream is{ R"([00:03.30]Ooh, ooh)" };
const Lyrics lyrics{ parseLyrics(is) };
EXPECT_TRUE(lyrics.displayArtist.empty());
EXPECT_TRUE(lyrics.displayAlbum.empty());
EXPECT_TRUE(lyrics.displayTitle.empty());
EXPECT_EQ(lyrics.offset, std::chrono::milliseconds{ 0 });
EXPECT_EQ(lyrics.unsynchronizedLines.size(), 0);
ASSERT_EQ(lyrics.synchronizedLines.size(), 1);
ASSERT_TRUE(lyrics.synchronizedLines.contains(3s + 300ms));
EXPECT_EQ(lyrics.synchronizedLines.find(3s + 300ms)->second, "Ooh, ooh");
}
TEST(Lyrics, synchronized_withTimestampsDelimiters)
{
std::istringstream is{ R"([00:03.30]Ooh, ooh ] [])" };
const Lyrics lyrics{ parseLyrics(is) };
EXPECT_TRUE(lyrics.displayArtist.empty());
EXPECT_TRUE(lyrics.displayAlbum.empty());
EXPECT_TRUE(lyrics.displayTitle.empty());
EXPECT_EQ(lyrics.offset, std::chrono::milliseconds{ 0 });
EXPECT_EQ(lyrics.unsynchronizedLines.size(), 0);
ASSERT_EQ(lyrics.synchronizedLines.size(), 1);
ASSERT_TRUE(lyrics.synchronizedLines.contains(3s + 300ms));
EXPECT_EQ(lyrics.synchronizedLines.find(3s + 300ms)->second, "Ooh, ooh ] []");
}
TEST(Lyrics, synchronized_timestampFormats)
{
std::istringstream is{ R"([00:03.30]First line
[00:01.301]in milliseconds
[0:02.301]leading with only one digit
[61:01.30]more than 60 minutes
[02:01:01.30]With hours
[3:01:01.30]With hours with only one digit)" };
const Lyrics lyrics{ parseLyrics(is) };
ASSERT_EQ(lyrics.synchronizedLines.size(), 6);
ASSERT_TRUE(lyrics.synchronizedLines.contains(3s + 300ms));
ASSERT_TRUE(lyrics.synchronizedLines.contains(1s + 301ms));
ASSERT_TRUE(lyrics.synchronizedLines.contains(2s + 301ms));
ASSERT_TRUE(lyrics.synchronizedLines.contains(61min + 1s + 300ms));
ASSERT_TRUE(lyrics.synchronizedLines.contains(2h + 1min + 1s + 300ms));
ASSERT_TRUE(lyrics.synchronizedLines.contains(3h + 1min + 1s + 300ms));
}
TEST(Lyrics, synchronized_keepBlankLinesExceptEOF)
{
std::istringstream is{ R"([00:03.30]Ooh, ooh
[00:06.75]Foo
)" };
const Lyrics lyrics{ parseLyrics(is) };
EXPECT_TRUE(lyrics.displayArtist.empty());
EXPECT_TRUE(lyrics.displayAlbum.empty());
EXPECT_TRUE(lyrics.displayTitle.empty());
EXPECT_EQ(lyrics.offset, std::chrono::milliseconds{ 0 });
EXPECT_EQ(lyrics.unsynchronizedLines.size(), 0);
ASSERT_EQ(lyrics.synchronizedLines.size(), 2);
ASSERT_TRUE(lyrics.synchronizedLines.contains(3s + 300ms));
EXPECT_EQ(lyrics.synchronizedLines.find(3s + 300ms)->second, "Ooh, ooh\n\n");
ASSERT_TRUE(lyrics.synchronizedLines.contains(6s + 750ms));
EXPECT_EQ(lyrics.synchronizedLines.find(6s + 750ms)->second, "Foo");
}
TEST(Lyrics, synchronized_blankLinesEnd)
{
std::istringstream is{ R"([00:03.30]Ooh, ooh
SecondLine
Even a third line!!
[00:06.75]Foo
)" };
const Lyrics lyrics{ parseLyrics(is) };
EXPECT_TRUE(lyrics.displayArtist.empty());
EXPECT_TRUE(lyrics.displayAlbum.empty());
EXPECT_TRUE(lyrics.displayTitle.empty());
EXPECT_EQ(lyrics.offset, std::chrono::milliseconds{ 0 });
EXPECT_EQ(lyrics.unsynchronizedLines.size(), 0);
ASSERT_EQ(lyrics.synchronizedLines.size(), 2);
ASSERT_TRUE(lyrics.synchronizedLines.contains(3s + 300ms));
EXPECT_EQ(lyrics.synchronizedLines.find(3s + 300ms)->second, "Ooh, ooh\nSecondLine\n Even a third line!!");
ASSERT_TRUE(lyrics.synchronizedLines.contains(6s + 750ms));
EXPECT_EQ(lyrics.synchronizedLines.find(6s + 750ms)->second, "Foo");
}
TEST(Lyrics, synchronized_multitimestamps)
{
std::istringstream is{ R"([00:03.30][00:09.16] [00:15.16]Ooh, ooh
[00:06.75]I, I just woke up from a dream)" };
const Lyrics lyrics{ parseLyrics(is) };
EXPECT_TRUE(lyrics.displayArtist.empty());
EXPECT_TRUE(lyrics.displayAlbum.empty());
EXPECT_TRUE(lyrics.displayTitle.empty());
EXPECT_EQ(lyrics.offset, std::chrono::milliseconds{ 0 });
EXPECT_EQ(lyrics.unsynchronizedLines.size(), 0);
ASSERT_EQ(lyrics.synchronizedLines.size(), 4);
ASSERT_TRUE(lyrics.synchronizedLines.contains(3s + 300ms));
EXPECT_EQ(lyrics.synchronizedLines.find(3s + 300ms)->second, "Ooh, ooh");
ASSERT_TRUE(lyrics.synchronizedLines.contains(6s + 750ms));
EXPECT_EQ(lyrics.synchronizedLines.find(6s + 750ms)->second, "I, I just woke up from a dream");
ASSERT_TRUE(lyrics.synchronizedLines.contains(9s + 160ms));
EXPECT_EQ(lyrics.synchronizedLines.find(9s + 160ms)->second, "Ooh, ooh");
ASSERT_TRUE(lyrics.synchronizedLines.contains(15s + 160ms));
EXPECT_EQ(lyrics.synchronizedLines.find(15s + 160ms)->second, "Ooh, ooh");
}
TEST(Lyrics, synchronized_multitimestamps_blank)
{
std::istringstream is{ R"([00:03.30]Ooh, ooh
[00:06.75]
[00:09.16]I, I just woke up from a dream
[00:10.16]
)" };
const Lyrics lyrics{ parseLyrics(is) };
EXPECT_TRUE(lyrics.displayArtist.empty());
EXPECT_TRUE(lyrics.displayAlbum.empty());
EXPECT_TRUE(lyrics.displayTitle.empty());
EXPECT_EQ(lyrics.offset, std::chrono::milliseconds{ 0 });
EXPECT_EQ(lyrics.unsynchronizedLines.size(), 0);
ASSERT_EQ(lyrics.synchronizedLines.size(), 4);
ASSERT_TRUE(lyrics.synchronizedLines.contains(3s + 300ms));
EXPECT_EQ(lyrics.synchronizedLines.find(3s + 300ms)->second, "Ooh, ooh");
ASSERT_TRUE(lyrics.synchronizedLines.contains(6s + 750ms));
EXPECT_EQ(lyrics.synchronizedLines.find(6s + 750ms)->second, "");
ASSERT_TRUE(lyrics.synchronizedLines.contains(9s + 160ms));
EXPECT_EQ(lyrics.synchronizedLines.find(9s + 160ms)->second, "I, I just woke up from a dream");
ASSERT_TRUE(lyrics.synchronizedLines.contains(10s + 160ms));
EXPECT_EQ(lyrics.synchronizedLines.find(10s + 160ms)->second, "");
}
TEST(Lyrics, synchronized_multitimestamps_multilines)
{
std::istringstream is{ R"([00:03.30][00:09.16]Ooh, ooh
Second line
Third line
Fifth line after an empty one...
[00:06.75]I, I just woke up from a dream
Cool)" };
const Lyrics lyrics{ parseLyrics(is) };
EXPECT_TRUE(lyrics.displayArtist.empty());
EXPECT_TRUE(lyrics.displayAlbum.empty());
EXPECT_TRUE(lyrics.displayTitle.empty());
EXPECT_EQ(lyrics.offset, std::chrono::milliseconds{ 0 });
EXPECT_EQ(lyrics.unsynchronizedLines.size(), 0);
ASSERT_EQ(lyrics.synchronizedLines.size(), 3);
ASSERT_TRUE(lyrics.synchronizedLines.contains(3s + 300ms));
EXPECT_EQ(lyrics.synchronizedLines.find(3s + 300ms)->second, "Ooh, ooh\nSecond line\n Third line\n\nFifth line after an empty one...");
ASSERT_TRUE(lyrics.synchronizedLines.contains(6s + 750ms));
EXPECT_EQ(lyrics.synchronizedLines.find(6s + 750ms)->second, "I, I just woke up from a dream\nCool");
ASSERT_TRUE(lyrics.synchronizedLines.contains(9s + 160ms));
EXPECT_EQ(lyrics.synchronizedLines.find(9s + 160ms)->second, "Ooh, ooh\nSecond line\n Third line\n\nFifth line after an empty one...");
}
TEST(Lyrics, unsynchronized)
{
std::istringstream is{ R"([id: dqsxdkbu]
[ar: Lady Gaga]
[al: Lady Gaga]
[ti: Die With A Smile]
[length: 04:12]
[offset: -34]
Ooh, ooh
I, I just woke up from a dream
)" };
Lyrics lyrics{ parseLyrics(is) };
EXPECT_EQ(lyrics.displayArtist, "Lady Gaga");
EXPECT_EQ(lyrics.displayAlbum, "Lady Gaga");
EXPECT_EQ(lyrics.displayTitle, "Die With A Smile");
EXPECT_EQ(lyrics.offset, -34ms);
ASSERT_EQ(lyrics.unsynchronizedLines.size(), 5);
EXPECT_EQ(lyrics.unsynchronizedLines[0], "Ooh, ooh");
EXPECT_EQ(lyrics.unsynchronizedLines[1], "");
EXPECT_EQ(lyrics.unsynchronizedLines[2], "");
EXPECT_EQ(lyrics.unsynchronizedLines[3], "I, I just woke up from a dream");
EXPECT_EQ(lyrics.unsynchronizedLines[4], "");
}
} // namespace lms::metadata::tests