File indexing completed on 2024-06-16 04:38:27

0001 /*
0002     SPDX-FileCopyrightText: 2007-2009 Sergio Pistone <sergio_pistone@yahoo.com.ar>
0003     SPDX-FileCopyrightText: 2010-2022 Mladen Milinkovic <max@smoothware.net>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "richstringtest.h"
0009 #include "core/richstring.h"
0010 #include "helpers/common.h"
0011 
0012 #include <QDebug>
0013 #include <QTest>
0014 #include <QRegularExpression>
0015 
0016 using namespace SubtitleComposer;
0017 
0018 void
0019 RichStringTest::testStyleFlags()
0020 {
0021     RichString sstring("0123456789");
0022     sstring.setStyleFlagsAt(0, RichString::Bold);
0023     QVERIFY(sstring.styleFlagsAt(0) == RichString::Bold);
0024     QVERIFY(sstring.cummulativeStyleFlags() == RichString::Bold);
0025     QVERIFY(sstring.richString() == QLatin1String("<b>0</b>123456789"));
0026     sstring.setStyleFlagsAt(2, RichString::Italic);
0027     QVERIFY(sstring.styleFlagsAt(2) == RichString::Italic);
0028     QVERIFY(sstring.cummulativeStyleFlags() == (RichString::Bold | RichString::Italic));
0029     QVERIFY(sstring.richString() == QLatin1String("<b>0</b>1<i>2</i>3456789"));
0030     sstring.setStyleFlagsAt(1, RichString::Italic);
0031     QVERIFY(sstring.styleFlagsAt(1) == RichString::Italic);
0032     QVERIFY(sstring.cummulativeStyleFlags() == (RichString::Bold | RichString::Italic));
0033     QVERIFY(sstring.richString() == QLatin1String("<b>0</b><i>12</i>3456789"));
0034     sstring.setStyleFlagsAt(0, RichString::Italic);
0035     QVERIFY(sstring.styleFlagsAt(0) == RichString::Italic);
0036     QVERIFY(sstring.cummulativeStyleFlags() == RichString::Italic);
0037     QVERIFY(sstring.richString() == QLatin1String("<i>012</i>3456789"));
0038     sstring.setStyleFlagsAt(9, RichString::Underline);
0039     QVERIFY(sstring.styleFlagsAt(9) == RichString::Underline);
0040     QVERIFY(sstring.cummulativeStyleFlags() == (RichString::Italic | RichString::Underline));
0041     QVERIFY(sstring.richString() == QLatin1String("<i>012</i>345678<u>9</u>"));
0042 
0043     sstring.setStyleFlags(0, 15, 0);
0044     QVERIFY(sstring.richString() == QLatin1String("0123456789"));
0045     sstring.setStyleFlags(0, 3, RichString::Bold);
0046     QVERIFY(sstring.richString() == QLatin1String("<b>012</b>3456789"));
0047     sstring.setStyleFlags(3, 3, RichString::Italic);
0048     QVERIFY(sstring.richString() == QLatin1String("<b>012</b><i>345</i>6789"));
0049     sstring.setStyleFlags(6, 3, RichString::Underline);
0050     QVERIFY(sstring.richString() == QLatin1String("<b>012</b><i>345</i><u>678</u>9"));
0051     sstring.setStyleFlags(9, 3, RichString::StrikeThrough);
0052     QVERIFY(sstring.richString() == QLatin1String("<b>012</b><i>345</i><u>678</u><s>9</s>"));
0053 
0054     sstring.setStyleFlags(0, 15, RichString::Bold | RichString::Underline, false);
0055     QVERIFY(sstring.richString() == QLatin1String("012<i>345</i>678<s>9</s>"));
0056     sstring.setStyleFlags(0, 15, RichString::StrikeThrough, true);
0057     QVERIFY(sstring.richString() == QLatin1String("<s>012<i>345</i>6789</s>"));
0058     sstring.setStyleFlags(4, 1, RichString::Italic, false);
0059     QVERIFY(sstring.richString() == QLatin1String("<s>012<i>3</i>4<i>5</i>6789</s>"));
0060 }
0061 
0062 void
0063 RichStringTest::testLeftMidRight()
0064 {
0065     RichString sstring;
0066     sstring.setRichString("<b>012</b><i>345</i><u>678</u><s>9</s>");
0067 
0068     QVERIFY(sstring.left(-1).richString() == QLatin1String("<b>012</b><i>345</i><u>678</u><s>9</s>"));
0069     QVERIFY(sstring.left(-5).richString() == QLatin1String("<b>012</b><i>345</i><u>678</u><s>9</s>"));
0070     QVERIFY(sstring.left(10).richString() == QLatin1String("<b>012</b><i>345</i><u>678</u><s>9</s>"));
0071     QVERIFY(sstring.left(11).richString() == QLatin1String("<b>012</b><i>345</i><u>678</u><s>9</s>"));
0072     QVERIFY(sstring.left(4).richString() == QLatin1String("<b>012</b><i>3</i>"));
0073     QVERIFY(sstring.left(0).richString().isEmpty());
0074 
0075     QVERIFY(sstring.mid(1, -1).richString() == QLatin1String("<b>12</b><i>345</i><u>678</u><s>9</s>"));
0076     QVERIFY(sstring.mid(1, -5).richString() == QLatin1String("<b>12</b><i>345</i><u>678</u><s>9</s>"));
0077     QVERIFY(sstring.mid(1, 10).richString() == QLatin1String("<b>12</b><i>345</i><u>678</u><s>9</s>"));
0078     QVERIFY(sstring.mid(1, 11).richString() == QLatin1String("<b>12</b><i>345</i><u>678</u><s>9</s>"));
0079     QVERIFY(sstring.mid(1, 4).richString() == QLatin1String("<b>12</b><i>34</i>"));
0080     QVERIFY(sstring.mid(1, 0).richString().isEmpty());
0081     QVERIFY(sstring.mid(10, 2).richString().isEmpty());
0082     QVERIFY(sstring.mid(-2, 4).richString() == QLatin1String("<b>01</b>"));
0083     QVERIFY(sstring.mid(-2, 11).richString() == QLatin1String("<b>012</b><i>345</i><u>678</u>"));
0084     QVERIFY(sstring.mid(-2, -1).richString() == QLatin1String("<b>012</b><i>345</i><u>678</u><s>9</s>"));
0085 
0086     QVERIFY(sstring.right(-1).richString() == QLatin1String("<b>012</b><i>345</i><u>678</u><s>9</s>"));
0087     QVERIFY(sstring.right(-5).richString() == QLatin1String("<b>012</b><i>345</i><u>678</u><s>9</s>"));
0088     QVERIFY(sstring.right(10).richString() == QLatin1String("<b>012</b><i>345</i><u>678</u><s>9</s>"));
0089     QVERIFY(sstring.right(11).richString() == QLatin1String("<b>012</b><i>345</i><u>678</u><s>9</s>"));
0090     QVERIFY(sstring.right(4).richString() == QLatin1String("<u>678</u><s>9</s>"));
0091     QVERIFY(sstring.right(0).richString().isEmpty());
0092 }
0093 
0094 void
0095 RichStringTest::testInsert()
0096 {
0097     RichString sstring;
0098 
0099     sstring.append(QString());
0100     QVERIFY(sstring == RichString());
0101 
0102     sstring.append(RichString("x", RichString::Bold));
0103     QVERIFY(sstring.richString() == QLatin1String("<b>x</b>"));
0104     sstring.append($("y"));
0105     QVERIFY(sstring.richString() == QLatin1String("<b>xy</b>"));
0106     sstring.append('z');
0107     QVERIFY(sstring.richString() == QLatin1String("<b>xyz</b>"));
0108 
0109     sstring.prepend(RichString("c", RichString::Italic));
0110     QVERIFY(sstring.richString() == QLatin1String("<i>c</i><b>xyz</b>"));
0111     sstring.prepend($("b"));
0112     QVERIFY(sstring.richString() == QLatin1String("<i>bc</i><b>xyz</b>"));
0113     sstring.prepend('a');
0114     QVERIFY(sstring.richString() == QLatin1String("<i>abc</i><b>xyz</b>"));
0115 
0116     sstring.insert(3, RichString("g", RichString::Underline));
0117     QVERIFY(sstring.richString() == QLatin1String("<i>abc</i><u>g</u><b>xyz</b>"));
0118     sstring.insert(4, $("h"));
0119     QVERIFY(sstring.richString() == QLatin1String("<i>abc</i><u>gh</u><b>xyz</b>"));
0120     sstring.insert(5, 'i');
0121     QVERIFY(sstring.richString() == QLatin1String("<i>abc</i><u>ghi</u><b>xyz</b>"));
0122 
0123     sstring.clear();
0124     QVERIFY(sstring == RichString());
0125 }
0126 
0127 void
0128 RichStringTest::testReplace()
0129 {
0130     RichString sstring;
0131 
0132     // RichString & RichString::replace(int index, int len, const QString &replacement)
0133     sstring = RichString("0123456789");
0134     sstring.replace(-1, 4, $("aaaa"));
0135     QVERIFY(sstring == RichString("0123456789"));
0136     sstring.replace(-1, 0, $("bbbb"));
0137     QVERIFY(sstring == RichString("0123456789"));
0138     sstring.replace(15, 0, $("cccc"));
0139     QVERIFY(sstring == RichString("0123456789"));
0140     sstring.replace(15, 5, $("dddd"));
0141     QVERIFY(sstring == RichString("0123456789"));
0142     sstring.replace(0, 2, $("eeee"));
0143     QVERIFY(sstring == RichString("eeee23456789"));
0144     sstring.replace(5, -1, $("dddd"));
0145     QVERIFY(sstring == RichString("eeee2dddd"));
0146 
0147     // RichString & RichString::replace(int index, int len, const RichString &replacement)
0148     sstring = RichString("0123456789");
0149     sstring.replace(-1, 4, RichString("aaaa"));
0150     QVERIFY(sstring == RichString("0123456789"));
0151     sstring.replace(-1, 0, RichString("bbbb"));
0152     QVERIFY(sstring == RichString("0123456789"));
0153     sstring.replace(15, 0, RichString("cccc"));
0154     QVERIFY(sstring == RichString("0123456789"));
0155     sstring.replace(15, 5, RichString("dddd"));
0156     QVERIFY(sstring == RichString("0123456789"));
0157     sstring.replace(0, 2, RichString("eeee"));
0158     QVERIFY(sstring == RichString("eeee23456789"));
0159     sstring.replace(5, -1, RichString("dddd"));
0160     QVERIFY(sstring == RichString("eeee2dddd"));
0161 
0162     // RichString & RichString::replace(const QString &before, const QString &after, Qt::CaseSensitivity cs=Qt::CaseSensitive)
0163     sstring = RichString("01234567890123456789");
0164     sstring.replace($("0"), $("A"), Qt::CaseSensitive);
0165     QVERIFY(sstring == RichString("A123456789A123456789"));
0166     sstring.replace($("23"), $("B"), Qt::CaseSensitive);
0167     QVERIFY(sstring == RichString("A1B456789A1B456789"));
0168     sstring.replace($("89"), $("C"), Qt::CaseSensitive);
0169     QVERIFY(sstring == RichString("A1B4567CA1B4567C"));
0170     sstring.replace($("67CA1B"), $("D"), Qt::CaseSensitive);
0171     QVERIFY(sstring == RichString("A1B45D4567C"));
0172     sstring.replace(QString(), $("E"), Qt::CaseSensitive);
0173     QVERIFY(sstring == RichString("EAE1EBE4E5EDE4E5E6E7ECE"));
0174     sstring = RichString("3");
0175     sstring.replace(QString(), $("AA"), Qt::CaseSensitive);
0176     QVERIFY(sstring == RichString("AA3AA"));
0177     sstring = RichString();
0178     sstring.replace(QString(), $("AA"), Qt::CaseSensitive);
0179     QVERIFY(sstring == RichString("AA"));
0180     sstring.setRichString("c<b>a</b>c");
0181     sstring.replace($("c"), $("b"));
0182     QVERIFY(sstring.richString() == QLatin1String("b<b>a</b>b"));
0183 
0184     // RichString & RichString::replace(const QString &before, const RichString &after, Qt::CaseSensitivity cs=Qt::CaseSensitive)
0185     sstring = RichString("01234567890123456789");
0186     sstring.replace($("0"), RichString("A", RichString::Bold), Qt::CaseSensitive);
0187     QVERIFY(sstring.richString() == QLatin1String("<b>A</b>123456789<b>A</b>123456789"));
0188     sstring.replace($("23"), RichString("B", RichString::Italic), Qt::CaseSensitive);
0189     QVERIFY(sstring.richString() == QLatin1String("<b>A</b>1<i>B</i>456789<b>A</b>1<i>B</i>456789"));
0190     sstring.replace($("89"), RichString("C", RichString::Underline), Qt::CaseSensitive);
0191     QVERIFY(sstring.richString() == QLatin1String("<b>A</b>1<i>B</i>4567<u>C</u><b>A</b>1<i>B</i>4567<u>C</u>"));
0192     sstring.replace($("67CA1B"), RichString("D", RichString::StrikeThrough), Qt::CaseSensitive);
0193     QVERIFY(sstring.richString() == QLatin1String("<b>A</b>1<i>B</i>45<s>D</s>4567<u>C</u>"));
0194     sstring.replace(QString(), RichString("E"), Qt::CaseSensitive);
0195     QVERIFY(sstring.richString() == QLatin1String("E<b>A</b>E1E<i>B</i>E4E5E<s>D</s>E4E5E6E7E<u>C</u>E"));
0196     sstring = RichString("3");
0197     sstring.replace(QString(), RichString("AA", RichString::Bold), Qt::CaseSensitive);
0198     QVERIFY(sstring.richString() == QLatin1String("<b>AA</b>3<b>AA</b>"));
0199     sstring = RichString();
0200     sstring.replace(QString(), RichString("AA", RichString::Italic), Qt::CaseSensitive);
0201     QVERIFY(sstring.richString() == QLatin1String("<i>AA</i>"));
0202 
0203     // RichString & RichString::replace(const QRegularExpression &regExp, const QString &replacement)
0204     sstring = RichString("this is a pretty test");
0205     sstring.replace(RE$("^this"), "\\2\\0");
0206     QVERIFY(sstring.richString() == QLatin1String("\\2this is a pretty test"));
0207     sstring.replace(RE$("[\\w]+"), "w");
0208     QVERIFY(sstring.richString() == QLatin1String("\\w w w w w"));
0209     sstring = RichString("this is a pretty test");
0210     sstring.replace(RE$("([\\w]*)"), "[\\1]");
0211     QVERIFY(sstring.richString() == QLatin1String("[this][] [is][] [a][] [pretty][] [test][]"));
0212 
0213     // RichString & RichString::replace(const QRegularExpression &regExp, const QString &replacement)
0214     sstring = RichString("this is a pretty test");
0215     sstring.replace(RE$("^this"), "\\2\\0");
0216     QVERIFY(sstring.richString() == QLatin1String("\\2this is a pretty test"));
0217     sstring.replace(RE$("[\\w]+"), "w");
0218     QVERIFY(sstring.richString() == QLatin1String("\\w w w w w"));
0219     sstring = RichString("this is a pretty test");
0220     sstring.replace(RE$("([\\w]*)"), "[\\1]");
0221     QVERIFY(sstring.richString() == QLatin1String("[this][] [is][] [a][] [pretty][] [test][]"));
0222     sstring.setRichString("<b>a</b>");
0223     sstring.replace(RE$("a$"), "b");
0224     QVERIFY(sstring.richString() == QLatin1String("<b>b</b>"));
0225 
0226     // RichString & RichString::replace(QChar before, QChar after, Qt::CaseSensitivity cs=Qt::CaseSensitive)
0227     sstring.setRichString("<b>This </b>Is <i>a preTtI</i> testi");
0228     sstring.replace('I', 'X', Qt::CaseSensitive);
0229     QVERIFY(sstring.richString() == QLatin1String("<b>This</b> Xs <i>a preTtX</i> testi"));
0230     sstring.replace('T', 'w', Qt::CaseInsensitive);
0231     QVERIFY(sstring.richString() == QLatin1String("<b>whis</b> Xs <i>a prewwX</i> weswi"));
0232     sstring.setRichString("c<b>a</b>c");
0233     sstring.replace('c', 'b');
0234     QVERIFY(sstring.richString() == QLatin1String("b<b>a</b>b"));
0235 
0236     // RichString & RichString::replace(QChar ch, const QString &after, Qt::CaseSensitivity cs=Qt::CaseSensitive)
0237     sstring.setRichString("<b>This </b>Is <i>a preTtI</i> testi");
0238     sstring.replace('i', $("AA"), Qt::CaseInsensitive);
0239     QVERIFY(sstring.richString() == QLatin1String("<b>ThAAs</b> AAs <i>a preTtAA</i> testAA"));
0240     sstring.replace('T', $("XX"), Qt::CaseSensitive);
0241     QVERIFY(sstring.richString() == QLatin1String("<b>XXhAAs</b> AAs <i>a preXXtAA</i> testAA"));
0242 
0243     // RichString & RichString::replace(QChar ch, const RichString &after, Qt::CaseSensitivity cs=Qt::CaseSensitive)
0244     sstring.setRichString("<b>This </b>Is <i>a preTtI</i> testi");
0245     sstring.replace('i', RichString("A", RichString::Bold));
0246     QVERIFY(sstring.richString() == QLatin1String("<b>ThAs</b> Is <i>a preTtI</i> test<b>A</b>"));
0247     sstring.replace('T', RichString("X", RichString::Underline), Qt::CaseInsensitive);
0248     QVERIFY(sstring == RichString().setRichString("<u>X</u><b>hAs </b>Is <i>a pre</i><u>XX</u><i>I</i> <u>X</u>es<u>X</u><b>A</b>"));
0249 
0250     // RichString & RichString::remove(int index, int len);
0251     sstring.setRichString("<b>012</b><i>345</i><u>678</u><s>9</s>");
0252     sstring.remove(0, 0);
0253     QVERIFY(sstring.richString() == QLatin1String("<b>012</b><i>345</i><u>678</u><s>9</s>"));
0254     sstring.remove(0, 2);
0255     QVERIFY(sstring.richString() == QLatin1String("<b>2</b><i>345</i><u>678</u><s>9</s>"));
0256     sstring.remove(10, 2);
0257     QVERIFY(sstring.richString() == QLatin1String("<b>2</b><i>345</i><u>678</u><s>9</s>"));
0258     sstring.remove(8, 5);
0259     QVERIFY(sstring.richString() == QLatin1String("<b>2</b><i>345</i><u>678</u><s>9</s>"));
0260     sstring.remove(7, 3);
0261     QVERIFY(sstring.richString() == QLatin1String("<b>2</b><i>345</i><u>678</u>"));
0262     sstring.remove(0, 3);
0263     QVERIFY(sstring.richString() == QLatin1String("<i>5</i><u>678</u>"));
0264     sstring.remove(0, -1);
0265     QVERIFY(sstring.richString().isEmpty());
0266 
0267     // RichString & RichString::remove(const QString &str, Qt::CaseSensitivity cs=Qt::CaseSensitive);
0268     sstring.setRichString("<b>012</b><i>012</i><u>345</u><s>345</s>");
0269     sstring.remove("013");
0270     QVERIFY(sstring.richString() == QLatin1String("<b>012</b><i>012</i><u>345</u><s>345</s>"));
0271     sstring.remove("01");
0272     QVERIFY(sstring.richString() == QLatin1String("<b>2</b><i>2</i><u>345</u><s>345</s>"));
0273     sstring.remove("2345");
0274     QVERIFY(sstring.richString() == QLatin1String("<b>2</b><s>345</s>"));
0275 
0276     // RichString & RichString::remove(const QRegularExpression &regExp);
0277     sstring.setRichString("<b>012</b><i>012</i><u>345</u><s>345</s>");
0278     sstring.remove(RE$("^013"));
0279     QVERIFY(sstring.richString() == QLatin1String("<b>012</b><i>012</i><u>345</u><s>345</s>"));
0280     sstring.remove(RE$("^012"));
0281     QVERIFY(sstring.richString() == QLatin1String("<i>012</i><u>345</u><s>345</s>"));
0282     sstring.remove(RE$("345$"));
0283     QVERIFY(sstring.richString() == QLatin1String("<i>012</i><u>345</u>"));
0284     sstring.remove(RE$("\\d+"));
0285     QVERIFY(sstring.richString().isEmpty());
0286 
0287     // RichString & RichString::remove(QChar ch, Qt::CaseSensitivity cs=Qt::CaseSensitive);
0288     sstring.setRichString("<b>This </b>Is <i>a preTtI</i> testi");
0289     sstring.remove(QChar('T'), Qt::CaseSensitive);
0290     QVERIFY(sstring.richString() == QLatin1String("<b>his</b> Is <i>a pretI</i> testi"));
0291     sstring.remove(QChar('i'), Qt::CaseInsensitive);
0292     QVERIFY(sstring.richString() == QLatin1String("<b>hs</b> s <i>a pret</i> test"));
0293 
0294     // RichString & RichString::richString();
0295     sstring.setRichString("<b>This </b><i>  is a space testI</i>");
0296     QVERIFY(sstring.richString() == QLatin1String("<b>This</b>   <i>is a space testI</i>"));
0297 
0298     // RichString & Voice/Class
0299     sstring.setRichString("<v Person A>Hi <b>Person B</b>! How are you doing?\n<v Person B><c.test>Hi there.</c.test> Doing great!");
0300     sstring.replace($("are you"), $("is you"));
0301     QVERIFY(sstring.richString() == QLatin1String("<v Person A>Hi <b>Person B</b>! How is you doing?\n<v Person B><c.test>Hi there.</c> Doing great!"));
0302 }
0303 
0304 void
0305 RichStringTest::testStyleMerge()
0306 {
0307     RichString sstring;
0308 
0309     // append
0310     sstring.setRichString("<v voiceA><c.classA>This is one class</c>");
0311     sstring.append(RichString::fromRichString("<v voiceB><c.classB>This is another class</c>"));
0312     QVERIFY(sstring.richString() == QLatin1String("<v voiceA><c.classA>This is one class</c><v voiceB><c.classB>This is another class</c>"));
0313 
0314     // insert
0315     sstring.setRichString("<v voiceA><c.classA>This is one class</c>");
0316     sstring.insert(5, RichString::fromRichString("<v voiceB><c.classB>This is another class</c>"));
0317     QVERIFY(sstring.richString() == QLatin1String("<v voiceA><c.classA>This</c> <v voiceB><c.classB>This is another class</c><v voiceA><c.classA>is one class</c>"));
0318 
0319     // prepend
0320     sstring.setRichString("<v voiceA><c.classA>This is one class</c>");
0321     sstring.prepend(RichString::fromRichString("<v voiceB><c.classB>This is another class</c>"));
0322     QVERIFY(sstring.richString() == QLatin1String("<v voiceB><c.classB>This is another class</c><v voiceA><c.classA>This is one class</c>"));
0323 
0324     // remove unused
0325     sstring.setRichString("<v voiceA><c.classA>AAAA</c><v voiceB><c.classB>BBBB</c><v voiceC><c.classC>CCCC</c>");
0326     sstring.remove(0, 4);
0327     QVERIFY(sstring.richString() == QLatin1String("<v voiceB><c.classB>BBBB</c><v voiceC><c.classC>CCCC</c>"));
0328     QVERIFY(sstring.cummulativeClasses().size() == 2);
0329     QVERIFY(sstring.cummulativeVoices().size() == 2);
0330     sstring.remove(0, 4);
0331     QVERIFY(sstring.richString() == QLatin1String("<v voiceC><c.classC>CCCC</c>"));
0332     QVERIFY(sstring.cummulativeClasses().size() == 1);
0333     QVERIFY(sstring.cummulativeVoices().size() == 1);
0334 
0335     // remove unused nested
0336     sstring.setRichString("<v voiceA><c.classA>AAAA</c><v voiceB><c.classB>BBBB</c><v voiceC><c.classC>CCCC</c>");
0337     sstring.remove(0, 4);
0338     QVERIFY(sstring.richString() == QLatin1String("<v voiceB><c.classB>BBBB</c><v voiceC><c.classC>CCCC</c>"));
0339     QVERIFY(sstring.cummulativeClasses().size() == 2);
0340     QVERIFY(sstring.cummulativeVoices().size() == 2);
0341     sstring.remove(0, 4);
0342     QVERIFY(sstring.richString() == QLatin1String("<v voiceC><c.classC>CCCC</c>"));
0343     QVERIFY(sstring.cummulativeClasses().size() == 1);
0344     QVERIFY(sstring.cummulativeVoices().size() == 1);
0345 }
0346 
0347 QTEST_GUILESS_MAIN(RichStringTest);