summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/webxr/resources/webxr_test_asserts.js
blob: a82f7aaf90aabb8a49b9f10aa0d50ba795d798fe (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
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
// 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;
}

// |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);
  }
};

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 q2_flipped = flip_quaternion(q2);

  const mismatched_component = get_mismatched_component(q1, q2, epsilon);
  const mismatched_component_flipped = get_mismatched_component(q1, q2_flipped, epsilon);

  if (mismatched_component !== null && mismatched_component_flipped !== null) {
    // q1 doesn't match neither q2 nor -q2, so it definitely does not represent the same orientations,
    // log an assert failure.
    let error_message = prefix + ' Orientation comparison failed.\n';
    error_message += ` p1: {x: ${q1.x}, y: ${q1.y}, z: ${q1.z}, w: ${q1.w}}\n`;
    error_message += ` p2: {x: ${q2.x}, y: ${q2.y}, z: ${q2.z}, w: ${q2.w}}\n`;
    error_message += ` Difference in component ${mismatched_component} exceeded the given epsilon.\n`;
    assert_approx_equals(q2[mismatched_component], q1[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 = "") {

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

  let 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 components did not exceeded the given epsilon.\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");
};

// |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");

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

  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) {
    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");

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

  if (!mismatch) {
    let m1_str = '[';
    let m2_str = '[';
    for (let i = 0; i < 16; ++i) {
      m1_str += m1[i] + (i < 15 ? ', ' : '');
      m2_str += m2[i] + (i < 15 ? ', ' : '');
    }
    m1_str += ']';
    m2_str += ']';

    let error_message = prefix + 'Matrix comparison failed.\n';
    error_message +=
        ' No element exceeded the given epsilon ' + epsilon + '.\n';

    error_message += ' Matrix A: ' + m1_str + '\n';
    error_message += ' Matrix B: ' + m2_str + '\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:");
};