Example #1
0
    def test_can_use_existing_connection(self):
        DS = TestDataSource([1, 2, 3], 3)
        C = DictConnection()
        R = Reporter(DS, db_connection=C)

        self.assertEqual(C.get_topic(R.topic_id)["name"], "topic")
        self.assertEqual(C.get_topic(R.topic_id)["fields"], ["number"])
Example #2
0
    def test_run_data_tools_topic_not_found(self):
        C = DictConnection()

        result = C.get_overview(['invalid_id'])
        self.assertEqual(result.get('statistics'), [])

        warnings = result.get('warnings')
        self.assertEqual(warnings[0], topic_not_found('invalid_id'))
Example #3
0
    def test_topic_is_validated_on_creation(self):
        data_tools_d = {"field": "number", "method": "average"}

        C = DictConnection()
        with self.assertRaises(ValidationError):
            C.add_topic("topic",
                        description="description",
                        fields=["number"],
                        data_tools=data_tools_d)
Example #4
0
    def test_add_data_validations(self):
        s = ServerHandlers(DictConnection())

        self._assert_status(404, s.add_data, None, dict(number=3))

        topic_id = self._create_topic(s, dict(name="topic", fields=["number"]))
        self._assert_status(400, s.add_data, topic_id, dict(letter="a"))
Example #5
0
    def test_add_data_get_data_and_get_latest_and_get_summary_get_overview(self):
        s = ServerHandlers(DictConnection())

        self._assert_status(404, s.get_latest, None)

        data_tools = [
            {"field":"number", "method":"line"},
        ]
        topic_id = self._create_topic(s, dict(name="topic", fields=["number"], data_tools=data_tools))

        self._assert_status(404, s.get_latest, topic_id)

        response = self._assert_status(200, s.get_data, topic_id, {})
        self.assertEqual(len(response), 0)

        self._assert_status(200, s.add_data, topic_id, dict(number=3))

        response = self._assert_status(200, s.get_latest, topic_id)
        self.assertEqual(response.get("number"), 3)

        self._assert_status(200, s.add_data, topic_id, dict(number=3))

        response = self._assert_status(200, s.get_data, topic_id, {})
        self.assertEqual(len(response), 2)

        self._assert_status(200, s.get_summary, topic_id, {})

        for i in range(5):
            self._assert_status(200, s.add_data, topic_id, dict(number=i))

        response = self._assert_status(200, s.get_overview, None, dict(aggregate_to=3))
        data = response["statistics"][0]["payload"]["data"]["datasets"][0]["data"]
        self.assertLessEqual(len(data), 3)
Example #6
0
    def test_summary_overview_aggregate(self):
        data_tools = [
            {
                "field": "number",
                "method": "line"
            },
        ]

        units_d = {"field": "number", "unit": "scalar"}

        C = DictConnection()
        topic_id = C.add_topic("topic",
                               description="description",
                               fields=["number"],
                               data_tools=data_tools,
                               units=[units_d])
        for i in range(10):
            C.add_data(topic_id, {"number": i})

        result = C.get_overview(aggregate_to=3)
        data = result["statistics"][0]["payload"]["data"]["datasets"][0][
            "data"]
        self.assertEqual(len(data), 3)

        result = C.get_summary(topic_id, aggregate_to=3)
        data = result["statistics"][0]["payload"]["data"]["datasets"][0][
            "data"]
        self.assertEqual(len(data), 3)
Example #7
0
    def test_get_latest_returns_latest_data_element_for_topic(self):
        C = DictConnection()
        topic_id = C.add_topic("topic",
                               description="description",
                               fields=["number"])
        C.add_data(topic_id, {"number": 3})
        C.add_data(topic_id, {"number": 2})
        C.add_data(topic_id, {"number": 1})

        latest = C.get_latest(topic_id)
        self.assertEqual(latest["number"], 1)
Example #8
0
    def test_get_summary_average_ignores_invalid_values(self):
        data_tools = [{"field": "number", "method": "average"}]

        C = DictConnection()
        topic_id = C.add_topic("topic",
                               description="description",
                               fields=["number"],
                               data_tools=data_tools)
        C.add_data(topic_id, {"number": 3})
        C.add_data(topic_id, {"number": None})
        C.add_data(topic_id, {"number": "Not a number"})
        summary = C.get_summary(topic_id)
        self.assertEqual(summary["topic"], "topic")
        self.assertEqual(summary["description"], "description")

        value = summary["statistics"][0]["payload"]
        self.assertAlmostEqual(value["value"], 3.0)
        self.assertEqual(value["field"], "number")
        self.assertEqual(value["type"], "average")
Example #9
0
    def test_overview_and_comparison_include_units(self):
        data_tools = [
            {
                "field": "number",
                "method": "latest"
            },
        ]

        units_d = {"field": "number", "unit": "scalar"}

        C = DictConnection()
        for i in range(3):
            topic_id = C.add_topic("topic_" + str(i),
                                   description="description",
                                   fields=["number"],
                                   data_tools=data_tools,
                                   units=[units_d])
            C.add_data(topic_id, {"number": i})
        overview = C.get_overview()
        self.assertEqual(overview["topic_names"],
                         ["topic_0", "topic_1", "topic_2"])
        self.assertEqual(overview["fields"], ["number"])

        self.assertEqual(len(overview["statistics"]), 3)
        self.assertEqual(overview["statistics"][0]["payload"]["unit"],
                         "scalar")
Example #10
0
    def test_get_summary_ignores_invalid_fields(self):
        data_tools = [
            {
                "field": "number",
                "method": "average"
            },
            {
                "field": "number",
                "method": "doughnut"
            },
        ]

        C = DictConnection()
        topic_id = C.add_topic("topic",
                               description="description",
                               fields=["letter"],
                               data_tools=data_tools)
        C.add_data(topic_id, {"letter": "a"})

        summary = C.get_summary(topic_id)
        self.assertEqual(summary["topic"], "topic")
        self.assertEqual(summary["description"], "description")

        self.assertEqual(len(summary["warnings"]), 2)
        self.assertEqual(len(summary["statistics"]), 0)
Example #11
0
    def test_topics_backup_saves_dict_to_file(self):
        filename = f'{uuid4()}.json'
        C1 = DictConnection(f'/tmp/{filename}')
        C1.add_topic('Test topic 1')
        C1.add_topic('Test topic 2')

        C2 = DictConnection(f'/tmp/{filename}')
        topics = C2.get_topics()

        os.remove(f'/tmp/{filename}')

        self.assertEqual(len(topics), 2)
Example #12
0
    def test_latest_summary_returns_latest_item(self):
        data_tools = [{"field": "letter", "method": "latest"}]

        C = DictConnection()
        topic_id = C.add_topic("topic",
                               description="description",
                               fields=["letter"],
                               data_tools=data_tools)
        C.add_data(topic_id, {"letter": "a"})
        C.add_data(topic_id, {"letter": "b"})
        C.add_data(topic_id, {"letter": "c"})
        summary = C.get_summary(topic_id)

        value = summary["statistics"][0]["payload"]
        self.assertEqual(value["field"], "letter")
        self.assertEqual(value["type"], "latest")
        self.assertEqual(value["value"], "c")
Example #13
0
    def _test_run_data_tools_for_many(self, fn, data_tools):
        topic_ids = []
        C = DictConnection()
        for i in range(3):
            topic_ids.append(
                C.add_topic("topic_" + str(i),
                            description="description",
                            fields=["number"],
                            data_tools=data_tools))
            C.add_data(topic_ids[-1], {"number": 3})
            C.add_data(topic_ids[-1], {"number": 4})
            C.add_data(topic_ids[-1], {"number": 2})
        if fn == "get_comparison":
            result = C.get_overview(topic_ids)
        elif fn == "get_overview":
            result = C.get_overview()
        self.assertEqual(result["topic_names"],
                         ["topic_0", "topic_1", "topic_2"])
        self.assertEqual(result["fields"], ["number"])

        return result
