Beispiel #1
0
def setup():
  log_handler, log_buffer = setupLogging()

  status = monitor.status.Status()

  # Create our global shared status. Sort of a hard coded file adapter.
  config_file = os.path.join(BASE_DIR, 'server.json')
  with open(config_file, 'r') as f:
    status.set('status://server', json.load(f))

  # Setup the normal adapters.
  setupAdapters(status)

  # Create the manager for performing actions.
  action_manager = monitor.actions.ActionManager(status)

  # Instantiating the engine sets up the deferreds needed to keep it running.
  monitor.rules_engine.RulesEngine(status, action_manager)

  # Assemble the factory for our web server.
  # Serve the standard static web content, overlaid with our dynamic content
  root = File("./static")
  root.putChild("button", monitor.web_resources.Button(status))
  root.putChild("log", monitor.web_resources.Log(log_handler, log_buffer))
  root.putChild("restart", monitor.web_resources.Restart(status))
  root.putChild("status", monitor.web_resources.Status(status))

  reactor.listenTCP(status.get('status://server/port', 8080),
                    Site(root))
Beispiel #2
0
def setup():
    log_handler, log_buffer = setupLogging()

    status = monitor.status.Status()

    # Create our global shared status. Sort of a hard coded file adapter.
    config_file = os.path.join(BASE_DIR, 'server.json')
    with open(config_file, 'r') as f:
        status.set('status://server', json.load(f))

    # Setup the normal adapters.
    setupAdapters(status)

    # Create the manager for performing actions.
    action_manager = monitor.actions.ActionManager(status)

    # Instantiating the engine sets up the deferreds needed to keep it running.
    monitor.rules_engine.RulesEngine(status, action_manager)

    # Assemble the factory for our web server.
    # Serve the standard static web content, overlaid with our dynamic content
    root = File("./static")
    root.putChild("button", monitor.web_resources.Button(status))
    root.putChild("log", monitor.web_resources.Log(log_handler, log_buffer))
    root.putChild("restart", monitor.web_resources.Restart(status))
    root.putChild("status", monitor.web_resources.Status(status))

    reactor.listenTCP(status.get('status://server/port', 8080), Site(root))
Beispiel #3
0
    def test_url_not_updated(self):
        status = self._create_status({"foo": 1, "bar": 2})

        # Ask for a specialized notification.
        d = status.deferred(revision=1, url="status://bar")
        status.set("status://int", 3)
        self.assertFalse(d.called)
Beispiel #4
0
    def test_noop_change(self):
        """Ensure the deferred does not fire on a non-meaningful change."""
        status = self._create_status({'int': 2})

        d = status.deferred(revision=1)
        status.set('status://int', 2)
        self.assertFalse(d.called)
    def test_watch_rules_fired(self):
        """Setup and fire two watch rules in the rules_engine."""
        status, engine = self._setup_status_engine({
            'watch_test1': {
                'behavior': 'watch',
                'value': 'status://values/one',
                'action': 'take_action1'
            },
            'watch_test2': {
                'behavior': 'watch',
                'value': 'status://values/two',
                'action': 'take_action2'
            }
        })

        expected_actions = [
            'status://config/rule/watch_test1/action',
            'status://config/rule/watch_test2/action'
        ]
        d = self._test_actions_fired(engine, expected_actions)

        status.set('status://values/one', 2)
        status.set('status://values/two', 2)

        return d
Beispiel #6
0
    def test_noop_change(self):
        """Ensure the deferred does not fire on a non-meaningful change."""
        status = self._create_status({"int": 2})

        d = status.deferred(revision=1)
        status.set("status://int", 2)
        self.assertFalse(d.called)
Beispiel #7
0
    def test_set_revision(self):
        """Test Status.set() if revision is passed in."""

        # Make Sure initial revisions match expectations.
        status = self._create_status()

        # Set a new value, update with correct specified revision.
        status.set("status://int", 10, revision=1)
        self.assertEqual(status.revision(), 2)
        self.assertEqual(status.revision("status://int"), 2)

        # Update an existing value with correct specified revision.
        status.set("status://int", 20, revision=2)
        self.assertEqual(status.revision(), 3)
        self.assertEqual(status.revision("status://int"), 3)

        # Set a new value, update with incorrect specified revision.
        # Should raise exception, and modify nothing.
        self.assertRaises(monitor.status.RevisionMismatch, status.set, "status://int", 30, revision=1)
        self.assertEqual(status.get("status://int"), 20)
        self.assertEqual(status.revision(), 3)
        self.assertEqual(status.revision("status://int"), 3)

        # Set a new value, update with a future version.
        self.assertRaises(monitor.status.RevisionMismatch, status.set, "status://int", 30, revision=100)
        self.assertEqual(status.get("status://int"), 20)
        self.assertEqual(status.revision(), 3)
        self.assertEqual(status.revision("status://int"), 3)
Beispiel #8
0
    def test_url_not_updated(self):
        status = self._create_status({'foo': 1, 'bar': 2})

        # Ask for a specialized notification.
        d = status.deferred(revision=1, url='status://bar')
        status.set('status://int', 3)
        self.assertFalse(d.called)
Beispiel #9
0
    def test_single_change_no_url(self):
        status = self._create_status({'int': 2})

        # Test that the expected notification fires after we make a change.
        url = 'status://int'
        d = status.deferred()
        status.set(url, 3)
        d.addCallback(self.assertEquals, ['status://'])
        self.assertTrue(d.called)
Beispiel #10
0
    def test_double_change_no_url(self):
        """Ensure the deferred does not fire on a non-meaningful change."""
        status = self._create_status({'int': 2})

        d = status.deferred(revision=1)
        status.set('status://int', 3)
        status.set('status://int', 4)
        d.addCallback(self.assertEquals, ['status://'])
        self.assertTrue(d.called)
Beispiel #11
0
    def test_double_change_no_url(self):
        """Ensure the deferred does not fire on a non-meaningful change."""
        status = self._create_status({"int": 2})

        d = status.deferred(revision=1)
        status.set("status://int", 3)
        status.set("status://int", 4)
        d.addCallback(self.assertEquals, ["status://"])
        self.assertTrue(d.called)
Beispiel #12
0
    def test_single_change_no_url(self):
        status = self._create_status({"int": 2})

        # Test that the expected notification fires after we make a change.
        url = "status://int"
        d = status.deferred()
        status.set(url, 3)
        d.addCallback(self.assertEquals, ["status://"])
        self.assertTrue(d.called)
Beispiel #13
0
    def test_non_existent_url(self):
        status = self._create_status()

        # Ask for a specialized notification.
        url = "status://foo"
        d = status.deferred(url=url)
        status.set(url, 3)
        d.addCallback(self.assertEquals, [url])
        self.assertTrue(d.called)
Beispiel #14
0
    def test_non_existent_url(self):
        status = self._create_status()

        # Ask for a specialized notification.
        url = 'status://foo'
        d = status.deferred(url=url)
        status.set(url, 3)
        d.addCallback(self.assertEquals, [url])
        self.assertTrue(d.called)
Beispiel #15
0
    def test_url_double_updated(self):
        status = self._create_status()

        # Ask for a specialized notification.
        url = "status://int"
        d = status.deferred(revision=1, url=url)
        d.addCallback(self.assertEquals, [url])
        status.set(url, 3)
        status.set(url, 4)
        self.assertTrue(d.called)
Beispiel #16
0
    def test_url_double_updated(self):
        status = self._create_status()

        # Ask for a specialized notification.
        url = 'status://int'
        d = status.deferred(revision=1, url=url)
        d.addCallback(self.assertEquals, [url])
        status.set(url, 3)
        status.set(url, 4)
        self.assertTrue(d.called)
Beispiel #17
0
    def test_url_parent_different_revision(self):
        status = self._create_status({"foo": 1, "bar": 2})
        status.set("status://foo", 3)

        self.assertEqual(status.revision(), 2)
        self.assertEqual(status.revision("status://bar"), 1)

        # Ask for a specialized notification with the parents revision, not
        # the revision of the url.
        d = status.deferred(revision=1, url="status://bar")
        status.set("status://int", 3)
        self.assertFalse(d.called)
    def test_watch_rule_fired(self):
        """Setup and fire a single watch rule in the rules_engine."""
        status, engine = self._setup_status_engine(
            {"watch_test": {"behavior": "watch", "value": "status://values/one", "action": "take_action"}}
        )

        expected_actions = ["status://config/rule/watch_test/action"]
        d = self._test_actions_fired(engine, expected_actions)

        status.set("status://values/one", 2)

        return d
Beispiel #19
0
    def test_url_parent_different_revision(self):
        status = self._create_status({'foo': 1, 'bar': 2})
        status.set('status://foo', 3)

        self.assertEqual(status.revision(), 2)
        self.assertEqual(status.revision('status://bar'), 1)

        # Ask for a specialized notification with the parents revision, not
        # the revision of the url.
        d = status.deferred(revision=1, url='status://bar')
        status.set('status://int', 3)
        self.assertFalse(d.called)
Beispiel #20
0
    def test_url_nested_updates(self):
        status = self._create_status()
        url = 'status://int'

        def callback(value, new_int):
            status.set(url, new_int)
            return value

        d = status.deferred(url=url)
        d.addCallback(callback, 4)
        d.addCallback(callback, 5)
        status.set(url, 3)
        self.assertTrue(d.called)
    def test_watch_rule_value_cleared(self):
        """Setup and clear value a watch rule watches."""
        status, engine = self._setup_status_engine(
            {"watch_test": {"behavior": "watch", "value": "status://values/one", "action": "take_action"}}
        )

        # If a value is cleared, we shouldn't fire at all.
        expected_actions = []
        d = self._test_actions_fired(engine, expected_actions)

        status.set("status://values", {})

        return d
Beispiel #22
0
    def test_url_nested_updates(self):
        status = self._create_status()
        url = "status://int"

        def callback(value, new_int):
            status.set(url, new_int)
            return value

        d = status.deferred(url=url)
        d.addCallback(callback, 4)
        d.addCallback(callback, 5)
        status.set(url, 3)
        self.assertTrue(d.called)
    def test_watch_rules_fired(self):
        """Setup and fire two watch rules in the rules_engine."""
        status, engine = self._setup_status_engine(
            {
                "watch_test1": {"behavior": "watch", "value": "status://values/one", "action": "take_action1"},
                "watch_test2": {"behavior": "watch", "value": "status://values/two", "action": "take_action2"},
            }
        )

        expected_actions = ["status://config/rule/watch_test1/action", "status://config/rule/watch_test2/action"]
        d = self._test_actions_fired(engine, expected_actions)

        status.set("status://values/one", 2)
        status.set("status://values/two", 2)

        return d
    def test_watch_rule_value_cleared(self):
        """Setup and clear value a watch rule watches."""
        status, engine = self._setup_status_engine({
            'watch_test': {
                'behavior': 'watch',
                'value': 'status://values/one',
                'action': 'take_action'
            }
        })

        # If a value is cleared, we shouldn't fire at all.
        expected_actions = []
        d = self._test_actions_fired(engine, expected_actions)

        status.set('status://values', {})

        return d
    def test_watch_rule_fired_twice(self):
        """Setup and fire a single watch rule in the rules_engine twice."""
        status, engine = self._setup_status_engine({
            'watch_test': {
                'behavior': 'watch',
                'value': 'status://values/one',
                'action': 'take_action'
            }
        })

        expected_actions = [
            'status://config/rule/watch_test/action',
            'status://config/rule/watch_test/action'
        ]
        d = self._test_actions_fired(engine, expected_actions)

        status.set('status://values/one', 2)
        status.set('status://values/one', 3)

        return d
Beispiel #26
0
    def test_url_circular_deferreds(self):
        status = self._create_status({"foo": 1, "bar": 1})

        url_foo = "status://foo"
        url_bar = "status://bar"

        d_foo = status.deferred(url=url_foo)
        d_bar = status.deferred(url=url_bar)

        def callback(value, new_url, new_int):
            status.set(new_url, new_int)
            return value

        d_foo.addCallback(callback, url_bar, 3)
        d_bar.addCallback(callback, url_foo, 3)

        status.set(url_foo, 2)
        status.set(url_bar, 2)

        self.assertTrue(d_foo.called)
        self.assertTrue(d_bar.called)
Beispiel #27
0
    def test_url_circular_deferreds(self):
        status = self._create_status({'foo': 1, 'bar': 1})

        url_foo = 'status://foo'
        url_bar = 'status://bar'

        d_foo = status.deferred(url=url_foo)
        d_bar = status.deferred(url=url_bar)

        def callback(value, new_url, new_int):
            status.set(new_url, new_int)
            return value

        d_foo.addCallback(callback, url_bar, 3)
        d_bar.addCallback(callback, url_foo, 3)

        status.set(url_foo, 2)
        status.set(url_bar, 2)

        self.assertTrue(d_foo.called)
        self.assertTrue(d_bar.called)
Beispiel #28
0
    def test_set_revision(self):
        """Test Status.set() if revision is passed in."""

        # Make Sure initial revisions match expectations.
        status = self._create_status()

        # Set a new value, update with correct specified revision.
        status.set('status://int', 10, revision=1)
        self.assertEqual(status.revision(), 2)
        self.assertEqual(status.revision('status://int'), 2)

        # Update an existing value with correct specified revision.
        status.set('status://int', 20, revision=2)
        self.assertEqual(status.revision(), 3)
        self.assertEqual(status.revision('status://int'), 3)

        # Set a new value, update with incorrect specified revision.
        # Should raise exception, and modify nothing.
        self.assertRaises(monitor.status.RevisionMismatch,
                          status.set,
                          'status://int',
                          30,
                          revision=1)
        self.assertEqual(status.get('status://int'), 20)
        self.assertEqual(status.revision(), 3)
        self.assertEqual(status.revision('status://int'), 3)

        # Set a new value, update with a future version.
        self.assertRaises(monitor.status.RevisionMismatch,
                          status.set,
                          'status://int',
                          30,
                          revision=100)
        self.assertEqual(status.get('status://int'), 20)
        self.assertEqual(status.revision(), 3)
        self.assertEqual(status.revision('status://int'), 3)
Beispiel #29
0
    def test_set(self):
        status = self._create_status()

        self.assertEqual(status.revision(), 1)
        self.assertEqual(status.get("status://int"), 2)
        self.assertEqual(status.get("status://list"), [])
        self.assertEqual(status.get("status://dict"), {"sub1": 3, "sub2": 4})

        # Revision didn't change with the gets.
        self.assertEqual(status.revision(), 1)

        # Set an integer
        status.set("status://int", 10)
        self.assertEqual(status.get("status://int"), 10)
        self.assertEqual(status.revision(), 2)

        # Set a complex structure, and ensure it is copied, not referenced.
        l = []
        status.set("status://list2", l)
        self.assertEqual(status.get("status://list2"), [])
        l.append(1)
        self.assertEqual(status.get("status://list2"), [])
        self.assertEqual(status.revision(), 3)

        # Ensure that setting to an unchanged value does not increment revision.
        status.set("status://int", 10)
        self.assertEqual(status.get("status://int"), 10)
        self.assertEqual(status.revision(), 3)

        # Set a nested value.
        status.set("status://dict/sub1", 5)
        self.assertEqual(status.get("status://dict/sub1"), 5)
        self.assertEqual(status.revision(), 4)

        # Set a nested value with new intermediate paths.
        status.set("status://nest1/nest2/nest3", "foo")
        self.assertEqual(status.get("status://nest1"), {"nest2": {"nest3": "foo"}})
        self.assertEqual(status.revision(), 5)

        # Clear an existing value.
        status.set("status://dict/sub1", None)
        self.assertEqual(status.get("status://dict"), {"sub1": None, "sub2": 4})
        self.assertEqual(status.revision(), 6)

        # Clear a sub-tree
        status.set("status://nest1", None)
        self.assertEqual(
            status.get("status://"),
            {"dict": {"sub1": None, "sub2": 4}, "int": 10, "list": [], "list2": [], "nest1": None},
        )
        self.assertEqual(status.revision(), 7)

        # Clear a nonexitent value
        status.set("status://nonexistent", None)
        self.assertEqual(
            status.get("status://"),
            {"dict": {"sub1": None, "sub2": 4}, "int": 10, "list": [], "list2": [], "nest1": None},
        )
        self.assertEqual(status.revision(), 7)
Beispiel #30
0
 def callback(value, new_url, new_int):
     status.set(new_url, new_int)
     return value
Beispiel #31
0
 def callback(value, new_url, new_int):
     status.set(new_url, new_int)
     return value
Beispiel #32
0
    def test_nested_revisions(self):
        """Test Status.revision() handles nested revision numbers."""

        # Make Sure initial revisions match expectations.
        status = self._create_status(
            {
                "int": 1,
                "string": "foo",
                "list": [],
                "deep1": {"foo": 2},
                "deep2": {"sub_deep1": {"foo": 3}, "sub_deep2": {"foo": 4}},
            }
        )

        self.assertEqual(status.revision(), 1)
        self.assertEqual(status.revision("status://int"), 1)
        self.assertEqual(status.revision("status://string"), 1)
        self.assertEqual(status.revision("status://list"), 1)
        self.assertEqual(status.revision("status://deep1"), 1)
        self.assertEqual(status.revision("status://deep1/foo"), 1)
        self.assertEqual(status.revision("status://deep2"), 1)
        self.assertEqual(status.revision("status://deep2/sub_deep1"), 1)
        self.assertEqual(status.revision("status://deep2/sub_deep1/foo"), 1)
        self.assertEqual(status.revision("status://deep2/sub_deep2"), 1)
        self.assertEqual(status.revision("status://deep2/sub_deep2/foo"), 1)

        self.assertRaises(monitor.status.UnknownUrl, status.revision, "status://nonexistent")

        # Make a simple update.
        status.set("status://int", 10)

        self.assertEqual(status.revision(), 2)
        self.assertEqual(status.revision("status://int"), 2)
        self.assertEqual(status.revision("status://string"), 1)
        self.assertEqual(status.revision("status://list"), 1)
        self.assertEqual(status.revision("status://deep1"), 1)
        self.assertEqual(status.revision("status://deep1/foo"), 1)
        self.assertEqual(status.revision("status://deep2"), 1)
        self.assertEqual(status.revision("status://deep2/sub_deep1"), 1)
        self.assertEqual(status.revision("status://deep2/sub_deep1/foo"), 1)
        self.assertEqual(status.revision("status://deep2/sub_deep2"), 1)
        self.assertEqual(status.revision("status://deep2/sub_deep2/foo"), 1)

        # Make a nested update.
        status.set("status://deep1/foo", 20)

        self.assertEqual(status.revision(), 3)
        self.assertEqual(status.revision("status://int"), 2)
        self.assertEqual(status.revision("status://string"), 1)
        self.assertEqual(status.revision("status://list"), 1)
        self.assertEqual(status.revision("status://deep1"), 3)
        self.assertEqual(status.revision("status://deep1/foo"), 3)
        self.assertEqual(status.revision("status://deep2"), 1)
        self.assertEqual(status.revision("status://deep2/sub_deep1"), 1)
        self.assertEqual(status.revision("status://deep2/sub_deep1/foo"), 1)
        self.assertEqual(status.revision("status://deep2/sub_deep2"), 1)
        self.assertEqual(status.revision("status://deep2/sub_deep2/foo"), 1)

        # Make a deeper nested update.
        status.set("status://deep2/sub_deep1/foo", 30)

        self.assertEqual(status.revision(), 4)
        self.assertEqual(status.revision("status://int"), 2)
        self.assertEqual(status.revision("status://string"), 1)
        self.assertEqual(status.revision("status://list"), 1)
        self.assertEqual(status.revision("status://deep1"), 3)
        self.assertEqual(status.revision("status://deep1/foo"), 3)
        self.assertEqual(status.revision("status://deep2"), 4)
        self.assertEqual(status.revision("status://deep2/sub_deep1"), 4)
        self.assertEqual(status.revision("status://deep2/sub_deep1/foo"), 4)
        self.assertEqual(status.revision("status://deep2/sub_deep2"), 1)
        self.assertEqual(status.revision("status://deep2/sub_deep2/foo"), 1)

        # Replace a sub-tree
        status.set("status://deep2/sub_deep1", {"foo": 40, "bar": 50})

        self.assertEqual(status.revision(), 5)
        self.assertEqual(status.revision("status://int"), 2)
        self.assertEqual(status.revision("status://string"), 1)
        self.assertEqual(status.revision("status://list"), 1)
        self.assertEqual(status.revision("status://deep1"), 3)
        self.assertEqual(status.revision("status://deep1/foo"), 3)
        self.assertEqual(status.revision("status://deep2"), 5)
        self.assertEqual(status.revision("status://deep2/sub_deep1"), 5)
        self.assertEqual(status.revision("status://deep2/sub_deep1/foo"), 5)
        self.assertEqual(status.revision("status://deep2/sub_deep1/bar"), 5)
        self.assertEqual(status.revision("status://deep2/sub_deep2"), 1)
        self.assertEqual(status.revision("status://deep2/sub_deep2/foo"), 1)

        # Replace a sub-tree, unchanged.
        status.set("status://deep2/sub_deep1", {"foo": 40, "bar": 50})

        self.assertEqual(status.revision(), 5)
        self.assertEqual(status.revision("status://int"), 2)
        self.assertEqual(status.revision("status://string"), 1)
        self.assertEqual(status.revision("status://list"), 1)
        self.assertEqual(status.revision("status://deep1"), 3)
        self.assertEqual(status.revision("status://deep1/foo"), 3)
        self.assertEqual(status.revision("status://deep2"), 5)
        self.assertEqual(status.revision("status://deep2/sub_deep1"), 5)
        self.assertEqual(status.revision("status://deep2/sub_deep1/foo"), 5)
        self.assertEqual(status.revision("status://deep2/sub_deep1/bar"), 5)
        self.assertEqual(status.revision("status://deep2/sub_deep2"), 1)
        self.assertEqual(status.revision("status://deep2/sub_deep2/foo"), 1)
Beispiel #33
0
    def test_set_revision_nested(self):
        """Test Status.set() if revision is passed in."""

        # Make Sure initial revisions match expectations.
        status = self._create_status({"int": 1, "deep": {"foo": 2}})

        # Update one section.
        status.set("status://int", 10, revision=1)
        self.assertEqual(status.revision(), 2)
        self.assertEqual(status.revision("status://int"), 2)
        self.assertEqual(status.revision("status://deep"), 1)
        self.assertEqual(status.revision("status://deep/foo"), 1)

        # Ensure old section can still update using original revision.
        status.set("status://deep/foo", 20, revision=1)
        self.assertEqual(status.revision(), 3)
        self.assertEqual(status.revision("status://int"), 2)
        self.assertEqual(status.revision("status://deep"), 3)
        self.assertEqual(status.revision("status://deep/foo"), 3)

        # Ensure new creation works with nested revisions.
        status.set("status://deep/bar", 30, revision=3)
        self.assertEqual(status.revision(), 4)
        self.assertEqual(status.revision("status://int"), 2)
        self.assertEqual(status.revision("status://deep"), 4)
        self.assertEqual(status.revision("status://deep/foo"), 3)
        self.assertEqual(status.revision("status://deep/bar"), 4)

        # Ensure value can be updated using a parents revision.
        status.set("status://deep/foo", 21, revision=4)
        self.assertEqual(status.revision(), 5)
        self.assertEqual(status.revision("status://int"), 2)
        self.assertEqual(status.revision("status://deep"), 5)
        self.assertEqual(status.revision("status://deep/foo"), 5)
        self.assertEqual(status.revision("status://deep/bar"), 4)

        # Ensure new creation works with updated revisions.
        status.set("status://deep/bar", 31, revision=4)
        self.assertEqual(status.revision(), 6)
        self.assertEqual(status.revision("status://int"), 2)
        self.assertEqual(status.revision("status://deep"), 6)
        self.assertEqual(status.revision("status://deep/foo"), 5)
        self.assertEqual(status.revision("status://deep/bar"), 6)

        # Ensure value can be updated using a parents revision.
        status.set("status://int", 11, revision=6)
        status.set("status://int", 12, revision=7)
        self.assertEqual(status.revision(), 8)
        self.assertEqual(status.revision("status://int"), 8)
        self.assertEqual(status.revision("status://deep"), 6)
        self.assertEqual(status.revision("status://deep/foo"), 5)
        self.assertEqual(status.revision("status://deep/bar"), 6)

        # Ensure value can NOT be updated using an outdated parent version.
        self.assertRaises(monitor.status.RevisionMismatch, status.set, "status://deep/foo", 21, revision=7)

        self.assertEqual(status.revision(), 8)
        self.assertEqual(status.revision("status://int"), 8)
        self.assertEqual(status.revision("status://deep"), 6)
        self.assertEqual(status.revision("status://deep/foo"), 5)
        self.assertEqual(status.revision("status://deep/bar"), 6)
Beispiel #34
0
    def test_set(self):
        status = self._create_status()

        self.assertEqual(status.revision(), 1)
        self.assertEqual(status.get('status://int'), 2)
        self.assertEqual(status.get('status://list'), [])
        self.assertEqual(status.get('status://dict'), {'sub1': 3, 'sub2': 4})

        # Revision didn't change with the gets.
        self.assertEqual(status.revision(), 1)

        # Set an integer
        status.set('status://int', 10)
        self.assertEqual(status.get('status://int'), 10)
        self.assertEqual(status.revision(), 2)

        # Set a complex structure, and ensure it is copied, not referenced.
        l = []
        status.set('status://list2', l)
        self.assertEqual(status.get('status://list2'), [])
        l.append(1)
        self.assertEqual(status.get('status://list2'), [])
        self.assertEqual(status.revision(), 3)

        # Ensure that setting to an unchanged value does not increment revision.
        status.set('status://int', 10)
        self.assertEqual(status.get('status://int'), 10)
        self.assertEqual(status.revision(), 3)

        # Set a nested value.
        status.set('status://dict/sub1', 5)
        self.assertEqual(status.get('status://dict/sub1'), 5)
        self.assertEqual(status.revision(), 4)

        # Set a nested value with new intermediate paths.
        status.set('status://nest1/nest2/nest3', 'foo')
        self.assertEqual(status.get('status://nest1'),
                         {'nest2': {
                             'nest3': 'foo'
                         }})
        self.assertEqual(status.revision(), 5)

        # Clear an existing value.
        status.set('status://dict/sub1', None)
        self.assertEqual(status.get('status://dict'), {
            'sub1': None,
            'sub2': 4
        })
        self.assertEqual(status.revision(), 6)

        # Clear a sub-tree
        status.set('status://nest1', None)
        self.assertEqual(
            status.get('status://'), {
                'dict': {
                    'sub1': None,
                    'sub2': 4
                },
                'int': 10,
                'list': [],
                'list2': [],
                'nest1': None
            })
        self.assertEqual(status.revision(), 7)

        # Clear a nonexitent value
        status.set('status://nonexistent', None)
        self.assertEqual(
            status.get('status://'), {
                'dict': {
                    'sub1': None,
                    'sub2': 4
                },
                'int': 10,
                'list': [],
                'list2': [],
                'nest1': None
            })
        self.assertEqual(status.revision(), 7)
Beispiel #35
0
    def test_set_revision_nested(self):
        """Test Status.set() if revision is passed in."""

        # Make Sure initial revisions match expectations.
        status = self._create_status({
            'int': 1,
            'deep': {
                'foo': 2
            },
        })

        # Update one section.
        status.set('status://int', 10, revision=1)
        self.assertEqual(status.revision(), 2)
        self.assertEqual(status.revision('status://int'), 2)
        self.assertEqual(status.revision('status://deep'), 1)
        self.assertEqual(status.revision('status://deep/foo'), 1)

        # Ensure old section can still update using original revision.
        status.set('status://deep/foo', 20, revision=1)
        self.assertEqual(status.revision(), 3)
        self.assertEqual(status.revision('status://int'), 2)
        self.assertEqual(status.revision('status://deep'), 3)
        self.assertEqual(status.revision('status://deep/foo'), 3)

        # Ensure new creation works with nested revisions.
        status.set('status://deep/bar', 30, revision=3)
        self.assertEqual(status.revision(), 4)
        self.assertEqual(status.revision('status://int'), 2)
        self.assertEqual(status.revision('status://deep'), 4)
        self.assertEqual(status.revision('status://deep/foo'), 3)
        self.assertEqual(status.revision('status://deep/bar'), 4)

        # Ensure value can be updated using a parents revision.
        status.set('status://deep/foo', 21, revision=4)
        self.assertEqual(status.revision(), 5)
        self.assertEqual(status.revision('status://int'), 2)
        self.assertEqual(status.revision('status://deep'), 5)
        self.assertEqual(status.revision('status://deep/foo'), 5)
        self.assertEqual(status.revision('status://deep/bar'), 4)

        # Ensure new creation works with updated revisions.
        status.set('status://deep/bar', 31, revision=4)
        self.assertEqual(status.revision(), 6)
        self.assertEqual(status.revision('status://int'), 2)
        self.assertEqual(status.revision('status://deep'), 6)
        self.assertEqual(status.revision('status://deep/foo'), 5)
        self.assertEqual(status.revision('status://deep/bar'), 6)

        # Ensure value can be updated using a parents revision.
        status.set('status://int', 11, revision=6)
        status.set('status://int', 12, revision=7)
        self.assertEqual(status.revision(), 8)
        self.assertEqual(status.revision('status://int'), 8)
        self.assertEqual(status.revision('status://deep'), 6)
        self.assertEqual(status.revision('status://deep/foo'), 5)
        self.assertEqual(status.revision('status://deep/bar'), 6)

        # Ensure value can NOT be updated using an outdated parent version.
        self.assertRaises(monitor.status.RevisionMismatch,
                          status.set,
                          'status://deep/foo',
                          21,
                          revision=7)

        self.assertEqual(status.revision(), 8)
        self.assertEqual(status.revision('status://int'), 8)
        self.assertEqual(status.revision('status://deep'), 6)
        self.assertEqual(status.revision('status://deep/foo'), 5)
        self.assertEqual(status.revision('status://deep/bar'), 6)
