summaryrefslogtreecommitdiffstats
path: root/services/sync/tests/unit/test_tab_engine.js
blob: 0492502306aae4ff801887c60c9212f39df8d307 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/* Any copyright is dedicated to the Public Domain.
   http://creativecommons.org/publicdomain/zero/1.0/ */

Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/engines/tabs.js");
Cu.import("resource://services-sync/record.js");
Cu.import("resource://services-sync/service.js");
Cu.import("resource://services-sync/util.js");
Cu.import("resource://testing-common/services/sync/utils.js");

function getMocks() {
  let engine = new TabEngine(Service);
  let store = engine._store;
  store.getTabState = mockGetTabState;
  store.shouldSkipWindow = mockShouldSkipWindow;
  return [engine, store];
}

function run_test() {
  run_next_test();
}

add_test(function test_getOpenURLs() {
  _("Test getOpenURLs.");
  let [engine, store] = getMocks();

  let superLongURL = "http://" + (new Array(MAX_UPLOAD_BYTES).join("w")) + ".com/";
  let urls = ["http://bar.com", "http://foo.com", "http://foobar.com", superLongURL];
  function fourURLs() {
    return urls.pop();
  }
  store.getWindowEnumerator = mockGetWindowEnumerator.bind(this, fourURLs, 1, 4);

  let matches;

  _("  test matching works (true)");
  let openurlsset = engine.getOpenURLs();
  matches = openurlsset.has("http://foo.com");
  ok(matches);

  _("  test matching works (false)");
  matches = openurlsset.has("http://barfoo.com");
  ok(!matches);

  _("  test matching works (too long)");
  matches = openurlsset.has(superLongURL);
  ok(!matches);

  run_next_test();
});

add_test(function test_tab_engine_skips_incoming_local_record() {
  _("Ensure incoming records that match local client ID are never applied.");
  let [engine, store] = getMocks();
  let localID = engine.service.clientsEngine.localID;
  let apply = store.applyIncoming;
  let applied = [];

  store.applyIncoming = function (record) {
    notEqual(record.id, localID, "Only apply tab records from remote clients");
    applied.push(record);
    apply.call(store, record);
  }

  let collection = new ServerCollection();

  _("Creating remote tab record with local client ID");
  let localRecord = encryptPayload({id: localID, clientName: "local"});
  collection.insert(localID, localRecord);

  _("Creating remote tab record with a different client ID");
  let remoteID = "different";
  let remoteRecord = encryptPayload({id: remoteID, clientName: "not local"});
  collection.insert(remoteID, remoteRecord);

  _("Setting up Sync server");
  let server = sync_httpd_setup({
      "/1.1/foo/storage/tabs": collection.handler()
  });

  let syncTesting = new SyncTestingInfrastructure(server);
  Service.identity.username = "foo";

  let meta_global = Service.recordManager.set(engine.metaURL,
                                              new WBORecord(engine.metaURL));
  meta_global.payload.engines = {tabs: {version: engine.version,
                                        syncID: engine.syncID}};

  generateNewKeys(Service.collectionKeys);

  let syncFinish = engine._syncFinish;
  engine._syncFinish = function () {
    equal(applied.length, 1, "Remote client record was applied");
    equal(applied[0].id, remoteID, "Remote client ID matches");

    syncFinish.call(engine);
    run_next_test();
  }

  _("Start sync");
  engine._sync();
});

add_test(function test_reconcile() {
  let [engine, store] = getMocks();

  _("Setup engine for reconciling");
  engine._syncStartup();

  _("Create an incoming remote record");
  let remoteRecord = {id: "remote id",
                      cleartext: "stuff and things!",
                      modified: 1000};

  ok(engine._reconcile(remoteRecord), "Apply a recently modified remote record");

  remoteRecord.modified = 0;
  ok(engine._reconcile(remoteRecord), "Apply a remote record modified long ago");

  // Remote tab records are never tracked locally, so the only
  // time they're skipped is when they're marked as deleted.
  remoteRecord.deleted = true;
  ok(!engine._reconcile(remoteRecord), "Skip a deleted remote record");

  _("Create an incoming local record");
  // The locally tracked tab record always takes precedence over its
  // remote counterparts.
  let localRecord = {id: engine.service.clientsEngine.localID,
                     cleartext: "this should always be skipped",
                     modified: 2000};

  ok(!engine._reconcile(localRecord), "Skip incoming local if recently modified");

  localRecord.modified = 0;
  ok(!engine._reconcile(localRecord), "Skip incoming local if modified long ago");

  localRecord.deleted = true;
  ok(!engine._reconcile(localRecord), "Skip incoming local if deleted");

  run_next_test();
});