Example #14
0
    def test_get_summary_produces_summary(self):
        types = (
            "doughnut",
            "pie",
        )

        data_tools = [dict(field="number", method=_type)
                      for _type in types] + [{
                          "field": "number",
                          "method": "average"
                      }]

        C = DictConnection()
        topic_id = C.add_topic("topic",
                               description="description",
                               fields=["number"],
                               data_tools=data_tools)
        C.add_data(topic_id, {"number": 3})
        C.add_data(topic_id, {"number": 4})
        C.add_data(topic_id, {"number": 2})
        summary = C.get_summary(topic_id)
        self.assertEqual(summary["topic"], "topic")
        self.assertEqual(summary["description"], "description")

        statistics = summary["statistics"]
        value = next(i for i in statistics
                     if i.get("type") == "value").get("payload")
        self.assertAlmostEqual(value["value"], 3.0)
        self.assertEqual(value["field"], "number")
        self.assertEqual(value["type"], "average")

        charts = [
            i.get("payload") for i in statistics if i.get("type") == "chart"
        ]
        self.assertEqual(charts, [{
            "field": "number",
            "type": type_,
            "data": {
                "datasets": [{
                    "data": [1, 1, 1],
                    "label": "topic"
                }],
                "labels": [2, 3, 4],
            }
        } for type_ in types])
Example #15
0
    def test_aggregate(self):
        s = ServerHandlers(DictConnection())
        topic_id = self._create_topic(s, AGGREGATE_ALWAYS_TOPIC)
        for data in AGGREGATE_ALWAYS_DATA:
            data['timestamp'] = isoparse(data['timestamp']).replace(tzinfo=None)
            self._assert_status(200, s.add_data, topic_id, data)

        tests = [
            (s.get_summary, (topic_id, dict(aggregate_to="5", aggregate_with='sum')), 4),
            (s.get_summary, (topic_id, dict(aggregate_to="5", aggregate_with='sum', aggregate_always="tRuE")), 2),
            (s.get_overview, (None, dict(aggregate_to="5", aggregate_with='sum')), 4),
            (s.get_overview, (None, dict(aggregate_to="5", aggregate_with='sum', aggregate_always="True")), 2),
        ]

        for fn, params, count in tests:
            data = self._assert_status(200, fn, *params)
            aggregated = data['statistics'][0]['payload']['data']['datasets'][0]['data']
            self.assertEqual(len(aggregated), count)
Example #16
0
    def test_line_visualization_gives_timestamps_in_utc(self):
        data_tools = [{"field": "number", "method": "line"}]

        C = DictConnection()
        topic_id = C.add_topic("topic",
                               description="description",
                               fields=["number"],
                               data_tools=data_tools)
        C.add_data(topic_id, {"number": 1})
        C.add_data(topic_id, {"number": 2})
        C.add_data(topic_id, {"number": 3})
        summary = C.get_summary(topic_id)

        chart = summary["statistics"][0]["payload"]
        self.assertEqual(chart["field"], "number")
        self.assertEqual(chart["type"], "line")

        iso8601z_re = r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{6}Z"
        field_to_test = chart["data"]["datasets"][0]["data"][0]["x"]

        self.assertRegex(field_to_test, iso8601z_re)
Example #17
0
    def test_overview_ignores_templates(self):
        data_tools = [
            {
                "field": "number",
                "method": "line"
            },
        ]

        units_d = {"field": "number", "unit": "scalar"}

        C = DictConnection()
        C.add_topic("Test template",
                    type_str="template",
                    fields=['number'],
                    units=[units_d],
                    data_tools=data_tools)
        C.add_topic("Test topic", template="Test template")

        data = C.get_overview()
        self.assertEqual(len(data["warnings"]), 1)
        self.assertNotIn(data["warnings"][0], "template")
