summaryrefslogtreecommitdiffstats
path: root/js/xpconnect/tests/marionette/test_preloader_telemetry.py
blob: 6eed275df432c4526bddf2d23a65ae3799c6abe3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# Any copyright is dedicated to the Public Domain.
# http://creativecommons.org/publicdomain/zero/1.0/

from __future__ import absolute_import

import time
import os
from marionette_harness import MarionetteTestCase

LABELS_SCRIPT_PRELOADER_REQUESTS = {
    "Hit": "0",
    "HitChild": "1",
    "Miss": "2",
}


class TestScriptPreloader(MarionetteTestCase):
    def test_preloader_requests_histogram(self):
        start_time = time.time()
        self.invalidate_caches()
        self.marionette.restart(clean=False, in_app=True)
        histogram = self.get_histogram("SCRIPT_PRELOADER_REQUESTS")
        misses = histogram.get(LABELS_SCRIPT_PRELOADER_REQUESTS["Miss"], 0)
        hits = histogram.get(LABELS_SCRIPT_PRELOADER_REQUESTS["Hit"], 0)
        child_hits = histogram.get(LABELS_SCRIPT_PRELOADER_REQUESTS["HitChild"], 0)
        self.assertMuchGreaterThan(misses, hits)
        self.assertMuchGreaterThan(misses, child_hits)

        profile = self.marionette.profile_path
        self.wait_for_file_change(
            start_time, "{}/startupCache/scriptCache.bin".format(profile)
        )
        self.wait_for_file_change(
            start_time, "{}/startupCache/scriptCache-child.bin".format(profile)
        )
        self.marionette.restart(clean=False, in_app=True)
        histogram = self.get_histogram("SCRIPT_PRELOADER_REQUESTS")
        misses = histogram.get(LABELS_SCRIPT_PRELOADER_REQUESTS["Miss"], 0)
        hits = histogram.get(LABELS_SCRIPT_PRELOADER_REQUESTS["Hit"], 0)
        child_hits = histogram.get(LABELS_SCRIPT_PRELOADER_REQUESTS["HitChild"], 0)
        # This is just heuristic. We certainly want to be made aware if this ratio
        # changes and we didn't intend it to.
        self.assertSimilar(misses, hits)
        self.assertNotEqual(child_hits, 0)

    def assertMuchGreaterThan(self, lhs, rhs):
        self.assertTrue(lhs > 4 * rhs)

    def assertSimilar(self, lhs, rhs):
        self.assertTrue(lhs < 2 * rhs)
        self.assertTrue(lhs > rhs / 2)

    def wait_for_file_change(self, start_time, path):
        expires = time.time() + 20
        while True:
            try:
                if os.stat(path).st_mtime > start_time:
                    return
                if time.time() > expires:
                    raise Exception("Never observed file change for {}".format(path))
                time.sleep(1)
            except OSError:
                pass

    def wait_for_observer_notification(self, name):
        with self.marionette.using_context(self.marionette.CONTEXT_CHROME):
            return self.marionette.execute_script(
                """
                let [resolve] = arguments;
                Services.obs.addObserver(() => resolve(), "{}");
            """.format(
                    name
                )
            )

    def get_histogram(self, name):
        with self.marionette.using_context(self.marionette.CONTEXT_CHROME):
            return self.marionette.execute_script(
                """
                let snapshot = Services.telemetry.getSnapshotForHistograms("main", true);
                return snapshot.parent.{}.values;
            """.format(
                    name
                )
            )

    def invalidate_caches(self):
        with self.marionette.using_context(self.marionette.CONTEXT_CHROME):
            return self.marionette.execute_script(
                "Services.obs.notifyObservers(null, 'startupcache-invalidate');"
            )