Advertisement
Guest User

Untitled

a guest
Jul 19th, 2018
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 29.79 KB | None | 0 0
  1. /*jshint globalstrict:false, strict:false, unused: false */
  2. /*global fail, assertEqual, assertTrue, assertFalse, assertNull, assertNotNull, arango, ARGUMENTS */
  3.  
  4. ////////////////////////////////////////////////////////////////////////////////
  5. /// @brief test the global replication
  6. ///
  7. /// @file
  8. ///
  9. /// DISCLAIMER
  10. ///
  11. /// Copyright 2017 ArangoDB GmbH, Cologne, Germany
  12. ///
  13. /// Licensed under the Apache License, Version 2.0 (the "License");
  14. /// you may not use this file except in compliance with the License.
  15. /// You may obtain a copy of the License at
  16. ///
  17. /// http://www.apache.org/licenses/LICENSE-2.0
  18. ///
  19. /// Unless required by applicable law or agreed to in writing, software
  20. /// distributed under the License is distributed on an "AS IS" BASIS,
  21. /// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  22. /// See the License for the specific language governing permissions and
  23. /// limitations under the License.
  24. ///
  25. /// Copyright holder is ArangoDB GmbH, Cologne, Germany
  26. ///
  27. /// @author Michael Hackstein
  28. /// @author Copyright 2017, ArangoDB GmbH, Cologne, Germany
  29. ////////////////////////////////////////////////////////////////////////////////
  30.  
  31. const jsunity = require("jsunity");
  32. const arangodb = require("@arangodb");
  33. const errors = arangodb.errors;
  34. const db = arangodb.db;
  35.  
  36. const replication = require("@arangodb/replication");
  37. const compareTicks = replication.compareTicks;
  38. const console = require("console");
  39. const internal = require("internal");
  40.  
  41. const masterEndpoint = arango.getEndpoint();
  42. const slaveEndpoint = ARGUMENTS[0];
  43.  
  44. const cn = "UnitTestsReplication";
  45. const cn2 = "UnitTestsReplication2";
  46.  
  47. const connectToMaster = function() {
  48. arango.reconnect(masterEndpoint, db._name(), "root", "");
  49. db._flushCache();
  50. };
  51.  
  52. const connectToSlave = function() {
  53. arango.reconnect(slaveEndpoint, db._name(), "root", "");
  54. db._flushCache();
  55. };
  56.  
  57. const collectionChecksum = function(name) {
  58. var c = db._collection(name).checksum(true, true);
  59. return c.checksum;
  60. };
  61.  
  62. const collectionCount = function(name) {
  63. return db._collection(name).count();
  64. };
  65.  
  66. const compare = function(masterFunc, masterFunc2, slaveFuncOngoing, slaveFuncFinal, applierConfiguration) {
  67. var state = {};
  68.  
  69. db._flushCache();
  70. masterFunc(state);
  71.  
  72. connectToSlave();
  73. replication.globalApplier.stop();
  74. replication.globalApplier.forget();
  75.  
  76. while (replication.globalApplier.state().state.running) {
  77. internal.wait(0.1, false);
  78. }
  79.  
  80. applierConfiguration = applierConfiguration || {};
  81. applierConfiguration.endpoint = masterEndpoint;
  82. applierConfiguration.username = "root";
  83. applierConfiguration.password = "";
  84. applierConfiguration.includeSystem = false;
  85. applierConfiguration.force32mode = false;
  86.  
  87. var syncResult = replication.syncGlobal({
  88. endpoint: masterEndpoint,
  89. username: "root",
  90. password: "",
  91. verbose: true,
  92. includeSystem: false,
  93. keepBarrier: false,
  94. restrictType: applierConfiguration.restrictType,
  95. restrictCollections: applierConfiguration.restrictCollections
  96. });
  97.  
  98. assertTrue(syncResult.hasOwnProperty('lastLogTick'));
  99.  
  100. connectToMaster();
  101. masterFunc2(state);
  102.  
  103. // use lastLogTick as of now
  104. state.lastLogTick = replication.logger.state().state.lastLogTick;
  105.  
  106. if (!applierConfiguration.hasOwnProperty('chunkSize')) {
  107. applierConfiguration.chunkSize = 16384;
  108. }
  109.  
  110. connectToSlave();
  111.  
  112. replication.globalApplier.properties(applierConfiguration);
  113. replication.globalApplier.start(syncResult.lastLogTick);
  114.  
  115. var printed = false, handled = false;
  116.  
  117. while (true) {
  118. if (!handled) {
  119. var r = slaveFuncOngoing(state);
  120. if (r === "wait") {
  121. // special return code that tells us to hang on
  122. internal.wait(0.5, false);
  123. continue;
  124. }
  125.  
  126. handled = true;
  127. }
  128.  
  129. var slaveState = replication.globalApplier.state();
  130.  
  131. if (slaveState.state.lastError.errorNum > 0) {
  132. console.log("slave has errored:", JSON.stringify(slaveState.state.lastError));
  133. break;
  134. }
  135.  
  136. if (!slaveState.state.running) {
  137. console.log("slave is not running");
  138. break;
  139. }
  140. if (compareTicks(slaveState.state.lastAppliedContinuousTick, state.lastLogTick) >= 0 ||
  141. compareTicks(slaveState.state.lastProcessedContinuousTick, state.lastLogTick) >= 0) { // ||
  142. // compareTicks(slaveState.state.lastAvailableContinuousTick, syncResult.lastLogTick) > 0) {
  143. console.log("slave has caught up. state.lastLogTick:", state.lastLogTick, "slaveState.lastAppliedContinuousTick:", slaveState.state.lastAppliedContinuousTick, "slaveState.lastProcessedContinuousTick:", slaveState.state.lastProcessedContinuousTick);
  144. break;
  145. }
  146.  
  147. if (!printed) {
  148. console.log("waiting for slave to catch up");
  149. printed = true;
  150. }
  151. internal.wait(0.5, false);
  152. }
  153.  
  154. db._flushCache();
  155. slaveFuncFinal(state);
  156. };
  157.  
  158. ////////////////////////////////////////////////////////////////////////////////
  159. /// @brief Base Test Config. Identitical part for _system and other DB
  160. ////////////////////////////////////////////////////////////////////////////////
  161.  
  162. function BaseTestConfig() {
  163. 'use strict';
  164.  
  165. return {
  166.  
  167. testIncludeCollection: function() {
  168. connectToMaster();
  169.  
  170. compare(
  171. function(state) {
  172. },
  173.  
  174. function(state) {
  175. db._create(cn);
  176. db._create(cn + "2");
  177. for (var i = 0; i < 100; ++i) {
  178. db._collection(cn).save({ value: i });
  179. db._collection(cn + "2").save({ value: i });
  180. }
  181. internal.wal.flush(true, true);
  182. },
  183.  
  184. function(state) {
  185. return true;
  186. },
  187.  
  188. function(state) {
  189. assertTrue(db._collection(cn).count() === 100);
  190. assertNull(db._collection(cn + "2"));
  191. },
  192.  
  193. { restrictType: "include", restrictCollections: [cn] }
  194. );
  195. },
  196.  
  197. testExcludeCollection: function() {
  198. connectToMaster();
  199.  
  200. compare(
  201. function(state) {
  202. },
  203.  
  204. function(state) {
  205. db._create(cn);
  206. db._create(cn + "2");
  207. for (var i = 0; i < 100; ++i) {
  208. db._collection(cn).save({ value: i });
  209. db._collection(cn + "2").save({ value: i });
  210. }
  211. internal.wal.flush(true, true);
  212. },
  213.  
  214. function(state) {
  215. return true;
  216. },
  217.  
  218. function(state) {
  219. assertTrue(db._collection(cn).count() === 100);
  220. assertNull(db._collection(cn + "2"));
  221. },
  222.  
  223. { restrictType: "exclude", restrictCollections: [cn + "2"] }
  224. );
  225. },
  226.  
  227. ////////////////////////////////////////////////////////////////////////////////
  228. /// @brief test collection creation
  229. ////////////////////////////////////////////////////////////////////////////////
  230.  
  231. testCreateCollection: function() {
  232. connectToMaster();
  233.  
  234. compare(
  235. function(state) {
  236. },
  237.  
  238. function(state) {
  239. db._create(cn);
  240. for (var i = 0; i < 100; ++i) {
  241. db._collection(cn).save({
  242. value: i
  243. });
  244. }
  245. internal.wal.flush(true, true);
  246. },
  247.  
  248. function(state) {
  249. return true;
  250. },
  251.  
  252. function(state) {
  253. assertTrue(db._collection(cn).count() === 100);
  254. }
  255. );
  256. },
  257.  
  258. ////////////////////////////////////////////////////////////////////////////////
  259. /// @brief test collection dropping
  260. ////////////////////////////////////////////////////////////////////////////////
  261.  
  262. testDropCollection: function() {
  263. connectToMaster();
  264.  
  265. compare(
  266. function(state) {
  267. },
  268.  
  269. function(state) {
  270. db._create(cn);
  271. for (var i = 0; i < 100; ++i) {
  272. db._collection(cn).save({
  273. value: i
  274. });
  275. }
  276. db._drop(cn);
  277. internal.wal.flush(true, true);
  278. },
  279.  
  280. function(state) {
  281. return true;
  282. },
  283.  
  284. function(state) {
  285. assertNull(db._collection(cn));
  286. }
  287. );
  288. },
  289.  
  290. ////////////////////////////////////////////////////////////////////////////////
  291. /// @brief test index creation
  292. ////////////////////////////////////////////////////////////////////////////////
  293.  
  294. testCreateIndex: function() {
  295. connectToMaster();
  296.  
  297. compare(
  298. function(state) {
  299. },
  300.  
  301. function(state) {
  302. db._create(cn);
  303. db._collection(cn).ensureIndex({ type: "hash", fields: ["value"] });
  304. },
  305.  
  306. function(state) {
  307. return true;
  308. },
  309.  
  310. function(state) {
  311. var col = db._collection(cn);
  312. assertNotNull(col, "collection does not exist");
  313. var idx = col.getIndexes();
  314. assertEqual(2, idx.length);
  315. assertEqual("primary", idx[0].type);
  316. assertEqual("hash", idx[1].type);
  317. assertEqual(["value"], idx[1].fields);
  318. }
  319. );
  320. },
  321.  
  322. ////////////////////////////////////////////////////////////////////////////////
  323. /// @brief test index dropping
  324. ////////////////////////////////////////////////////////////////////////////////
  325.  
  326. testDropIndex: function() {
  327. connectToMaster();
  328.  
  329. compare(
  330. function(state) {
  331. },
  332.  
  333. function(state) {
  334. db._create(cn);
  335. var idx = db._collection(cn).ensureIndex({ type: "hash", fields: ["value"] });
  336. db._collection(cn).dropIndex(idx);
  337. },
  338.  
  339. function(state) {
  340. return true;
  341. },
  342.  
  343. function(state) {
  344. var idx = db._collection(cn).getIndexes();
  345. assertEqual(1, idx.length);
  346. assertEqual("primary", idx[0].type);
  347. }
  348. );
  349. },
  350.  
  351. ////////////////////////////////////////////////////////////////////////////////
  352. /// @brief test renaming
  353. ////////////////////////////////////////////////////////////////////////////////
  354.  
  355. testRenameCollection: function() {
  356. connectToMaster();
  357.  
  358. compare(
  359. function(state) {
  360. },
  361.  
  362. function(state) {
  363. db._create(cn);
  364. db._collection(cn).rename(cn + "Renamed");
  365. },
  366.  
  367. function(state) {
  368. return true;
  369. },
  370.  
  371. function(state) {
  372. assertNull(db._collection(cn));
  373. assertNotNull(db._collection(cn + "Renamed"));
  374. }
  375. );
  376. },
  377.  
  378. ////////////////////////////////////////////////////////////////////////////////
  379. /// @brief test renaming
  380. ////////////////////////////////////////////////////////////////////////////////
  381.  
  382. testChangeCollection: function() {
  383. connectToMaster();
  384.  
  385. compare(
  386. function(state) {
  387. },
  388.  
  389. function(state) {
  390. db._create(cn);
  391. assertFalse(db._collection(cn).properties().waitForSync);
  392. db._collection(cn).properties({ waitForSync: true });
  393. },
  394.  
  395. function(state) {
  396. return true;
  397. },
  398.  
  399. function(state) {
  400. assertTrue(db._collection(cn).properties().waitForSync);
  401. }
  402. );
  403. },
  404.  
  405. ////////////////////////////////////////////////////////////////////////////////
  406. /// @brief test long transaction, blocking
  407. ////////////////////////////////////////////////////////////////////////////////
  408.  
  409. testLongTransactionBlocking: function() {
  410. connectToMaster();
  411.  
  412. compare(
  413. function(state) {
  414. db._create(cn);
  415. },
  416.  
  417. function(state) {
  418. db._executeTransaction({
  419. collections: {
  420. write: cn
  421. },
  422. action: function(params) {
  423. var wait = require("internal").wait;
  424. var db = require("internal").db;
  425. var c = db._collection(params.cn);
  426.  
  427. for (var i = 0; i < 10; ++i) {
  428. c.save({
  429. test1: i,
  430. type: "longTransactionBlocking",
  431. coll: "UnitTestsReplication"
  432. });
  433. c.save({
  434. test2: i,
  435. type: "longTransactionBlocking",
  436. coll: "UnitTestsReplication"
  437. });
  438.  
  439. // intentionally delay the transaction
  440. wait(0.75, false);
  441. }
  442. },
  443. params: {
  444. cn: cn
  445. }
  446. });
  447.  
  448. state.checksum = collectionChecksum(cn);
  449. state.count = collectionCount(cn);
  450. assertEqual(20, state.count);
  451. },
  452.  
  453. function(state) {
  454. // stop and restart replication on the slave
  455. assertTrue(replication.globalApplier.state().state.running);
  456. replication.globalApplier.stop();
  457. assertFalse(replication.globalApplier.state().state.running);
  458.  
  459. internal.wait(0.5, false);
  460. replication.globalApplier.start();
  461. internal.wait(0.5, false);
  462. assertTrue(replication.globalApplier.state().state.running);
  463.  
  464. return true;
  465. },
  466.  
  467. function(state) {
  468. internal.wait(3, false);
  469. assertEqual(state.count, collectionCount(cn));
  470. assertEqual(state.checksum, collectionChecksum(cn));
  471. }
  472. );
  473. },
  474.  
  475. ////////////////////////////////////////////////////////////////////////////////
  476. /// @brief test long transaction, asynchronous
  477. ////////////////////////////////////////////////////////////////////////////////
  478.  
  479. testLongTransactionAsync: function() {
  480. connectToMaster();
  481.  
  482. compare(
  483. function(state) {
  484. db._create(cn);
  485. },
  486.  
  487. function(state) {
  488. var func = db._executeTransaction({
  489. collections: {
  490. write: cn
  491. },
  492. action: function(params) {
  493. var wait = require("internal").wait;
  494. var db = require("internal").db;
  495. var c = db._collection(params.cn);
  496.  
  497. for (var i = 0; i < 10; ++i) {
  498. c.save({
  499. test1: i,
  500. type: "longTransactionAsync",
  501. coll: "UnitTestsReplication"
  502. });
  503. c.save({
  504. test2: i,
  505. type: "longTransactionAsync",
  506. coll: "UnitTestsReplication"
  507. });
  508.  
  509. // intentionally delay the transaction
  510. wait(3.0, false);
  511. }
  512. },
  513. params: {
  514. cn: cn
  515. }
  516. });
  517.  
  518. state.task = require("@arangodb/tasks").register({
  519. name: "replication-test-async",
  520. command: String(func),
  521. params: {
  522. cn: cn
  523. }
  524. }).id;
  525. },
  526.  
  527. function(state) {
  528. assertTrue(replication.globalApplier.state().state.running);
  529.  
  530. connectToMaster();
  531. try {
  532. require("@arangodb/tasks").get(state.task);
  533. // task exists
  534. connectToSlave();
  535. return "wait";
  536. } catch (err) {
  537. // task does not exist. we're done
  538. state.lastLogTick = replication.logger.state().state.lastLogTick;
  539. state.checksum = collectionChecksum(cn);
  540. state.count = collectionCount(cn);
  541. assertEqual(20, state.count);
  542. connectToSlave();
  543. return true;
  544. }
  545. },
  546.  
  547. function(state) {
  548. assertTrue(state.hasOwnProperty("count"));
  549. assertEqual(state.count, collectionCount(cn));
  550. }
  551. );
  552. },
  553.  
  554. ////////////////////////////////////////////////////////////////////////////////
  555. /// @brief test long transaction, asynchronous
  556. ////////////////////////////////////////////////////////////////////////////////
  557.  
  558. testLongTransactionAsyncWithSlaveRestarts: function() {
  559. connectToMaster();
  560.  
  561. compare(
  562. function(state) {
  563. db._create(cn);
  564. },
  565.  
  566. function(state) {
  567. var func = db._executeTransaction({
  568. collections: {
  569. write: cn
  570. },
  571. action: function(params) {
  572. var wait = require("internal").wait;
  573. var db = require("internal").db;
  574. var c = db._collection(params.cn);
  575.  
  576. for (var i = 0; i < 10; ++i) {
  577. c.save({
  578. test1: i,
  579. type: "longTransactionAsyncWithSlaveRestarts",
  580. coll: "UnitTestsReplication"
  581. });
  582. c.save({
  583. test2: i,
  584. type: "longTransactionAsyncWithSlaveRestarts",
  585. coll: "UnitTestsReplication"
  586. });
  587.  
  588. // intentionally delay the transaction
  589. wait(0.75, false);
  590. }
  591. },
  592. params: {
  593. cn: cn
  594. }
  595. });
  596.  
  597. state.task = require("@arangodb/tasks").register({
  598. name: "replication-test-async-with-restart",
  599. command: String(func),
  600. params: {
  601. cn: cn
  602. }
  603. }).id;
  604. },
  605.  
  606. function(state) {
  607. // stop and restart replication on the slave
  608. assertTrue(replication.globalApplier.state().state.running);
  609. replication.globalApplier.stop();
  610. assertFalse(replication.globalApplier.state().state.running);
  611.  
  612. connectToMaster();
  613. try {
  614. require("@arangodb/tasks").get(state.task);
  615. // task exists
  616. connectToSlave();
  617.  
  618. internal.wait(0.5, false);
  619. replication.globalApplier.start();
  620. assertTrue(replication.globalApplier.state().state.running);
  621. return "wait";
  622. } catch (err) {
  623. // task does not exist anymore. we're done
  624. state.lastLogTick = replication.logger.state().state.lastLogTick;
  625. state.checksum = collectionChecksum(cn);
  626. state.count = collectionCount(cn);
  627. assertEqual(20, state.count);
  628. connectToSlave();
  629. replication.globalApplier.start();
  630. assertTrue(replication.globalApplier.state().state.running);
  631. return true;
  632. }
  633. },
  634.  
  635. function(state) {
  636. assertEqual(state.count, collectionCount(cn));
  637. }
  638. );
  639. },
  640.  
  641. testViewBasic: function() {
  642. connectToMaster();
  643.  
  644. compare(
  645. function() {},
  646. function(state) {
  647. try {
  648. db._create(cn);
  649. let view = db._createView("UnitTestsSyncView", "arangosearch", {});
  650. let links = {};
  651. links[cn] = {
  652. includeAllFields: true,
  653. fields: {
  654. text: { analyzers: [ "text_en" ] }
  655. }
  656. };
  657. view.properties({"links": links});
  658. state.arangoSearchEnabled = true;
  659. } catch (err) { }
  660. },
  661. function() {},
  662. function(state) {
  663. if (!state.arangoSearchEnabled) {
  664. return;
  665. }
  666.  
  667. let view = db._view("UnitTestsSyncView");
  668. assertTrue(view !== null);
  669. let props = view.properties();
  670. assertEqual(Object.keys(props.links).length, 1);
  671. assertTrue(props.hasOwnProperty("links"));
  672. assertTrue(props.links.hasOwnProperty(cn));
  673. },
  674. {}
  675. );
  676. },
  677.  
  678. testViewRename: function() {
  679. connectToMaster();
  680.  
  681. compare(
  682. function(state) {
  683. try {
  684. db._create(cn);
  685. let view = db._createView("UnitTestsSyncView", "arangosearch", {});
  686. let links = {};
  687. links[cn] = {
  688. includeAllFields: true,
  689. fields: {
  690. text: { analyzers: [ "text_en" ] }
  691. }
  692. };
  693. view.properties({"links": links});
  694. state.arangoSearchEnabled = true;
  695. } catch (err) { }
  696. },
  697. function(state) {
  698. if (!state.arangoSearchEnabled) {
  699. return;
  700. }
  701. // rename view on master
  702. let view = db._view("UnitTestsSyncView");
  703. view.rename("UnitTestsSyncViewRenamed");
  704. view = db._view("UnitTestsSyncViewRenamed");
  705. assertTrue(view !== null);
  706. let props = view.properties();
  707. assertEqual(Object.keys(props.links).length, 1);
  708. assertTrue(props.hasOwnProperty("links"));
  709. assertTrue(props.links.hasOwnProperty(cn));
  710. },
  711. function(state) {},
  712. function(state) {
  713. if (!state.arangoSearchEnabled) {
  714. return;
  715. }
  716.  
  717. let view = db._view("UnitTestsSyncViewRenamed");
  718. assertTrue(view !== null);
  719. let props = view.properties();
  720. assertEqual(Object.keys(props.links).length, 1);
  721. assertTrue(props.hasOwnProperty("links"));
  722. assertTrue(props.links.hasOwnProperty(cn));
  723. },
  724. {}
  725. );
  726. }
  727.  
  728. };
  729. }
  730.  
  731. ////////////////////////////////////////////////////////////////////////////////
  732. /// @brief test suite for _system
  733. ////////////////////////////////////////////////////////////////////////////////
  734.  
  735. function ReplicationSuite() {
  736. 'use strict';
  737. let suite = BaseTestConfig();
  738.  
  739. ////////////////////////////////////////////////////////////////////////////////
  740. /// @brief set up
  741. ////////////////////////////////////////////////////////////////////////////////
  742.  
  743. suite.setUp = function() {
  744. connectToSlave();
  745. try {
  746. replication.global.stop();
  747. replication.global.forget();
  748. }
  749. catch (err) {
  750. }
  751.  
  752. connectToMaster();
  753.  
  754. db._drop(cn);
  755. db._drop(cn2);
  756. db._drop(cn + "Renamed");
  757. };
  758.  
  759. ////////////////////////////////////////////////////////////////////////////////
  760. /// @brief tear down
  761. ////////////////////////////////////////////////////////////////////////////////
  762.  
  763. suite.tearDown = function() {
  764. connectToMaster();
  765.  
  766. db._drop(cn);
  767. db._drop(cn2);
  768. db._dropView("UnitTestsSyncView");
  769.  
  770. connectToSlave();
  771. replication.globalApplier.stop();
  772. replication.globalApplier.forget();
  773.  
  774. db._drop(cn);
  775. db._drop(cn2);
  776. db._drop(cn + "Renamed");
  777. db._dropView("UnitTestsSyncViewRenamed");
  778. };
  779.  
  780. return suite;
  781. }
  782.  
  783. ////////////////////////////////////////////////////////////////////////////////
  784. /// @brief test suite for other database
  785. ////////////////////////////////////////////////////////////////////////////////
  786.  
  787. function ReplicationOtherDBSuite() {
  788. 'use strict';
  789. let suite = BaseTestConfig();
  790. const dbName = "UnitTestDB";
  791.  
  792. // Setup documents to be stored on the master.
  793.  
  794. let docs = [];
  795. for (let i = 0; i < 50; ++i) {
  796. docs.push({value: i});
  797. }
  798.  
  799. ////////////////////////////////////////////////////////////////////////////////
  800. /// @brief set up
  801. ////////////////////////////////////////////////////////////////////////////////
  802.  
  803. suite.setUp = function() {
  804. db._useDatabase("_system");
  805. connectToSlave();
  806. try {
  807. replication.globalApplier.stop();
  808. replication.globalApplier.forget();
  809. } catch (err) {
  810. }
  811.  
  812. try {
  813. db._dropDatabase(dbName);
  814. } catch (e) {
  815. }
  816.  
  817. db._createDatabase(dbName);
  818.  
  819. connectToMaster();
  820.  
  821. try {
  822. db._dropDatabase(dbName);
  823. } catch (e) {
  824. }
  825. db._createDatabase(dbName);
  826. db._useDatabase(dbName);
  827. };
  828.  
  829. ////////////////////////////////////////////////////////////////////////////////
  830. /// @brief tear down
  831. ////////////////////////////////////////////////////////////////////////////////
  832.  
  833. suite.tearDown = function() {
  834. db._useDatabase("_system");
  835.  
  836. connectToSlave();
  837. db._useDatabase(dbName);
  838.  
  839. replication.globalApplier.stop();
  840. replication.globalApplier.forget();
  841.  
  842. db._useDatabase("_system");
  843. try {
  844. db._dropDatabase(dbName);
  845. } catch (e) {
  846. }
  847.  
  848. connectToMaster();
  849.  
  850. db._useDatabase("_system");
  851. try {
  852. db._dropDatabase(dbName);
  853. } catch (e) {
  854. }
  855.  
  856. };
  857.  
  858. // Shared function that sets up replication
  859. // of the collection and inserts 50 documents.
  860. const setupReplication = function() {
  861. // Section - Master
  862. connectToMaster();
  863.  
  864. // Create the collection
  865. db._flushCache();
  866. db._create(cn);
  867.  
  868. // Section - Follower
  869. connectToSlave();
  870.  
  871. // Setup Replication
  872. replication.globalApplier.stop();
  873. replication.globalApplier.forget();
  874.  
  875. while (replication.globalApplier.state().state.running) {
  876. internal.wait(0.1, false);
  877. }
  878.  
  879. let config = {
  880. endpoint: masterEndpoint,
  881. username: "root",
  882. password: "",
  883. verbose: true,
  884. includeSystem: false,
  885. restrictType: "",
  886. restrictCollections: [],
  887. keepBarrier: false
  888. };
  889.  
  890. replication.setupReplicationGlobal(config);
  891.  
  892. // Section - Master
  893. connectToMaster();
  894. // Insert some documents
  895. db._collection(cn).save(docs);
  896. // Flush wal to trigger replication
  897. internal.wal.flush(true, true);
  898. internal.wait(6, false);
  899. // Use counter as indicator
  900. let count = collectionCount(cn);
  901. assertEqual(50, count);
  902.  
  903. // Section - Slave
  904. connectToSlave();
  905.  
  906. // Give it some time to sync
  907. internal.wait(6, false);
  908. // Now we should have the same amount of documents
  909. assertEqual(count, collectionCount(cn));
  910. };
  911.  
  912. ////////////////////////////////////////////////////////////////////////////////
  913. /// @brief test dropping a database on slave while replication is ongoing
  914. ////////////////////////////////////////////////////////////////////////////////
  915.  
  916. suite.testDropDatabaseOnSlaveDuringReplication = function() {
  917. setupReplication();
  918.  
  919. // Section - Slave
  920. connectToSlave();
  921.  
  922. assertTrue(replication.globalApplier.state().state.running);
  923.  
  924. // Now do the evil stuff: drop the database that is replicating right now.
  925. db._useDatabase("_system");
  926.  
  927. // This shall not fail.
  928. db._dropDatabase(dbName);
  929.  
  930. // Section - Master
  931. connectToMaster();
  932.  
  933. // Just write some more
  934. db._useDatabase(dbName);
  935. db._collection(cn).save(docs);
  936. internal.wal.flush(true, true);
  937. internal.wait(6, false);
  938.  
  939. db._useDatabase("_system");
  940.  
  941. // Section - Slave
  942. connectToSlave();
  943.  
  944. // The DB should be gone and the server should be running.
  945. let dbs = db._databases();
  946. assertEqual(-1, dbs.indexOf(dbName));
  947.  
  948. // We can setup everything here without problems.
  949. try {
  950. db._createDatabase(dbName);
  951. } catch (e) {
  952. assertFalse(true, "Could not recreate database on slave: " + e);
  953. }
  954.  
  955. db._useDatabase(dbName);
  956.  
  957. try {
  958. db._createDocumentCollection(cn);
  959. } catch (e) {
  960. assertFalse(true, "Could not recreate collection on slave: " + e);
  961. }
  962.  
  963. // Collection should be empty
  964. assertEqual(0, collectionCount(cn));
  965.  
  966. // now test if the replication is actually
  967. // switched off
  968.  
  969. // Section - Master
  970. connectToMaster();
  971. // Insert some documents
  972. db._collection(cn).save(docs);
  973. // Flush wal to trigger replication
  974. internal.wal.flush(true, true);
  975.  
  976. // Section - Slave
  977. connectToSlave();
  978.  
  979. // Give it some time to sync (eventually, should not do anything...)
  980. internal.wait(6, false);
  981.  
  982. // Now should still have empty collection
  983. assertEqual(0, collectionCount(cn));
  984.  
  985. assertFalse(replication.globalApplier.state().state.running);
  986. };
  987.  
  988. suite.testDropDatabaseOnMasterDuringReplication = function() {
  989. var waitUntil = function(cb) {
  990. var tries = 0;
  991. while (tries++ < 60 * 2) {
  992. if (cb()) {
  993. return;
  994. }
  995. internal.wait(0.5, false);
  996. }
  997. assertFalse(true, "required condition not satisified: " + String(cb));
  998. };
  999.  
  1000. setupReplication();
  1001.  
  1002. db._useDatabase("_system");
  1003. connectToSlave();
  1004. // wait until database is present on slave as well
  1005. waitUntil(function() { return (db._databases().indexOf(dbName) !== -1); });
  1006.  
  1007. // Section - Master
  1008. // Now do the evil stuff: drop the database that is replicating from right now.
  1009. connectToMaster();
  1010. // This shall not fail.
  1011. db._dropDatabase(dbName);
  1012.  
  1013. db._useDatabase("_system");
  1014. connectToSlave();
  1015. waitUntil(function() { return (db._databases().indexOf(dbName) === -1); });
  1016.  
  1017. // Now recreate a new database with this name
  1018. connectToMaster();
  1019. db._createDatabase(dbName);
  1020.  
  1021. db._useDatabase(dbName);
  1022. db._createDocumentCollection(cn);
  1023. db._collection(cn).save(docs);
  1024.  
  1025. // Section - Slave
  1026. db._useDatabase("_system");
  1027. connectToSlave();
  1028. waitUntil(function() { return (db._databases().indexOf(dbName) !== -1); });
  1029. // database now present on slave
  1030.  
  1031. // Now test if the Slave did replicate the new database...
  1032. db._useDatabase(dbName);
  1033. // wait for collection to appear
  1034. waitUntil(function() {
  1035. let cc = db._collection(cn);
  1036. return cc !== null && cc.count() >= 50;
  1037. });
  1038. assertEqual(50, collectionCount(cn), "The slave inserted the new collection data into the old one, it skipped the drop.");
  1039.  
  1040. assertTrue(replication.globalApplier.state().state.running);
  1041. };
  1042.  
  1043. return suite;
  1044. }
  1045.  
  1046. ////////////////////////////////////////////////////////////////////////////////
  1047. /// @brief executes the test suite
  1048. ////////////////////////////////////////////////////////////////////////////////
  1049.  
  1050. jsunity.run(ReplicationSuite);
  1051. jsunity.run(ReplicationOtherDBSuite);
  1052.  
  1053. // TODO Add test for:
  1054. // Accessing globalApplier in non system database.
  1055. // Try to setup global repliaction in non system database.
  1056.  
  1057. return jsunity.done();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement