#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright 2021 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Tests for model.py."""
# TODO(crbug.com/40156926): Set up these tests to run on the tryjobs.
import sync.model as model
import unittest
class ModelTest(unittest.TestCase):
"""Tests for model.py."""
def assert_project(self, project, name, id_, summary, owners,
key_rotation_period):
self.assertEqual(project.name, name)
self.assertEqual(project.id, id_)
self.assertEqual(project.summary.strip(), summary)
self.assertEqual(len(project.owners), len(owners))
for actual, expected in zip(project.owners, owners):
self.assertEqual(actual, expected)
self.assertEqual(int(project.key_rotation_period), key_rotation_period)
def assert_event(self, event, name, summary):
self.assertEqual(event.name, name)
self.assertEqual(event.summary.strip(), summary)
def assert_metric(self, metric, name, type_, summary):
self.assertEqual(metric.name, name)
self.assertEqual(metric.type, type_)
self.assertEqual(metric.summary.strip(), summary)
def assert_model_raises(self, xml):
raised = False
try:
model.Model(xml, 'chrome')
except ValueError:
raised = True
self.assertTrue(raised)
def test_valid_xml(self):
xml = """\
<structured-metrics>
<project name="ProjectOne">
<owner>[email protected]</owner>
<owner>[email protected]</owner>
<id>none</id>
<scope>profile</scope>
<summary> Test project. </summary>
<key-rotation>65</key-rotation>
<event name="EventOne">
<summary> Test event. </summary>
<metric name="MetricOne" type="int">
<summary> Test metric. </summary>
</metric>
<metric name="MetricTwo" type="hmac-string">
<summary> Test metric. </summary>
</metric>
</event>
<event name="EventTwo">
<summary> Test event. </summary>
<metric name="MetricThree" type="int">
<summary> Test metric. </summary>
</metric>
</event>
</project>
<project name="ProjectTwo">
<owner>[email protected]</owner>
<id>uma</id>
<scope>device</scope>
<summary> Test project. </summary>
<event name="EventThree">
<summary> Test event. </summary>
<metric name="MetricFour" type="int">
<summary> Test metric. </summary>
</metric>
</event>
</project>
</structured-metrics>"""
data = model.Model(xml, 'chrome')
self.assertEqual(len(data.projects), 2)
project_one, project_two = data.projects
self.assert_project(project_one, 'ProjectOne', 'none', 'Test project.',
('[email protected]', '[email protected]'), 65)
self.assert_project(project_two, 'ProjectTwo', 'uma', 'Test project.',
('[email protected]', ),
model.DEFAULT_KEY_ROTATION_PERIOD)
self.assertEqual(len(project_one.events), 2)
self.assertEqual(len(project_two.events), 1)
event_one, event_two = project_one.events
event_three, = project_two.events
self.assert_event(event_one, 'EventOne', 'Test event.')
self.assert_event(event_two, 'EventTwo', 'Test event.')
self.assert_event(event_three, 'EventThree', 'Test event.')
self.assertEqual(len(event_one.metrics), 2)
self.assertEqual(len(event_two.metrics), 1)
self.assertEqual(len(event_three.metrics), 1)
metric_one, metric_two = event_one.metrics
metric_three, = event_two.metrics
metric_four, = event_three.metrics
self.assert_metric(metric_one, 'MetricOne', 'int', 'Test metric.')
self.assert_metric(metric_two, 'MetricTwo', 'hmac-string', 'Test metric.')
self.assert_metric(metric_three, 'MetricThree', 'int', 'Test metric.')
self.assert_metric(metric_four, 'MetricFour', 'int', 'Test metric.')
def test_owners_validation(self):
# No owner for project.
self.assert_model_raises("""\
<structured-metrics>
<project name="project">
<id>uma</id>
<summary> Test project. </summary>
<event name="EventThree">
<summary> Test event. </summary>
<metric name="MetricFour" type="int">
<summary> Test metric. </summary>
</metric>
</event>
</project>
</structured-metrics>""")
# Owner is username not email.
self.assert_model_raises("""\
<structured-metrics>
<project name="project">
<owner>test@</owner>
<id>uma</id>
<summary> Test project. </summary>
<event name="EventThree">
<summary> Test event. </summary>
<metric name="MetricFour" type="int">
<summary> Test metric. </summary>
</metric>
</event>
</project>
</structured-metrics>""")
def test_id_validation(self):
# Missing ID
self.assert_model_raises("""\
<structured-metrics>
<project name="MyProject">
<owner>[email protected]</owner>
<summary> Test project. </summary>
<event name="MyEvent">
<summary> Test event. </summary>
<metric name="MyMetric" type="int">
<summary> Test metric. </summary>
</metric>
</event>
</project>
</structured-metrics>""")
# Invalid ID
self.assert_model_raises("""\
<structured-metrics>
<project name="MyProject">
<owner>[email protected]</owner>
<id>invalid value</id>
<summary> Test project. </summary>
<event name="MyEvent">
<summary> Test event. </summary>
<metric name="MyMetric" type="int">
<summary> Test metric. </summary>
</metric>
</event>
</project>
</structured-metrics>""")
def test_type_validation(self):
# Missing type
self.assert_model_raises("""\
<structured-metrics>
<project name="MyProject">
<owner>[email protected]</owner>
<id>none</id>
<summary> Test project. </summary>
<event name="MyEvent">
<summary> Test event. </summary>
<metric name="MyMetric">
<summary> Test metric. </summary>
</metric>
</event>
</project>
</structured-metrics>""")
# Invalid type
self.assert_model_raises("""\
<structured-metrics>
<project name="MyProject">
<owner>[email protected]</owner>
<id>none</id>
<summary> Test project. </summary>
<event name="MyEvent">
<summary> Test event. </summary>
<metric name="MyMetric" type="invalid value">
<summary> Test metric. </summary>
</metric>
</event>
</project>
</structured-metrics>""")
def test_duplicate_summaries(self):
self.assert_model_raises("""\
<structured-metrics>
<project name="MyProject">
<owner>[email protected]</owner>
<id>none</id>
<summary> Test project. </summary>
<summary> Test project. </summary>
<event name="MyEvent">
<summary> Test event. </summary>
<metric name="MyMetric" type="int">
<summary> Test metric. </summary>
</metric>
</event>
</project>
</structured-metrics>""")
def test_duplicate_project_names(self):
# Two projects with name "Duplicate"
self.assert_model_raises("""\
<structured-metrics>
<project name="Duplicate">
<owner>test@</owner>
<id>uma</id>
<summary> Test project. </summary>
<event name="MyEvent">
<summary> Test event. </summary>
<metric name="MyMetric" type="int">
<summary> Test metric. </summary>
</metric>
</event>
</project>
<project name="Duplicate">
<owner>test@</owner>
<id>uma</id>
<summary> Test project. </summary>
<event name="MyEvent">
<summary> Test event. </summary>
<metric name="MyMetric" type="int">
<summary> Test metric. </summary>
</metric>
</event>
</project>
</structured-metrics>""")
def test_duplicate_event_names(self):
# Two events with name "Duplicate"
self.assert_model_raises("""\
<structured-metrics>
<project name="MyProject">
<owner>test@</owner>
<id>uma</id>
<summary> Test project. </summary>
<event name="Duplicate">
<summary> Test event. </summary>
<metric name="MyMetric" type="int">
<summary> Test metric. </summary>
</metric>
</event>
<event name="Duplicate">
<summary> Test event. </summary>
<metric name="MyMetric" type="int">
<summary> Test metric. </summary>
</metric>
</event>
</project>
</structured-metrics>""")
def test_duplicate_metric_names(self):
# Two metrics with name "Duplicate"
self.assert_model_raises("""\
<structured-metrics>
<project name="MyProject">
<owner>test@</owner>
<id>uma</id>
<summary> Test project. </summary>
<event name="MyEvent">
<summary> Test event. </summary>
<metric name="Duplicate" type="int">
<summary> Test metric. </summary>
</metric>
<metric name="Duplicate" type="int">
<summary> Test metric. </summary>
</metric>
</event>
</project>
</structured-metrics>""")
def test_key_rotation_validation(self):
# Key rotation not a number.
self.assert_model_raises("""\
<structured-metrics>
<project name="project">
<id>uma</id>
<summary> Test project. </summary>
<owner>[email protected]</owner>
<key-rotation>NaN123</key-rotation>
<event name="EventThree">
<summary> Test event. </summary>
<metric name="MetricFour" type="int">
<summary> Test metric. </summary>
</metric>
</event>
</project>
</structured-metrics>""")
if __name__ == '__main__':
unittest.main()