Exemple #1
0
 def setUp(self):
     self.A = make_job('a', name='A')
     self.B = make_job('b', name='B', plugin='local', description='foo')
     self.C = make_job('c', name='C')
     self.D = self.B.create_child_job_from_record(
         RFC822Record(data={
             'id': 'd',
             'name': 'D',
             'plugin': 'shell'
         },
                      origin=Origin(source=JobOutputTextSource(self.B),
                                    line_start=1,
                                    line_end=1)))
     self.E = self.B.create_child_job_from_record(
         RFC822Record(data={
             'id': 'e',
             'name': 'E',
             'plugin': 'shell'
         },
                      origin=Origin(source=JobOutputTextSource(self.B),
                                    line_start=1,
                                    line_end=1)))
     self.F = make_job('f', name='F', plugin='resource', description='baz')
     self.tree = SelectableJobTreeNode.create_tree(
         [self.A, self.B, self.C, self.D, self.E, self.F], legacy_mode=True)
Exemple #2
0
    def setUp(self):
        A = make_job('A')
        B = make_job('B', plugin='local', description='foo')
        C = make_job('C')
        D = B.create_child_job_from_record(
            RFC822Record(data={
                'id': 'D',
                'plugin': 'shell'
            },
                         origin=Origin(source=JobOutputTextSource(B),
                                       line_start=1,
                                       line_end=1)))
        E = B.create_child_job_from_record(
            RFC822Record(data={
                'id': 'E',
                'plugin': 'local',
                'description': 'bar'
            },
                         origin=Origin(source=JobOutputTextSource(B),
                                       line_start=1,
                                       line_end=1)))
        F = E.create_child_job_from_record(
            RFC822Record(data={
                'id': 'F',
                'plugin': 'shell'
            },
                         origin=Origin(source=JobOutputTextSource(E),
                                       line_start=1,
                                       line_end=1)))
        G = make_job('G', plugin='local', description='baz')
        R = make_job('R', plugin='resource')
        Z = make_job('Z', plugin='local', description='zaz')

        self.tree = JobTreeNode.create_tree([R, B, C, D, E, F, G, A, Z],
                                            legacy_mode=True)
Exemple #3
0
 def test_relative_to(self):
     """
     verify how Origin.relative_to() works in various situations
     """
     # if the source does not have relative_to method, nothing is changed
     origin = Origin(UnknownTextSource(), 1, 2)
     self.assertIs(origin.relative_to("/some/path"), origin)
     # otherwise the source is replaced and a new origin is returned
     self.assertEqual(
         Origin(FileTextSource("/some/path/file.txt"), 1,
                2).relative_to("/some/path"),
         Origin(FileTextSource("file.txt"), 1, 2))
Exemple #4
0
 def test_relative_to(self):
     """
     verify how Origin.relative_to() works in various situations
     """
     # if the source does not have relative_to method, nothing is changed
     origin = Origin(UnknownTextSource(), 1, 2)
     self.assertIs(origin.relative_to("/some/path"), origin)
     # otherwise the source is replaced and a new origin is returned
     self.assertEqual(
         Origin(
             FileTextSource("/some/path/file.txt"), 1, 2
         ).relative_to("/some/path"),
         Origin(FileTextSource("file.txt"), 1, 2))
Exemple #5
0
 def test_origin_caller(self):
     """
     verify that Origin.get_caller_origin() uses PythonFileTextSource as the
     origin.source attribute.
     """
     self.assertIsInstance(Origin.get_caller_origin().source,
                           PythonFileTextSource)
Exemple #6
0
 def test_origin_caller(self):
     """
     verify that Origin.get_caller_origin() uses PythonFileTextSource as the
     origin.source attribute.
     """
     self.assertIsInstance(
         Origin.get_caller_origin().source, PythonFileTextSource)
Exemple #7
0
 def test_via_does_not_change_checksum(self):
     """
     verify that the 'via' attribute in no way influences job checksum
     """
     # Create a 'parent' job
     parent = JobDefinition({'id': 'parent', 'plugin': 'local'})
     # Create a 'child' job, using create_child_job_from_record() should
     # time the two so that child.via should be parent.checksum.
     #
     # The elaborate record that gets passed has all the meta-data that
     # traces back to the 'parent' job (as well as some imaginary line_start
     # and line_end values for the purpose of the test).
     child = parent.create_child_job_from_record(
         RFC822Record(data={
             'id': 'test',
             'plugin': 'shell'
         },
                      origin=Origin(source=JobOutputTextSource(parent),
                                    line_start=1,
                                    line_end=1)))
     # Now 'child.via' should be the same as 'parent.checksum'
     self.assertEqual(child.via, parent.checksum)
     # Create an unrelated job 'helper' with the definition identical as
     # 'child' but without any ties to the 'parent' job
     helper = JobDefinition({'id': 'test', 'plugin': 'shell'})
     # And again, child.checksum should be the same as helper.checksum
     self.assertEqual(child.checksum, helper.checksum)
Exemple #8
0
    def from_string(cls,
                    text,
                    *,
                    filename=None,
                    name=None,
                    origin=None,
                    implicit_namespace=None):
        """
        Load and initialize the WhiteList object from the specified string.

        :param text:
            full text of the whitelist
        :param filename:
            (optional, keyword-only) filename from which text was read from.
            This simulates a call to :meth:`from_file()` which properly
            computes the name and origin of the whitelist.
        :param name:
            (optional) name of the whitelist, only used if filename is not
            specified.
        :param origin:
            (optional) origin of the whitelist, only used if a filename is not
            specified.  If omitted a default origin value will be constructed
            out of UnknownTextSource instance
        :param implicit_namespace:
            (optional) implicit namespace for jobs that are using partial
            identifiers (all jobs)
        :returns:
            a fresh WhiteList object

        The optional filename or a pair of name and origin arguments may be
        provided in order to have additional meta-data. This is typically
        needed when the :meth:`from_file()` method cannot be used as the caller
        already has the full text of the intended file available.
        """
        _logger.debug("Loaded whitelist from %r", filename)
        pattern_list, max_lineno = cls._parse_patterns(text)
        # generate name and origin if filename is provided
        if filename is not None:
            name = WhiteList.name_from_filename(filename)
            origin = Origin(FileTextSource(filename), 1, max_lineno)
        else:
            # otherwise generate origin if it's not specified
            if origin is None:
                origin = Origin(UnknownTextSource(), 1, max_lineno)
        return cls(pattern_list, name, origin, implicit_namespace)
Exemple #9
0
 def test_origin_source_filename_is_correct(self):
     """
     verify that make_job() can properly trace the filename of the python
     module that called make_job()
     """
     # Pass -1 to get_caller_origin() to have filename point at this file
     # instead of at whatever ends up calling the test method
     self.assertEqual(
         os.path.basename(Origin.get_caller_origin(-1).source.filename),
         "test_rfc822.py")
Exemple #10
0
 def test_parse_typical(self):
     """
     verify typical operation without any parsing errors
     """
     # Setup a mock job and result, give some io log to the result
     job = mock.Mock(spec=JobDefinition)
     result = mock.Mock(spec=IJobResult)
     result.get_io_log.return_value = [(0, 'stdout', b'attr: value1\n'),
                                       (0, 'stdout', b'\n'),
                                       (0, 'stdout', b'attr: value2\n')]
     # Parse the IO log records
     records = list(gen_rfc822_records_from_io_log(job, result))
     # Ensure that we saw both records
     self.assertEqual(records, [
         RFC822Record({'attr': 'value1'},
                      Origin(JobOutputTextSource(job), 1, 1)),
         RFC822Record({'attr': 'value2'},
                      Origin(JobOutputTextSource(job), 3, 3)),
     ])
Exemple #11
0
 def test_from_string__with_name_and_origin(self):
     """
     verify that WhiteList.from_string() works when passing name and origin
     """
     # construct a whitelist with some dummy data, the names, pathnames and
     # line ranges are arbitrary
     whitelist = WhiteList.from_string("\n".join(self._content),
                                       name="somefile",
                                       origin=Origin(
                                           FileTextSource("somefile.txt"),
                                           1, 3))
     # verify that the patterns are okay
     self.assertEqual(repr(whitelist.qualifier_list[0]),
                      "RegExpJobQualifier('^foo$', inclusive=True)")
     # verify that whitelist name is copied
     self.assertEqual(whitelist.name, "somefile")
     # verify that the origin is copied
     self.assertEqual(whitelist.origin,
                      Origin(FileTextSource("somefile.txt"), 1, 3))
Exemple #12
0
 def test_origin_source_filename_is_correct(self):
     """
     verify that make_job() can properly trace the filename of the python
     module that called make_job()
     """
     # Pass -1 to get_caller_origin() to have filename point at this file
     # instead of at whatever ends up calling the test method
     self.assertEqual(
         os.path.basename(Origin.get_caller_origin(-1).source.filename),
         "test_rfc822.py")
Exemple #13
0
 def test_job_data(self):
     """
     verify the contents of the loaded JobDefinition object
     """
     job = self.plugin.plugin_object[0]
     self.assertEqual(job.partial_id, "test/job")
     self.assertEqual(job.id, "2013.com.canonical.plainbox::test/job")
     self.assertEqual(job.plugin, "shell")
     self.assertEqual(job.command, "true")
     self.assertEqual(job.origin,
                      Origin(FileTextSource("/path/to/jobs.txt"), 1, 3))
Exemple #14
0
 def test_origin_from_filename_is_filename(self):
     # If the test's origin has a filename, we need a valid origin
     # with proper data.
     # We're faking the name by using a StringIO subclass with a
     # name property, which is how rfc822 gets that data.
     expected_origin = Origin(FileTextSource("file.txt"), 1, 1)
     with NamedStringIO("key:value", fake_filename="file.txt") as stream:
         records = type(self).loader(stream)
     self.assertEqual(len(records), 1)
     self.assertEqual(records[0].data, {'key': 'value'})
     self.assertEqual(records[0].origin, expected_origin)
Exemple #15
0
 def test_gt(self):
     """
     verify that Origin instances are ordered by their constituting
     components
     """
     self.assertTrue(
         Origin(FileTextSource('file.txt'), 1, 1) < Origin(
             FileTextSource('file.txt'), 1, 2) < Origin(
                 FileTextSource('file.txt'), 1, 3))
     self.assertTrue(
         Origin(FileTextSource('file.txt'), 1, 10) < Origin(
             FileTextSource('file.txt'), 2, 10) < Origin(
                 FileTextSource('file.txt'), 3, 10))
     self.assertTrue(
         Origin(FileTextSource('file1.txt'), 1, 10) < Origin(
             FileTextSource('file2.txt'), 1, 10) < Origin(
                 FileTextSource('file3.txt'), 1, 10))
Exemple #16
0
 def test_whitelist_data(self):
     """
     verify the contents of the loaded whitelist object
     """
     self.assertEqual(
         self.plugin.plugin_object.qualifier_list[0].pattern_text, "^foo$")
     self.assertEqual(
         self.plugin.plugin_object.qualifier_list[1].pattern_text, "^bar$")
     self.assertEqual(self.plugin.plugin_object.name, 'some')
     self.assertEqual(
         self.plugin.plugin_object.origin,
         Origin(FileTextSource('/path/to/some.whitelist'), 1, 2))
Exemple #17
0
 def test_from_string(self):
     """
     verify that WhiteList.from_string() works
     """
     whitelist = WhiteList.from_string("\n".join(self._content))
     # verify that the patterns are okay
     self.assertEqual(repr(whitelist.qualifier_list[0]),
                      "RegExpJobQualifier('^foo$', inclusive=True)")
     # verify that whitelist name is the empty default
     self.assertEqual(whitelist.name, None)
     # verify that the origin got set to the default constructed value
     self.assertEqual(whitelist.origin, Origin(UnknownTextSource(), 1, 3))
Exemple #18
0
 def __init__(self, data, origin=None, provider=None, controller=None):
     super(JobDefinition, self).__init__(data)
     if origin is None:
         origin = Origin.get_caller_origin()
     if controller is None:
         # XXX: moved here because of cyclic imports
         from plainbox.impl.ctrl import checkbox_session_state_ctrl
         controller = checkbox_session_state_ctrl
     self._resource_program = None
     self._origin = origin
     self._provider = provider
     self._controller = controller
Exemple #19
0
 def test_origin_from_stream_is_Unknown(self):
     """
     verify that gen_rfc822_records() uses origin instances with source
     equal to UnknownTextSource, when no explicit source is provided and the
     stream has no name to infer a FileTextSource() from.
     """
     expected_origin = Origin(UnknownTextSource(), 1, 1)
     with StringIO("key:value") as stream:
         records = type(self).loader(stream)
     self.assertEqual(len(records), 1)
     self.assertEqual(records[0].data, {'key': 'value'})
     self.assertEqual(records[0].origin, expected_origin)
Exemple #20
0
 def test_from_file(self):
     """
     verify that WhiteList.from_file() works
     """
     with self.mocked_file(self._name, self._content):
         whitelist = WhiteList.from_file(self._name)
     # verify that the patterns are okay
     self.assertEqual(repr(whitelist.qualifier_list[0]),
                      "RegExpJobQualifier('^foo$', inclusive=True)")
     # verify that whitelist name got set
     self.assertEqual(whitelist.name, "whitelist")
     # verify that the origin got set
     self.assertEqual(whitelist.origin,
                      Origin(FileTextSource("whitelist.txt"), 1, 3))
Exemple #21
0
 def test_eq(self):
     """
     verify instances of Origin are all equal to other instances with the
     same instance attributes but not equal to instances with different
     attributes
     """
     origin1 = Origin(self.origin.source, self.origin.line_start,
                      self.origin.line_end)
     origin2 = Origin(self.origin.source, self.origin.line_start,
                      self.origin.line_end)
     self.assertTrue(origin1 == origin2)
     origin_other1 = Origin(self.origin.source, self.origin.line_start + 1,
                            self.origin.line_end)
     self.assertTrue(origin1 != origin_other1)
     self.assertFalse(origin1 == origin_other1)
     origin_other2 = Origin(self.origin.source, self.origin.line_start,
                            self.origin.line_end + 1)
     self.assertTrue(origin1 != origin_other2)
     self.assertFalse(origin1 == origin_other2)
     origin_other3 = Origin(FileTextSource("unrelated"),
                            self.origin.line_start, self.origin.line_end)
     self.assertTrue(origin1 != origin_other3)
     self.assertFalse(origin1 == origin_other3)
Exemple #22
0
def make_job(id, plugin="dummy", requires=None, depends=None, **kwargs):
    """
    Make and return a dummy JobDefinition instance
    """
    data = {'id': id}
    if plugin is not None:
        data['plugin'] = plugin
    if requires is not None:
        data['requires'] = requires
    if depends is not None:
        data['depends'] = depends
    # Add any custom key-value properties
    data.update(kwargs)
    return JobDefinition(data, Origin.get_caller_origin())
Exemple #23
0
def make_job(id, plugin="dummy", requires=None, depends=None, **kwargs):
    """
    Make and return a dummy JobDefinition instance
    """
    data = {'id': id}
    if plugin is not None:
        data['plugin'] = plugin
    if requires is not None:
        data['requires'] = requires
    if depends is not None:
        data['depends'] = depends
    # Add any custom key-value properties
    data.update(kwargs)
    return JobDefinition(data, Origin.get_caller_origin())
