TestAutoType.cpp 18 KB

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