summaryrefslogtreecommitdiffstats
path: root/toolkit/components/glean/gtest/TestFog.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/glean/gtest/TestFog.cpp')
-rw-r--r--toolkit/components/glean/gtest/TestFog.cpp220
1 files changed, 220 insertions, 0 deletions
diff --git a/toolkit/components/glean/gtest/TestFog.cpp b/toolkit/components/glean/gtest/TestFog.cpp
new file mode 100644
index 0000000000..16add5b973
--- /dev/null
+++ b/toolkit/components/glean/gtest/TestFog.cpp
@@ -0,0 +1,220 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "gtest/gtest.h"
+#include "mozilla/glean/GleanMetrics.h"
+#include "mozilla/glean/GleanPings.h"
+#include "mozilla/glean/fog_ffi_generated.h"
+#include "mozilla/Maybe.h"
+#include "mozilla/Tuple.h"
+#include "nsTArray.h"
+
+#include "mozilla/Preferences.h"
+#include "mozilla/Unused.h"
+#include "nsString.h"
+#include "prtime.h"
+
+using mozilla::Preferences;
+using namespace mozilla::glean;
+using namespace mozilla::glean::impl;
+
+#define DATA_PREF "datareporting.healthreport.uploadEnabled"
+
+extern "C" {
+// This function is called by the rust code in test.rs if a non-fatal test
+// failure occurs.
+void GTest_FOG_ExpectFailure(const char* aMessage) {
+ EXPECT_STREQ(aMessage, "");
+}
+}
+
+// Initialize FOG exactly once.
+// This needs to be the first test to run!
+TEST(FOG, FogInitDoesntCrash)
+{
+ Preferences::SetInt("telemetry.fog.test.localhost_port", -1);
+ ASSERT_EQ(NS_OK, fog_init());
+ // Fog init isn't actually done (it passes work to a background thread)
+ Preferences::SetBool(DATA_PREF, false);
+ Preferences::SetBool(DATA_PREF, true);
+}
+
+// TODO: to be enabled after changes from bug 1677455 are vendored.
+// extern "C" void Rust_MeasureInitializeTime();
+// TEST(FOG, TestMeasureInitializeTime)
+// { Rust_MeasureInitializeTime(); }
+
+TEST(FOG, BuiltinPingsRegistered)
+{
+ Preferences::SetInt("telemetry.fog.test.localhost_port", -1);
+ nsAutoCString metricsPingName("metrics");
+ nsAutoCString baselinePingName("baseline");
+ nsAutoCString eventsPingName("events");
+ ASSERT_EQ(NS_OK, fog_submit_ping(&metricsPingName));
+ ASSERT_EQ(NS_OK, fog_submit_ping(&baselinePingName));
+ ASSERT_EQ(NS_OK, fog_submit_ping(&eventsPingName));
+}
+
+TEST(FOG, TestCppCounterWorks)
+{
+ mozilla::glean::test_only::bad_code.Add(42);
+
+ ASSERT_EQ(
+ 42,
+ mozilla::glean::test_only::bad_code.TestGetValue("test-ping"_ns).value());
+ // And test that the ping name's optional, while you're at it:
+ ASSERT_EQ(42, test_only::bad_code.TestGetValue().value());
+}
+
+TEST(FOG, TestCppStringWorks)
+{
+ auto kValue = "cheez!"_ns;
+ mozilla::glean::test_only::cheesy_string.Set(kValue);
+
+ ASSERT_STREQ(kValue.get(), mozilla::glean::test_only::cheesy_string
+ .TestGetValue("test-ping"_ns)
+ .value()
+ .get());
+}
+
+TEST(FOG, TestCppTimespanWorks)
+{
+ mozilla::glean::test_only::can_we_time_it.Start();
+ PR_Sleep(PR_MillisecondsToInterval(10));
+ mozilla::glean::test_only::can_we_time_it.Stop();
+
+ ASSERT_TRUE(
+ mozilla::glean::test_only::can_we_time_it.TestGetValue("test-ping"_ns)
+ .value() > 0);
+}
+
+TEST(FOG, TestCppUuidWorks)
+{
+ nsCString kTestUuid("decafdec-afde-cafd-ecaf-decafdecafde");
+ test_only::what_id_it.Set(kTestUuid);
+ ASSERT_STREQ(
+ kTestUuid.get(),
+ test_only::what_id_it.TestGetValue("test-ping"_ns).value().get());
+
+ test_only::what_id_it.GenerateAndSet();
+ // Since we generate v4 UUIDs, and the first character of the third group
+ // isn't 4, this won't ever collide with kTestUuid.
+ ASSERT_STRNE(
+ kTestUuid.get(),
+ test_only::what_id_it.TestGetValue("test-ping"_ns).value().get());
+}
+
+TEST(FOG, TestCppBooleanWorks)
+{
+ mozilla::glean::test_only::can_we_flag_it.Set(false);
+
+ ASSERT_EQ(false, mozilla::glean::test_only::can_we_flag_it
+ .TestGetValue("test-ping"_ns)
+ .value());
+}
+
+// TODO: to be enabled after changes from bug 1677448 are vendored.
+// TEST(FOG, TestCppDatetimeWorks)
+// {
+// PRExplodedTime date = {0, 35, 10, 12, 6, 10, 2020, 0, 0, {5 * 60 * 60, 0}};
+// test_only::what_a_date.Set(&date);
+//
+// auto received = test_only::what_a_date.TestGetValue("test-ping");
+// ASSERT_STREQ(received.value().get(), "2020-11-06T12:10:35+05:00");
+// }
+
+using mozilla::MakeTuple;
+using mozilla::Tuple;
+using mozilla::glean::test_only_ipc::AnEventKeys;
+
+TEST(FOG, TestCppEventWorks)
+{
+ test_only_ipc::no_extra_event.Record();
+ ASSERT_TRUE(test_only_ipc::no_extra_event.TestGetValue("store1"_ns).isSome());
+
+ // Ugh, this API...
+ nsTArray<Tuple<test_only_ipc::AnEventKeys, nsCString>> extra;
+ nsCString val = "can set extras"_ns;
+ extra.AppendElement(MakeTuple(AnEventKeys::Extra1, val));
+
+ test_only_ipc::an_event.Record(std::move(extra));
+ ASSERT_TRUE(test_only_ipc::an_event.TestGetValue("store1"_ns).isSome());
+}
+
+TEST(FOG, TestCppMemoryDistWorks)
+{
+ test_only::do_you_remember.Accumulate(7);
+ test_only::do_you_remember.Accumulate(17);
+
+ DistributionData data =
+ test_only::do_you_remember.TestGetValue("test-ping"_ns).ref();
+ // Sum is in bytes, test_only::do_you_remember is in megabytes. So
+ // multiplication ahoy!
+ ASSERT_EQ(data.sum, 24UL * 1024 * 1024);
+ for (auto iter = data.values.Iter(); !iter.Done(); iter.Next()) {
+ const uint64_t bucket = iter.Key();
+ const uint64_t count = iter.UserData();
+ ASSERT_TRUE(count == 0 ||
+ (count == 1 && (bucket == 17520006 || bucket == 7053950)))
+ << "Only two occupied buckets";
+ }
+}
+
+TEST(FOG, TestCppPings)
+{
+ auto ping = mozilla::glean_pings::OnePingOnly;
+ mozilla::Unused << ping;
+ // That's it. That's the test. It will fail to compile if it's missing.
+ // For a test that actually submits the ping, we have integration tests.
+ // See also bug 1681742.
+}
+
+TEST(FOG, TestCppStringLists)
+{
+ auto kValue = "cheez!"_ns;
+ auto kValue2 = "cheezier!"_ns;
+ auto kValue3 = "cheeziest."_ns;
+
+ nsTArray<nsCString> cheezList;
+ cheezList.EmplaceBack(kValue);
+ cheezList.EmplaceBack(kValue2);
+
+ test_only::cheesy_string_list.Set(cheezList);
+
+ auto val = test_only::cheesy_string_list.TestGetValue().value();
+ // Note: This is fragile if the order is ever not preserved.
+ ASSERT_STREQ(kValue.get(), val[0].get());
+ ASSERT_STREQ(kValue2.get(), val[1].get());
+
+ test_only::cheesy_string_list.Add(kValue3);
+
+ val = test_only::cheesy_string_list.TestGetValue().value();
+ ASSERT_STREQ(kValue3.get(), val[2].get());
+}
+
+TEST(FOG, TestCppTimingDistWorks)
+{
+ auto id1 = test_only::what_time_is_it.Start();
+ auto id2 = test_only::what_time_is_it.Start();
+ PR_Sleep(PR_MillisecondsToInterval(5));
+ auto id3 = test_only::what_time_is_it.Start();
+ test_only::what_time_is_it.Cancel(std::move(id1));
+ PR_Sleep(PR_MillisecondsToInterval(5));
+ test_only::what_time_is_it.StopAndAccumulate(std::move(id2));
+ test_only::what_time_is_it.StopAndAccumulate(std::move(id3));
+
+ DistributionData data = test_only::what_time_is_it.TestGetValue().ref();
+ const uint64_t NANOS_IN_MILLIS = 1e6;
+
+ // We don't know exactly how long those sleeps took, only that it was at
+ // least 15ms total.
+ ASSERT_GT(data.sum, (uint64_t)(15 * NANOS_IN_MILLIS));
+
+ // We also can't guarantee the buckets, but we can guarantee two samples.
+ uint64_t sampleCount = 0;
+ for (auto iter = data.values.Iter(); !iter.Done(); iter.Next()) {
+ sampleCount += iter.UserData();
+ }
+ ASSERT_EQ(sampleCount, (uint64_t)2);
+}