forked from qt-creator/qt-creator
C++: Add failing template-related tests to CheckSymbols
Runs much faster than plugin tests. Change-Id: Ie90d10c7d88b63f36bc00077af67d67e24cb4c50 Reviewed-by: Nikolai Kosjar <nikolai.kosjar@theqtcompany.com>
This commit is contained in:
committed by
Orgad Shaneh
parent
a7e456e8f0
commit
8a84a7305e
@@ -107,12 +107,10 @@ QT_END_NAMESPACE
|
||||
|
||||
namespace {
|
||||
|
||||
class TestCase
|
||||
class BaseTestCase
|
||||
{
|
||||
public:
|
||||
TestCase(const QByteArray &source,
|
||||
const UseList &expectedUsesAll,
|
||||
const UseList &expectedUsesMacros = UseList())
|
||||
BaseTestCase(const QByteArray &source, const UseList &expectedUsesMacros = UseList())
|
||||
{
|
||||
// Write source to temprorary file
|
||||
const QString filePath = QDir::tempPath() + QLatin1String("/file.h");
|
||||
@@ -124,29 +122,7 @@ public:
|
||||
snapshot.insert(document);
|
||||
|
||||
// Collect symbols
|
||||
CheckSymbols::Future future = runCheckSymbols(document, snapshot, expectedUsesMacros);
|
||||
|
||||
const int resultCount = future.resultCount();
|
||||
UseList actualUses;
|
||||
for (int i = 0; i < resultCount; ++i) {
|
||||
const Use use = future.resultAt(i);
|
||||
// When adding tests, you may want to uncomment the
|
||||
// following line in order to print out all found uses.
|
||||
// qDebug() << QTest::toString(use);
|
||||
actualUses.append(use);
|
||||
}
|
||||
|
||||
// Checks
|
||||
QVERIFY(resultCount > 0);
|
||||
QCOMPARE(resultCount, expectedUsesAll.count());
|
||||
|
||||
for (int i = 0; i < resultCount; ++i) {
|
||||
const Use actualUse = actualUses.at(i);
|
||||
const Use expectedUse = expectedUsesAll.at(i);
|
||||
QVERIFY(actualUse.isValid());
|
||||
QVERIFY(expectedUse.isValid());
|
||||
QCOMPARE(actualUse, expectedUse);
|
||||
}
|
||||
future = runCheckSymbols(document, snapshot, expectedUsesMacros);
|
||||
}
|
||||
|
||||
static CheckSymbols::Future runCheckSymbols(const Document::Ptr &document,
|
||||
@@ -176,6 +152,55 @@ public:
|
||||
|
||||
return document;
|
||||
}
|
||||
|
||||
Use findUse(unsigned line, unsigned column)
|
||||
{
|
||||
const int resultCount = future.resultCount();
|
||||
for (int i = resultCount - 1; i >= 0; --i) {
|
||||
Use result = future.resultAt(i);
|
||||
if (result.line > line)
|
||||
continue;
|
||||
if (result.line < line || result.column < column)
|
||||
break;
|
||||
if (result.column == column)
|
||||
return result;
|
||||
}
|
||||
return Use();
|
||||
}
|
||||
|
||||
CheckSymbols::Future future;
|
||||
};
|
||||
|
||||
class TestCase : public BaseTestCase
|
||||
{
|
||||
public:
|
||||
TestCase(const QByteArray &source,
|
||||
const UseList &expectedUsesAll,
|
||||
const UseList &expectedUsesMacros = UseList())
|
||||
: BaseTestCase(source, expectedUsesMacros)
|
||||
{
|
||||
const int resultCount = future.resultCount();
|
||||
UseList actualUses;
|
||||
for (int i = 0; i < resultCount; ++i) {
|
||||
const Use use = future.resultAt(i);
|
||||
// When adding tests, you may want to uncomment the
|
||||
// following line in order to print out all found uses.
|
||||
// qDebug() << QTest::toString(use);
|
||||
actualUses.append(use);
|
||||
}
|
||||
|
||||
// Checks
|
||||
QVERIFY(resultCount > 0);
|
||||
QCOMPARE(resultCount, expectedUsesAll.count());
|
||||
|
||||
for (int i = 0; i < resultCount; ++i) {
|
||||
const Use actualUse = actualUses.at(i);
|
||||
const Use expectedUse = expectedUsesAll.at(i);
|
||||
QVERIFY(actualUse.isValid());
|
||||
QVERIFY(expectedUse.isValid());
|
||||
QCOMPARE(actualUse, expectedUse);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
@@ -196,6 +221,9 @@ private slots:
|
||||
void test_checksymbols_infiniteLoop();
|
||||
|
||||
void test_parentOfBlock();
|
||||
|
||||
void findField();
|
||||
void findField_data();
|
||||
};
|
||||
|
||||
void tst_CheckSymbols::test_checksymbols()
|
||||
@@ -1086,11 +1114,7 @@ void tst_CheckSymbols::test_parentOfBlock()
|
||||
"{\n"
|
||||
" enum E { e1 };\n"
|
||||
"}\n";
|
||||
|
||||
const Document::Ptr document = TestCase::createDocument(QLatin1String("file1.cpp"), source);
|
||||
Snapshot snapshot;
|
||||
snapshot.insert(document);
|
||||
TestCase::runCheckSymbols(document, snapshot);
|
||||
BaseTestCase tc(source);
|
||||
}
|
||||
|
||||
void tst_CheckSymbols::test_checksymbols_infiniteLoop_data()
|
||||
@@ -1165,5 +1189,194 @@ void tst_CheckSymbols::test_checksymbols_infiniteLoop_data()
|
||||
;
|
||||
}
|
||||
|
||||
void tst_CheckSymbols::findField()
|
||||
{
|
||||
QFETCH(QByteArray, source);
|
||||
|
||||
int position = source.indexOf('@');
|
||||
QVERIFY(position != -1);
|
||||
QByteArray truncated = source;
|
||||
truncated.truncate(position);
|
||||
const unsigned line = truncated.count('\n') + 1;
|
||||
const unsigned column = position - truncated.lastIndexOf('\n', position) + 1;
|
||||
source[position] = ' ';
|
||||
BaseTestCase tc(source);
|
||||
Use use = tc.findUse(line, column);
|
||||
QEXPECT_FAIL("pointer_indirect_specialization", "QTCREATORBUG-14141", Abort);
|
||||
QEXPECT_FAIL("pointer_indirect_specialization_typedef", "QTCREATORBUG-14141", Abort);
|
||||
QEXPECT_FAIL("pointer_indirect_specialization_double_indirection", "QTCREATORBUG-14141", Abort);
|
||||
QEXPECT_FAIL("instantiation_of_pointer_typedef_in_block", "QTCREATORBUG-14141", Abort);
|
||||
QEXPECT_FAIL("pointer_indirect_specialization_double_indirection_with_base", "QTCREATORBUG-14141", Abort);
|
||||
QEXPECT_FAIL("recursive_instantiation_of_template_type", "QTCREATORBUG-14237", Abort);
|
||||
QEXPECT_FAIL("recursive_instantiation_of_template_type_2", "QTCREATORBUG-14141", Abort);
|
||||
QVERIFY(use.isValid());
|
||||
QVERIFY(use.kind == Highlighting::FieldUse);
|
||||
}
|
||||
|
||||
void tst_CheckSymbols::findField_data()
|
||||
{
|
||||
QTest::addColumn<QByteArray>("source");
|
||||
|
||||
QTest::newRow("pointer_indirect_specialization") << _(
|
||||
"template<typename T>\n"
|
||||
"struct Traits { typedef typename T::pointer pointer; };\n"
|
||||
"\n"
|
||||
"template<typename _Tp>\n"
|
||||
"struct Traits<_Tp*> { typedef _Tp *pointer; };\n"
|
||||
"\n"
|
||||
"template<typename T>\n"
|
||||
"class Temp\n"
|
||||
"{\n"
|
||||
"protected:\n"
|
||||
" typedef Traits<T> TraitsT;\n"
|
||||
"\n"
|
||||
"public:\n"
|
||||
" typedef typename TraitsT::pointer pointer;\n"
|
||||
" pointer p;\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"struct Foo { int bar; };\n"
|
||||
"\n"
|
||||
"void func()\n"
|
||||
"{\n"
|
||||
" Temp<Foo *> t;\n"
|
||||
" t.p->@bar;\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
QTest::newRow("pointer_indirect_specialization_typedef") << _(
|
||||
"template<typename T>\n"
|
||||
"struct Traits { typedef typename T::pointer pointer; };\n"
|
||||
"\n"
|
||||
"template<typename _Tp>\n"
|
||||
"struct Traits<_Tp*> { typedef _Tp *pointer; };\n"
|
||||
"\n"
|
||||
"struct Foo { int bar; };\n"
|
||||
"\n"
|
||||
"class Temp\n"
|
||||
"{\n"
|
||||
"protected:\n"
|
||||
" typedef Foo *FooPtr;\n"
|
||||
" typedef Traits<FooPtr> TraitsT;\n"
|
||||
"\n"
|
||||
"public:\n"
|
||||
" typedef typename TraitsT::pointer pointer;\n"
|
||||
" pointer p;\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"void func()\n"
|
||||
"{\n"
|
||||
" Temp t;\n"
|
||||
" t.p->@bar;\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
QTest::newRow("instantiation_of_pointer_typedef_in_block") << _(
|
||||
"template<typename _Tp>\n"
|
||||
"struct Temp { _Tp p; };\n"
|
||||
"\n"
|
||||
"struct Foo { int bar; };\n"
|
||||
"\n"
|
||||
"void func()\n"
|
||||
"{\n"
|
||||
" typedef Foo *pointer;\n"
|
||||
" Temp<pointer> t;\n"
|
||||
" t.p->@bar;\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
QTest::newRow("pointer_indirect_specialization_double_indirection") << _(
|
||||
"template<typename _Tp>\n"
|
||||
"struct Traits { };\n"
|
||||
"\n"
|
||||
"template<typename _Tp>\n"
|
||||
"struct Traits<_Tp*> { typedef _Tp *pointer; };\n"
|
||||
"\n"
|
||||
"struct Foo { int bar; };\n"
|
||||
"\n"
|
||||
"template<typename _Tp>\n"
|
||||
"struct IndirectT\n"
|
||||
"{\n"
|
||||
" typedef Traits<_Tp> TraitsT;\n"
|
||||
" typedef typename TraitsT::pointer pointer;\n"
|
||||
" pointer p;\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"template<typename _Tp>\n"
|
||||
"struct Temp\n"
|
||||
"{\n"
|
||||
" typedef _Tp *pointer;\n"
|
||||
" typedef IndirectT<pointer> indirect;\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"void func()\n"
|
||||
"{\n"
|
||||
" Temp<Foo>::indirect t;\n"
|
||||
" t.p->@bar;\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
QTest::newRow("pointer_indirect_specialization_double_indirection_with_base") << _(
|
||||
"template<typename _Tp>\n"
|
||||
"struct Traits { };\n"
|
||||
"\n"
|
||||
"template<typename _Tp>\n"
|
||||
"struct Traits<_Tp*> { typedef _Tp *pointer; };\n"
|
||||
"\n"
|
||||
"struct Foo { int bar; };\n"
|
||||
"\n"
|
||||
"template<typename _Tp>\n"
|
||||
"struct IndirectT\n"
|
||||
"{\n"
|
||||
" typedef Traits<_Tp> TraitsT;\n"
|
||||
" typedef typename TraitsT::pointer pointer;\n"
|
||||
" pointer p;\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"template<typename _Tp>\n"
|
||||
"struct TempBase { typedef _Tp *pointer; };\n"
|
||||
"\n"
|
||||
"template<typename _Tp>\n"
|
||||
"struct Temp : public TempBase<_Tp>\n"
|
||||
"{\n"
|
||||
" typedef TempBase<_Tp> _Base;\n"
|
||||
" typedef typename _Base::pointer pointer;\n"
|
||||
" typedef IndirectT<pointer> indirect;\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"void func()\n"
|
||||
"{\n"
|
||||
" Temp<Foo>::indirect t;\n"
|
||||
" t.p->@bar;\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
QTest::newRow("recursive_instantiation_of_template_type") << _(
|
||||
"template<typename _Tp>\n"
|
||||
"struct Temp { typedef _Tp value_type; };\n"
|
||||
"\n"
|
||||
"struct Foo { int bar; };\n"
|
||||
"\n"
|
||||
"void func()\n"
|
||||
"{\n"
|
||||
" Temp<Temp<Foo> >::value_type::value_type *p;\n"
|
||||
" p->@bar;\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
QTest::newRow("recursive_instantiation_of_template_type_2") << _(
|
||||
"template<typename _Tp>\n"
|
||||
"struct Temp { typedef _Tp value_type; };\n"
|
||||
"\n"
|
||||
"struct Foo { int bar; };\n"
|
||||
"\n"
|
||||
"void func()\n"
|
||||
"{\n"
|
||||
" Temp<Temp<Foo>::value_type>::value_type *p;\n"
|
||||
" p->@bar;\n"
|
||||
"}\n"
|
||||
);
|
||||
}
|
||||
|
||||
QTEST_APPLESS_MAIN(tst_CheckSymbols)
|
||||
#include "tst_checksymbols.moc"
|
||||
|
Reference in New Issue
Block a user