1 /*
2  *  Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "modules/audio_coding/audio_network_adaptor/util/threshold_curve.h"
12 
13 #include <memory>
14 
15 #include "test/gtest.h"
16 
17 // A threshold curve divides 2D space into three domains - below, on and above
18 // the threshold curve.
19 // The curve is defined by two points. Those points, P1 and P2, are ordered so
20 // that (P1.x <= P2.x && P1.y >= P2.y).
21 // The part of the curve which is between the two points is hereon referred
22 // to as the "segment".
23 // A "ray" extends from P1 directly upwards into infinity; that's the "vertical
24 // ray". Likewise, a "horizontal ray" extends from P2 directly rightwards.
25 //
26 //  ^   |                         //
27 //  |   | vertical ray            //
28 //  |   |                         //
29 //  |   |                         //
30 //  | P1|                         //
31 //  |    \                        //
32 //  |     \ segment               //
33 //  |      \                      //
34 //  |       \    horizontal ray   //
35 //  |     P2 ------------------   //
36 //  *---------------------------> //
37 
38 namespace webrtc {
39 
40 namespace {
41 enum RelativePosition { kBelow, kOn, kAbove };
42 
CheckRelativePosition(const ThresholdCurve & curve,ThresholdCurve::Point point,RelativePosition pos)43 void CheckRelativePosition(const ThresholdCurve& curve,
44                            ThresholdCurve::Point point,
45                            RelativePosition pos) {
46   RTC_CHECK(pos == kBelow || pos == kOn || pos == kAbove);
47 
48   EXPECT_EQ(pos == kBelow, curve.IsBelowCurve(point));
49   EXPECT_EQ(pos == kAbove, curve.IsAboveCurve(point));
50 }
51 }  // namespace
52 
53 // Test that the curve correctly reports the below/above position of points,
54 // when the curve is a "normal" one - P1 and P2 are different in both their
55 // X and Y values.
TEST(ThresholdCurveTest,PointPositionToCommonCurve)56 TEST(ThresholdCurveTest, PointPositionToCommonCurve) {
57   // The points (P1-P2) define the curve.           //
58   // All other points are above/below/on the curve. //
59   //                                                //
60   //  ^                                             //
61   //  |     |                                       //
62   //  |  A  F    J  R   V                           //
63   //  |     |                                       //
64   //  |  B  P1   K  S   W                           //
65   //  |      \                                      //
66   //  |       \                                     //
67   //  |        \ L                                  //
68   //  |         \                                   //
69   //  |  C  G    M  T   X                           //
70   //  |           \                                 //
71   //  |          N \                                //
72   //  |             \                               //
73   //  |  D  H    O  P2--Y----------------           //
74   //  |  E  I    Q  U   Z                           //
75   //  *---------------------------------->          //
76   constexpr ThresholdCurve::Point p1{1000, 2000};
77   constexpr ThresholdCurve::Point p2{2000, 1000};
78 
79   RTC_CHECK_GT((p1.x + p2.x) / 2, p1.x);
80   RTC_CHECK_LT((p1.x + p2.x) / 2, p2.x);
81   RTC_CHECK_LT((p1.y + p2.y) / 2, p1.y);
82   RTC_CHECK_GT((p1.y + p2.y) / 2, p2.y);
83 
84   const ThresholdCurve curve(p1, p2);
85 
86   {
87     // All cases where the point lies to the left of P1.
88     constexpr float x = p1.x - 1;
89     CheckRelativePosition(curve, {x, p1.y + 1}, kBelow);           // A
90     CheckRelativePosition(curve, {x, p1.y + 0}, kBelow);           // B
91     CheckRelativePosition(curve, {x, (p1.y + p2.y) / 2}, kBelow);  // C
92     CheckRelativePosition(curve, {x, p2.y + 0}, kBelow);           // D
93     CheckRelativePosition(curve, {x, p2.y - 1}, kBelow);           // E
94   }
95 
96   {
97     // All cases where the point has the same x-value as P1.
98     constexpr float x = p1.x;
99     CheckRelativePosition(curve, {x, p1.y + 1}, kOn);              // F
100     CheckRelativePosition(curve, {x, p1.y + 0}, kOn);              // P1
101     CheckRelativePosition(curve, {x, (p1.y + p2.y) / 2}, kBelow);  // G
102     CheckRelativePosition(curve, {x, p2.y + 0}, kBelow);           // H
103     CheckRelativePosition(curve, {x, p2.y - 1}, kBelow);           // I
104   }
105 
106   {
107     // To make sure we're really covering all of the cases, make sure that P1
108     // and P2 were chosen so that L would really be below K, and O would really
109     // be below N. (This would not hold if the Y values are too close together.)
110     RTC_CHECK_LT(((p1.y + p2.y) / 2) + 1, p1.y);
111     RTC_CHECK_LT(p2.y, ((p1.y + p2.y) / 2) - 1);
112 
113     // All cases where the point's x-value is between P1 and P2.
114     constexpr float x = (p1.x + p2.x) / 2;
115     CheckRelativePosition(curve, {x, p1.y + 1}, kAbove);                 // J
116     CheckRelativePosition(curve, {x, p1.y + 0}, kAbove);                 // K
117     CheckRelativePosition(curve, {x, ((p1.y + p2.y) / 2) + 1}, kAbove);  // L
118     CheckRelativePosition(curve, {x, (p1.y + p2.y) / 2}, kOn);           // M
119     CheckRelativePosition(curve, {x, ((p1.y + p2.y) / 2) - 1}, kBelow);  // N
120     CheckRelativePosition(curve, {x, p2.y + 0}, kBelow);                 // O
121     CheckRelativePosition(curve, {x, p2.y - 1}, kBelow);                 // Q
122   }
123 
124   {
125     // All cases where the point has the same x-value as P2.
126     constexpr float x = p2.x;
127     CheckRelativePosition(curve, {x, p1.y + 1}, kAbove);           // R
128     CheckRelativePosition(curve, {x, p1.y + 0}, kAbove);           // S
129     CheckRelativePosition(curve, {x, (p1.y + p2.y) / 2}, kAbove);  // T
130     CheckRelativePosition(curve, {x, p2.y + 0}, kOn);              // P2
131     CheckRelativePosition(curve, {x, p2.y - 1}, kBelow);           // U
132   }
133 
134   {
135     // All cases where the point lies to the right of P2.
136     constexpr float x = p2.x + 1;
137     CheckRelativePosition(curve, {x, p1.y + 1}, kAbove);           // V
138     CheckRelativePosition(curve, {x, p1.y + 0}, kAbove);           // W
139     CheckRelativePosition(curve, {x, (p1.y + p2.y) / 2}, kAbove);  // X
140     CheckRelativePosition(curve, {x, p2.y + 0}, kOn);              // Y
141     CheckRelativePosition(curve, {x, p2.y - 1}, kBelow);           // Z
142   }
143 }
144 
145 // Test that the curve correctly reports the below/above position of points,
146 // when the curve is defined by two points with the same Y value.
TEST(ThresholdCurveTest,PointPositionToCurveWithHorizaontalSegment)147 TEST(ThresholdCurveTest, PointPositionToCurveWithHorizaontalSegment) {
148   // The points (P1-P2) define the curve.
149   // All other points are above/below/on the curve.
150   //
151   //  ^
152   //  |    |
153   //  |    |
154   //  | A  D   F  I  K
155   //  |    |
156   //  |    |
157   //  | B  P1--G--P2-L--
158   //  | C  E   H  J  M
159   //  *------------------>
160 
161   constexpr ThresholdCurve::Point p1{100, 200};
162   constexpr ThresholdCurve::Point p2{p1.x + 1, p1.y};
163 
164   RTC_CHECK_GT((p1.x + p2.x) / 2, p1.x);
165   RTC_CHECK_LT((p1.x + p2.x) / 2, p2.x);
166 
167   const ThresholdCurve curve(p1, p2);
168 
169   {
170     // All cases where the point lies to the left of P1.
171     constexpr float x = p1.x - 1;
172     CheckRelativePosition(curve, {x, p1.y + 1}, kBelow);  // A
173     CheckRelativePosition(curve, {x, p1.y + 0}, kBelow);  // B
174     CheckRelativePosition(curve, {x, p1.y - 1}, kBelow);  // C
175   }
176 
177   {
178     // All cases where the point has the same x-value as P1.
179     constexpr float x = p1.x;
180     CheckRelativePosition(curve, {x, p1.y + 1}, kOn);     // D
181     CheckRelativePosition(curve, {x, p1.y + 0}, kOn);     // P1
182     CheckRelativePosition(curve, {x, p1.y - 1}, kBelow);  // E
183   }
184 
185   {
186     // All cases where the point's x-value is between P1 and P2.
187     constexpr float x = (p1.x + p2.x) / 2;
188     CheckRelativePosition(curve, {x, p1.y + 1}, kAbove);  // F
189     CheckRelativePosition(curve, {x, p1.y + 0}, kOn);     // G
190     CheckRelativePosition(curve, {x, p1.y - 1}, kBelow);  // H
191   }
192 
193   {
194     // All cases where the point has the same x-value as P2.
195     constexpr float x = p2.x;
196     CheckRelativePosition(curve, {x, p1.y + 1}, kAbove);  // I
197     CheckRelativePosition(curve, {x, p1.y + 0}, kOn);     // P2
198     CheckRelativePosition(curve, {x, p1.y - 1}, kBelow);  // J
199   }
200 
201   {
202     // All cases where the point lies to the right of P2.
203     constexpr float x = p2.x + 1;
204     CheckRelativePosition(curve, {x, p1.y + 1}, kAbove);  // K
205     CheckRelativePosition(curve, {x, p1.y + 0}, kOn);     // L
206     CheckRelativePosition(curve, {x, p1.y - 1}, kBelow);  // M
207   }
208 }
209 
210 // Test that the curve correctly reports the below/above position of points,
211 // when the curve is defined by two points with the same X value.
TEST(ThresholdCurveTest,PointPositionToCurveWithVerticalSegment)212 TEST(ThresholdCurveTest, PointPositionToCurveWithVerticalSegment) {
213   // The points (P1-P2) define the curve.
214   // All other points are above/below/on the curve.
215   //
216   //  ^
217   //  |    |
218   //  | A  B   C
219   //  |    |
220   //  | D  P1  E
221   //  |    |
222   //  | F  G   H
223   //  |    |
224   //  | I  P2--J------
225   //  | K  L   M
226   //  *------------------>
227 
228   constexpr ThresholdCurve::Point p1{100, 200};
229   constexpr ThresholdCurve::Point p2{p1.x, p1.y - 1};
230 
231   constexpr float left = p1.x - 1;
232   constexpr float on = p1.x;
233   constexpr float right = p1.x + 1;
234 
235   RTC_CHECK_LT((p1.y + p2.y) / 2, p1.y);
236   RTC_CHECK_GT((p1.y + p2.y) / 2, p2.y);
237 
238   const ThresholdCurve curve(p1, p2);
239 
240   {
241     // All cases where the point lies above P1.
242     constexpr float y = p1.y + 1;
243     CheckRelativePosition(curve, {left, y}, kBelow);   // A
244     CheckRelativePosition(curve, {on, y}, kOn);        // B
245     CheckRelativePosition(curve, {right, y}, kAbove);  // C
246   }
247 
248   {
249     // All cases where the point has the same y-value as P1.
250     constexpr float y = p1.y;
251     CheckRelativePosition(curve, {left, y}, kBelow);   // D
252     CheckRelativePosition(curve, {on, y}, kOn);        // P1
253     CheckRelativePosition(curve, {right, y}, kAbove);  // E
254   }
255 
256   {
257     // All cases where the point's y-value is between P1 and P2.
258     constexpr float y = (p1.y + p2.y) / 2;
259     CheckRelativePosition(curve, {left, y}, kBelow);   // F
260     CheckRelativePosition(curve, {on, y}, kOn);        // G
261     CheckRelativePosition(curve, {right, y}, kAbove);  // H
262   }
263 
264   {
265     // All cases where the point has the same y-value as P2.
266     constexpr float y = p2.y;
267     CheckRelativePosition(curve, {left, y}, kBelow);  // I
268     CheckRelativePosition(curve, {on, y}, kOn);       // P2
269     CheckRelativePosition(curve, {right, y}, kOn);    // J
270   }
271 
272   {
273     // All cases where the point lies below P2.
274     constexpr float y = p2.y - 1;
275     CheckRelativePosition(curve, {left, y}, kBelow);   // K
276     CheckRelativePosition(curve, {on, y}, kBelow);     // L
277     CheckRelativePosition(curve, {right, y}, kBelow);  // M
278   }
279 }
280 
281 // Test that the curve correctly reports the below/above position of points,
282 // when the curve is defined by two points which are identical.
TEST(ThresholdCurveTest,PointPositionCurveWithNullSegment)283 TEST(ThresholdCurveTest, PointPositionCurveWithNullSegment) {
284   // The points (P1-P2) define the curve.
285   // All other points are above/below/on the curve.
286   //
287   //  ^
288   //  |    |
289   //  | A  D   F
290   //  |    |
291   //  | B  P---G------
292   //  | C  E   H
293   //  *------------------>
294 
295   constexpr ThresholdCurve::Point p{100, 200};
296 
297   const ThresholdCurve curve(p, p);
298 
299   {
300     // All cases where the point lies to the left of P.
301     constexpr float x = p.x - 1;
302     CheckRelativePosition(curve, {x, p.y + 1}, kBelow);  // A
303     CheckRelativePosition(curve, {x, p.y + 0}, kBelow);  // B
304     CheckRelativePosition(curve, {x, p.y - 1}, kBelow);  // C
305   }
306 
307   {
308     // All cases where the point has the same x-value as P.
309     constexpr float x = p.x + 0;
310     CheckRelativePosition(curve, {x, p.y + 1}, kOn);     // D
311     CheckRelativePosition(curve, {x, p.y + 0}, kOn);     // P
312     CheckRelativePosition(curve, {x, p.y - 1}, kBelow);  // E
313   }
314 
315   {
316     // All cases where the point lies to the right of P.
317     constexpr float x = p.x + 1;
318     CheckRelativePosition(curve, {x, p.y + 1}, kAbove);  // F
319     CheckRelativePosition(curve, {x, p.y + 0}, kOn);     // G
320     CheckRelativePosition(curve, {x, p.y - 1}, kBelow);  // H
321   }
322 }
323 
324 // Test that the relative position of two curves is computed correctly when
325 // the two curves have the same projection on the X-axis.
TEST(ThresholdCurveTest,TwoCurvesSegmentHasSameProjectionAxisX)326 TEST(ThresholdCurveTest, TwoCurvesSegmentHasSameProjectionAxisX) {
327   //  ^                        //
328   //  | C1 + C2                //
329   //  |  |                     //
330   //  |  |\                    //
331   //  |  | \                   //
332   //  |   \ \                  //
333   //  |    \ \                 //
334   //  |     \ \                //
335   //  |      \ -------- C2     //
336   //  |       --------- C1     //
337   //  *--------------------->  //
338 
339   constexpr ThresholdCurve::Point c1_left{5, 10};
340   constexpr ThresholdCurve::Point c1_right{10, 5};
341   const ThresholdCurve c1_curve(c1_left, c1_right);
342 
343   // Same x-values, but higher on Y. (Can be parallel, but doesn't have to be.)
344   constexpr ThresholdCurve::Point c2_left{c1_left.x, c1_left.y + 20};
345   constexpr ThresholdCurve::Point c2_right{c1_right.x, c1_right.y + 10};
346   const ThresholdCurve c2_curve(c2_left, c2_right);
347 
348   EXPECT_TRUE(c1_curve <= c2_curve);
349   EXPECT_FALSE(c2_curve <= c1_curve);
350 }
351 
352 // Test that the relative position of two curves is computed correctly when
353 // the higher curve's projection on the X-axis is a strict subset of the
354 // lower curve's projection on the X-axis (on both ends).
TEST(ThresholdCurveTest,TwoCurvesSegmentOfHigherSubsetProjectionAxisX)355 TEST(ThresholdCurveTest, TwoCurvesSegmentOfHigherSubsetProjectionAxisX) {
356   //  ^                       //
357   //  | C1    C2              //
358   //  |  |    |               //
359   //  |  |    |               //
360   //  |   \   |               //
361   //  |    \  |               //
362   //  |     \ \               //
363   //  |      \ \              //
364   //  |       \ --------- C2  //
365   //  |        \              //
366   //  |         \             //
367   //  |          ---------C1  //
368   //  *---------------------> //
369 
370   constexpr ThresholdCurve::Point c1_left{5, 10};
371   constexpr ThresholdCurve::Point c1_right{10, 5};
372   const ThresholdCurve c1_curve(c1_left, c1_right);
373 
374   constexpr ThresholdCurve::Point c2_left{6, 11};
375   constexpr ThresholdCurve::Point c2_right{9, 7};
376   const ThresholdCurve c2_curve(c2_left, c2_right);
377 
378   EXPECT_TRUE(c1_curve <= c2_curve);
379   EXPECT_FALSE(c2_curve <= c1_curve);
380 }
381 
382 // Test that the relative position of two curves is computed correctly when
383 // the higher curve's right point is above lower curve's horizontal ray (meaning
384 // the higher curve's projection on the X-axis extends further right than
385 // the lower curve's).
TEST(ThresholdCurveTest,TwoCurvesRightPointOfHigherCurveAboveHorizontalRayOfLower)386 TEST(ThresholdCurveTest,
387      TwoCurvesRightPointOfHigherCurveAboveHorizontalRayOfLower) {
388   //  ^                        //
389   //  | C1 + C2                //
390   //  |  |                     //
391   //  |  |\                    //
392   //  |  | \                   //
393   //  |  |  \                  //
394   //  |  |   \                 //
395   //  |  |    \                //
396   //  |   \    \               //
397   //  |    \    \              //
398   //  |     \    \             //
399   //  |      \    ----- C2     //
400   //  |       --------- C1     //
401   //  *--------------------->  //
402 
403   constexpr ThresholdCurve::Point c1_left{5, 10};
404   constexpr ThresholdCurve::Point c1_right{10, 5};
405   const ThresholdCurve c1_curve(c1_left, c1_right);
406 
407   constexpr ThresholdCurve::Point c2_left{c1_left.x, c1_left.y + 1};
408   constexpr ThresholdCurve::Point c2_right{c1_right.x + 1, c1_right.y + 1};
409   const ThresholdCurve c2_curve(c2_left, c2_right);
410 
411   EXPECT_TRUE(c1_curve <= c2_curve);
412   EXPECT_FALSE(c2_curve <= c1_curve);
413 }
414 
415 // Test that the relative position of two curves is computed correctly when
416 // the higher curve's points are on the lower curve's rays (left point on the
417 // veritcal ray, right point on the horizontal ray).
TEST(ThresholdCurveTest,TwoCurvesPointsOfHigherOnRaysOfLower)418 TEST(ThresholdCurveTest, TwoCurvesPointsOfHigherOnRaysOfLower) {
419   //  ^
420   //  | C1 + C2               //
421   //  |  |                    //
422   //  |  |\                   //
423   //  |  | \                  //
424   //  |   \ \                 //
425   //  |    \ \                //
426   //  |     \ \               //
427   //  |      \ \              //
428   //  |       ----- C1 + C2   //
429   //  *---------------------> //
430 
431   constexpr ThresholdCurve::Point c1_left{5, 10};
432   constexpr ThresholdCurve::Point c1_right{10, 5};
433   const ThresholdCurve c1_curve(c1_left, c1_right);
434 
435   // Same x-values, but one of the points is higher on Y (the other isn't).
436   constexpr ThresholdCurve::Point c2_left{c1_left.x, c1_left.y + 2};
437   constexpr ThresholdCurve::Point c2_right{c1_right.x + 3, c1_right.y};
438   const ThresholdCurve c2_curve(c2_left, c2_right);
439 
440   EXPECT_TRUE(c1_curve <= c2_curve);
441   EXPECT_FALSE(c2_curve <= c1_curve);
442 }
443 
444 // Test that the relative position of two curves is computed correctly when
445 // the second curve's segment intersects the first curve's vertical ray.
TEST(ThresholdCurveTest,SecondCurveCrossesVerticalRayOfFirstCurve)446 TEST(ThresholdCurveTest, SecondCurveCrossesVerticalRayOfFirstCurve) {
447   //  ^                       //
448   //  | C2 C1                 //
449   //  |  | |                  //
450   //  |   \|                  //
451   //  |    |                  //
452   //  |    |\                 //
453   //  |    | \                //
454   //  |     \ \               //
455   //  |      \ \              //
456   //  |       \ \             //
457   //  |        \ ------- C2   //
458   //  |         -------- C1   //
459   //  *---------------------> //
460 
461   constexpr ThresholdCurve::Point c1_left{5, 10};
462   constexpr ThresholdCurve::Point c1_right{10, 5};
463   const ThresholdCurve c1_curve(c1_left, c1_right);
464 
465   constexpr ThresholdCurve::Point c2_left{c1_left.x - 1, c1_left.y + 1};
466   constexpr ThresholdCurve::Point c2_right{c1_right.x, c1_right.y + 1};
467   const ThresholdCurve c2_curve(c2_left, c2_right);
468 
469   EXPECT_FALSE(c1_curve <= c2_curve);
470   EXPECT_FALSE(c2_curve <= c1_curve);
471 }
472 
473 // Test that the relative position of two curves is computed correctly when
474 // the second curve's segment intersects the first curve's horizontal ray.
TEST(ThresholdCurveTest,SecondCurveCrossesHorizontalRayOfFirstCurve)475 TEST(ThresholdCurveTest, SecondCurveCrossesHorizontalRayOfFirstCurve) {
476   //  ^                      //
477   //  | C1 +  C2             //
478   //  |  |                   //
479   //  |  |\                  //
480   //  |  \ \                 //
481   //  |   \ \                //
482   //  |    \ \               //
483   //  |     \ \              //
484   //  |      ----------- C1  //
485   //  |         \            //
486   //  |          ------- C2  //
487   //  *--------------------> //
488 
489   constexpr ThresholdCurve::Point c1_left{5, 10};
490   constexpr ThresholdCurve::Point c1_right{10, 5};
491   const ThresholdCurve c1_curve(c1_left, c1_right);
492 
493   constexpr ThresholdCurve::Point c2_left{c1_left.x, c1_left.y + 1};
494   constexpr ThresholdCurve::Point c2_right{c1_right.x + 2, c1_right.y - 1};
495   const ThresholdCurve c2_curve(c2_left, c2_right);
496 
497   EXPECT_FALSE(c1_curve <= c2_curve);
498   EXPECT_FALSE(c2_curve <= c1_curve);
499 }
500 
501 // Test that the relative position of two curves is computed correctly when
502 // the second curve's segment intersects the first curve's segment.
TEST(ThresholdCurveTest,TwoCurvesWithCrossingSegments)503 TEST(ThresholdCurveTest, TwoCurvesWithCrossingSegments) {
504   //  ^                           //
505   //  | C2 C1                     //
506   //  | |  |                      //
507   //  | |  |                      //
508   //  | |  \                      //
509   //  | |   \                     //
510   //  |  -_  \                    //
511   //  |    -_ \                   //
512   //  |      -_\                  //
513   //  |        -_                 //
514   //  |          \-_              //
515   //  |           \ ---------- C2 //
516   //  |            ----------- C1 //
517   //  |                           //
518   //  |                           //
519   //  *-------------------------> //
520 
521   constexpr ThresholdCurve::Point c1_left{5, 10};
522   constexpr ThresholdCurve::Point c1_right{10, 5};
523   const ThresholdCurve c1_curve(c1_left, c1_right);
524 
525   constexpr ThresholdCurve::Point c2_left{4, 9};
526   constexpr ThresholdCurve::Point c2_right{10, 6};
527   const ThresholdCurve c2_curve(c2_left, c2_right);
528 
529   // The test is structured so that the two curves intersect at (8, 7).
530   RTC_CHECK(!c1_curve.IsAboveCurve({8, 7}));
531   RTC_CHECK(!c1_curve.IsBelowCurve({8, 7}));
532   RTC_CHECK(!c2_curve.IsAboveCurve({8, 7}));
533   RTC_CHECK(!c2_curve.IsBelowCurve({8, 7}));
534 
535   EXPECT_FALSE(c1_curve <= c2_curve);
536   EXPECT_FALSE(c2_curve <= c1_curve);
537 }
538 
539 // Test that the relative position of two curves is computed correctly when
540 // both curves are identical.
TEST(ThresholdCurveTest,IdenticalCurves)541 TEST(ThresholdCurveTest, IdenticalCurves) {
542   //  ^                       //
543   //  |  C1 + C2              //
544   //  |  |                    //
545   //  |  |                    //
546   //  |   \                   //
547   //  |    \                  //
548   //  |     \                 //
549   //  |      ------- C1 + C2  //
550   //  *---------------------> //
551 
552   constexpr ThresholdCurve::Point left{5, 10};
553   constexpr ThresholdCurve::Point right{10, 5};
554 
555   const ThresholdCurve c1_curve(left, right);
556   const ThresholdCurve c2_curve(left, right);
557 
558   EXPECT_TRUE(c1_curve <= c2_curve);
559   EXPECT_TRUE(c2_curve <= c1_curve);
560 }
561 
562 // Test that the relative position of two curves is computed correctly when
563 // they are "nearly identical" - the first curve's segment is contained within
564 // the second curve's segment, but the second curve's segment extends further
565 // to the left (which also produces separate vertical rays for the curves).
TEST(ThresholdCurveTest,NearlyIdenticalCurvesSecondContinuesOnOtherLeftSide)566 TEST(ThresholdCurveTest, NearlyIdenticalCurvesSecondContinuesOnOtherLeftSide) {
567   //  ^                       //
568   //  | C2 C1                 //
569   //  |  | |                  //
570   //  |  | |                  //
571   //  |   \|                  //
572   //  |    |                  //
573   //  |     \                 //
574   //  |      \                //
575   //  |       \               //
576   //  |        ----- C1 + C2  //
577   //  *---------------------> //
578 
579   constexpr ThresholdCurve::Point c1_left{5, 10};
580   constexpr ThresholdCurve::Point c1_right{10, 5};
581   const ThresholdCurve c1_curve(c1_left, c1_left);
582 
583   constexpr ThresholdCurve::Point c2_left{c1_left.x - 1, c1_left.y + 1};
584   constexpr ThresholdCurve::Point c2_right = c1_right;
585   const ThresholdCurve c2_curve(c2_left, c2_right);
586 
587   EXPECT_FALSE(c1_curve <= c2_curve);
588   EXPECT_TRUE(c2_curve <= c1_curve);
589 }
590 
591 // Test that the relative position of two curves is computed correctly when
592 // they are "nearly identical" - the first curve's segment is contained within
593 // the second curve's segment, but the second curve's segment extends further
594 // to the right (which also produces separate horizontal rays for the curves).
TEST(ThresholdCurveTest,NearlyIdenticalCurvesSecondContinuesOnOtherRightSide)595 TEST(ThresholdCurveTest, NearlyIdenticalCurvesSecondContinuesOnOtherRightSide) {
596   //  ^                       //
597   //  | C1 + C2               //
598   //  |  |                    //
599   //  |  |                    //
600   //  |   \                   //
601   //  |    \                  //
602   //  |     \                 //
603   //  |      \----------- C1  //
604   //  |       \               //
605   //  |        ---------- C2  //
606   //  *---------------------> //
607 
608   constexpr ThresholdCurve::Point c1_left{5, 10};
609   constexpr ThresholdCurve::Point c1_right{10, 5};
610   const ThresholdCurve c1_curve(c1_left, c1_left);
611 
612   constexpr ThresholdCurve::Point c2_left = c1_left;
613   constexpr ThresholdCurve::Point c2_right{c1_right.x + 1, c1_right.y - 1};
614   const ThresholdCurve c2_curve(c2_left, c2_right);
615 
616   EXPECT_FALSE(c1_curve <= c2_curve);
617   EXPECT_TRUE(c2_curve <= c1_curve);
618 }
619 
620 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
621 // The higher-left point must be given as the first point, and the lower-right
622 // point must be given as the second.
623 // This necessarily produces a non-positive slope.
TEST(ThresholdCurveDeathTest,WrongOrderPoints)624 TEST(ThresholdCurveDeathTest, WrongOrderPoints) {
625   std::unique_ptr<ThresholdCurve> curve;
626   constexpr ThresholdCurve::Point left{5, 10};
627   constexpr ThresholdCurve::Point right{10, 5};
628   EXPECT_DEATH(curve.reset(new ThresholdCurve(right, left)), "");
629 }
630 #endif
631 
632 }  // namespace webrtc
633