mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-04-03 20:47:37 +03:00
Fix various quirks with CSV import widget and parser
* Fixes #11502 - correct improper handling of text qualifiers * Improve layout of csv import widget * Hide error messages when trying to import again
This commit is contained in:
parent
244ed42231
commit
1b1643b5d1
8 changed files with 248 additions and 120 deletions
|
@ -22,6 +22,18 @@
|
|||
|
||||
QTEST_GUILESS_MAIN(TestCsvParser)
|
||||
|
||||
void TestCsvParser::writeToFile(const QString& contents)
|
||||
{
|
||||
if (!file->open()) {
|
||||
QFAIL("Cannot open temporary file!");
|
||||
}
|
||||
QTextStream out(file.data());
|
||||
out.setCodec("UTF-8");
|
||||
out << contents;
|
||||
out.flush();
|
||||
file->close();
|
||||
}
|
||||
|
||||
void TestCsvParser::initTestCase()
|
||||
{
|
||||
parser.reset(new CsvParser());
|
||||
|
@ -30,9 +42,7 @@ void TestCsvParser::initTestCase()
|
|||
void TestCsvParser::init()
|
||||
{
|
||||
file.reset(new QTemporaryFile());
|
||||
if (not file->open()) {
|
||||
QFAIL("Cannot open file!");
|
||||
}
|
||||
|
||||
parser->setBackslashSyntax(false);
|
||||
parser->setComment('#');
|
||||
parser->setFieldSeparator(',');
|
||||
|
@ -47,36 +57,34 @@ void TestCsvParser::cleanup()
|
|||
/****************** TEST CASES ******************/
|
||||
void TestCsvParser::testMissingQuote()
|
||||
{
|
||||
writeToFile("A,B\n:BM,1");
|
||||
parser->setTextQualifier(':');
|
||||
QTextStream out(file.data());
|
||||
out << "A,B\n:BM,1";
|
||||
QEXPECT_FAIL("", "Bad format", Continue);
|
||||
QVERIFY(parser->parse(file.data()));
|
||||
t = parser->getCsvTable();
|
||||
|
||||
QVERIFY(!parser->parse(file.data()));
|
||||
QWARN(parser->getStatus().toLatin1());
|
||||
}
|
||||
|
||||
void TestCsvParser::testMalformed()
|
||||
{
|
||||
writeToFile("A,B,C\n:BM::,1,:2:");
|
||||
parser->setTextQualifier(':');
|
||||
QTextStream out(file.data());
|
||||
out << "A,B,C\n:BM::,1,:2:";
|
||||
QEXPECT_FAIL("", "Bad format", Continue);
|
||||
QVERIFY(parser->parse(file.data()));
|
||||
t = parser->getCsvTable();
|
||||
|
||||
QVERIFY(!parser->parse(file.data()));
|
||||
QWARN(parser->getStatus().toLatin1());
|
||||
}
|
||||
|
||||
void TestCsvParser::testBackslashSyntax()
|
||||
{
|
||||
// attended result: one"\t\"wo
|
||||
writeToFile("Xone\\\"\\\\t\\\\\\\"w\noX\n"
|
||||
"X13X,X2\\X,X,\"\"3\"X\r"
|
||||
"3,X\"4\"X,,\n"
|
||||
"XX\n"
|
||||
"\\");
|
||||
|
||||
parser->setBackslashSyntax(true);
|
||||
parser->setTextQualifier(QChar('X'));
|
||||
QTextStream out(file.data());
|
||||
// attended result: one"\t\"wo
|
||||
out << "Xone\\\"\\\\t\\\\\\\"w\noX\n"
|
||||
<< "X13X,X2\\X,X,\"\"3\"X\r" << "3,X\"4\"X,,\n"
|
||||
<< "XX\n"
|
||||
<< "\\";
|
||||
|
||||
QVERIFY(parser->parse(file.data()));
|
||||
t = parser->getCsvTable();
|
||||
QVERIFY(t.at(0).at(0) == "one\"\\t\\\"w\no");
|
||||
|
@ -93,9 +101,9 @@ void TestCsvParser::testBackslashSyntax()
|
|||
|
||||
void TestCsvParser::testQuoted()
|
||||
{
|
||||
QTextStream out(file.data());
|
||||
out << "ro,w,\"end, of \"\"\"\"\"\"row\"\"\"\"\"\n"
|
||||
<< "2\n";
|
||||
writeToFile("ro,w,\"end, of \"\"\"\"\"\"row\"\"\"\"\"\n"
|
||||
"2\n");
|
||||
|
||||
QVERIFY(parser->parse(file.data()));
|
||||
t = parser->getCsvTable();
|
||||
QVERIFY(t.at(0).at(0) == "ro");
|
||||
|
@ -107,8 +115,6 @@ void TestCsvParser::testQuoted()
|
|||
|
||||
void TestCsvParser::testEmptySimple()
|
||||
{
|
||||
QTextStream out(file.data());
|
||||
out << "";
|
||||
QVERIFY(parser->parse(file.data()));
|
||||
t = parser->getCsvTable();
|
||||
QVERIFY(t.isEmpty());
|
||||
|
@ -116,8 +122,8 @@ void TestCsvParser::testEmptySimple()
|
|||
|
||||
void TestCsvParser::testEmptyQuoted()
|
||||
{
|
||||
QTextStream out(file.data());
|
||||
out << "\"\"";
|
||||
writeToFile("\"\"");
|
||||
|
||||
QVERIFY(parser->parse(file.data()));
|
||||
t = parser->getCsvTable();
|
||||
QVERIFY(t.isEmpty());
|
||||
|
@ -125,8 +131,8 @@ void TestCsvParser::testEmptyQuoted()
|
|||
|
||||
void TestCsvParser::testEmptyNewline()
|
||||
{
|
||||
QTextStream out(file.data());
|
||||
out << "\"\n\"";
|
||||
writeToFile("\"\n\"");
|
||||
|
||||
QVERIFY(parser->parse(file.data()));
|
||||
t = parser->getCsvTable();
|
||||
QVERIFY(t.isEmpty());
|
||||
|
@ -141,8 +147,8 @@ void TestCsvParser::testEmptyFile()
|
|||
|
||||
void TestCsvParser::testNewline()
|
||||
{
|
||||
QTextStream out(file.data());
|
||||
out << "1,2\n\n\n";
|
||||
writeToFile("1,2\n\n\n");
|
||||
|
||||
QVERIFY(parser->parse(file.data()));
|
||||
t = parser->getCsvTable();
|
||||
QVERIFY(t.size() == 1);
|
||||
|
@ -152,8 +158,8 @@ void TestCsvParser::testNewline()
|
|||
|
||||
void TestCsvParser::testCR()
|
||||
{
|
||||
QTextStream out(file.data());
|
||||
out << "1,2\r3,4";
|
||||
writeToFile("1,2\r3,4");
|
||||
|
||||
QVERIFY(parser->parse(file.data()));
|
||||
t = parser->getCsvTable();
|
||||
QVERIFY(t.size() == 2);
|
||||
|
@ -165,8 +171,8 @@ void TestCsvParser::testCR()
|
|||
|
||||
void TestCsvParser::testLF()
|
||||
{
|
||||
QTextStream out(file.data());
|
||||
out << "1,2\n3,4";
|
||||
writeToFile("1,2\n3,4");
|
||||
|
||||
QVERIFY(parser->parse(file.data()));
|
||||
t = parser->getCsvTable();
|
||||
QVERIFY(t.size() == 2);
|
||||
|
@ -178,8 +184,8 @@ void TestCsvParser::testLF()
|
|||
|
||||
void TestCsvParser::testCRLF()
|
||||
{
|
||||
QTextStream out(file.data());
|
||||
out << "1,2\r\n3,4";
|
||||
writeToFile("1,2\r\n3,4");
|
||||
|
||||
QVERIFY(parser->parse(file.data()));
|
||||
t = parser->getCsvTable();
|
||||
QVERIFY(t.size() == 2);
|
||||
|
@ -191,11 +197,12 @@ void TestCsvParser::testCRLF()
|
|||
|
||||
void TestCsvParser::testComments()
|
||||
{
|
||||
QTextStream out(file.data());
|
||||
out << " #one\n"
|
||||
<< " \t # two, three \r\n"
|
||||
<< " #, sing\t with\r" << " #\t me!\n"
|
||||
<< "useful,text #1!";
|
||||
writeToFile(" #one\n"
|
||||
" \t # two, three \r\n"
|
||||
" #, sing\t with\r"
|
||||
" #\t me!\n"
|
||||
"useful,text #1!");
|
||||
|
||||
QVERIFY(parser->parse(file.data()));
|
||||
t = parser->getCsvTable();
|
||||
QVERIFY(t.size() == 1);
|
||||
|
@ -205,10 +212,10 @@ void TestCsvParser::testComments()
|
|||
|
||||
void TestCsvParser::testColumns()
|
||||
{
|
||||
QTextStream out(file.data());
|
||||
out << "1,2\n"
|
||||
<< ",,,,,,,,,a\n"
|
||||
<< "a,b,c,d\n";
|
||||
writeToFile("1,2\n"
|
||||
",,,,,,,,,a\n"
|
||||
"a,b,c,d\n");
|
||||
|
||||
QVERIFY(parser->parse(file.data()));
|
||||
t = parser->getCsvTable();
|
||||
QVERIFY(parser->getCsvCols() == 10);
|
||||
|
@ -216,10 +223,10 @@ void TestCsvParser::testColumns()
|
|||
|
||||
void TestCsvParser::testSimple()
|
||||
{
|
||||
QTextStream out(file.data());
|
||||
out << ",,2\r,2,3\n"
|
||||
<< "A,,B\"\n"
|
||||
<< " ,,\n";
|
||||
writeToFile(",,2\r,2,3\n"
|
||||
"A,,B\"\n"
|
||||
" ,,\n");
|
||||
|
||||
QVERIFY(parser->parse(file.data()));
|
||||
t = parser->getCsvTable();
|
||||
QVERIFY(t.size() == 4);
|
||||
|
@ -239,11 +246,12 @@ void TestCsvParser::testSimple()
|
|||
|
||||
void TestCsvParser::testSeparator()
|
||||
{
|
||||
writeToFile("\t\t2\r\t2\t3\n"
|
||||
"A\t\tB\"\n"
|
||||
" \t\t\n");
|
||||
|
||||
parser->setFieldSeparator('\t');
|
||||
QTextStream out(file.data());
|
||||
out << "\t\t2\r\t2\t3\n"
|
||||
<< "A\t\tB\"\n"
|
||||
<< " \t\t\n";
|
||||
|
||||
QVERIFY(parser->parse(file.data()));
|
||||
t = parser->getCsvTable();
|
||||
QVERIFY(t.size() == 4);
|
||||
|
@ -263,10 +271,11 @@ void TestCsvParser::testSeparator()
|
|||
|
||||
void TestCsvParser::testMultiline()
|
||||
{
|
||||
writeToFile(":1\r\n2a::b:,:3\r4:\n"
|
||||
"2\n");
|
||||
|
||||
parser->setTextQualifier(QChar(':'));
|
||||
QTextStream out(file.data());
|
||||
out << ":1\r\n2a::b:,:3\r4:\n"
|
||||
<< "2\n";
|
||||
|
||||
QVERIFY(parser->parse(file.data()));
|
||||
t = parser->getCsvTable();
|
||||
QVERIFY(t.at(0).at(0) == "1\n2a:b");
|
||||
|
@ -275,41 +284,34 @@ void TestCsvParser::testMultiline()
|
|||
QVERIFY(t.size() == 2);
|
||||
}
|
||||
|
||||
void TestCsvParser::testEmptyReparsing()
|
||||
{
|
||||
parser->parse(nullptr);
|
||||
QVERIFY(parser->reparse());
|
||||
t = parser->getCsvTable();
|
||||
QVERIFY(t.isEmpty());
|
||||
}
|
||||
|
||||
void TestCsvParser::testReparsing()
|
||||
{
|
||||
QTextStream out(file.data());
|
||||
out << ":te\r\nxt1:,:te\rxt2:,:end of \"this\n string\":\n"
|
||||
<< "2\n";
|
||||
writeToFile(":te\r\nxt1:,:te\rxt2:,:end of \"this\n string\":\n"
|
||||
"2\n");
|
||||
|
||||
QVERIFY(parser->parse(file.data()));
|
||||
t = parser->getCsvTable();
|
||||
|
||||
QEXPECT_FAIL("", "Wrong qualifier", Continue);
|
||||
QVERIFY(t.at(0).at(0) == "te\nxt1");
|
||||
QCOMPARE(t.at(0).at(0), QString(":te"));
|
||||
|
||||
parser->setTextQualifier(QChar(':'));
|
||||
|
||||
QVERIFY(parser->reparse());
|
||||
t = parser->getCsvTable();
|
||||
QVERIFY(t.at(0).at(0) == "te\nxt1");
|
||||
QVERIFY(t.at(0).at(1) == "te\nxt2");
|
||||
QVERIFY(t.at(0).at(2) == "end of \"this\n string\"");
|
||||
QVERIFY(t.at(1).at(0) == "2");
|
||||
QVERIFY(t.size() == 2);
|
||||
QCOMPARE(t.at(0).at(0), QString("te\nxt1"));
|
||||
QCOMPARE(t.at(0).at(1), QString("te\nxt2"));
|
||||
QCOMPARE(t.at(0).at(2), QString("end of \"this\n string\""));
|
||||
QCOMPARE(t.at(1).at(0), QString("2"));
|
||||
QCOMPARE(t.size(), 2);
|
||||
}
|
||||
|
||||
void TestCsvParser::testQualifier()
|
||||
{
|
||||
writeToFile("X1X,X2XX,X,\"\"3\"\"\"X\r"
|
||||
"3,X\"4\"X,,\n");
|
||||
|
||||
parser->setTextQualifier(QChar('X'));
|
||||
QTextStream out(file.data());
|
||||
out << "X1X,X2XX,X,\"\"3\"\"\"X\r" << "3,X\"4\"X,,\n";
|
||||
|
||||
QVERIFY(parser->parse(file.data()));
|
||||
t = parser->getCsvTable();
|
||||
QVERIFY(t.size() == 2);
|
||||
|
@ -328,10 +330,9 @@ void TestCsvParser::testUnicode()
|
|||
// CORRECT QString g("\u20AC");
|
||||
// CORRECT QChar g(0x20AC);
|
||||
// ERROR QChar g("\u20AC");
|
||||
writeToFile("€1A2śA\"3śAż\"Ażac");
|
||||
|
||||
parser->setFieldSeparator(QChar('A'));
|
||||
QTextStream out(file.data());
|
||||
out.setCodec("UTF-8");
|
||||
out << QString("€1A2śA\"3śAż\"Ażac");
|
||||
|
||||
QVERIFY(parser->parse(file.data()));
|
||||
t = parser->getCsvTable();
|
||||
|
|
|
@ -37,7 +37,6 @@ private slots:
|
|||
|
||||
void testUnicode();
|
||||
void testLF();
|
||||
void testEmptyReparsing();
|
||||
void testSimple();
|
||||
void testEmptyQuoted();
|
||||
void testEmptyNewline();
|
||||
|
@ -58,6 +57,8 @@ private slots:
|
|||
void testColumns();
|
||||
|
||||
private:
|
||||
void writeToFile(const QString& contents);
|
||||
|
||||
QScopedPointer<QTemporaryFile> file;
|
||||
QScopedPointer<CsvParser> parser;
|
||||
CsvTable t;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue