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
|
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* This runs the xpcshell binary with different cases for the executable path.
* They should all result in the same installation hash.
*/
const { Subprocess } = ChromeUtils.importESModule(
"resource://gre/modules/Subprocess.sys.mjs"
);
const XRE = Cc["@mozilla.org/xre/directory-provider;1"].getService(
Ci.nsIXREDirProvider
);
const HASH = XRE.getInstallHash(false);
const EXE = Services.dirsvc.get("XREExeF", Ci.nsIFile);
const SCRIPT = do_get_file("show_hash.js", false);
async function getHash(bin) {
try {
// If this test is running through firefox.exe -xpcshell, we need
// to make sure to execute the script through it as well.
let args = [];
if (!bin.leafName.startsWith("xpcshell")) {
args.push("-xpcshell");
}
args.push(SCRIPT.path);
let proc = await Subprocess.call({
command: bin.path,
arguments: args,
});
let result = "";
let string;
while ((string = await proc.stdout.readString())) {
result += string;
}
return result.trim();
} catch (e) {
if (e.errorCode == Subprocess.ERROR_BAD_EXECUTABLE) {
return null;
}
throw e;
}
}
// Walks through a path's entries and calls a mutator function to change the
// case of each.
function mutatePath(path, mutator) {
let parts = [];
let index = 0;
while (path.parent != null) {
parts.push(mutator(path.leafName, index++));
path = path.parent;
}
while (parts.length) {
path.append(parts.pop());
}
return path;
}
// Counts how many path parts a mutator will be called for.
function countParts(path) {
let index = 0;
while (path.parent != null) {
path = path.parent;
index++;
}
return index;
}
add_task(async function testSameBinary() {
// Running with the same binary path should definitely work and give the same
// hash.
Assert.equal(
await getHash(EXE),
HASH,
"Should have the same hash when running the same binary."
);
});
add_task(async function testUpperCase() {
let upper = mutatePath(EXE, p => p.toLocaleUpperCase());
let hash = await getHash(upper);
// We may not get a hash if any part of the filesystem is case sensitive.
if (hash) {
Assert.equal(
hash,
HASH,
`Should have seen the same hash from ${upper.path}.`
);
}
});
add_task(async function testLowerCase() {
let lower = mutatePath(EXE, p => p.toLocaleLowerCase());
let hash = await getHash(lower);
// We may not get a hash if any part of the filesystem is case sensitive.
if (hash) {
Assert.equal(
hash,
HASH,
`Should have seen the same hash from ${lower.path}.`
);
}
});
add_task(async function testEachPart() {
// We need to check the case where only some of the directories in the path
// are case insensitive.
let count = countParts(EXE);
for (let i = 0; i < count; i++) {
let upper = mutatePath(EXE, (p, index) =>
index == i ? p.toLocaleUpperCase() : p
);
let lower = mutatePath(EXE, (p, index) =>
index == i ? p.toLocaleLowerCase() : p
);
let upperHash = await getHash(upper);
if (upperHash) {
Assert.equal(
upperHash,
HASH,
`Should have seen the same hash from ${upper.path}.`
);
}
let lowerHash = await getHash(lower);
if (lowerHash) {
Assert.equal(
lowerHash,
HASH,
`Should have seen the same hash from ${lower.path}.`
);
}
}
});
|