summaryrefslogtreecommitdiffstats
path: root/toolkit/components/telemetry/geckoview/gtest/TestGeckoViewStreaming.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/telemetry/geckoview/gtest/TestGeckoViewStreaming.cpp')
-rw-r--r--toolkit/components/telemetry/geckoview/gtest/TestGeckoViewStreaming.cpp237
1 files changed, 237 insertions, 0 deletions
diff --git a/toolkit/components/telemetry/geckoview/gtest/TestGeckoViewStreaming.cpp b/toolkit/components/telemetry/geckoview/gtest/TestGeckoViewStreaming.cpp
new file mode 100644
index 0000000000..ebaa7099a8
--- /dev/null
+++ b/toolkit/components/telemetry/geckoview/gtest/TestGeckoViewStreaming.cpp
@@ -0,0 +1,237 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "mozilla/gtest/MozAssertions.h"
+#include "mozilla/Preferences.h"
+#include "mozilla/Services.h"
+#include "mozilla/Telemetry.h"
+#include "nsIObserverService.h"
+#include "nsThreadUtils.h"
+#include "TelemetryFixture.h"
+#include "TelemetryTestHelpers.h"
+#include "streaming/GeckoViewStreamingTelemetry.h"
+
+using namespace mozilla;
+using namespace mozilla::Telemetry;
+using namespace TelemetryTestHelpers;
+using GeckoViewStreamingTelemetry::StreamingTelemetryDelegate;
+using mozilla::Telemetry::ScalarID;
+using ::testing::_;
+using ::testing::Eq;
+using ::testing::StrictMock;
+
+namespace {
+
+const char* kGeckoViewStreamingPref = "toolkit.telemetry.geckoview.streaming";
+const char* kBatchTimeoutPref = "toolkit.telemetry.geckoview.batchDurationMS";
+
+constexpr auto kTestHgramName = "TELEMETRY_TEST_STREAMING"_ns;
+constexpr auto kTestHgramName2 = "TELEMETRY_TEST_STREAMING_2"_ns;
+constexpr auto kTestCategoricalName = "TELEMETRY_TEST_CATEGORICAL_OPTOUT"_ns;
+const HistogramID kTestHgram = Telemetry::TELEMETRY_TEST_STREAMING;
+const HistogramID kTestHgram2 = Telemetry::TELEMETRY_TEST_STREAMING_2;
+
+class TelemetryStreamingFixture : public TelemetryTestFixture {
+ protected:
+ virtual void SetUp() {
+ TelemetryTestFixture::SetUp();
+ Preferences::SetBool(kGeckoViewStreamingPref, true);
+ Preferences::SetInt(kBatchTimeoutPref, 5000);
+ }
+ virtual void TearDown() {
+ TelemetryTestFixture::TearDown();
+ Preferences::SetBool(kGeckoViewStreamingPref, false);
+ GeckoViewStreamingTelemetry::RegisterDelegate(nullptr);
+ }
+};
+
+class MockDelegate : public StreamingTelemetryDelegate {
+ public:
+ MOCK_METHOD2(ReceiveHistogramSamples,
+ void(const nsCString& aHistogramName,
+ const nsTArray<uint32_t>& aSamples));
+ MOCK_METHOD2(ReceiveCategoricalHistogramSamples,
+ void(const nsCString& aHistogramName,
+ const nsTArray<uint32_t>& aSamples));
+ MOCK_METHOD2(ReceiveBoolScalarValue,
+ void(const nsCString& aScalarName, bool aValue));
+ MOCK_METHOD2(ReceiveStringScalarValue,
+ void(const nsCString& aScalarName, const nsCString& aValue));
+ MOCK_METHOD2(ReceiveUintScalarValue,
+ void(const nsCString& aScalarName, uint32_t aValue));
+}; // class MockDelegate
+
+TEST_F(TelemetryStreamingFixture, HistogramSamples) {
+ const uint32_t kSampleOne = 401;
+ const uint32_t kSampleTwo = 2019;
+
+ CopyableTArray<uint32_t> samplesArray;
+ samplesArray.AppendElement(kSampleOne);
+ samplesArray.AppendElement(kSampleTwo);
+
+ auto md = MakeRefPtr<MockDelegate>();
+ EXPECT_CALL(*md, ReceiveHistogramSamples(Eq(kTestHgramName),
+ Eq(std::move(samplesArray))));
+ GeckoViewStreamingTelemetry::RegisterDelegate(md);
+
+ Telemetry::Accumulate(Telemetry::TELEMETRY_TEST_STREAMING, kSampleOne);
+ Preferences::SetInt(kBatchTimeoutPref, 0);
+ Telemetry::Accumulate(Telemetry::TELEMETRY_TEST_STREAMING, kSampleTwo);
+}
+
+TEST_F(TelemetryStreamingFixture, CategoricalHistogramSamples) {
+ auto kSampleOne =
+ Telemetry::LABELS_TELEMETRY_TEST_CATEGORICAL_OPTOUT::CommonLabel;
+ auto kSampleTwo = Telemetry::LABELS_TELEMETRY_TEST_CATEGORICAL_OPTOUT::Label5;
+
+ CopyableTArray<uint32_t> samplesArray;
+ samplesArray.AppendElement(static_cast<uint32_t>(kSampleOne));
+ samplesArray.AppendElement(static_cast<uint32_t>(kSampleOne));
+ samplesArray.AppendElement(static_cast<uint32_t>(kSampleTwo));
+
+ auto md = MakeRefPtr<MockDelegate>();
+ EXPECT_CALL(*md, ReceiveCategoricalHistogramSamples(
+ Eq(kTestCategoricalName), Eq(std::move(samplesArray))));
+ GeckoViewStreamingTelemetry::RegisterDelegate(md);
+
+ Telemetry::AccumulateCategorical(kSampleOne);
+ Telemetry::AccumulateCategorical(kSampleOne);
+ Preferences::SetInt(kBatchTimeoutPref, 0);
+ Telemetry::AccumulateCategorical(kSampleTwo);
+}
+
+TEST_F(TelemetryStreamingFixture, MultipleHistograms) {
+ const uint32_t kSample1 = 400;
+ const uint32_t kSample2 = 1 << 31;
+ const uint32_t kSample3 = 7;
+ CopyableTArray<uint32_t> samplesArray1;
+ samplesArray1.AppendElement(kSample1);
+ samplesArray1.AppendElement(kSample2);
+ CopyableTArray<uint32_t> samplesArray2;
+ samplesArray2.AppendElement(kSample3);
+
+ auto md = MakeRefPtr<MockDelegate>();
+ EXPECT_CALL(*md, ReceiveHistogramSamples(Eq(kTestHgramName),
+ Eq(std::move(samplesArray1))));
+ EXPECT_CALL(*md, ReceiveHistogramSamples(Eq(kTestHgramName2),
+ Eq(std::move(samplesArray2))));
+
+ GeckoViewStreamingTelemetry::RegisterDelegate(md);
+
+ Telemetry::Accumulate(kTestHgram, kSample1);
+ Telemetry::Accumulate(kTestHgram2, kSample3);
+ Preferences::SetInt(kBatchTimeoutPref, 0);
+ Telemetry::Accumulate(kTestHgram, kSample2);
+}
+
+// If we can find a way to convert the expectation's arg into an stl container,
+// we can use gmock's own ::testing::UnorderedElementsAre() instead.
+auto MatchUnordered(uint32_t sample1, uint32_t sample2) {
+ CopyableTArray<uint32_t> samplesArray1;
+ samplesArray1.AppendElement(sample1);
+ samplesArray1.AppendElement(sample2);
+
+ CopyableTArray<uint32_t> samplesArray2;
+ samplesArray2.AppendElement(sample2);
+ samplesArray2.AppendElement(sample1);
+
+ return ::testing::AnyOf(Eq(std::move(samplesArray1)),
+ Eq(std::move(samplesArray2)));
+}
+
+TEST_F(TelemetryStreamingFixture, MultipleThreads) {
+ const uint32_t kSample1 = 4;
+ const uint32_t kSample2 = 14;
+
+ auto md = MakeRefPtr<MockDelegate>();
+ // In this test, samples for the second test hgram are uninteresting.
+ EXPECT_CALL(*md, ReceiveHistogramSamples(Eq(kTestHgramName2), _));
+ EXPECT_CALL(*md, ReceiveHistogramSamples(Eq(kTestHgramName),
+ MatchUnordered(kSample1, kSample2)));
+
+ GeckoViewStreamingTelemetry::RegisterDelegate(md);
+
+ nsCOMPtr<nsIThread> t1;
+ nsCOMPtr<nsIThread> t2;
+ nsCOMPtr<nsIThread> t3;
+
+ nsCOMPtr<nsIRunnable> r1 = NS_NewRunnableFunction(
+ "accumulate 4", [&]() { Telemetry::Accumulate(kTestHgram, kSample1); });
+ nsCOMPtr<nsIRunnable> r2 = NS_NewRunnableFunction(
+ "accumulate 14", [&]() { Telemetry::Accumulate(kTestHgram, kSample2); });
+
+ nsresult rv = NS_NewNamedThread("t1", getter_AddRefs(t1), r1);
+ EXPECT_NS_SUCCEEDED(rv);
+ rv = NS_NewNamedThread("t2", getter_AddRefs(t2), r2);
+ EXPECT_NS_SUCCEEDED(rv);
+
+ // Give the threads a chance to do their work.
+ PR_Sleep(PR_MillisecondsToInterval(1));
+
+ Preferences::SetInt(kBatchTimeoutPref, 0);
+ Telemetry::Accumulate(kTestHgram2, kSample1);
+}
+
+TEST_F(TelemetryStreamingFixture, ScalarValues) {
+ constexpr auto kBoolScalarName = "telemetry.test.boolean_kind"_ns;
+ constexpr auto kStringScalarName = "telemetry.test.string_kind"_ns;
+ constexpr auto kUintScalarName = "telemetry.test.unsigned_int_kind"_ns;
+
+ const bool kBoolScalarValue = true;
+ constexpr auto kStringScalarValue = "a string scalar value"_ns;
+ const uint32_t kUintScalarValue = 42;
+
+ auto md = MakeRefPtr<MockDelegate>();
+ EXPECT_CALL(
+ *md, ReceiveBoolScalarValue(Eq(kBoolScalarName), Eq(kBoolScalarValue)));
+ EXPECT_CALL(*md, ReceiveStringScalarValue(Eq(kStringScalarName),
+ Eq(kStringScalarValue)));
+ EXPECT_CALL(
+ *md, ReceiveUintScalarValue(Eq(kUintScalarName), Eq(kUintScalarValue)));
+
+ GeckoViewStreamingTelemetry::RegisterDelegate(md);
+
+ Telemetry::ScalarSet(ScalarID::TELEMETRY_TEST_BOOLEAN_KIND, kBoolScalarValue);
+ Telemetry::ScalarSet(ScalarID::TELEMETRY_TEST_STRING_KIND,
+ NS_ConvertUTF8toUTF16(kStringScalarValue));
+ Preferences::SetInt(kBatchTimeoutPref,
+ 0); // Trigger batch on next accumulation.
+ Telemetry::ScalarSet(ScalarID::TELEMETRY_TEST_UNSIGNED_INT_KIND,
+ kUintScalarValue);
+}
+
+TEST_F(TelemetryStreamingFixture, ExpiredHistogram) {
+ const HistogramID kExpiredHistogram = Telemetry::TELEMETRY_TEST_EXPIRED;
+ const uint32_t kSample = 401;
+
+ // Strict Mock fails on any method calls.
+ auto md = MakeRefPtr<StrictMock<MockDelegate>>();
+ GeckoViewStreamingTelemetry::RegisterDelegate(md);
+
+ Preferences::SetInt(kBatchTimeoutPref, 0);
+ Telemetry::Accumulate(kExpiredHistogram, kSample);
+}
+
+TEST_F(TelemetryStreamingFixture, SendOnAppBackground) {
+ constexpr auto kBoolScalarName = "telemetry.test.boolean_kind"_ns;
+ const bool kBoolScalarValue = true;
+ const char* kApplicationBackgroundTopic = "application-background";
+
+ auto md = MakeRefPtr<MockDelegate>();
+ EXPECT_CALL(
+ *md, ReceiveBoolScalarValue(Eq(kBoolScalarName), Eq(kBoolScalarValue)));
+
+ GeckoViewStreamingTelemetry::RegisterDelegate(md);
+ Telemetry::ScalarSet(ScalarID::TELEMETRY_TEST_BOOLEAN_KIND, kBoolScalarValue);
+
+ nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
+ ASSERT_TRUE(!!os)
+ << "Observer Service unavailable?!?!";
+ os->NotifyObservers(nullptr, kApplicationBackgroundTopic, nullptr);
+}
+
+} // namespace