Beispiel #36
0
    def test_nested_revisions(self):
        """Test Status.revision() handles nested revision numbers."""

        # Make Sure initial revisions match expectations.
        status = self._create_status({
            'int': 1,
            'string': 'foo',
            'list': [],
            'deep1': {
                'foo': 2
            },
            'deep2': {
                'sub_deep1': {
                    'foo': 3
                },
                'sub_deep2': {
                    'foo': 4
                }
            },
        })

        self.assertEqual(status.revision(), 1)
        self.assertEqual(status.revision('status://int'), 1)
        self.assertEqual(status.revision('status://string'), 1)
        self.assertEqual(status.revision('status://list'), 1)
        self.assertEqual(status.revision('status://deep1'), 1)
        self.assertEqual(status.revision('status://deep1/foo'), 1)
        self.assertEqual(status.revision('status://deep2'), 1)
        self.assertEqual(status.revision('status://deep2/sub_deep1'), 1)
        self.assertEqual(status.revision('status://deep2/sub_deep1/foo'), 1)
        self.assertEqual(status.revision('status://deep2/sub_deep2'), 1)
        self.assertEqual(status.revision('status://deep2/sub_deep2/foo'), 1)

        self.assertRaises(monitor.status.UnknownUrl, status.revision,
                          'status://nonexistent')

        # Make a simple update.
        status.set('status://int', 10)

        self.assertEqual(status.revision(), 2)
        self.assertEqual(status.revision('status://int'), 2)
        self.assertEqual(status.revision('status://string'), 1)
        self.assertEqual(status.revision('status://list'), 1)
        self.assertEqual(status.revision('status://deep1'), 1)
        self.assertEqual(status.revision('status://deep1/foo'), 1)
        self.assertEqual(status.revision('status://deep2'), 1)
        self.assertEqual(status.revision('status://deep2/sub_deep1'), 1)
        self.assertEqual(status.revision('status://deep2/sub_deep1/foo'), 1)
        self.assertEqual(status.revision('status://deep2/sub_deep2'), 1)
        self.assertEqual(status.revision('status://deep2/sub_deep2/foo'), 1)

        # Make a nested update.
        status.set('status://deep1/foo', 20)

        self.assertEqual(status.revision(), 3)
        self.assertEqual(status.revision('status://int'), 2)
        self.assertEqual(status.revision('status://string'), 1)
        self.assertEqual(status.revision('status://list'), 1)
        self.assertEqual(status.revision('status://deep1'), 3)
        self.assertEqual(status.revision('status://deep1/foo'), 3)
        self.assertEqual(status.revision('status://deep2'), 1)
        self.assertEqual(status.revision('status://deep2/sub_deep1'), 1)
        self.assertEqual(status.revision('status://deep2/sub_deep1/foo'), 1)
        self.assertEqual(status.revision('status://deep2/sub_deep2'), 1)
        self.assertEqual(status.revision('status://deep2/sub_deep2/foo'), 1)

        # Make a deeper nested update.
        status.set('status://deep2/sub_deep1/foo', 30)

        self.assertEqual(status.revision(), 4)
        self.assertEqual(status.revision('status://int'), 2)
        self.assertEqual(status.revision('status://string'), 1)
        self.assertEqual(status.revision('status://list'), 1)
        self.assertEqual(status.revision('status://deep1'), 3)
        self.assertEqual(status.revision('status://deep1/foo'), 3)
        self.assertEqual(status.revision('status://deep2'), 4)
        self.assertEqual(status.revision('status://deep2/sub_deep1'), 4)
        self.assertEqual(status.revision('status://deep2/sub_deep1/foo'), 4)
        self.assertEqual(status.revision('status://deep2/sub_deep2'), 1)
        self.assertEqual(status.revision('status://deep2/sub_deep2/foo'), 1)

        # Replace a sub-tree
        status.set('status://deep2/sub_deep1', {'foo': 40, 'bar': 50})

        self.assertEqual(status.revision(), 5)
        self.assertEqual(status.revision('status://int'), 2)
        self.assertEqual(status.revision('status://string'), 1)
        self.assertEqual(status.revision('status://list'), 1)
        self.assertEqual(status.revision('status://deep1'), 3)
        self.assertEqual(status.revision('status://deep1/foo'), 3)
        self.assertEqual(status.revision('status://deep2'), 5)
        self.assertEqual(status.revision('status://deep2/sub_deep1'), 5)
        self.assertEqual(status.revision('status://deep2/sub_deep1/foo'), 5)
        self.assertEqual(status.revision('status://deep2/sub_deep1/bar'), 5)
        self.assertEqual(status.revision('status://deep2/sub_deep2'), 1)
        self.assertEqual(status.revision('status://deep2/sub_deep2/foo'), 1)

        # Replace a sub-tree, unchanged.
        status.set('status://deep2/sub_deep1', {'foo': 40, 'bar': 50})

        self.assertEqual(status.revision(), 5)
        self.assertEqual(status.revision('status://int'), 2)
        self.assertEqual(status.revision('status://string'), 1)
        self.assertEqual(status.revision('status://list'), 1)
        self.assertEqual(status.revision('status://deep1'), 3)
        self.assertEqual(status.revision('status://deep1/foo'), 3)
        self.assertEqual(status.revision('status://deep2'), 5)
        self.assertEqual(status.revision('status://deep2/sub_deep1'), 5)
        self.assertEqual(status.revision('status://deep2/sub_deep1/foo'), 5)
        self.assertEqual(status.revision('status://deep2/sub_deep1/bar'), 5)
        self.assertEqual(status.revision('status://deep2/sub_deep2'), 1)
        self.assertEqual(status.revision('status://deep2/sub_deep2/foo'), 1)