Example #18
0
    def test_last_truthy_falsy_summary_returns_correct_timestamp(self):
        data_tools = [{
            "field": "onoff",
            "method": "last_truthy"
        }, {
            "field": "onoff",
            "method": "last_falsy"
        }]

        C = DictConnection()
        topic_id = C.add_topic("topic",
                               description="description",
                               fields=["onoff"],
                               data_tools=data_tools)
        for i in [False, True, False, True]:
            C.add_data(topic_id, {"onoff": i})

        summary = C.get_summary(topic_id)
        data = C.get_data(topic_id)

        self.assertEqual(summary["statistics"][0]["payload"]["value"],
                         data[3]["timestamp"])
        self.assertEqual(summary["statistics"][1]["payload"]["value"],
                         data[2]["timestamp"])
Example #19
0
    def test_get_summary_writes_warning_to_output_when_unsupported_method_requested(
            self):
        data_tools = [
            {
                "field": "number",
                "method": "cow"
            },
            {
                "field": "number",
                "method": "moose"
            },
        ]

        C = DictConnection()
        topic_id = C.add_topic("topic",
                               description="description",
                               fields=["number"],
                               data_tools=data_tools)
        C.add_data(topic_id, {"number": 3})
        summary = C.get_summary(topic_id)
        self.assertEqual(summary["warnings"], [
            'The requested method "cow" is not supported.',
            'The requested method "moose" is not supported.'
        ])
Example #20
0
 def setUp(self):
     self.connection = DictConnection()
     self.server = generate_app(db_connection=self.connection).test_client()
Example #21
0
    def test_get_topic(self):
        s = ServerHandlers(DictConnection())

        self._assert_status(404, s.get_topic, None)
        topic_id = self._create_topic(s, dict(name="topic", fields=["number"]))
        self._assert_status(200, s.get_topic, topic_id)
Example #22
0
 def test_add_topic_returns_400_when_topic_name_missing(self):
     s = ServerHandlers(DictConnection())
     self._assert_status(400, s.add_topic, {})
Example #23
0
 def test_add_topic_returns_400_when_topic_data_is_invalid(self):
     s = ServerHandlers(DictConnection())
     self._assert_status(400, s.add_topic, dict(name="test", fields=123))
Example #24
0
 def test_add_topic_returns_200_on_success(self):
     s = ServerHandlers(DictConnection())
     self._assert_status(200, s.add_topic, dict(name="topic"))
Example #25
0
 def setUp(self):
     self.C = DictConnection()
Example #26
0
    def test_get_topics_raises_keyerror_on_template_not_found(self):
        C = DictConnection()
        C.add_topic('test_template', type_str='template')
        C.add_topic('topic', template='test_template')

        C.get_topics()

        C._dict['topics'] = C._dict['topics'][1:]
        with self.assertRaises(KeyError):
            C.get_topics()
