strawberry-audio-player-win.../tests/taglib/test_string.cpp

363 lines
13 KiB
C++

/***************************************************************************
copyright : (C) 2007 by Lukas Lalinsky
email : lukas@oxygene.sk
***************************************************************************/
/***************************************************************************
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License version *
* 2.1 as published by the Free Software Foundation. *
* *
* This library 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 *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
* 02110-1301 USA *
* *
* Alternatively, this file is available under the Mozilla Public *
* License Version 1.1. You may obtain a copy of the License at *
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include <cstring>
#include <cppunit/extensions/HelperMacros.h>
#include "tstring.h"
using namespace std;
using namespace Strawberry_TagLib::TagLib;
class TestString : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(TestString);
CPPUNIT_TEST(testString);
CPPUNIT_TEST(testRfind);
CPPUNIT_TEST(testUTF16Encode);
CPPUNIT_TEST(testUTF16Decode);
CPPUNIT_TEST(testUTF16DecodeInvalidBOM);
CPPUNIT_TEST(testUTF16DecodeEmptyWithBOM);
CPPUNIT_TEST(testSurrogatePair);
CPPUNIT_TEST(testAppendCharDetach);
CPPUNIT_TEST(testAppendStringDetach);
CPPUNIT_TEST(testToInt);
CPPUNIT_TEST(testFromInt);
CPPUNIT_TEST(testSubstr);
CPPUNIT_TEST(testNewline);
CPPUNIT_TEST(testUpper);
CPPUNIT_TEST(testEncodeNonLatin1);
CPPUNIT_TEST(testEncodeEmpty);
CPPUNIT_TEST(testEncodeNonBMP);
CPPUNIT_TEST(testIterator);
CPPUNIT_TEST(testInvalidUTF8);
CPPUNIT_TEST_SUITE_END();
public:
void testString() {
// Needs to know the system byte order for some Unicode tests.
bool littleEndian;
{
union {
int i;
char c;
} u;
u.i = 1;
littleEndian = (u.c == 1) ? true : false;
}
String s = "taglib string";
ByteVector v = "taglib string";
CPPUNIT_ASSERT(v == s.data(String::Latin1));
char str[] = "taglib string";
CPPUNIT_ASSERT(strcmp(s.toCString(), str) == 0);
s.clear();
CPPUNIT_ASSERT(s.isEmpty());
String unicode("José Carlos", String::UTF8);
CPPUNIT_ASSERT(strcmp(unicode.toCString(), "Jos\xe9 Carlos") == 0);
String latin = "Jos\xe9 Carlos";
CPPUNIT_ASSERT(strcmp(latin.toCString(true), "José Carlos") == 0);
String c;
c = "1";
CPPUNIT_ASSERT(c == L"1");
c = L'\u4E00';
CPPUNIT_ASSERT(c == L"\u4E00");
String unicode2(unicode.to8Bit(true), String::UTF8);
CPPUNIT_ASSERT(unicode == unicode2);
String unicode3(L"\u65E5\u672C\u8A9E");
CPPUNIT_ASSERT(*(unicode3.toCWString() + 1) == L'\u672C');
String unicode4(L"\u65e5\u672c\u8a9e");
CPPUNIT_ASSERT(unicode4[1] == L'\u672c');
String unicode5(L"\u65e5\u672c\u8a9e", String::UTF16BE);
CPPUNIT_ASSERT(unicode5[1] == (littleEndian ? L'\u2c67' : L'\u672c'));
String unicode6(L"\u65e5\u672c\u8a9e", String::UTF16LE);
CPPUNIT_ASSERT(unicode6[1] == (littleEndian ? L'\u672c' : L'\u2c67'));
CPPUNIT_ASSERT(String(" foo ").stripWhiteSpace() == String("foo"));
CPPUNIT_ASSERT(String("foo ").stripWhiteSpace() == String("foo"));
CPPUNIT_ASSERT(String(" foo").stripWhiteSpace() == String("foo"));
CPPUNIT_ASSERT(String("foo").stripWhiteSpace() == String("foo"));
CPPUNIT_ASSERT(String("f o o").stripWhiteSpace() == String("f o o"));
CPPUNIT_ASSERT(String(" f o o ").stripWhiteSpace() == String("f o o"));
CPPUNIT_ASSERT(memcmp(String("foo").data(String::Latin1).data(), "foo", 3) == 0);
CPPUNIT_ASSERT(memcmp(String("f").data(String::Latin1).data(), "f", 1) == 0);
}
void testUTF16Encode() {
String a("foo");
ByteVector b("\0f\0o\0o", 6);
ByteVector c("f\0o\0o\0", 6);
ByteVector d("\377\376f\0o\0o\0", 8);
CPPUNIT_ASSERT(a.data(String::UTF16BE) != a.data(String::UTF16LE));
CPPUNIT_ASSERT(b == a.data(String::UTF16BE));
CPPUNIT_ASSERT(c == a.data(String::UTF16LE));
CPPUNIT_ASSERT_EQUAL(d, a.data(String::UTF16));
}
void testUTF16Decode() {
String a("foo");
ByteVector b("\0f\0o\0o", 6);
ByteVector c("f\0o\0o\0", 6);
ByteVector d("\377\376f\0o\0o\0", 8);
CPPUNIT_ASSERT_EQUAL(a, String(b, String::UTF16BE));
CPPUNIT_ASSERT_EQUAL(a, String(c, String::UTF16LE));
CPPUNIT_ASSERT_EQUAL(a, String(d, String::UTF16));
}
// this test is expected to print "TagLib: String::copyFromUTF16() -
// Invalid UTF16 string." on the console 3 times
void testUTF16DecodeInvalidBOM() {
ByteVector b(" ", 1);
ByteVector c(" ", 2);
ByteVector d(" \0f\0o\0o", 8);
CPPUNIT_ASSERT_EQUAL(String(), String(b, String::UTF16));
CPPUNIT_ASSERT_EQUAL(String(), String(c, String::UTF16));
CPPUNIT_ASSERT_EQUAL(String(), String(d, String::UTF16));
}
void testUTF16DecodeEmptyWithBOM() {
ByteVector a("\377\376", 2);
ByteVector b("\376\377", 2);
CPPUNIT_ASSERT_EQUAL(String(), String(a, String::UTF16));
CPPUNIT_ASSERT_EQUAL(String(), String(b, String::UTF16));
}
void testSurrogatePair() {
// Make sure that a surrogate pair is converted into single UTF-8 char
// and vice versa.
const ByteVector v1("\xff\xfe\x42\xd8\xb7\xdf\xce\x91\x4b\x5c");
const ByteVector v2("\xf0\xa0\xae\xb7\xe9\x87\x8e\xe5\xb1\x8b");
const String s1(v1, String::UTF16);
CPPUNIT_ASSERT_EQUAL(s1.data(String::UTF8), v2);
const String s2(v2, String::UTF8);
CPPUNIT_ASSERT_EQUAL(s2.data(String::UTF16), v1);
const ByteVector v3("\xfe\xff\xd8\x01\x30\x42");
CPPUNIT_ASSERT(String(v3, String::UTF16).data(String::UTF8).isEmpty());
const ByteVector v4("\xfe\xff\x30\x42\xdc\x01");
CPPUNIT_ASSERT(String(v4, String::UTF16).data(String::UTF8).isEmpty());
const ByteVector v5("\xfe\xff\xdc\x01\xd8\x01");
CPPUNIT_ASSERT(String(v5, String::UTF16).data(String::UTF8).isEmpty());
}
void testAppendStringDetach() {
String a("abc");
String b = a;
String c = a;
b += "def";
c += L"def";
CPPUNIT_ASSERT_EQUAL(String("abc"), a);
CPPUNIT_ASSERT_EQUAL(String("abcdef"), b);
CPPUNIT_ASSERT_EQUAL(String("abcdef"), c);
}
void testAppendCharDetach() {
String a("abc");
String b = a;
String c = a;
b += 'd';
c += L'd';
CPPUNIT_ASSERT_EQUAL(String("abc"), a);
CPPUNIT_ASSERT_EQUAL(String("abcd"), b);
CPPUNIT_ASSERT_EQUAL(String("abcd"), c);
}
void testRfind() {
CPPUNIT_ASSERT_EQUAL(String::npos(), String("foo.bar").rfind(".", 0));
CPPUNIT_ASSERT_EQUAL(String::npos(), String("foo.bar").rfind(".", 1));
CPPUNIT_ASSERT_EQUAL(String::npos(), String("foo.bar").rfind(".", 2));
CPPUNIT_ASSERT_EQUAL((size_t)3, String("foo.bar").rfind(".", 3));
CPPUNIT_ASSERT_EQUAL((size_t)3, String("foo.bar").rfind(".", 4));
CPPUNIT_ASSERT_EQUAL((size_t)3, String("foo.bar").rfind(".", 5));
CPPUNIT_ASSERT_EQUAL((size_t)3, String("foo.bar").rfind(".", 6));
CPPUNIT_ASSERT_EQUAL((size_t)3, String("foo.bar").rfind(".", 7));
CPPUNIT_ASSERT_EQUAL((size_t)3, String("foo.bar").rfind("."));
}
void testToInt() {
bool ok;
CPPUNIT_ASSERT_EQUAL(String("123").toInt(&ok), 123);
CPPUNIT_ASSERT_EQUAL(ok, true);
CPPUNIT_ASSERT_EQUAL(String("-123").toInt(&ok), -123);
CPPUNIT_ASSERT_EQUAL(ok, true);
CPPUNIT_ASSERT_EQUAL(String("123aa").toInt(&ok), 123);
CPPUNIT_ASSERT_EQUAL(ok, false);
CPPUNIT_ASSERT_EQUAL(String("-123aa").toInt(&ok), -123);
CPPUNIT_ASSERT_EQUAL(ok, false);
CPPUNIT_ASSERT_EQUAL(String("abc").toInt(&ok), 0);
CPPUNIT_ASSERT_EQUAL(ok, false);
CPPUNIT_ASSERT_EQUAL(String("1x").toInt(&ok), 1);
CPPUNIT_ASSERT_EQUAL(ok, false);
CPPUNIT_ASSERT_EQUAL(String("").toInt(&ok), 0);
CPPUNIT_ASSERT_EQUAL(ok, false);
CPPUNIT_ASSERT_EQUAL(String("-").toInt(&ok), 0);
CPPUNIT_ASSERT_EQUAL(ok, false);
String("9999999999").toInt(&ok);
CPPUNIT_ASSERT_EQUAL(ok, false);
CPPUNIT_ASSERT_EQUAL(String("0000").toInt(), 0);
CPPUNIT_ASSERT_EQUAL(String("0001").toInt(), 1);
String("2147483648").toInt(&ok);
CPPUNIT_ASSERT_EQUAL(ok, false);
String("-2147483649").toInt(&ok);
CPPUNIT_ASSERT_EQUAL(ok, false);
}
void testFromInt() {
CPPUNIT_ASSERT_EQUAL(String::number(0), String("0"));
CPPUNIT_ASSERT_EQUAL(String::number(12345678), String("12345678"));
CPPUNIT_ASSERT_EQUAL(String::number(-12345678), String("-12345678"));
}
void testSubstr() {
CPPUNIT_ASSERT_EQUAL(String("01"), String("0123456").substr(0, 2));
CPPUNIT_ASSERT_EQUAL(String("12"), String("0123456").substr(1, 2));
CPPUNIT_ASSERT_EQUAL(String("123456"), String("0123456").substr(1, 200));
CPPUNIT_ASSERT_EQUAL(String("0123456"), String("0123456").substr(0, 7));
CPPUNIT_ASSERT_EQUAL(String("0123456"), String("0123456").substr(0, 200));
}
void testNewline() {
ByteVector cr("abc\x0dxyz", 7);
ByteVector lf("abc\x0axyz", 7);
ByteVector crlf("abc\x0d\x0axyz", 8);
CPPUNIT_ASSERT_EQUAL((size_t)7, String(cr).size());
CPPUNIT_ASSERT_EQUAL((size_t)7, String(lf).size());
CPPUNIT_ASSERT_EQUAL((size_t)8, String(crlf).size());
CPPUNIT_ASSERT_EQUAL(L'\x0d', String(cr)[3]);
CPPUNIT_ASSERT_EQUAL(L'\x0a', String(lf)[3]);
CPPUNIT_ASSERT_EQUAL(L'\x0d', String(crlf)[3]);
CPPUNIT_ASSERT_EQUAL(L'\x0a', String(crlf)[4]);
}
void testUpper() {
String s1 = "tagLIB 012 strING";
String s2 = s1.upper();
CPPUNIT_ASSERT_EQUAL(String("tagLIB 012 strING"), s1);
CPPUNIT_ASSERT_EQUAL(String("TAGLIB 012 STRING"), s2);
}
void testEncodeNonLatin1() {
const String jpn(L"\u65E5\u672C\u8A9E");
CPPUNIT_ASSERT_EQUAL(ByteVector("\xE5\x2C\x9E"), jpn.data(String::Latin1));
CPPUNIT_ASSERT_EQUAL(ByteVector("\xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E"), jpn.data(String::UTF8));
CPPUNIT_ASSERT_EQUAL(ByteVector("\xFF\xFE\xE5\x65\x2C\x67\x9E\x8A"), jpn.data(String::UTF16));
CPPUNIT_ASSERT_EQUAL(ByteVector("\xE5\x65\x2C\x67\x9E\x8A"), jpn.data(String::UTF16LE));
CPPUNIT_ASSERT_EQUAL(ByteVector("\x65\xE5\x67\x2C\x8A\x9E"), jpn.data(String::UTF16BE));
CPPUNIT_ASSERT_EQUAL(std::string("\xE5\x2C\x9E"), jpn.to8Bit(false));
CPPUNIT_ASSERT_EQUAL(std::string("\xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E"), jpn.to8Bit(true));
}
void testEncodeEmpty() {
const String empty;
CPPUNIT_ASSERT(empty.data(String::Latin1).isEmpty());
CPPUNIT_ASSERT(empty.data(String::UTF8).isEmpty());
CPPUNIT_ASSERT_EQUAL(ByteVector("\xFF\xFE"), empty.data(String::UTF16));
CPPUNIT_ASSERT(empty.data(String::UTF16LE).isEmpty());
CPPUNIT_ASSERT(empty.data(String::UTF16BE).isEmpty());
CPPUNIT_ASSERT(empty.to8Bit(false).empty());
CPPUNIT_ASSERT(empty.to8Bit(true).empty());
}
void testEncodeNonBMP() {
const ByteVector a("\xFF\xFE\x3C\xD8\x50\xDD\x40\xD8\xF5\xDC\x3C\xD8\x00\xDE", 14);
const ByteVector b("\xF0\x9F\x85\x90\xF0\xA0\x83\xB5\xF0\x9F\x88\x80");
CPPUNIT_ASSERT_EQUAL(b, String(a, String::UTF16).data(String::UTF8));
}
void testIterator() {
String s1 = "taglib string";
String s2 = s1;
String::Iterator it1 = s1.begin();
String::Iterator it2 = s2.begin();
CPPUNIT_ASSERT_EQUAL(L't', *it1);
CPPUNIT_ASSERT_EQUAL(L't', *it2);
std::advance(it1, 4);
std::advance(it2, 4);
*it2 = L'I';
CPPUNIT_ASSERT_EQUAL(L'i', *it1);
CPPUNIT_ASSERT_EQUAL(L'I', *it2);
}
void testInvalidUTF8() {
CPPUNIT_ASSERT_EQUAL(String("/"), String(ByteVector("\x2F"), String::UTF8));
CPPUNIT_ASSERT(String(ByteVector("\xC0\xAF"), String::UTF8).isEmpty());
CPPUNIT_ASSERT(String(ByteVector("\xE0\x80\xAF"), String::UTF8).isEmpty());
CPPUNIT_ASSERT(String(ByteVector("\xF0\x80\x80\xAF"), String::UTF8).isEmpty());
CPPUNIT_ASSERT(String(ByteVector("\xF8\x80\x80\x80\x80"), String::UTF8).isEmpty());
CPPUNIT_ASSERT(String(ByteVector("\xFC\x80\x80\x80\x80\x80"), String::UTF8).isEmpty());
CPPUNIT_ASSERT(String(ByteVector("\xC2"), String::UTF8).isEmpty());
CPPUNIT_ASSERT(String(ByteVector("\xE0\x80"), String::UTF8).isEmpty());
CPPUNIT_ASSERT(String(ByteVector("\xF0\x80\x80"), String::UTF8).isEmpty());
CPPUNIT_ASSERT(String(ByteVector("\xF8\x80\x80\x80"), String::UTF8).isEmpty());
CPPUNIT_ASSERT(String(ByteVector("\xFC\x80\x80\x80\x80"), String::UTF8).isEmpty());
CPPUNIT_ASSERT(String('\x80', String::UTF8).isEmpty());
CPPUNIT_ASSERT(String(ByteVector("\xED\xA0\x80\xED\xB0\x80"), String::UTF8).isEmpty());
CPPUNIT_ASSERT(String(ByteVector("\xED\xB0\x80\xED\xA0\x80"), String::UTF8).isEmpty());
}
};
CPPUNIT_TEST_SUITE_REGISTRATION(TestString);