Bug 1376248 - Part 2: Allow tree_ordering sub-test to generate records in any order when simultaneously starting animations. r=birtles
authorCameron McCormack <cam@mcc.id.au>
Mon, 24 Jul 2017 16:03:42 +0800
changeset 615069 8b5b751e81df6f8cc9c7f6b3d678f084cb68e47a
parent 615068 f98953cb41ef6eecaa7c2d348974b4c584e37618
child 615070 ad4358c129b1d5ae50a3cba9145eafaddab19c2e
push id70238
push usergsquelart@mozilla.com
push dateTue, 25 Jul 2017 12:24:25 +0000
reviewersbirtles
bugs1376248
milestone56.0a1
Bug 1376248 - Part 2: Allow tree_ordering sub-test to generate records in any order when simultaneously starting animations. r=birtles MozReview-Commit-ID: AHkOA7DrXji
dom/animation/test/chrome/test_animation_observers_async.html
--- a/dom/animation/test/chrome/test_animation_observers_async.html
+++ b/dom/animation/test/chrome/test_animation_observers_async.html
@@ -139,16 +139,56 @@ function assert_records(expected, desc) 
   }
   for (var i = 0; i < records.length; i++) {
     assert_record_list(records[i].addedAnimations, expected[i].added, desc, i, "addedAnimations");
     assert_record_list(records[i].changedAnimations, expected[i].changed, desc, i, "changedAnimations");
     assert_record_list(records[i].removedAnimations, expected[i].removed, desc, i, "removedAnimations");
   }
 }
 
+function assert_records_any_order(expected, desc) {
+  // Generate a unique label for each Animation object.
+  let animation_labels = new Map();
+  let animation_counter = 0;
+  for (let record of gRecords) {
+    for (let a of [...record.addedAnimations, ...record.changedAnimations, ...record.removedAnimations]) {
+      if (!animation_labels.has(a)) {
+        animation_labels.set(a, ++animation_counter);
+      }
+    }
+  }
+  for (let record of expected) {
+    for (let a of [...record.added, ...record.changed, ...record.removed]) {
+      if (!animation_labels.has(a)) {
+        animation_labels.set(a, ++animation_counter);
+      }
+    }
+  }
+
+  function record_label(record) {
+    // Generate a label of the form:
+    //
+    //   <added-animations>:<changed-animations>:<removed-animations>
+    let added   = record.addedAnimations   || record.added;
+    let changed = record.changedAnimations || record.changed;
+    let removed = record.removedAnimations || record.removed;
+    return [added  .map(a => animation_labels.get(a)).sort().join(),
+            changed.map(a => animation_labels.get(a)).sort().join(),
+            removed.map(a => animation_labels.get(a)).sort().join()]
+           .join(":");
+  }
+
+  // Sort records by their label.
+  gRecords.sort((a, b) => record_label(a) < record_label(b));
+  expected.sort((a, b) => record_label(a) < record_label(b));
+
+  // Assert the sorted record lists are equal.
+  assert_records(expected, desc);
+}
+
 // -- Tests ------------------------------------------------------------------
 
 // We run all tests first targeting the div and observing the div, then again
 // targeting the div and observing its parent while using the subtree:true
 // MutationObserver option.
 
 [
   { observe: div,            target: div, subtree: false },
@@ -1109,29 +1149,27 @@ addAsyncAnimTest("tree_ordering", { obse
   var childBPseudoAnimations =
     [ for (x of docAnims) if (x.effect.target.parentElement == childB) x ];
 
   // The order in which we get the corresponding records is currently
   // based on the order we visit these nodes when updating styles.
   //
   // That is because we don't do any document-level batching of animation
   // mutation records when we flush styles. We may introduce that in the
-  // future but for now all we are interested in testing here is that the order
-  // these records are dispatched is consistent between runs.
-  //
-  // We currently expect to get records in order div::after, childA, childB,
-  // childB::before, div, div::before
+  // future but for now all we are interested in testing here is that the
+  // right records are generated, but we allow them to occur in any order.
   yield waitForFrame();
-  assert_records([{ added: divAfterAnimations, changed: [], removed: [] },
-                  { added: childAAnimations, changed: [], removed: [] },
-                  { added: childBAnimations, changed: [], removed: [] },
-                  { added: childBPseudoAnimations, changed: [], removed: [] },
-                  { added: divAnimations, changed: [], removed: [] },
-                  { added: divBeforeAnimations, changed: [], removed: [] }],
-                 "records after simultaneous animation start");
+  assert_records_any_order(
+    [{ added: divAfterAnimations, changed: [], removed: [] },
+     { added: childAAnimations, changed: [], removed: [] },
+     { added: childBAnimations, changed: [], removed: [] },
+     { added: childBPseudoAnimations, changed: [], removed: [] },
+     { added: divAnimations, changed: [], removed: [] },
+     { added: divBeforeAnimations, changed: [], removed: [] }],
+    "records after simultaneous animation start");
 
   // The one case where we *do* currently perform document-level (or actually
   // timeline-level) batching is when animations are updated from a refresh
   // driver tick. In particular, this means that when animations finish
   // naturally the removed records should be dispatched according to the
   // position of the elements in the tree.
 
   // First, flatten the set of animations. we put the animations targeting to