Bug 1454606 - Test scalar semantics when pending operations are applied. r?dexter draft
authorJan-Erik Rediger <jrediger@mozilla.com>
Wed, 23 May 2018 12:00:38 +0200
changeset 802597 556c2536b938f9acb0b296e20063e8e387500267
parent 801426 5d8077e674f8e51bfb60ceefd2d3eb205f3afd51
child 802598 4929bea70c5ecfabdd09cd4545ca630652980f51
push id111924
push userbmo:jrediger@mozilla.com
push dateFri, 01 Jun 2018 08:01:16 +0000
reviewersdexter
bugs1454606
milestone62.0a1
Bug 1454606 - Test scalar semantics when pending operations are applied. r?dexter MozReview-Commit-ID: KXzuIHaBbIb
toolkit/components/telemetry/geckoview/gtest/TestGeckoView.cpp
--- a/toolkit/components/telemetry/geckoview/gtest/TestGeckoView.cpp
+++ b/toolkit/components/telemetry/geckoview/gtest/TestGeckoView.cpp
@@ -470,8 +470,177 @@ TEST_F(TelemetryGeckoViewFixture, TimerH
 
   // Verify that the scalars were correctly persisted and restored.
   CheckUintScalar("telemetry.persistence_timer_hit_count", cx.GetJSContext(),
                   scalarsSnapshot, 2);
 
   // Cleanup/remove the files.
   RemovePersistenceFile();
 }