Exemple #24
0
 def setUp(self):
     self._full_record = RFC822Record(
         {
             'plugin': 'plugin',
             'id': 'id',
             'summary': 'summary',
             'requires': 'requires',
             'command': 'command',
             'description': 'description'
         }, Origin(FileTextSource('file.txt'), 1, 5))
     self._full_gettext_record = RFC822Record(
         {
             '_plugin': 'plugin',
             '_id': 'id',
             '_summary': 'summary',
             '_requires': 'requires',
             '_command': 'command',
             '_description': 'description'
         }, Origin(FileTextSource('file.txt.in'), 1, 5))
     self._min_record = RFC822Record({
         'plugin': 'plugin',
         'id': 'id',
     }, Origin(FileTextSource('file.txt'), 1, 2))
Exemple #25
0
    def from_file(cls, pathname, implicit_namespace=None):
        """
        Load and initialize the WhiteList object from the specified file.

        :param pathname:
            file to load
        :param implicit_namespace:
            (optional) implicit namespace for jobs that are using partial
            identifiers (all jobs)
        :returns:
            a fresh WhiteList object
        """
        pattern_list, max_lineno = cls._load_patterns(pathname)
        name = os.path.splitext(os.path.basename(pathname))[0]
        origin = Origin(FileTextSource(pathname), 1, max_lineno)
        return cls(pattern_list, name, origin, implicit_namespace)
Exemple #26
0
 def test_parse_error(self, mock_logger):
     # Setup a mock job and result, give some io log to the result
     job = mock.Mock(spec=JobDefinition)
     result = mock.Mock(spec=IJobResult)
     result.get_io_log.return_value = [(0, 'stdout', b'attr: value1\n'),
                                       (0, 'stdout', b'\n'),
                                       (0, 'stdout', b'error\n'),
                                       (0, 'stdout', b'\n'),
                                       (0, 'stdout', b'attr: value2\n')]
     # Parse the IO log records
     records = list(gen_rfc822_records_from_io_log(job, result))
     # Ensure that only the first record was generated
     self.assertEqual(records, [
         RFC822Record({'attr': 'value1'},
                      Origin(JobOutputTextSource(job), 1, 1)),
     ])
     # Ensure that a warning was logged
     mock_logger.warning.assert_called_once_with(
         "local script %s returned invalid RFC822 data: %s", job,
         RFC822SyntaxError(None, 3,
                           "Unexpected non-empty line: 'error\\n'"))
Exemple #27
0
    def __init__(self, data, origin=None, provider=None, controller=None,
                 raw_data=None):
        """
        Initialize a new JobDefinition instance.

        :param data:
            Normalized data that makes up this job definition
        :param origin:
            An (optional) Origin object. If omitted a fake origin object is
            created. Normally the origin object should be obtained from the
            RFC822Record object.
        :param provider:
            An (optional) Provider1 object. If omitted it defaults to None but
            the actual job definition is not suitable for execution. All job
            definitions are expected to have a provider.
        :param controller:
            An (optional) session state controller. If omitted a checkbox
            session state controller is implicitly used. The controller defines
            how this job influences the session it executes in.
        :param raw_data:
            An (optional) raw version of data, without whitespace
            normalization. If omitted then raw_data is assumed to be data.

        .. note::
            You should almost always use :meth:`from_rfc822_record()` instead.
        """
        super(JobDefinition, self).__init__(data, raw_data)
        if origin is None:
            origin = Origin.get_caller_origin()
        if controller is None:
            # XXX: moved here because of cyclic imports
            from plainbox.impl.ctrl import checkbox_session_state_ctrl
            controller = checkbox_session_state_ctrl
        self._resource_program = None
        self._origin = origin
        self._provider = provider
        self._controller = controller
Exemple #28
0
 def setUp(self):
     self.origin = Origin(FileTextSource("file.txt"), 10, 12)
Exemple #29
0
 def setUp(self):
     self.raw_data = {'key': ' value'}
     self.data = {'key': 'value'}
     self.origin = Origin(FileTextSource('file.txt'), 1, 1)
     self.record = RFC822Record(self.data, self.origin, self.raw_data)