File: webxr_test_asserts.js

package info (click to toggle)
firefox 144.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 4,637,504 kB
  • sloc: cpp: 7,576,692; javascript: 6,430,831; ansic: 3,748,119; python: 1,398,978; xml: 628,810; asm: 438,679; java: 186,194; sh: 63,212; makefile: 19,159; objc: 13,086; perl: 12,986; yacc: 4,583; cs: 3,846; pascal: 3,448; lex: 1,720; ruby: 1,003; exp: 762; php: 436; lisp: 258; awk: 247; sql: 66; sed: 53; csh: 10
file content (288 lines) | stat: -rw-r--r-- 12,553 bytes parent folder | download | duplicates (15)
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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
// Utility assert functions.
// Relies on resources/testharness.js to be included before this file.
// Relies on webxr_test_constants.js to be included before this file.
// Relies on webxr_math_utils.js to be included before this file.


// |p1|, |p2| - objects with x, y, z, w components that are floating point numbers.
// Returns the name of mismatching component between p1 and p2.
const get_mismatched_component = function(p1, p2, epsilon = FLOAT_EPSILON) {
  for (const v of ['x', 'y', 'z', 'w']) {
    if (Math.abs(p1[v] - p2[v]) > epsilon) {
      return v;
    }
  }

  return null;
}

// Internal helper to find the mismatched component for orientations.
// Considers that q and -q represent the same orientation.
// Returns the component name ('x', 'y', 'z', 'w') of the first mismatch
// Returns null if q1 is approximately equal to q2 or -q2.
const get_mismatched_orientation_component = function(q1, q2, epsilon) {
  const direct_mismatch = get_mismatched_component(q1, q2, epsilon);
  // q1 == q2, for our purposes there is no mismatched component.
  if (direct_mismatch === null) {
    return null;
  }
  // q1 != q2, but check q1 vs -q2
  const q2_flipped = flip_quaternion(q2);
  if (get_mismatched_component(q1, q2_flipped, epsilon) === null) {
    return null;
  }
  // q1 is not approx equal to q2 or -q2.
  // both q2 and q2_flipped have non-null mismatchecs, but for ease of debugging
  // return the mismatch from the direct comparison.
  return direct_mismatch;
};

// Internal helper to find the index of the first mismatched matrix element.
// Returns the index (0-15) or -1 if matrices are approximately equal.
const get_mismatched_matrix_element_index = function(m1, m2, epsilon, prefix="") {
  assert_equals(m1.length, 16, prefix + "m1 must have length of 16");
  assert_equals(m2.length, 16, prefix + "m2 must have length of 16");

  for (let i = 0; i < 16; ++i) {
    if (Math.abs(m1[i] - m2[i]) > epsilon) {
      return i;
    }
  }
  return -1;
}

// |p1|, |p2| - objects with x, y, z, w components that are floating point numbers.
// |epsilon| - float specifying precision
// |prefix| - string used as a prefix for logging
const assert_point_approx_equals = function(p1, p2, epsilon = FLOAT_EPSILON, prefix = "") {
  if (p1 == null && p2 == null) {
    return;
  }

  assert_not_equals(p1, null, prefix + "p1 must be non-null");
  assert_not_equals(p2, null, prefix + "p2 must be non-null");

  const mismatched_component = get_mismatched_component(p1, p2, epsilon);

  if (mismatched_component !== null) {
    let error_message = prefix + ' Point comparison failed.\n';
    error_message += ` p1: {x: ${p1.x}, y: ${p1.y}, z: ${p1.z}, w: ${p1.w}}\n`;
    error_message += ` p2: {x: ${p2.x}, y: ${p2.y}, z: ${p2.z}, w: ${p2.w}}\n`;
    error_message += ` Difference in component ${mismatched_component} exceeded the given epsilon.\n`;
    assert_approx_equals(p2[mismatched_component], p1[mismatched_component], epsilon, error_message);
  }
};

// |p1|, |p2| - objects with x, y, z, w components that are floating point numbers.
// |epsilon| - float specifying precision
// |prefix| - string used as a prefix for logging
const assert_point_significantly_not_equals = function(p1, p2, epsilon = FLOAT_EPSILON, prefix = "") {
  if (p1 == null || p2 == null) {
    assert_not_equals(p2, p1, prefix + "p1 and p2 are both null");
    return;
  }

  const mismatched_component = get_mismatched_component(p1, p2, epsilon);
  if (mismatched_component === null) {
    let error_message = prefix + ' Point comparison failed (expected significant difference).\n';
    error_message += ` p1: {x: ${p1.x}, y: ${p1.y}, z: ${p1.z}, w: ${p1.w}}\n`;
    error_message += ` p2: {x: ${p2.x}, y: ${p2.y}, z: ${p2.z}, w: ${p2.w}}\n`;
    error_message += ` Difference in components did not exceeded the given epsilon.\n`;
    assert_unreached(error_message);
  }
};

