Пример #1
0
    def test_exception_on_serverset_callback(self):
        """
        When serverset's callback has exception, It should not prevent other
        watchers from getting notified.
        """
        fd, tmp_file = tempfile.mkstemp()

        def on_change1(value):
            raise Exception

        test_data2 = [0, None]

        def on_change2(value):
            test_data2[0] += 1
            test_data2[1] = value

        new_content = "hello\nworld"
        watch = FileWatch(polling=False)
        watch._clear_all_watches()
        self._validate_empty_internal_map(watch)
        watch.add_watch(tmp_file, on_change1, watch_type='serverset')
        self._validate_internal_map(watch, tmp_file, 'serverset', 1)
        watch.add_watch(tmp_file, on_change2, watch_type='serverset')
        self._validate_internal_map(watch, tmp_file, 'serverset', 2)
        time.sleep(1)
        f = open(tmp_file, 'w')
        f.write(new_content)
        f.close()
        expected_serverset = new_content.split('\n')
        watch._check_file_updates()
        self._validate_internal_map(watch, tmp_file, 'serverset', 2)
        self.assertEqual(test_data2[0], 2)
        self.assertEqual(test_data2[1], expected_serverset)
        del watch
        os.remove(tmp_file)
Пример #2
0
    def test_serverset_change(self):
        """
        When monitored serverset is changed, the callback should be invoked.
        """
        fd, tmp_file = tempfile.mkstemp()

        test_data = [0, None]

        def on_change(value):
            test_data[0] += 1
            test_data[1] = value

        new_content = "hello"
        watch = FileWatch(polling=False)
        watch._clear_all_watches()
        self._validate_empty_internal_map(watch)
        watch.add_watch(tmp_file, on_change, watch_type='serverset')
        self._validate_internal_map(watch, tmp_file, 'serverset', 1)
        time.sleep(1)
        f = open(tmp_file, 'w')
        f.write(new_content)
        f.close()
        watch._check_file_updates()
        self._validate_internal_map(watch, tmp_file, 'serverset', 1)
        self.assertEqual(test_data[0], 2)
        self.assertEqual(test_data[1], [new_content])

        # Rerun check_updates won't invoke callback
        watch._check_file_updates()
        self.assertEqual(test_data[0], 2)
        self.assertEqual(test_data[1], [new_content])

        del watch
        os.remove(tmp_file)
Пример #3
0
 def test_null_callback_serverset(self):
     watch = FileWatch(polling=False)
     watch._clear_all_watches()
     self._validate_empty_internal_map(watch)
     self.assertRaises(AssertionError, watch.add_watch, "__nonexistent__",
                       None, 'serverset')
     self._validate_empty_internal_map(watch)
     del watch
Пример #4
0
    def test_serverset_change(self):
        """
        When monitored serverset is changed, the callback should be invoked.
        """
        fd, tmp_file = tempfile.mkstemp()

        test_data = [0, None]

        def on_change(value):
            test_data[0] += 1
            test_data[1] = value

        new_content = "hello"
        watch = FileWatch(polling=False)
        watch._clear_all_watches()
        self._validate_empty_internal_map(watch)
        watch.add_watch(tmp_file, on_change, watch_type='serverset')
        self._validate_internal_map(watch, tmp_file, 'serverset', 1)
        time.sleep(1)
        f = open(tmp_file, 'w')
        f.write(new_content)
        f.close()
        watch._check_file_updates()
        self._validate_internal_map(watch, tmp_file, 'serverset', 1)
        self.assertEqual(test_data[0], 2)
        self.assertEqual(test_data[1], [new_content])

        # Rerun check_updates won't invoke callback
        watch._check_file_updates()
        self.assertEqual(test_data[0], 2)
        self.assertEqual(test_data[1], [new_content])

        del watch
        os.remove(tmp_file)
