3 #include "../id3/id3genres.h"
4 #include "../tagvalue.h"
6 #include <c++utilities/chrono/format.h>
7 #include <c++utilities/conversion/conversionexception.h>
11 #include <cppunit/TestFixture.h>
12 #include <cppunit/extensions/HelperMacros.h>
17 using namespace CPPUNIT_NS;
24 CPPUNIT_TEST(testBasics);
25 CPPUNIT_TEST(testBinary);
26 CPPUNIT_TEST(testInteger);
27 CPPUNIT_TEST(testPositionInSet);
28 CPPUNIT_TEST(testTimeSpan);
29 CPPUNIT_TEST(testDateTime);
30 CPPUNIT_TEST(testString);
31 CPPUNIT_TEST(testEqualityOperator);
32 CPPUNIT_TEST_SUITE_END();
35 void setUp()
override;
36 void tearDown()
override;
41 void testPositionInSet();
45 void testEqualityOperator();
60 CPPUNIT_ASSERT(TagValue::empty().isEmpty());
66 const TagValue binary(
"123", 3, TagDataType::Binary);
67 CPPUNIT_ASSERT_EQUAL(TagDataType::Binary, binary.
type());
69 CPPUNIT_ASSERT_THROW(binary.
toString(), ConversionException);
70 CPPUNIT_ASSERT_THROW(binary.
toInteger(), ConversionException);
79 CPPUNIT_ASSERT(!integer.
isEmpty());
80 CPPUNIT_ASSERT_EQUAL(TagDataType::Integer, integer.
type());
81 CPPUNIT_ASSERT_EQUAL(
static_cast<std::int32_t
>(42), integer.
toInteger());
82 CPPUNIT_ASSERT_EQUAL(
"42"s, integer.
toString());
84 CPPUNIT_ASSERT_EQUAL(
"Country"s,
string(Id3Genres::stringFromIndex(integer.
toStandardGenreIndex())));
92 CPPUNIT_ASSERT_EQUAL(
"-25"s, integer.
toString());
98 CPPUNIT_ASSERT_MESSAGE(
"explicitely assigned zero not considered empty", !integer.
isEmpty());
99 CPPUNIT_ASSERT_EQUAL(
"0"s, integer.
toString());
101 CPPUNIT_ASSERT_EQUAL(TimeSpan(), integer.
toTimeSpan());
105 CPPUNIT_ASSERT_MESSAGE(
"cleared vale considered empty", integer.
isEmpty());
106 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"only date (but not type) cleared"s, TagDataType::Integer, integer.
type());
107 CPPUNIT_ASSERT_EQUAL(
static_cast<std::int32_t
>(0), integer.
toInteger());
108 CPPUNIT_ASSERT_EQUAL(
string(), integer.
toString());
110 CPPUNIT_ASSERT_EQUAL(TimeSpan(), integer.
toTimeSpan());
117 CPPUNIT_ASSERT_EQUAL(test.
toInteger(), 4);
118 CPPUNIT_ASSERT_EQUAL(
"4/23"s, test.
toString());
120 CPPUNIT_ASSERT_THROW(test.
toDateTime(), ConversionException);
121 CPPUNIT_ASSERT_THROW(test.
toTimeSpan(), ConversionException);
126 const TimeSpan fiveMinutes(TimeSpan::fromMinutes(5));
129 CPPUNIT_ASSERT_EQUAL(timeSpan,
TagValue(timeSpan));
130 CPPUNIT_ASSERT_EQUAL(fiveMinutes, timeSpan.
toTimeSpan());
131 CPPUNIT_ASSERT_EQUAL(fiveMinutes.toString(), timeSpan.
toString());
132 CPPUNIT_ASSERT_THROW(timeSpan.
toInteger(), ConversionException);
133 CPPUNIT_ASSERT_THROW(timeSpan.
toDateTime(), ConversionException);
139 const DateTime now(DateTime::now());
142 CPPUNIT_ASSERT_EQUAL(dateTime,
TagValue(dateTime));
143 CPPUNIT_ASSERT_EQUAL(now, dateTime.
toDateTime());
144 CPPUNIT_ASSERT_EQUAL(now.toString(DateTimeOutputFormat::IsoOmittingDefaultComponents), dateTime.
toString());
145 CPPUNIT_ASSERT_THROW(dateTime.
toInteger(), ConversionException);
146 CPPUNIT_ASSERT_THROW(dateTime.
toTimeSpan(), ConversionException);
155 CPPUNIT_ASSERT_EQUAL(
"\x31\0\x35\0"s,
TagValue(15).toString(TagTextEncoding::Utf16LittleEndian));
156 CPPUNIT_ASSERT_EQUAL(
"\0\x31\0\x35"s,
TagValue(15).toString(TagTextEncoding::Utf16BigEndian));
157 CPPUNIT_ASSERT_EQUAL(15,
TagValue(
"\0\x31\0\x35"s, TagTextEncoding::Utf16BigEndian).toInteger());
158 CPPUNIT_ASSERT_EQUAL_MESSAGE(
160 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"original encoding preserved",
"\0\x31\0\x35"s,
161 TagValue(
"\0\x31\0\x35", 4, TagTextEncoding::Utf16BigEndian).toString(TagTextEncoding::Unspecified));
162 CPPUNIT_ASSERT_EQUAL_MESSAGE(
164 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"UTF-16 LE BOM truncated",
"\0t\0\xe4\0s\0t"s,
165 TagValue(
"\xff\xfe\0t\0\xe4\0s\0t", 10, TagTextEncoding::Utf16LittleEndian).toString(TagTextEncoding::Unspecified));
166 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"UTF-16 BE BOM truncated",
"t\0\xe4\0s\0t\0"s,
167 TagValue(
"\xfe\xfft\0\xe4\0s\0t\0", 10, TagTextEncoding::Utf16BigEndian).toString(TagTextEncoding::Unspecified));
168 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"conversion via c'tor",
"15\xe4"s,
171 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"conversion to int", 15,
TagValue(
"\0\x31\0\x35", 4, TagTextEncoding::Utf16BigEndian).toInteger());
174 CPPUNIT_ASSERT_EQUAL_MESSAGE(
175 "conversion to pos",
PositionInSet(15),
TagValue(
"\0\x31\0\x35", 4, TagTextEncoding::Utf16BigEndian).toPositionInSet());
176 CPPUNIT_ASSERT_THROW_MESSAGE(
"failing conversion pos",
TagValue(
"a4 / 15", 7,
TagTextEncoding::Utf8).toPositionInSet(), ConversionException);
177 CPPUNIT_ASSERT_EQUAL_MESSAGE(
179 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"conversion to date from UTF-16", DateTime::fromDate(2015, 4, 15),
180 TagValue(
"\0\x32\0\x30\0\x31\0\x35\0\x2d\0\x30\0\x34\0\x2d\0\x31\0\x35", 20, TagTextEncoding::Utf16BigEndian).toDateTime());
182 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"conversion to time span", TimeSpan::fromHours(1.5),
TagValue(
"01:30:00", 10,
TagTextEncoding::Utf8).toTimeSpan());
183 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"conversion to time span from UTF-16", TimeSpan::fromHours(1.5),
184 TagValue(
"\0\x31\0\x3a\0\x33\0\x30\0\x3a\0\x30\0\x30", 14, TagTextEncoding::Utf16BigEndian).toTimeSpan());
186 CPPUNIT_ASSERT_EQUAL_MESSAGE(
187 "conversion to genre from index", 15,
TagValue(
"\0\x31\0\x35", 4, TagTextEncoding::Utf16BigEndian).toStandardGenreIndex());
188 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"conversion to genre from name", 2,
TagValue(
"Country", 7, TagTextEncoding::Latin1).toStandardGenreIndex());
189 CPPUNIT_ASSERT_THROW_MESSAGE(
190 "failing conversion to genre",
TagValue(
"Kountry", 7, TagTextEncoding::Latin1).toStandardGenreIndex(), ConversionException);
195 CPPUNIT_ASSERT_MESSAGE(
"equality requires identical types or identical string representation"s,
TagValue(0) != TagValue::empty());
196 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"comparision of equal types"s,
TagValue(15),
TagValue(15));
197 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"types might differ"s,
TagValue(
"15", 2, TagTextEncoding::Latin1),
TagValue(15));
198 CPPUNIT_ASSERT_MESSAGE(
"but some types shall never be considered equal"s,
TagValue(
DateTime(0)) !=
TagValue(TimeSpan(0)));
199 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"comparision of equal UTF-16 strings"s,
TagValue(
"\x31\0\x32\0", 4, TagTextEncoding::Utf16LittleEndian),
200 TagValue(
"\x31\0\x32\0", 4, TagTextEncoding::Utf16LittleEndian));
201 CPPUNIT_ASSERT_MESSAGE(
"comparision of different UTF-16 strings"s,
202 TagValue(
"\x31\0\x33\0", 4, TagTextEncoding::Utf16LittleEndian) !=
TagValue(
"\x31\0\x32\0", 4, TagTextEncoding::Utf16LittleEndian));
203 CPPUNIT_ASSERT_EQUAL_MESSAGE(
204 "comparision of equal binary data"s,
TagValue(
"\x31\0\x32\0", 4, TagDataType::Binary),
TagValue(
"\x31\0\x32\0", 4, TagDataType::Binary));
205 CPPUNIT_ASSERT_MESSAGE(
"comparision of different binary data"s,
206 TagValue(
"\x31\0\x33\0", 4, TagDataType::Binary) !=
TagValue(
"\x31\0\x32\0", 4, TagDataType::Binary));
207 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"different encodings are converted if neccassary"s,
TagValue(
"\0\x31\0\x35", 4, TagTextEncoding::Utf16BigEndian),
208 TagValue(
"15", 2, TagTextEncoding::Latin1));
209 CPPUNIT_ASSERT_EQUAL_MESSAGE(
210 "encoding is ignored when not relevant for types"s,
TagValue(
"\0\x31\0\x35", 4, TagTextEncoding::Utf16BigEndian),
TagValue(15));
211 const TagValue fooTagValue(
"foo", 3, TagDataType::Text), fOoTagValue(
"fOo", 3, TagDataType::Text);
212 CPPUNIT_ASSERT_MESSAGE(
"string comparison case-sensitive by default"s, fooTagValue != fOoTagValue);
213 CPPUNIT_ASSERT_MESSAGE(
"case-insensitive string comparision"s, fooTagValue.compareTo(fOoTagValue, TagValueComparisionFlags::CaseInsensitive));
218 CPPUNIT_ASSERT_MESSAGE(
"meta-data must be equal"s, withDescription !=
TagValue(15));
219 CPPUNIT_ASSERT_MESSAGE(
"different meta-data ignored"s, withDescription.
compareTo(
TagValue(15), TagValueComparisionFlags::IgnoreMetaData));
220 TagValue withDescription2(withDescription);
221 CPPUNIT_ASSERT_EQUAL(withDescription, withDescription2);
223 CPPUNIT_ASSERT(withDescription != withDescription2);
225 CPPUNIT_ASSERT_EQUAL(withDescription, withDescription2);
227 CPPUNIT_ASSERT_MESSAGE(
"meta-data case must match by default"s, withDescription != withDescription2);
228 CPPUNIT_ASSERT_MESSAGE(
"meta-data case ignored"s, withDescription.
compareTo(withDescription2, TagValueComparisionFlags::CaseInsensitive));