+
+TEST_F(TelemetryGeckoViewFixture, EmptyPendingOperations) {
+  AutoJSContextWithGlobal cx(mCleanGlobal);
+
+  Unused << mTelemetry->ClearScalars();
+
+  // Force loading mode
+  TelemetryScalar::DeserializationStarted();
+
+  // Do nothing explicitely
+
+  // Force pending operations to be applied and end load mode.
+  // It should not crash and don't change any scalars.
+  TelemetryScalar::ApplyPendingOperations();
+
+  // Check that the snapshot is empty
+  JS::RootedValue scalarsSnapshot(cx.GetJSContext());
+  GetScalarsSnapshot(false, cx.GetJSContext(), &scalarsSnapshot);
+
+  ASSERT_TRUE(scalarsSnapshot.isUndefined()) << "Scalars snapshot should not contain any data.";
+}
+
+TEST_F(TelemetryGeckoViewFixture, SimpleAppendOperation) {
+  AutoJSContextWithGlobal cx(mCleanGlobal);
+
+  Unused << mTelemetry->ClearScalars();
+
+  // Set an initial value, so we can test that it is not overwritten.
+  uint32_t initialValue = 1;
+  Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_UNSIGNED_INT_KIND, initialValue);
+
+  // Force loading mode
+  TelemetryScalar::DeserializationStarted();
+
+  // Add to a scalar
+  uint32_t value = 37;
+  Telemetry::ScalarAdd(Telemetry::ScalarID::TELEMETRY_TEST_UNSIGNED_INT_KIND, value);
+
+  // Verify that this was not yet applied.
+  JS::RootedValue scalarsSnapshot(cx.GetJSContext());
+  GetScalarsSnapshot(false, cx.GetJSContext(), &scalarsSnapshot);
+
+  CheckUintScalar("telemetry.test.unsigned_int_kind", cx.GetJSContext(), scalarsSnapshot, initialValue);
+
+  // Force pending operations to be applied and end load mode
+  TelemetryScalar::ApplyPendingOperations();
+
+  // Verify recorded operations are applied
+  GetScalarsSnapshot(false, cx.GetJSContext(), &scalarsSnapshot);
+  CheckUintScalar("telemetry.test.unsigned_int_kind", cx.GetJSContext(), scalarsSnapshot, initialValue+value);
+}
+
+TEST_F(TelemetryGeckoViewFixture, ApplyPendingOperationsAfterLoad) {
+  AutoJSContextWithGlobal cx(mCleanGlobal);
+
+  Unused << mTelemetry->ClearScalars();
+
+  const char persistedData[] = R"({
+ "scalars": {
+  "parent": {
+   "telemetry.test.unsigned_int_kind": 14
+  }
+ }
+})";
+
+  // Force loading mode
+  TelemetryScalar::DeserializationStarted();
+
+  // Add to a scalar, this should be recorded
+  uint32_t addValue = 10;
+  Telemetry::ScalarAdd(Telemetry::ScalarID::TELEMETRY_TEST_UNSIGNED_INT_KIND, addValue);
+
+  // Load persistence file
+  RefPtr<DataLoadedObserver> loadingFinished = new DataLoadedObserver();
+  WritePersistenceFile(nsDependentCString(persistedData));
+  TelemetryGeckoViewPersistence::InitPersistence();
+  loadingFinished->WaitForNotification();
+
+  // At this point all pending operations should have been applied.
+
+  // Increment again, now directly applied
+  uint32_t val = 1;
+  Telemetry::ScalarAdd(Telemetry::ScalarID::TELEMETRY_TEST_UNSIGNED_INT_KIND, val);
+
+
+  JS::RootedValue scalarsSnapshot(cx.GetJSContext());
+  GetScalarsSnapshot(false, cx.GetJSContext(), &scalarsSnapshot);
+
+  uint32_t expectedValue = 25;
+  CheckUintScalar("telemetry.test.unsigned_int_kind", cx.GetJSContext(), scalarsSnapshot, expectedValue);
+}
+
+TEST_F(TelemetryGeckoViewFixture, MultipleAppendOperations) {
+  AutoJSContextWithGlobal cx(mCleanGlobal);
+
+  Unused << mTelemetry->ClearScalars();
+
+  // Force loading mode
+  TelemetryScalar::DeserializationStarted();
+
+  // Modify all kinds of scalars
+  uint32_t startValue = 35;
+  uint32_t expectedValue = 40;
+  Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_UNSIGNED_INT_KIND, startValue);
+  Telemetry::ScalarSetMaximum(Telemetry::ScalarID::TELEMETRY_TEST_UNSIGNED_INT_KIND, startValue + 2);
+  Telemetry::ScalarAdd(Telemetry::ScalarID::TELEMETRY_TEST_UNSIGNED_INT_KIND, 3);
+
+  Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_BOOLEAN_KIND, true);
+  Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_STRING_KIND, NS_LITERAL_STRING("Star Wars VI"));
+
+  // Modify all kinds of keyed scalars
+  Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_KEYED_UNSIGNED_INT,
+      NS_LITERAL_STRING("chewbacca"), startValue);
+  Telemetry::ScalarSetMaximum(Telemetry::ScalarID::TELEMETRY_TEST_KEYED_UNSIGNED_INT,
+      NS_LITERAL_STRING("chewbacca"), startValue + 2);
+  Telemetry::ScalarAdd(Telemetry::ScalarID::TELEMETRY_TEST_KEYED_UNSIGNED_INT,
+      NS_LITERAL_STRING("chewbacca"), 3);
+
+  Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_KEYED_BOOLEAN_KIND,
+      NS_LITERAL_STRING("chewbacca"),
+      true);
+
+  // Force pending operations to be applied and end load mode
+  TelemetryScalar::ApplyPendingOperations();
+
+  JS::RootedValue scalarsSnapshot(cx.GetJSContext());
+  JS::RootedValue keyedScalarsSnapshot(cx.GetJSContext());
+  GetScalarsSnapshot(false, cx.GetJSContext(), &scalarsSnapshot);
+  GetScalarsSnapshot(true, cx.GetJSContext(), &keyedScalarsSnapshot);
+
+  CheckUintScalar("telemetry.test.unsigned_int_kind", cx.GetJSContext(), scalarsSnapshot, expectedValue);
+  CheckBoolScalar("telemetry.test.boolean_kind", cx.GetJSContext(), scalarsSnapshot, true);
+  CheckStringScalar("telemetry.test.string_kind", cx.GetJSContext(), scalarsSnapshot, "Star Wars VI");
+
+  CheckKeyedUintScalar("telemetry.test.keyed_unsigned_int", "chewbacca",
+      cx.GetJSContext(), keyedScalarsSnapshot, expectedValue);
+  CheckKeyedBoolScalar("telemetry.test.keyed_boolean_kind", "chewbacca",
+      cx.GetJSContext(), keyedScalarsSnapshot, true);
+}
+
+TEST_F(TelemetryGeckoViewFixture, PendingOperationsHighWater) {
+  AutoJSContextWithGlobal cx(mCleanGlobal);
+
+  Unused << mTelemetry->ClearScalars();
+
+  uint32_t initialValue = 0;
+  Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_UNSIGNED_INT_KIND, initialValue);
+
+  // Force loading mode
+  TelemetryScalar::DeserializationStarted();
+
+  // Fill up the pending operations list
+  uint32_t expectedValue = 10000;
+  for (uint32_t i=0; i < expectedValue; i++) {
+    Telemetry::ScalarAdd(Telemetry::ScalarID::TELEMETRY_TEST_UNSIGNED_INT_KIND, 1);
+  }
+
+  // Nothing should be applied yet
+  JS::RootedValue scalarsSnapshot(cx.GetJSContext());
+  GetScalarsSnapshot(false, cx.GetJSContext(), &scalarsSnapshot);
+  CheckUintScalar("telemetry.test.unsigned_int_kind", cx.GetJSContext(), scalarsSnapshot, 0);
+
+  // Spill over the buffer to immediately apply all operations
+  Telemetry::ScalarAdd(Telemetry::ScalarID::TELEMETRY_TEST_UNSIGNED_INT_KIND, 1);
+
+  // Now we should see all values
+  GetScalarsSnapshot(false, cx.GetJSContext(), &scalarsSnapshot);
+  CheckUintScalar("telemetry.test.unsigned_int_kind", cx.GetJSContext(), scalarsSnapshot, expectedValue+1);
+}