Example #27
0
class ParallelExecTest(TestCase):
    def _create_topic(self, name, cmd, db_connection=None):
        argv = [
            *COMMON_ARGS, 'create', '-N', name, '--start-in', '0',
            '--repeat-for', '0.5', '-c', *cmd
        ]
        with patch('sys.argv', argv):
            main()

        topics = db_connection.get_topics(template='execution')
        self.assertEqual(len(topics), 1)

        topic_d = topics[0]
        self.assertEqual(topic_d['name'], f'{name} #1')
        self.assertEqual(topic_d['metadata']['command'], cmd)

        return topic_d['id']

    def _execute(self, name, *args):
        with patch('sys.argv', [*COMMON_ARGS, 'exec', '-N', name, *args]):
            main()

    @patch('builtins.print')
    @patch('fdbk.builtin.parallel_exec._should_repeat',
           side_effect=[True, True, True, False])
    @patch('fdbk.builtin.parallel_exec.run')
    @patch('fdbk.builtin.parallel_exec.create_db_connection',
           return_value=DictConnection())
    def test_main(self, create_mock, run_mock, repeat_mock, print_mock):
        C = create_mock.return_value

        cmd = ['sleep', '5']
        topic_id = self._create_topic(TEST_EXEC_NAME, cmd, C)

        topics = C.get_topics(template='execution')
        self.assertEqual(len(topics), 1)

        topic_d = topics[0]
        topic_id = topic_d['id']
        self.assertEqual(topic_d['name'], f'{TEST_EXEC_NAME} #1')
        self.assertEqual(topic_d['metadata']['command'], cmd)

        # Execute
        process = CompletedProcess(cmd, 0, b'asd')
        run_mock.return_value = process

        self._execute(TEST_EXEC_NAME)

        run_mock.assert_called_with(cmd, stderr=STDOUT, stdout=PIPE)
        self.assertEqual(len(run_mock.mock_calls), 2)
        self.assertEqual(len(C.get_data(topic_id)), 2)

        console = C.get_data(topic_id)[0]["output"]
        self.assertIn('+ sleep 5', console)

    @patch('builtins.print')
    @patch('fdbk.builtin.parallel_exec.create_db_connection',
           return_value=DictConnection())
    def test_main_suffix(self, create_mock, print_mock):
        C = create_mock.return_value

        # Create topics
        for name, repeat_for in [
            (TEST_EXEC_NAME, '0'),
            (TEST_EXEC_NAME, '0.1'),
            ('Another test', '1'),
        ]:
            cmd = ['sleep', '0.1']
            with patch('sys.argv', [
                    *COMMON_ARGS, 'create', '-N', name, '--start-in', '0',
                    '--repeat-for', repeat_for, '-c', *cmd
            ]):
                main()

        topic_ids = [i.get('id') for i in C.get_topics(template='execution')]
        self.assertEqual(len(topic_ids), 3)

        self._execute(TEST_EXEC_NAME)

        self.assertEqual(len(C.get_data(topic_ids[0])), 0)
        self.assertGreaterEqual(len(C.get_data(topic_ids[1])), 1)
        self.assertEqual(len(C.get_data(topic_ids[2])), 0)

    @patch('builtins.exit')
    @patch('builtins.print')
    @patch('fdbk.builtin.parallel_exec.create_db_connection')
    def test_main_create_error(self, create_mock, print_mock, exit_mock):
        create_mock.return_value.add_topic.side_effect = RuntimeError

        name = 'Test execution'
        cmd = ['sleep', '5']
        with patch(
                'sys.argv',
            [*COMMON_ARGS, 'create', '-N', name, '--start-in', 0, '-c', *cmd]):
            main()

        exit_mock.assert_called_with(TOPIC_CREATION_FAILED)

    @patch('builtins.print')
    @patch('fdbk.builtin.parallel_exec.create_db_connection',
           return_value=DictConnection())
    def test_json_console(self, create_mock, print_mock):
        C = create_mock.return_value

        cmd = [
            executable or 'python', '-c', 'import sys, time;'
            'print("out");'
            'time.sleep(0.5);'
            'print("err", file=sys.stderr);'
        ]

        topic_id = self._create_topic(TEST_EXEC_NAME, cmd, C)

        self._execute(TEST_EXEC_NAME, '--console-as-json')

        self.assertEqual(len(C.get_data(topic_id)), 1)
        console = C.get_data(topic_id)[0]['output']
        self.assertEqual(len(console), 3)
        self.assertEqual(shlex.split(console[0]['text']), cmd)

        for stream, text in [
            ('stdout', 'out'),
            ('stderr', 'err'),
        ]:
            msg = next(i for i in console if i['stream'] == stream)

            self.assertEqual(msg['stream'], stream, f'Stream: {stream}')
            self.assertEqual(msg['text'], text, f'Stream: {stream}')
Example #28
0
 def test_get_latest_handles_empty_list(self):
     C = DictConnection()
     topic_id = C.add_topic("topic")
     with self.assertRaises(IndexError):
         C.get_latest(topic_id)