summaryrefslogtreecommitdiffstats
path: root/toolkit/components/osfile/tests/xpcshell/test_read_write.js
blob: 6fe554c9220fc5a514e0795c0d50ce164e87e2d8 (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
/* Any copyright is dedicated to the Public Domain.
 * http://creativecommons.org/publicdomain/zero/1.0/ */

"use strict";

var SHARED_PATH;

var EXISTING_FILE = do_get_file("xpcshell.ini").path;

add_task(async function init() {
  do_get_profile();
  SHARED_PATH = OS.Path.join(
    OS.Constants.Path.profileDir,
    "test_osfile_read.tmp"
  );
});

// Check that OS.File.read() is executed after the previous operation
add_test_pair(async function ordering() {
  let string1 = "Initial state " + Math.random();
  let string2 = "After writing " + Math.random();
  await OS.File.writeAtomic(SHARED_PATH, string1);
  OS.File.writeAtomic(SHARED_PATH, string2);
  let string3 = await OS.File.read(SHARED_PATH, { encoding: "utf-8" });
  Assert.equal(string3, string2);
});

add_test_pair(async function read_write_all() {
  let DEST_PATH = SHARED_PATH + Math.random();
  let TMP_PATH = DEST_PATH + ".tmp";

  let test_with_options = function(options, suffix) {
    return (async function() {
      info(
        "Running test read_write_all with options " + JSON.stringify(options)
      );
      let TEST = "read_write_all " + suffix;

      let optionsBackup = JSON.parse(JSON.stringify(options));

      // Check that read + writeAtomic performs a correct copy
      let currentDir = await OS.File.getCurrentDirectory();
      let pathSource = OS.Path.join(currentDir, EXISTING_FILE);
      let contents = await OS.File.read(pathSource);
      Assert.ok(!!contents); // Content is not empty
      let bytesRead = contents.byteLength;

      let bytesWritten = await OS.File.writeAtomic(
        DEST_PATH,
        contents,
        options
      );
      Assert.equal(bytesRead, bytesWritten); // Correct number of bytes written

      // Check that options are not altered
      Assert.equal(JSON.stringify(options), JSON.stringify(optionsBackup));
      await reference_compare_files(pathSource, DEST_PATH, TEST);

      // Check that temporary file was removed or never created exist
      Assert.ok(!new FileUtils.File(TMP_PATH).exists());

      // Check that writeAtomic fails if noOverwrite is true and the destination
      // file already exists!
      contents = new Uint8Array(300);
      let view = new Uint8Array(contents.buffer, 10, 200);
      try {
        let opt = JSON.parse(JSON.stringify(options));
        opt.noOverwrite = true;
        await OS.File.writeAtomic(DEST_PATH, view, opt);
        do_throw(
          "With noOverwrite, writeAtomic should have refused to overwrite file (" +
            suffix +
            ")"
        );
      } catch (err) {
        if (err instanceof OS.File.Error && err.becauseExists) {
          info(
            "With noOverwrite, writeAtomic correctly failed (" + suffix + ")"
          );
        } else {
          throw err;
        }
      }
      await reference_compare_files(pathSource, DEST_PATH, TEST);

      // Check that temporary file was removed or never created
      Assert.ok(!new FileUtils.File(TMP_PATH).exists());

      // Now write a subset
      let START = 10;
      let LENGTH = 100;
      contents = new Uint8Array(300);
      for (let i = 0; i < contents.byteLength; i++) {
        contents[i] = i % 256;
      }
      view = new Uint8Array(contents.buffer, START, LENGTH);
      bytesWritten = await OS.File.writeAtomic(DEST_PATH, view, options);
      Assert.equal(bytesWritten, LENGTH);

      let array2 = await OS.File.read(DEST_PATH);
      Assert.equal(LENGTH, array2.length);
      for (let j = 0; j < LENGTH; j++) {
        Assert.equal(array2[j], (j + START) % 256);
      }

      // Cleanup.
      await OS.File.remove(DEST_PATH);
      await OS.File.remove(TMP_PATH);
    })();
  };

  await test_with_options({ tmpPath: TMP_PATH }, "Renaming, not flushing");
  await test_with_options(
    { tmpPath: TMP_PATH, flush: true },
    "Renaming, flushing"
  );
  await test_with_options({}, "Not renaming, not flushing");
  await test_with_options({ flush: true }, "Not renaming, flushing");
});