TestAutoType.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. /*
  2. * Copyright (C) 2012 Felix Geyer <debfx@fobos.de>
  3. * Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 2 or (at your option)
  8. * version 3 of the License.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include "TestAutoType.h"
  19. #include <QPluginLoader>
  20. #include <QTest>
  21. #include "autotype/AutoType.h"
  22. #include "autotype/AutoTypePlatformPlugin.h"
  23. #include "autotype/test/AutoTypeTestInterface.h"
  24. #include "core/Config.h"
  25. #include "core/Group.h"
  26. #include "core/Resources.h"
  27. #include "crypto/Crypto.h"
  28. #include "gui/MessageBox.h"
  29. #include "gui/osutils/OSUtils.h"
  30. #include "util/TemporaryFile.h"
  31. QTEST_GUILESS_MAIN(TestAutoType)
  32. void TestAutoType::initTestCase()
  33. {
  34. QVERIFY(Crypto::init());
  35. // Create temporary config file
  36. Config::createConfigFromFile(TemporaryFile::createTempConfigFile(), {});
  37. config()->set(Config::AutoTypeDelay, 1);
  38. config()->set(Config::Security_AutoTypeAsk, false);
  39. AutoType::createTestInstance();
  40. QPluginLoader loader(resources()->pluginPath("keepassxc-autotype-test"));
  41. loader.setLoadHints(QLibrary::ResolveAllSymbolsHint);
  42. QVERIFY(loader.instance());
  43. m_platform = qobject_cast<AutoTypePlatformInterface*>(loader.instance());
  44. QVERIFY(m_platform);
  45. m_test = qobject_cast<AutoTypeTestInterface*>(loader.instance());
  46. QVERIFY(m_test);
  47. m_autoType = AutoType::instance();
  48. }
  49. void TestAutoType::init()
  50. {
  51. config()->set(Config::AutoTypeEntryTitleMatch, false);
  52. m_test->clearActions();
  53. m_db = QSharedPointer<Database>::create();
  54. m_dbList.clear();
  55. m_dbList.append(m_db);
  56. m_group = m_db->rootGroup();
  57. AutoTypeAssociations::Association association;
  58. m_entry1 = new Entry();
  59. m_entry1->setGroup(m_group);
  60. m_entry1->setUsername("myuser");
  61. m_entry1->setPassword("mypass");
  62. association.window = "custom window";
  63. association.sequence = "{username}association{password}";
  64. m_entry1->autoTypeAssociations()->add(association);
  65. m_entry2 = new Entry();
  66. m_entry2->setGroup(m_group);
  67. m_entry2->setPassword("myuser");
  68. m_entry2->setTitle("entry title");
  69. m_entry3 = new Entry();
  70. m_entry3->setGroup(m_group);
  71. m_entry3->setPassword("regex");
  72. association.window = "//REGEX1//";
  73. association.sequence = "regex1";
  74. m_entry3->autoTypeAssociations()->add(association);
  75. association.window = "//^REGEX2$//";
  76. association.sequence = "regex2";
  77. m_entry3->autoTypeAssociations()->add(association);
  78. association.window = "//^REGEX3-([rd]\\d){2}$//";
  79. association.sequence = "regex3";
  80. m_entry3->autoTypeAssociations()->add(association);
  81. m_entry4 = new Entry();
  82. m_entry4->setGroup(m_group);
  83. m_entry4->setPassword("custom_attr");
  84. m_entry4->attributes()->set("CUSTOM", "Attribute", false);
  85. m_entry4->attributes()->set("CustomAttrFirst", "AttrValueFirst", false);
  86. m_entry4->attributes()->set("CustomAttrSecond", "AttrValueSecond", false);
  87. m_entry4->attributes()->set("CustomAttrThird", "AttrValueThird", false);
  88. association.window = "//^CustomAttr1$//";
  89. association.sequence = "{PASSWORD}:{S:CUSTOM}";
  90. m_entry4->autoTypeAssociations()->add(association);
  91. association.window = "//^CustomAttr2$//";
  92. association.sequence = "{S:CuStOm}";
  93. m_entry4->autoTypeAssociations()->add(association);
  94. association.window = "//^CustomAttr3$//";
  95. association.sequence = "{PaSSworD}";
  96. m_entry4->autoTypeAssociations()->add(association);
  97. association.window = "//^{S:CustomAttrFirst}$//";
  98. association.sequence = "custom_attr_first";
  99. m_entry4->autoTypeAssociations()->add(association);
  100. association.window = "//{S:CustomAttrFirst}And{S:CustomAttrSecond}//";
  101. association.sequence = "custom_attr_first_and_second";
  102. m_entry4->autoTypeAssociations()->add(association);
  103. association.window = "//{S:CustomAttrThird}//";
  104. association.sequence = "custom_attr_third";
  105. m_entry4->autoTypeAssociations()->add(association);
  106. m_entry5 = new Entry();
  107. m_entry5->setGroup(m_group);
  108. m_entry5->setPassword("example5");
  109. m_entry5->setTitle("some title");
  110. m_entry5->setUrl("http://example.org");
  111. }
  112. void TestAutoType::cleanup()
  113. {
  114. }
  115. void TestAutoType::testInternal()
  116. {
  117. QVERIFY(m_platform->activeWindowTitle().isEmpty());
  118. m_test->setActiveWindowTitle("Test");
  119. QCOMPARE(m_platform->activeWindowTitle(), QString("Test"));
  120. }
  121. void TestAutoType::testSingleAutoType()
  122. {
  123. m_autoType->performAutoType(m_entry1);
  124. QCOMPARE(m_test->actionCount(), 14);
  125. QCOMPARE(m_test->actionChars(),
  126. QString("myuser%1mypass%2").arg(m_test->keyToString(Qt::Key_Tab)).arg(m_test->keyToString(Qt::Key_Enter)));
  127. }
  128. void TestAutoType::testGlobalAutoTypeWithNoMatch()
  129. {
  130. m_test->setActiveWindowTitle("nomatch");
  131. MessageBox::setNextAnswer(MessageBox::Ok);
  132. m_autoType->performGlobalAutoType(m_dbList);
  133. QCOMPARE(m_test->actionChars(), QString());
  134. }
  135. void TestAutoType::testGlobalAutoTypeWithOneMatch()
  136. {
  137. m_test->setActiveWindowTitle("custom window");
  138. emit osUtils->globalShortcutTriggered("autotype");
  139. m_autoType->performGlobalAutoType(m_dbList);
  140. QCOMPARE(m_test->actionChars(), QString("%1association%2").arg(m_entry1->username()).arg(m_entry1->password()));
  141. }
  142. void TestAutoType::testGlobalAutoTypeTitleMatch()
  143. {
  144. config()->set(Config::AutoTypeEntryTitleMatch, true);
  145. m_test->setActiveWindowTitle("An Entry Title!");
  146. emit osUtils->globalShortcutTriggered("autotype");
  147. m_autoType->performGlobalAutoType(m_dbList);
  148. QCOMPARE(m_test->actionChars(), QString("%1%2").arg(m_entry2->password(), m_test->keyToString(Qt::Key_Enter)));
  149. }
  150. void TestAutoType::testGlobalAutoTypeUrlMatch()
  151. {
  152. config()->set(Config::AutoTypeEntryTitleMatch, true);
  153. m_test->setActiveWindowTitle("Dummy - http://example.org/ - <My Browser>");
  154. emit osUtils->globalShortcutTriggered("autotype");
  155. m_autoType->performGlobalAutoType(m_dbList);
  156. QCOMPARE(m_test->actionChars(), QString("%1%2").arg(m_entry5->password(), m_test->keyToString(Qt::Key_Enter)));
  157. }
  158. void TestAutoType::testGlobalAutoTypeUrlSubdomainMatch()
  159. {
  160. config()->set(Config::AutoTypeEntryTitleMatch, true);
  161. m_test->setActiveWindowTitle("Dummy - http://sub.example.org/ - <My Browser>");
  162. emit osUtils->globalShortcutTriggered("autotype");
  163. m_autoType->performGlobalAutoType(m_dbList);
  164. QCOMPARE(m_test->actionChars(), QString("%1%2").arg(m_entry5->password(), m_test->keyToString(Qt::Key_Enter)));
  165. }
  166. void TestAutoType::testGlobalAutoTypeTitleMatchDisabled()
  167. {
  168. m_test->setActiveWindowTitle("An Entry Title!");
  169. emit osUtils->globalShortcutTriggered("autotype");
  170. MessageBox::setNextAnswer(MessageBox::Ok);
  171. m_autoType->performGlobalAutoType(m_dbList);
  172. QCOMPARE(m_test->actionChars(), QString());
  173. }
  174. void TestAutoType::testGlobalAutoTypeRegExp()
  175. {
  176. // substring matches are ok
  177. m_test->setActiveWindowTitle("lorem REGEX1 ipsum");
  178. emit osUtils->globalShortcutTriggered("autotype");
  179. m_autoType->performGlobalAutoType(m_dbList);
  180. QCOMPARE(m_test->actionChars(), QString("regex1"));
  181. m_test->clearActions();
  182. // should be case-insensitive
  183. m_test->setActiveWindowTitle("lorem regex1 ipsum");
  184. emit osUtils->globalShortcutTriggered("autotype");
  185. m_autoType->performGlobalAutoType(m_dbList);
  186. QCOMPARE(m_test->actionChars(), QString("regex1"));
  187. m_test->clearActions();
  188. // exact match
  189. m_test->setActiveWindowTitle("REGEX2");
  190. emit osUtils->globalShortcutTriggered("autotype");
  191. m_autoType->performGlobalAutoType(m_dbList);
  192. QCOMPARE(m_test->actionChars(), QString("regex2"));
  193. m_test->clearActions();
  194. // a bit more complicated regex
  195. m_test->setActiveWindowTitle("REGEX3-R2D2");
  196. emit osUtils->globalShortcutTriggered("autotype");
  197. m_autoType->performGlobalAutoType(m_dbList);
  198. QCOMPARE(m_test->actionChars(), QString("regex3"));
  199. m_test->clearActions();
  200. // with custom attributes
  201. m_test->setActiveWindowTitle("CustomAttr1");
  202. emit osUtils->globalShortcutTriggered("autotype");
  203. m_autoType->performGlobalAutoType(m_dbList);
  204. QCOMPARE(m_test->actionChars(), QString("custom_attr:Attribute"));
  205. m_test->clearActions();
  206. // with (non uppercase) undefined custom attributes
  207. m_test->setActiveWindowTitle("CustomAttr2");
  208. emit osUtils->globalShortcutTriggered("autotype");
  209. m_autoType->performGlobalAutoType(m_dbList);
  210. QCOMPARE(m_test->actionChars(), QString(""));
  211. m_test->clearActions();
  212. // with mixedcase default attributes
  213. m_test->setActiveWindowTitle("CustomAttr3");
  214. emit osUtils->globalShortcutTriggered("autotype");
  215. m_autoType->performGlobalAutoType(m_dbList);
  216. QCOMPARE(m_test->actionChars(), QString("custom_attr"));
  217. m_test->clearActions();
  218. // with resolve placeholders in window association title
  219. m_test->setActiveWindowTitle("AttrValueFirst");
  220. emit osUtils->globalShortcutTriggered("autotype");
  221. m_autoType->performGlobalAutoType(m_dbList);
  222. QCOMPARE(m_test->actionChars(), QString("custom_attr_first"));
  223. m_test->clearActions();
  224. m_test->setActiveWindowTitle("lorem AttrValueFirstAndAttrValueSecond ipsum");
  225. emit osUtils->globalShortcutTriggered("autotype");
  226. m_autoType->performGlobalAutoType(m_dbList);
  227. QCOMPARE(m_test->actionChars(), QString("custom_attr_first_and_second"));
  228. m_test->clearActions();
  229. m_test->setActiveWindowTitle("lorem AttrValueThird ipsum");
  230. emit osUtils->globalShortcutTriggered("autotype");
  231. m_autoType->performGlobalAutoType(m_dbList);
  232. QCOMPARE(m_test->actionChars(), QString("custom_attr_third"));
  233. m_test->clearActions();
  234. }
  235. void TestAutoType::testAutoTypeResults()
  236. {
  237. QScopedPointer<Entry> entry(new Entry());
  238. entry->setUsername("Username");
  239. entry->setPassword("Password@1");
  240. entry->setUrl("https://example.com");
  241. entry->attributes()->set("attr1", "value1");
  242. entry->attributes()->set("attr2", "decode%20me");
  243. QFETCH(QString, sequence);
  244. QFETCH(QString, expectedResult);
  245. m_autoType->performAutoTypeWithSequence(entry.data(), sequence);
  246. QCOMPARE(m_test->actionChars(), expectedResult);
  247. }
  248. void TestAutoType::testAutoTypeResults_data()
  249. {
  250. QTest::addColumn<QString>("sequence");
  251. QTest::addColumn<QString>("expectedResult");
  252. // Normal Sequences
  253. QTest::newRow("Sequence with Attributes") << QString("{USERNAME} {PASSWORD} {URL} {S:attr1}")
  254. << QString("Username Password@1 https://example.com value1");
  255. QTest::newRow("Sequence with Comment") << QString("{USERNAME}{TAB}{C:Extra Tab}{TAB}{S:attr1}")
  256. << QString("Username[Key0x1000001][Key0x1000001]value1");
  257. // Conversions and Replacements
  258. QTest::newRow("T-CONV UPPER") << QString("{T-CONV:/{USERNAME}/UPPER/}") << QString("USERNAME");
  259. QTest::newRow("T-CONV LOWER") << QString("{T-CONV:/{USERNAME}/LOWER/}") << QString("username");
  260. QTest::newRow("T-CONV BASE64") << QString("{T-CONV:/{USERNAME}/BASE64/}") << QString("VXNlcm5hbWU=");
  261. QTest::newRow("T-CONV HEX") << QString("{T-CONV:/{USERNAME}/HEX/}") << QString("557365726e616d65");
  262. QTest::newRow("T-CONV URI ENCODE") << QString("{T-CONV:/{URL}/URI/}") << QString("https%3A%2F%2Fexample.com");
  263. QTest::newRow("T-CONV URI DECODE") << QString("{T-CONV:/{S:attr2}/URI-DEC/}") << QString("decode me");
  264. QTest::newRow("T-REPLACE-RX") << QString("{T-REPLACE-RX:/{USERNAME}/(User)/$1Pass/}") << QString("UserPassname");
  265. }
  266. void TestAutoType::testAutoTypeSyntaxChecks()
  267. {
  268. auto entry = new Entry();
  269. QString error;
  270. // Huge sequence
  271. QVERIFY2(AutoType::verifyAutoTypeSyntax(
  272. "{F1 23}{~ 23}{% 23}{^}{F12}{(}{) 23}{[}{[}{]}{Delay=23}{+}{SUBTRACT}~+%@fixedstring", entry, error),
  273. error.toLatin1());
  274. QVERIFY2(AutoType::verifyAutoTypeSyntax("{NUMPAD1 3}", entry, error), error.toLatin1());
  275. QVERIFY2(AutoType::verifyAutoTypeSyntax("{S:SPECIALTOKEN}", entry, error), error.toLatin1());
  276. QVERIFY2(AutoType::verifyAutoTypeSyntax("{S:SPECIAL TOKEN}", entry, error), error.toLatin1());
  277. QVERIFY2(AutoType::verifyAutoTypeSyntax("{S:SPECIAL_TOKEN}", entry, error), error.toLatin1());
  278. QVERIFY2(AutoType::verifyAutoTypeSyntax("{S:SPECIAL-TOKEN}", entry, error), error.toLatin1());
  279. QVERIFY2(AutoType::verifyAutoTypeSyntax("{S:SPECIAL:TOKEN}", entry, error), error.toLatin1());
  280. QVERIFY2(AutoType::verifyAutoTypeSyntax("{S:SPECIAL_TOKEN}{ENTER}", entry, error), error.toLatin1());
  281. QVERIFY2(AutoType::verifyAutoTypeSyntax("{S:FOO}{S:HELLO WORLD}", entry, error), error.toLatin1());
  282. QVERIFY2(!AutoType::verifyAutoTypeSyntax("{S:SPECIAL_TOKEN{}}", entry, error), error.toLatin1());
  283. QVERIFY2(AutoType::verifyAutoTypeSyntax("{BEEP 3 3}", entry, error), error.toLatin1());
  284. QVERIFY2(AutoType::verifyAutoTypeSyntax("{BEEP 3}", entry, error), error.toLatin1());
  285. QVERIFY2(AutoType::verifyAutoTypeSyntax("{VKEY 0x01}", entry, error), error.toLatin1());
  286. QVERIFY2(AutoType::verifyAutoTypeSyntax("{VKEY VK_LBUTTON}", entry, error), error.toLatin1());
  287. QVERIFY2(AutoType::verifyAutoTypeSyntax("{VKEY-EX 0x01}", entry, error), error.toLatin1());
  288. // Bad sequence
  289. QVERIFY2(!AutoType::verifyAutoTypeSyntax("{{{}}{}{}}{{}}", entry, error), error.toLatin1());
  290. // Good sequence
  291. QVERIFY2(AutoType::verifyAutoTypeSyntax("{{}{}}{}}{{}", entry, error), error.toLatin1());
  292. QVERIFY2(AutoType::verifyAutoTypeSyntax("{]}{[}{[}{]}", entry, error), error.toLatin1());
  293. QVERIFY2(AutoType::verifyAutoTypeSyntax("{)}{(}{(}{)}", entry, error), error.toLatin1());
  294. // High delay
  295. QVERIFY2(!AutoType::verifyAutoTypeSyntax("{DELAY 50000}", entry, error), error.toLatin1());
  296. QVERIFY2(AutoType::verifyAutoTypeSyntax("{delay 50}", entry, error), error.toLatin1());
  297. // Slow typing
  298. QVERIFY2(!AutoType::verifyAutoTypeSyntax("{DELAY=50000}", entry, error), error.toLatin1());
  299. QVERIFY2(AutoType::verifyAutoTypeSyntax("{delay=50}", entry, error), error.toLatin1());
  300. // Many repetition
  301. QVERIFY2(!AutoType::verifyAutoTypeSyntax("{LEFT 50000000}", entry, error), error.toLatin1());
  302. QVERIFY2(AutoType::verifyAutoTypeSyntax("{SPACE 10}{TAB 3}{RIGHT 50}", entry, error), error.toLatin1());
  303. QVERIFY2(AutoType::verifyAutoTypeSyntax("{delay 5000000000}", entry, error), error.toLatin1());
  304. // Conversion and Regex
  305. QVERIFY2(AutoType::verifyAutoTypeSyntax("{T-CONV:/{USERNAME}/base64/}", entry, error), error.toLatin1());
  306. QVERIFY2(!AutoType::verifyAutoTypeSyntax("{T-CONV:/{USERNAME}/junk/}", entry, error), error.toLatin1());
  307. QVERIFY2(!AutoType::verifyAutoTypeSyntax("{T-CONV:}", entry, error), error.toLatin1());
  308. QVERIFY2(AutoType::verifyAutoTypeSyntax("{T-REPLACE-RX:/{USERNAME}/a/b/}", entry, error), error.toLatin1());
  309. QVERIFY2(!AutoType::verifyAutoTypeSyntax("{T-REPLACE-RX:/{USERNAME}/a/}", entry, error), error.toLatin1());
  310. QVERIFY2(!AutoType::verifyAutoTypeSyntax("{T-REPLACE-RX:}", entry, error), error.toLatin1());
  311. }
  312. void TestAutoType::testAutoTypeEffectiveSequences()
  313. {
  314. QString defaultSequence("{USERNAME}{TAB}{PASSWORD}{ENTER}");
  315. QString sequenceG1("{TEST_GROUP1}");
  316. QString sequenceG3("{TEST_GROUP3}");
  317. QString sequenceE2("{TEST_ENTRY2}");
  318. QString sequenceDisabled("{TEST_DISABLED}");
  319. QString sequenceOrphan("{TEST_ORPHAN}");
  320. QScopedPointer<Database> db(new Database());
  321. QPointer<Group> rootGroup = db->rootGroup();
  322. // Group with autotype enabled and custom default sequence
  323. QPointer<Group> group1 = new Group();
  324. group1->setParent(rootGroup);
  325. group1->setDefaultAutoTypeSequence(sequenceG1);
  326. // Child group with inherit
  327. QPointer<Group> group2 = new Group();
  328. group2->setParent(group1);
  329. // Group with autotype disabled and custom default sequence
  330. QPointer<Group> group3 = new Group();
  331. group3->setParent(group1);
  332. group3->setAutoTypeEnabled(Group::Disable);
  333. group3->setDefaultAutoTypeSequence(sequenceG3);
  334. QCOMPARE(rootGroup->defaultAutoTypeSequence(), QString());
  335. QCOMPARE(rootGroup->effectiveAutoTypeSequence(), defaultSequence);
  336. QCOMPARE(group1->defaultAutoTypeSequence(), sequenceG1);
  337. QCOMPARE(group1->effectiveAutoTypeSequence(), sequenceG1);
  338. QCOMPARE(group2->defaultAutoTypeSequence(), QString());
  339. QCOMPARE(group2->effectiveAutoTypeSequence(), sequenceG1);
  340. QCOMPARE(group3->defaultAutoTypeSequence(), sequenceG3);
  341. QCOMPARE(group3->effectiveAutoTypeSequence(), QString());
  342. // Entry from root group
  343. QPointer<Entry> entry1 = new Entry();
  344. entry1->setGroup(rootGroup);
  345. // Entry with custom default sequence
  346. QPointer<Entry> entry2 = new Entry();
  347. entry2->setDefaultAutoTypeSequence(sequenceE2);
  348. entry2->setGroup(rootGroup);
  349. // Entry from enabled child group
  350. QPointer<Entry> entry3 = new Entry();
  351. entry3->setGroup(group2);
  352. // Entry from disabled group
  353. QPointer<Entry> entry4 = new Entry();
  354. entry4->setDefaultAutoTypeSequence(sequenceDisabled);
  355. entry4->setGroup(group3);
  356. // Entry from enabled group with disabled autotype
  357. QPointer<Entry> entry5 = new Entry();
  358. entry5->setGroup(group2);
  359. entry5->setDefaultAutoTypeSequence(sequenceDisabled);
  360. entry5->setAutoTypeEnabled(false);
  361. // Entry with no parent
  362. QScopedPointer<Entry> entry6(new Entry());
  363. entry6->setDefaultAutoTypeSequence(sequenceOrphan);
  364. QCOMPARE(entry1->defaultAutoTypeSequence(), QString());
  365. QCOMPARE(entry1->effectiveAutoTypeSequence(), defaultSequence);
  366. QCOMPARE(entry2->defaultAutoTypeSequence(), sequenceE2);
  367. QCOMPARE(entry2->effectiveAutoTypeSequence(), sequenceE2);
  368. QCOMPARE(entry3->defaultAutoTypeSequence(), QString());
  369. QCOMPARE(entry3->effectiveAutoTypeSequence(), sequenceG1);
  370. QCOMPARE(entry4->defaultAutoTypeSequence(), sequenceDisabled);
  371. QCOMPARE(entry4->effectiveAutoTypeSequence(), QString());
  372. QCOMPARE(entry5->defaultAutoTypeSequence(), sequenceDisabled);
  373. QCOMPARE(entry5->effectiveAutoTypeSequence(), QString());
  374. QCOMPARE(entry6->defaultAutoTypeSequence(), sequenceOrphan);
  375. QCOMPARE(entry6->effectiveAutoTypeSequence(), QString());
  376. }