378 lines
14 KiB
C++
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
|