// |q1|, |q2| - objects with x, y, z, w components that are floating point numbers.
// |epsilon| - float specifying precision
// |prefix| - string used as a prefix for logging
const assert_orientation_approx_equals = function(q1, q2, epsilon = FLOAT_EPSILON, prefix = "") {
  if (q1 == null && q2 == null) {
    return;
  }

  assert_not_equals(q1, null, prefix + "q1 must be non-null");
  assert_not_equals(q2, null, prefix + "q2 must be non-null");

  const mismatched_component = get_mismatched_orientation_component(q1, q2, epsilon);
  // q1 doesn't match neither q2 nor -q2, so it definitely does not represent the same orientations,
  // log an assert failure.
  if (mismatched_component !== null) {
    let error_message = prefix + ' Orientation comparison failed.\n';
    error_message += ` q1: {x: ${q1.x}, y: ${q1.y}, z: ${q1.z}, w: ${q1.w}}\n`;
    error_message += ` q2: {x: ${q2.x}, y: ${q2.y}, z: ${q2.z}, w: ${q2.w}}\n`;
    error_message += ` Neither q2 nor -q2 are approximately equal to q1.\n`;
    error_message += ` For q1 vs q2, difference in component ${mismatched_component} exceeded the given epsilon.\n`;
    assert_approx_equals(q2[mismatched_component], q1[mismatched_component], epsilon, error_message);
  }
};

// |q1|, |q2| - objects with x, y, z, w components that are floating point numbers.
// |epsilon| - float specifying precision
// |prefix| - string used as a prefix for logging
const assert_orientation_significantly_not_equals = function(q1, q2, epsilon = FLOAT_EPSILON, prefix = "") {
  if (q1 == null || q2 == null) {
    assert_not_equals(q2, q1, prefix + "q1 and q2 are both null");
    return;
  }

  const mismatched_component = get_mismatched_orientation_component(q1, q2, epsilon);
  // IF there is no mismatch q1 matches either q2 or -q2 (which are equivalent).
  if (mismatched_component === null) {
    let error_message = prefix + ' Orientation comparison failed (expected significant difference).\n';
    error_message += ` q1: {x: ${q1.x}, y: ${q1.y}, z: ${q1.z}, w: ${q1.w}}\n`;
    error_message += ` q2: {x: ${q2.x}, y: ${q2.y}, z: ${q2.z}, w: ${q2.w}}\n`;
    error_message += ` q1 is approximately equal to q2 or -q2, but a significant difference was expected.\n`;
    assert_unreached(error_message);
  }
};

// |t1|, |t2| - objects containing position and orientation.
// |epsilon| - float specifying precision
// |prefix| - string used as a prefix for logging
const assert_transform_approx_equals = function(t1, t2, epsilon = FLOAT_EPSILON, prefix = "") {
  if (t1 == null && t2 == null) {
    return;
  }

  assert_not_equals(t1, null, prefix + "t1 must be non-null");
  assert_not_equals(t2, null, prefix + "t2 must be non-null");

  assert_point_approx_equals(t1.position, t2.position, epsilon, prefix + "positions must be equal");
  assert_orientation_approx_equals(t1.orientation, t2.orientation, epsilon, prefix + "orientations must be equal");
};

// |t1|, |t2| - objects containing position and orientation.
// |epsilon| - float specifying precision
// |prefix| - string used as a prefix for logging
const assert_transform_significantly_not_equals = function(t1, t2, epsilon = FLOAT_EPSILON, prefix = "") {
  if (t1 == null || t2 == null) {
    assert_not_equals(t1, t2, prefix + "t1 and t2 cannot both be null.");
    return;
  }

  // It is okay for one of position or orientation to be equal; but not for both
  // to be equal in order for the transform to not be equal.
  let mismatched_position = get_mismatched_component(t1.position, t2.position, epsilon);
  let mismatched_orientation = get_mismatched_orientation_component(t1.orientation, t2.orientation, epsilon);
  if (mismatched_position === null && mismatched_orientation === null) {
      assert_point_significantly_not_equals(t1.position, t2.position, epsilon, prefix + "positions must not be equal");
      assert_orientation_significantly_not_equals(t1.orientation, t2.orientation, epsilon, prefix + "orientations must not be equal");
  }
}