Пример #5
0
    def test_exception_on_serverset_callback(self):
        """
        When serverset's callback has exception, It should not prevent other
        watchers from getting notified.
        """
        fd, tmp_file = tempfile.mkstemp()

        def on_change1(value):
            raise Exception

        test_data2 = [0, None]

        def on_change2(value):
            test_data2[0] += 1
            test_data2[1] = value

        new_content = "hello\nworld"
        watch = FileWatch(polling=False)
        watch._clear_all_watches()
        self._validate_empty_internal_map(watch)
        watch.add_watch(tmp_file, on_change1, watch_type='serverset')
        self._validate_internal_map(watch, tmp_file, 'serverset', 1)
        watch.add_watch(tmp_file, on_change2, watch_type='serverset')
        self._validate_internal_map(watch, tmp_file, 'serverset', 2)
        time.sleep(1)
        f = open(tmp_file, 'w')
        f.write(new_content)
        f.close()
        expected_serverset = new_content.split('\n')
        watch._check_file_updates()
        self._validate_internal_map(watch, tmp_file, 'serverset', 2)
        self.assertEqual(test_data2[0], 2)
        self.assertEqual(test_data2[1], expected_serverset)
        del watch
        os.remove(tmp_file)
Пример #6
0
    def test_nonexistent_serverest(self):
        def on_change(value):
            pass

        watch = FileWatch(polling=False)
        watch._clear_all_watches()
        self._validate_empty_internal_map(watch)
        self.assertRaises(OSError, watch.add_watch, "__nonexistent__",
                          on_change, 'serverset')
        self._validate_empty_internal_map(watch)
        del watch
Пример #7
0
 def test_null_callback_config(self):
     watch = FileWatch(polling=False)
     watch._clear_all_watches()
     self._validate_empty_internal_map(watch)
     self.assertRaises(
         AssertionError,
         watch.add_watch,
         "__nonexistent__",
         None
     )
     self._validate_empty_internal_map(watch)
     del watch
Пример #8
0
    def test_unrecognized_watch_type(self):
        fd, tmp_file = tempfile.mkstemp()

        watch = FileWatch(polling=False)
        watch._clear_all_watches()
        self._validate_empty_internal_map(watch)

        def on_change(value, stat):
            pass

        self.assertRaises(Exception, watch.add_watch, tmp_file, on_change,
                          "__not_exist")
        self._validate_empty_internal_map(watch)
        del watch
Пример #9
0
    def test_nonexistent_config(self):
        def on_change(value, stat):
            pass

        watch = FileWatch(polling=False)
        watch._clear_all_watches()
        self._validate_empty_internal_map(watch)
        self.assertRaises(
            OSError,
            watch.add_watch,
            "__nonexistent__",
            on_change
        )
        self._validate_empty_internal_map(watch)
        del watch
Пример #10
0
    def test_config_content_not_change(self):
        """
        When monitored config has mtime changed but not the content,
        callback should not be triggered.
        """
        fd, tmp_file = tempfile.mkstemp()

        test_data = [0, None, None]

        def on_change(value, stat):
            test_data[0] += 1
            test_data[1] = value
            test_data[2] = stat.version

        new_content = "hello"
        watch = FileWatch(polling=False)
        watch._clear_all_watches()
        self._validate_empty_internal_map(watch)
        watch.add_watch(tmp_file, on_change)
        self._validate_internal_map(watch, tmp_file, 'config', 1)
        time.sleep(1)
        f = open(tmp_file, 'w')
        f.write(new_content)
        f.close()
        watch._check_file_updates()
        self._validate_internal_map(watch, tmp_file, 'config', 1)
        old_update_time = os.path.getmtime(tmp_file)
        self.assertEqual(test_data[0], 2)
        self.assertEqual(test_data[1], new_content)
        self.assertEqual(test_data[2], old_update_time)

        time.sleep(1)
        f = open(tmp_file, 'w')
        # Writing the same content
        f.write(new_content)
        f.close()
        new_update_time = os.path.getmtime(tmp_file)
        self.assertNotEqual(old_update_time, new_update_time)
        # Rerun check_updates won't invoke callback
        watch._check_file_updates()
        self._validate_internal_map(watch, tmp_file, 'config', 1)
        self.assertEqual(test_data[0], 2)
        self.assertEqual(test_data[1], new_content)
        self.assertEqual(test_data[2], old_update_time)

        del watch
        os.remove(tmp_file)
Пример #11
0
    def test_unrecognized_watch_type(self):
        fd, tmp_file = tempfile.mkstemp()

        watch = FileWatch(polling=False)
        watch._clear_all_watches()
        self._validate_empty_internal_map(watch)

        def on_change(value, stat):
            pass
        self.assertRaises(
            Exception,
            watch.add_watch,
            tmp_file,
            on_change,
            "__not_exist"
        )
        self._validate_empty_internal_map(watch)
        del watch
Пример #12
0
    def test_multiple_watchers_on_single_config(self):
        """
        When one config file has multiple watchers, all will be invoked
        when the config changes.
        """
        fd, tmp_file = tempfile.mkstemp()

        test_data1 = [0, None, None]

        def on_change1(value, stat):
            test_data1[0] += 1
            test_data1[1] = value
            test_data1[2] = stat.version

        test_data2 = [0, None, None]

        def on_change2(value, stat):
            test_data2[0] += 1
            test_data2[1] = value
            test_data2[2] = stat.version

        new_content = "hello"
        watch = FileWatch(polling=False)
        watch._clear_all_watches()
        self._validate_empty_internal_map(watch)
        watch.add_watch(tmp_file, on_change1)
        self._validate_internal_map(watch, tmp_file, 'config', 1)
        watch.add_watch(tmp_file, on_change2)
        self._validate_internal_map(watch, tmp_file, 'config', 2)
        time.sleep(1)
        f = open(tmp_file, 'w')
        f.write(new_content)
        f.close()
        watch._check_file_updates()
        self._validate_internal_map(watch, tmp_file, 'config', 2)
        self.assertEqual(test_data1[0], 2)
        self.assertEqual(test_data1[1], new_content)
        self.assertEqual(test_data1[2], os.path.getmtime(tmp_file))
        self.assertEqual(test_data2[0], 2)
        self.assertEqual(test_data2[1], new_content)
        self.assertEqual(test_data2[2], os.path.getmtime(tmp_file))
        del watch
        os.remove(tmp_file)
Пример #13
0
    def test_config_content_not_change(self):
        """
        When monitored config has mtime changed but not the content,
        callback should not be triggered.
        """
        fd, tmp_file = tempfile.mkstemp()

        test_data = [0, None, None]

        def on_change(value, stat):
            test_data[0] += 1
            test_data[1] = value
            test_data[2] = stat.version

        new_content = "hello"
        watch = FileWatch(polling=False)
        watch._clear_all_watches()
        self._validate_empty_internal_map(watch)
        watch.add_watch(tmp_file, on_change)
        self._validate_internal_map(watch, tmp_file, 'config', 1)
        time.sleep(1)
        f = open(tmp_file, 'w')
        f.write(new_content)
        f.close()
        watch._check_file_updates()
        self._validate_internal_map(watch, tmp_file, 'config', 1)
        old_update_time = os.path.getmtime(tmp_file)
        self.assertEqual(test_data[0], 2)
        self.assertEqual(test_data[1], new_content)
        self.assertEqual(test_data[2], old_update_time)

        time.sleep(1)
        f = open(tmp_file, 'w')
        # Writing the same content
        f.write(new_content)
        f.close()
        new_update_time = os.path.getmtime(tmp_file)
        self.assertNotEqual(old_update_time, new_update_time)
        # Rerun check_updates won't invoke callback
        watch._check_file_updates()
        self._validate_internal_map(watch, tmp_file, 'config', 1)
        self.assertEqual(test_data[0], 2)
        self.assertEqual(test_data[1], new_content)
        self.assertEqual(test_data[2], old_update_time)

        del watch
        os.remove(tmp_file)
Пример #14
0
    def test_add_serverset_monitor(self):
        """
        When adding a monitor, the callback should be invoked.
        """
        fd, tmp_file = tempfile.mkstemp()

        test_data = [0, None]

        def on_change(children):
            test_data[0] += 1
            test_data[1] = children

        watch = FileWatch(polling=False)
        watch._clear_all_watches()
        self._validate_empty_internal_map(watch)
        watch.add_watch(tmp_file, on_change, watch_type='serverset')
        self._validate_internal_map(watch, tmp_file, 'serverset', 1)
        self.assertEqual(test_data[0], 1)
        self.assertEqual(test_data[1], [])
        del watch
        os.remove(tmp_file)
Пример #15
0
    def test_multiple_watchers_on_single_serverset(self):
        """
        When one serverset file has multiple watchers, all will be invoked
        when the serverset changes.
        """
        fd, tmp_file = tempfile.mkstemp()

        test_data1 = [0, None]

        def on_change1(value):
            test_data1[0] += 1
            test_data1[1] = value

        test_data2 = [0, None]

        def on_change2(value):
            test_data2[0] += 1
            test_data2[1] = value

        new_content = "hello\nworld"
        watch = FileWatch(polling=False)
        watch._clear_all_watches()
        self._validate_empty_internal_map(watch)
        watch.add_watch(tmp_file, on_change1, watch_type='serverset')
        self._validate_internal_map(watch, tmp_file, 'serverset', 1)
        watch.add_watch(tmp_file, on_change2, watch_type='serverset')
        self._validate_internal_map(watch, tmp_file, 'serverset', 2)
        time.sleep(1)
        f = open(tmp_file, 'w')
        f.write(new_content)
        f.close()
        expected_serverset = new_content.split('\n')
        watch._check_file_updates()
        self._validate_internal_map(watch, tmp_file, 'serverset', 2)
        self.assertEqual(test_data1[0], 2)
        self.assertEqual(test_data1[1], expected_serverset)
        self.assertEqual(test_data2[0], 2)
        self.assertEqual(test_data2[1], expected_serverset)
        del watch
        os.remove(tmp_file)
Пример #16
0
    def test_multiple_watchers_on_single_config(self):
        """
        When one config file has multiple watchers, all will be invoked
        when the config changes.
        """
        fd, tmp_file = tempfile.mkstemp()

        test_data1 = [0, None, None]

        def on_change1(value, stat):
            test_data1[0] += 1
            test_data1[1] = value
            test_data1[2] = stat.version

        test_data2 = [0, None, None]

        def on_change2(value, stat):
            test_data2[0] += 1
            test_data2[1] = value
            test_data2[2] = stat.version

        new_content = "hello"
        watch = FileWatch(polling=False)
        watch._clear_all_watches()
        self._validate_empty_internal_map(watch)
        watch.add_watch(tmp_file, on_change1)
        self._validate_internal_map(watch, tmp_file, 'config', 1)
        watch.add_watch(tmp_file, on_change2)
        self._validate_internal_map(watch, tmp_file, 'config', 2)
        time.sleep(1)
        f = open(tmp_file, 'w')
        f.write(new_content)
        f.close()
        watch._check_file_updates()
        self._validate_internal_map(watch, tmp_file, 'config', 2)
        self.assertEqual(test_data1[0], 2)
        self.assertEqual(test_data1[1], new_content)
        self.assertEqual(test_data1[2], os.path.getmtime(tmp_file))
        self.assertEqual(test_data2[0], 2)
        self.assertEqual(test_data2[1], new_content)
        self.assertEqual(test_data2[2], os.path.getmtime(tmp_file))
        del watch
        os.remove(tmp_file)
Пример #17
0
    def test_add_config_monitor(self):
        """
        When adding a monitor, the callback should be invoked.
        """
        fd, tmp_file = tempfile.mkstemp()

        test_data = [0, None, None]

        def on_change(value, stat):
            test_data[0] += 1
            test_data[1] = value
            test_data[2] = stat.version

        watch = FileWatch(polling=False)
        watch._clear_all_watches()
        self._validate_empty_internal_map(watch)
        watch.add_watch(tmp_file, on_change)
        self._validate_internal_map(watch, tmp_file, 'config', 1)
        self.assertEqual(test_data[0], 1)
        self.assertEqual(test_data[1], "")
        self.assertEqual(test_data[2], os.path.getmtime(tmp_file))
        del watch
        os.remove(tmp_file)
Пример #18
0
    def test_exception_on_config_callback(self):
        """
        When config's callback has exception, It should not prevent other
        watchers from getting notified.
        """
        fd, tmp_file = tempfile.mkstemp()

        def on_change1(value, stat):
            raise Exception

        test_data2 = [0, None, None]

        def on_change2(value, stat):
            test_data2[0] += 1
            test_data2[1] = value
            test_data2[2] = stat.version

        new_content = "hello"
        watch = FileWatch(polling=False)
        watch._clear_all_watches()
        self._validate_empty_internal_map(watch)
        watch.add_watch(tmp_file, on_change1)
        self._validate_internal_map(watch, tmp_file, 'config', 1)
        watch.add_watch(tmp_file, on_change2)
        self._validate_internal_map(watch, tmp_file, 'config', 2)
        time.sleep(1)
        f = open(tmp_file, 'w')
        f.write(new_content)
        f.close()
        watch._check_file_updates()
        self._validate_internal_map(watch, tmp_file, 'config', 2)
        self.assertEqual(test_data2[0], 2)
        self.assertEqual(test_data2[1], new_content)
        self.assertEqual(test_data2[2], os.path.getmtime(tmp_file))
        del watch
        os.remove(tmp_file)
Пример #19
0
    def test_multiple_watchers_on_single_serverset(self):
        """
        When one serverset file has multiple watchers, all will be invoked
        when the serverset changes.
        """
        fd, tmp_file = tempfile.mkstemp()

        test_data1 = [0, None]

        def on_change1(value):
            test_data1[0] += 1
            test_data1[1] = value

        test_data2 = [0, None]

        def on_change2(value):
            test_data2[0] += 1
            test_data2[1] = value

        new_content = "hello\nworld"
        watch = FileWatch(polling=False)
        watch._clear_all_watches()
        self._validate_empty_internal_map(watch)
        watch.add_watch(tmp_file, on_change1, watch_type='serverset')
        self._validate_internal_map(watch, tmp_file, 'serverset', 1)
        watch.add_watch(tmp_file, on_change2, watch_type='serverset')
        self._validate_internal_map(watch, tmp_file, 'serverset', 2)
        time.sleep(1)
        f = open(tmp_file, 'w')
        f.write(new_content)
        f.close()
        expected_serverset = new_content.split('\n')
        watch._check_file_updates()
        self._validate_internal_map(watch, tmp_file, 'serverset', 2)
        self.assertEqual(test_data1[0], 2)
        self.assertEqual(test_data1[1], expected_serverset)
        self.assertEqual(test_data2[0], 2)
        self.assertEqual(test_data2[1], expected_serverset)
        del watch
        os.remove(tmp_file)
Пример #20
0
    def test_exception_on_config_callback(self):
        """
        When config's callback has exception, It should not prevent other
        watchers from getting notified.
        """
        fd, tmp_file = tempfile.mkstemp()

        def on_change1(value, stat):
            raise Exception

        test_data2 = [0, None, None]

        def on_change2(value, stat):
            test_data2[0] += 1
            test_data2[1] = value
            test_data2[2] = stat.version

        new_content = "hello"
        watch = FileWatch(polling=False)
        watch._clear_all_watches()
        self._validate_empty_internal_map(watch)
        watch.add_watch(tmp_file, on_change1)
        self._validate_internal_map(watch, tmp_file, 'config', 1)
        watch.add_watch(tmp_file, on_change2)
        self._validate_internal_map(watch, tmp_file, 'config', 2)
        time.sleep(1)
        f = open(tmp_file, 'w')
        f.write(new_content)
        f.close()
        watch._check_file_updates()
        self._validate_internal_map(watch, tmp_file, 'config', 2)
        self.assertEqual(test_data2[0], 2)
        self.assertEqual(test_data2[1], new_content)
        self.assertEqual(test_data2[2], os.path.getmtime(tmp_file))
        del watch
        os.remove(tmp_file)
Пример #21
0
    def test_multiple_serverset_changes(self):
        """
        When monitored serverset is changed multiple times, the callback
        should be invoked every time.
        """
        fd, tmp_file = tempfile.mkstemp()

        test_data = [0, None]

        def on_change(value):
            test_data[0] += 1
            test_data[1] = value

        new_content = "hello"
        watch = FileWatch(polling=False)
        watch._clear_all_watches()
        self._validate_empty_internal_map(watch)
        watch.add_watch(tmp_file, on_change, watch_type='serverset')
        self._validate_internal_map(watch, tmp_file, 'serverset', 1)
        times = 3
        expected_content = []
        isFirst = True
        for i in range(times):
            time.sleep(1)
            new_line = new_content + str(i)
            f = open(tmp_file, 'a')
            if isFirst:
                isFirst = False
            else:
                f.write("\n")
            f.write(new_line)
            f.close()
            watch._check_file_updates()
            self._validate_internal_map(watch, tmp_file, 'serverset', 1)
            expected_content.append(new_line)
            self.assertEqual(test_data[0], i + 2)
            self.assertEqual(test_data[1], expected_content)
        del watch
        os.remove(tmp_file)
Пример #22
0
    def test_multiple_config_changes(self):
        """
        When monitored file is changed multiple times, the callback
        should be invoked every time.
        """
        fd, tmp_file = tempfile.mkstemp()

        test_data = [0, None, None]

        def on_change(value, stat):
            test_data[0] += 1
            test_data[1] = value
            test_data[2] = stat.version

        new_content = "hello"
        watch = FileWatch(polling=False)
        watch._clear_all_watches()
        self._validate_empty_internal_map(watch)
        watch.add_watch(tmp_file, on_change)
        self._validate_internal_map(watch, tmp_file, 'config', 1)
        times = 3
        expected_content = ""
        for i in range(times):
            time.sleep(1)
            new_line = new_content + str(i) + '\n'
            f = open(tmp_file, 'a')
            f.write(new_line)
            f.close()
            watch._check_file_updates()
            self._validate_internal_map(watch, tmp_file, 'config', 1)
            expected_content += new_line
            self.assertEqual(test_data[0], i + 2)
            self.assertEqual(test_data[1], expected_content)
            self.assertEqual(test_data[2], os.path.getmtime(tmp_file))
        del watch
        os.remove(tmp_file)
Пример #23
0
    def test_multiple_serverset_changes(self):
        """
        When monitored serverset is changed multiple times, the callback
        should be invoked every time.
        """
        fd, tmp_file = tempfile.mkstemp()

        test_data = [0, None]

        def on_change(value):
            test_data[0] += 1
            test_data[1] = value

        new_content = "hello"
        watch = FileWatch(polling=False)
        watch._clear_all_watches()
        self._validate_empty_internal_map(watch)
        watch.add_watch(tmp_file, on_change, watch_type='serverset')
        self._validate_internal_map(watch, tmp_file, 'serverset', 1)
        times = 3
        expected_content = []
        isFirst = True
        for i in range(times):
            time.sleep(1)
            new_line = new_content + str(i)
            f = open(tmp_file, 'a')
            if isFirst:
                isFirst = False
            else:
                f.write("\n")
            f.write(new_line)
            f.close()
            watch._check_file_updates()
            self._validate_internal_map(watch, tmp_file, 'serverset', 1)
            expected_content.append(new_line)
            self.assertEqual(test_data[0], i+2)
            self.assertEqual(test_data[1], expected_content)
        del watch
        os.remove(tmp_file)
Пример #24
0
    def test_multiple_config_changes(self):
        """
        When monitored file is changed multiple times, the callback
        should be invoked every time.
        """
        fd, tmp_file = tempfile.mkstemp()

        test_data = [0, None, None]

        def on_change(value, stat):
            test_data[0] += 1
            test_data[1] = value
            test_data[2] = stat.version

        new_content = "hello"
        watch = FileWatch(polling=False)
        watch._clear_all_watches()
        self._validate_empty_internal_map(watch)
        watch.add_watch(tmp_file, on_change)
        self._validate_internal_map(watch, tmp_file, 'config', 1)
        times = 3
        expected_content = ""
        for i in range(times):
            time.sleep(1)
            new_line = new_content + str(i) + '\n'
            f = open(tmp_file, 'a')
            f.write(new_line)
            f.close()
            watch._check_file_updates()
            self._validate_internal_map(watch, tmp_file, 'config', 1)
            expected_content += new_line
            self.assertEqual(test_data[0], i+2)
            self.assertEqual(test_data[1], expected_content)
            self.assertEqual(test_data[2], os.path.getmtime(tmp_file))
        del watch
        os.remove(tmp_file)
Пример #25
0
    def test_add_serverset_monitor(self):
        """
        When adding a monitor, the callback should be invoked.
        """
        fd, tmp_file = tempfile.mkstemp()

        test_data = [0, None]

        def on_change(children):
            test_data[0] += 1
            test_data[1] = children

        watch = FileWatch(polling=False)
        watch._clear_all_watches()
        self._validate_empty_internal_map(watch)
        watch.add_watch(tmp_file, on_change, watch_type='serverset')
        self._validate_internal_map(watch, tmp_file, 'serverset', 1)
        self.assertEqual(test_data[0], 1)
        self.assertEqual(test_data[1], [])
        del watch
        os.remove(tmp_file)
Пример #26
0
    def test_add_config_monitor(self):
        """
        When adding a monitor, the callback should be invoked.
        """
        fd, tmp_file = tempfile.mkstemp()

        test_data = [0, None, None]

        def on_change(value, stat):
            test_data[0] += 1
            test_data[1] = value
            test_data[2] = stat.version

        watch = FileWatch(polling=False)
        watch._clear_all_watches()
        self._validate_empty_internal_map(watch)
        watch.add_watch(tmp_file, on_change)
        self._validate_internal_map(watch, tmp_file, 'config', 1)
        self.assertEqual(test_data[0], 1)
        self.assertEqual(test_data[1], "")
        self.assertEqual(test_data[2], os.path.getmtime(tmp_file))
        del watch
        os.remove(tmp_file)
Пример #27
0
class ServerSetWithFileTestCase(unittest.TestCase):
    """Test server set with local file."""

    SERVER_SET_PATH = "/test_server_set"
    SERVER_SET_DESTROY_PATH = "/test_server_set_destroy"
    PORT_1 = 8088
    PORT_2 = 8189
    END_POINT_1 = "%s:%d" % (socket.gethostname(), PORT_1)
    END_POINT_2 = "%s:%d" % (socket.gethostname(), PORT_2)
    END_POINTS = [END_POINT_1, END_POINT_2]

    # Initialize a singleton file watch with low wait time
    FILE_WATCH = FileWatch(polling_wait_in_seconds=0.5)
    FILE_WATCH._clear_all_watches()

    @mock.patch("kazoo.client.KazooClient.__new__",
                new=mock.Mock(side_effect=testutil.get_mock_kazoo_client))
    def test_server_set(self):
        """Test various failure scenarios on server set implementation.

        1. When a new server joins the set, the watcher should be notified.
           In practice there is a daemon monitoring the server set change in
           zk and update the local file.
        2. When the underlying zk client disconnects and then recovers,
           the server set should be transparent to server set participants
           and watchers.
        3. When the underlying zk client messes up beyond recovery,
           it should be transparent to server set participants and watchers.

        Although when a local file is being watched, now all the code paths
        about the above behaviors got affected, we still want to test all the
        scenarios to make sure nothing breaks when a file is used.

        NOTE: to simulate the behavior in practice, when a server joins or
        leaves, we assume that there is a daemon to make the corresponding
        change to the local file.
        """
        fd, tmp_file = tempfile.mkstemp()
        all_children = []
        watcher_triggered = Event()

        def server_set_watcher(children):
            while all_children:
                all_children.pop()
            for child in children:
                all_children.append(child)
            watcher_triggered.set()

        testutil.initialize_kazoo_client_manager(ZK_HOSTS)
        client = KazooClientManager().get_client()
        server_set = ServerSet(ServerSetWithFileTestCase.SERVER_SET_PATH,
                               ZK_HOSTS,
                               waiting_in_secs=0.01,
                               file_path=tmp_file)
        server_set.join(ServerSetWithFileTestCase.PORT_1, use_ip=False).join()
        # update the local file manually here, suppose there is a daemon
        with open(tmp_file, 'w') as f:
            f.write(ServerSetWithFileTestCase.END_POINT_1)
        gevent.sleep(1)
        server_set.monitor(server_set_watcher).join()
        watcher_triggered.wait(1)
        # Now the server set should only contain end point 1
        self.assertEqual(all_children, [ServerSetWithFileTestCase.END_POINT_1])
        watcher_triggered.clear()
        server_set.join(ServerSetWithFileTestCase.PORT_2, use_ip=False).join()
        # update the local file manually here, suppose there is a daemon
        with open(tmp_file, 'w') as f:
            f.write(ServerSetWithFileTestCase.END_POINT_1 + "\n" +
                    ServerSetWithFileTestCase.END_POINT_2)
        gevent.sleep(1)
        watcher_triggered.wait(1)
        all_children.sort()
        # Now the server set should contain both end point 1 and 2
        self.assertEqual(all_children, ServerSetWithFileTestCase.END_POINTS)
        # Test recoverable failure
        client.stop()
        watcher_triggered.clear()
        client.start()
        watcher_triggered.wait(1)
        # Server set should remain the same when the client recovers
        all_children.sort()
        self.assertEqual(all_children, ServerSetWithFileTestCase.END_POINTS)
        # Test client change
        client.stop()
        watcher_triggered.clear()
        # give the monit greenlet a chance to detect failures
        gevent.sleep(1)
        watcher_triggered.wait(1)
        # Server set should survive the underlying client being swapped out
        all_children.sort()
        self.assertEqual(all_children, ServerSetWithFileTestCase.END_POINTS)

        self.FILE_WATCH._clear_all_watches()
        os.remove(tmp_file)

    @attr('destroy_serverset')
    @mock.patch("kazoo.client.KazooClient.__new__",
                new=mock.Mock(side_effect=testutil.get_mock_kazoo_client))
    def test_serverset_destroy(self):
        testutil.initialize_kazoo_client_manager(ZK_HOSTS)
        client = KazooClientManager().get_client()
        client.start()
        fd, tmp_file = tempfile.mkstemp()
        server_set = ServerSet(
            ServerSetWithFileTestCase.SERVER_SET_DESTROY_PATH,
            ZK_HOSTS,
            waiting_in_secs=0.01)
        server_set.join(ServerSetWithFileTestCase.PORT_1, use_ip=False)
        server_set.join(ServerSetWithFileTestCase.PORT_2, use_ip=False)
        # update the local file manually here, suppose there is a daemon
        with open(tmp_file, 'w') as f:
            f.write(ServerSetWithFileTestCase.END_POINT_1 + "\n" +
                    ServerSetWithFileTestCase.END_POINT_2)
        # Give time to let server set join to do its magic.
        gevent.sleep(1)
        server_set._destroy(ServerSetWithFileTestCase.END_POINT_1)
        # update the local file manually here, suppose there is a daemon
        with open(tmp_file, 'w') as f:
            f.write(ServerSetWithFileTestCase.END_POINT_2)
        gevent.sleep(1)
        children = client.get_children(
            ServerSetWithFileTestCase.SERVER_SET_DESTROY_PATH)
        for child in children:
            self.assertFalse(
                child.endswith(ServerSetWithFileTestCase.END_POINT_1))
        self.FILE_WATCH._clear_all_watches()
        os.remove(tmp_file)
Пример #28
0
class DataWatcherWithFileTestCase(unittest.TestCase):
    """
    Test the data watcher with a local file provided.
    """
    TEST_PATH = "/test_data_watcher"
    DATA_0 = "foo"
    DATA_1 = "bar"

    # Initialize a singleton file watch with low wait time
    FILE_WATCH = FileWatch(polling_wait_in_seconds=0.5)

    @mock.patch("kazoo.client.KazooClient.__new__",
                new=mock.Mock(side_effect=testutil.get_mock_kazoo_client))
    def test_data_watcher(self):
        """Test data watcher with a local file:

        1. When data get changed, watcher callback should be invoked.
        2. When the underlying zk client disconnects and then recovers,
           the watcher callback should be invoked.
        3. When the underlying zk client messes up beyond recovery,
           the underlying client should be replaced, and once the new client
           is in place, the watcher callback should be invoked again.

        Although when a local file is being watched, now all the code paths
        about the above behaviors got affected, we still want to test all the
        scenarios to make sure nothing breaks when a file is used.
        """
        data_stat = []
        watcher_triggered = Event()

        fd, tmp_file = tempfile.mkstemp()
        with open(tmp_file, 'w') as f:
            f.write(self.DATA_0)

        def data_watch(data, stat):
            while data_stat:
                data_stat.pop()
            data_stat.append(data)
            data_stat.append(stat)
            watcher_triggered.set()

        data_watcher = DataWatcher(DataWatcherWithFileTestCase.TEST_PATH,
                                   ZK_HOSTS,
                                   waiting_in_secs=0.01,
                                   file_path=tmp_file)
        data_watcher.watch(data_watch).join()
        watcher_triggered.wait(1)
        # Now the data and version should be foo and the mtime of file.
        mtime = os.path.getmtime(tmp_file)
        self.assertEqual(data_stat[0], DataWatcherWithFileTestCase.DATA_0)
        self.assertEqual(data_stat[1].version, mtime)
        self.assertEqual(data_watcher.get_data()[0],
                         DataWatcherWithFileTestCase.DATA_0)
        self.assertEqual(data_watcher.get_data()[1].version, mtime)
        watcher_triggered.clear()

        gevent.sleep(1)
        with open(tmp_file, 'w') as f:
            f.write(self.DATA_1)
        watcher_triggered.wait(1)
        # Make sure that watch callback is triggered.
        mtime = os.path.getmtime(tmp_file)
        self.assertEqual(data_stat[0], DataWatcherWithFileTestCase.DATA_1)
        self.assertEqual(data_stat[1].version, mtime)
        self.assertEqual(data_watcher.get_data()[0],
                         DataWatcherWithFileTestCase.DATA_1)
        self.assertEqual(data_watcher.get_data()[1].version, mtime)
        data_stat.pop()
        data_stat.pop()

        # Test recoverable failure, even though the watcher with a file path
        # is not changing any implementation or behavior in this part, we want
        # to keep the tests here to ensure.
        watcher_triggered.clear()

        self.FILE_WATCH._clear_all_watches()
        os.remove(tmp_file)