summaryrefslogtreecommitdiffstats
path: root/toolkit/components/telemetry/tests/unit/test_MigratePendingPings.js
blob: bb618bb8daaf16d42353a3af0a6d24356ecc3b0f (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
142
143
144
145
146
147
148
149
150
151
152
153
/* Any copyright is dedicated to the Public Domain.
   http://creativecommons.org/publicdomain/zero/1.0/
*/

"use strict";

const { TelemetryStorage } = ChromeUtils.importESModule(
  "resource://gre/modules/TelemetryStorage.sys.mjs"
);
const { TelemetryUtils } = ChromeUtils.importESModule(
  "resource://gre/modules/TelemetryUtils.sys.mjs"
);
const { makeFakeAppDir } = ChromeUtils.importESModule(
  "resource://testing-common/AppData.sys.mjs"
);

// The name of the pending pings directory outside of the user profile,
// in the user app data directory.
const PENDING_PING_DIR_NAME = "Pending Pings";

// Create a directory inside the profile and register it as UAppData, so
// we can stick fake crash pings inside there. We put it inside the profile
// just because we know that will get cleaned up after the test runs.
async function createFakeAppDir() {
  // Create "<profile>/UAppData/Pending Pings".
  const pendingPingsPath = PathUtils.join(
    PathUtils.profileDir,
    "UAppData",
    PENDING_PING_DIR_NAME
  );
  await IOUtils.makeDirectory(pendingPingsPath, {
    ignoreExisting: true,
    createAncestors: true,
  });

  await makeFakeAppDir();
}

add_task(async function setup() {
  // Init the profile.
  do_get_profile();
  await createFakeAppDir();
  // Make sure we don't generate unexpected pings due to pref changes.
  await setEmptyPrefWatchlist();
});

add_task(async function test_migrateUnsentPings() {
  const PINGS = [
    {
      type: "crash",
      id: TelemetryUtils.generateUUID(),
      payload: { foo: "bar" },
      dateCreated: new Date(2010, 1, 1, 10, 0, 0),
    },
    {
      type: "other",
      id: TelemetryUtils.generateUUID(),
      payload: { moo: "meh" },
      dateCreated: new Date(2010, 2, 1, 10, 2, 0),
    },
  ];
  const APP_DATA_DIR = Services.dirsvc.get("UAppData", Ci.nsIFile).path;
  const APPDATA_PINGS_DIR = PathUtils.join(APP_DATA_DIR, PENDING_PING_DIR_NAME);

  // Create some pending pings outside of the user profile.
  for (let ping of PINGS) {
    const pingPath = PathUtils.join(APPDATA_PINGS_DIR, ping.id + ".json");
    await TelemetryStorage.savePingToFile(ping, pingPath, true);
  }

  // Make sure the pending ping list is empty.
  await TelemetryStorage.testClearPendingPings();

  // Start the migration from TelemetryStorage.
  let pendingPings = await TelemetryStorage.loadPendingPingList();
  Assert.equal(
    pendingPings.length,
    2,
    "TelemetryStorage must have migrated 2 pings."
  );

  for (let ping of PINGS) {
    // Verify that the pings were migrated and are among the pending pings.
    Assert.ok(
      pendingPings.find(p => p.id == ping.id),
      "The ping must have been migrated."
    );

    // Try to load the migrated ping from the user profile.
    let migratedPing = await TelemetryStorage.loadPendingPing(ping.id);
    Assert.equal(
      ping.id,
      migratedPing.id,
      "Should have loaded the correct ping id."
    );
    Assert.equal(
      ping.type,
      migratedPing.type,
      "Should have loaded the correct ping type."
    );
    Assert.deepEqual(
      ping.payload,
      migratedPing.payload,
      "Should have loaded the correct payload."
    );

    // Verify that the pings are no longer outside of the user profile.
    const pingPath = PathUtils.join(APPDATA_PINGS_DIR, ping.id + ".json");
    Assert.ok(
      !(await IOUtils.exists(pingPath)),
      "The ping should not be in the Pending Pings directory anymore."
    );
  }
});

add_task(async function test_migrateIncompatiblePing() {
  const APP_DATA_DIR = Services.dirsvc.get("UAppData", Ci.nsIFile).path;
  const APPDATA_PINGS_DIR = PathUtils.join(APP_DATA_DIR, PENDING_PING_DIR_NAME);

  // Create a ping incompatible with migration outside of the user profile.
  const pingPath = PathUtils.join(APPDATA_PINGS_DIR, "incompatible.json");
  await TelemetryStorage.savePingToFile({ incom: "patible" }, pingPath, true);

  // Ensure the pending ping list is empty.
  await TelemetryStorage.testClearPendingPings();
  TelemetryStorage.reset();

  // Start the migration from TelemetryStorage.
  let pendingPings = await TelemetryStorage.loadPendingPingList();
  Assert.equal(
    pendingPings.length,
    0,
    "TelemetryStorage must have migrated no pings." +
      JSON.stringify(pendingPings)
  );

  Assert.ok(
    !(await IOUtils.exists(pingPath)),
    "The incompatible ping must have been deleted by the migration"
  );
});

add_task(async function teardown() {
  // Delete the UAppData directory and make sure nothing breaks.
  const APP_DATA_DIR = Services.dirsvc.get("UAppData", Ci.nsIFile).path;
  await IOUtils.remove(APP_DATA_DIR, { recursive: true });
  Assert.ok(
    !(await IOUtils.exists(APP_DATA_DIR)),
    "The UAppData directory must not exist anymore."
  );
  TelemetryStorage.reset();
  await TelemetryStorage.loadPendingPingList();
});