// |m1|, |m2| - arrays of floating point numbers
// |epsilon| - float specifying precision
// |prefix| - string used as a prefix for logging
const assert_matrix_approx_equals = function(m1, m2, epsilon = FLOAT_EPSILON, prefix = "") {
  if (m1 == null && m2 == null) {
    return;
  }

  assert_not_equals(m1, null, prefix + "m1 must be non-null");
  assert_not_equals(m2, null, prefix + "m2 must be non-null");

  assert_equals(m1.length, 16, prefix + "m1 must have length of 16");
  assert_equals(m2.length, 16, prefix + "m2 must have length of 16");

  const mismatched_element = get_mismatched_matrix_element_index(m1, m2, epsilon, prefix);
  if (mismatched_element !== -1) {
    let error_message = prefix + 'Matrix comparison failed.\n';
    error_message += ' Difference in element ' + mismatched_element +
        ' exceeded the given epsilon.\n';

    error_message += ' Matrix 1: [' + m1.join(',') + ']\n';
    error_message += ' Matrix 2: [' + m2.join(',') + ']\n';

    assert_approx_equals(
        m1[mismatched_element], m2[mismatched_element], epsilon,
        error_message);
  }
};

// |m1|, |m2| - arrays of floating point numbers.
// |epsilon| - float specifying precision
// |prefix| - string used as a prefix for logging
const assert_matrix_significantly_not_equals = function(m1, m2, epsilon = FLOAT_EPSILON, prefix = "") {
  if (m1 == null || m2 == null) {
    assert_not_equals(m1, m2, prefix + "m1 and m2 must not both be null");
    return;
  }

  assert_equals(m1.length, 16, prefix + "m1 must have length of 16");
  assert_equals(m2.length, 16, prefix + "m2 must have length of 16");

  const mismatched_index = get_mismatched_matrix_element_index(m1, m2, epsilon, prefix);
  if (mismatched_index === -1) {
    let error_message = prefix + ' Matrix comparison failed (expected significant difference).\n';
    error_message +=
        ' No element exceeded the given epsilon ' + epsilon + '.\n';

    error_message += ' Matrix 1: [' + m1.join(',') + ']\n';
    error_message += ' Matrix 2: [' + m2.join(',') + ']\n';

    assert_unreached(error_message);
  }
};

// |r1|, |r2| - XRRay objects
// |epsilon| - float specifying precision
// |prefix| - string used as a prefix for logging
const assert_ray_approx_equals = function(r1, r2, epsilon = FLOAT_EPSILON, prefix = "") {
  assert_point_approx_equals(r1.origin, r2.origin, epsilon, prefix + "origin:");
  assert_point_approx_equals(r1.direction, r2.direction, epsilon, prefix + "direction:");
  assert_matrix_approx_equals(r1.matrix, r2.matrix, epsilon, prefix + "matrix:");
};

// |actualBuffer|, |expectedBuffer| - ArrayBuffer objects
// |message| - string used as a prefix for logging
const assert_array_buffer_equals = function(actualBuffer, expectedBuffer, message = "ArrayBuffers should be equal") {
  if (actualBuffer == null && expectedBuffer == null) {
    return;
  }

  assert_not_equals(actualBuffer, null, message + " (actualBuffer is null)");
  assert_not_equals(expectedBuffer, null, message + " (expectedBuffer is null)");

  assert_equals(actualBuffer.byteLength, expectedBuffer.byteLength, message + " (byteLength mismatch)");

  const actualView = new Uint8Array(actualBuffer);
  const expectedView = new Uint8Array(expectedBuffer);

  for (let i = 0; i < actualView.length; i++) {
    // Check each byte. If a mismatch is found, assert_equals will fail the test
    // and provide a detailed message.
    if (actualView[i] !== expectedView[i]) {
      assert_equals(actualView[i], expectedView[i], `${message} (mismatch at byte ${i})`);
      return;
    }
  }
  // If the loop completes without an assert_equals failure, the buffers are identical.
};

// |actualBuffer|, |expectedBuffer| - ArrayBuffer objects
// |message| - string used as a prefix for logging
const assert_array_buffer_not_equals = function(actualBuffer, expectedBuffer, message = "ArrayBuffers should not be equal") {
  if (actualBuffer == null || expectedBuffer == null) {
    assert_not_equals(actualBuffer, expectedBuffer, message+ " (actualBuffer and expectedBuffer both null)");
    return;
  }

  assert_not_equals(actualBuffer, null, message + " (actualBuffer is null)");
  assert_not_equals(expectedBuffer, null, message + " (expectedBuffer is null)");

  if (actualBuffer.byteLength !== expectedBuffer.byteLength) {
    return;
  }

  const actualView = new Uint8Array(actualBuffer);
  const expectedView = new Uint8Array(expectedBuffer);

  for (let i = 0; i < actualView.length; i++) {
    // Once one byte is different, then the two buffers aren't the same and we
    // can return.
    if (actualView[i] !== expectedView[i]) {
      return;
    }
  }
  assert_unreached(`${message} (buffers are identical`);
};