예제 #1
0
 def test_numbers(self):
     result = v2.StreamResultToBytes(BytesIO())
     packet = []
     self.assertRaises(Exception, result._write_number, -1, packet)  # noqa
     self.assertEqual([], packet)
     result._write_number(0, packet)
     self.assertEqual([b'\x00'], packet)
     del packet[:]
     result._write_number(63, packet)
     self.assertEqual([b'\x3f'], packet)
     del packet[:]
     result._write_number(64, packet)
     self.assertEqual([b'\x40\x40'], packet)
     del packet[:]
     result._write_number(16383, packet)
     self.assertEqual([b'\x7f\xff'], packet)
     del packet[:]
     result._write_number(16384, packet)
     self.assertEqual([b'\x80\x40', b'\x00'], packet)
     del packet[:]
     result._write_number(4194303, packet)
     self.assertEqual([b'\xbf\xff', b'\xff'], packet)
     del packet[:]
     result._write_number(4194304, packet)
     self.assertEqual([b'\xc0\x40\x00\x00'], packet)
     del packet[:]
     result._write_number(1073741823, packet)
     self.assertEqual([b'\xff\xff\xff\xff'], packet)
     del packet[:]
     self.assertRaises(
         Exception,
         result._write_number,  # noqa
         1073741824,
         packet)
     self.assertEqual([], packet)
예제 #2
0
 def test_remove_tag(self):
     reference = io.BytesIO()
     stream = v2.StreamResultToBytes(reference)
     stream.status(test_id='test',
                   test_status='inprogress',
                   test_tags=set(['foo']))
     stream.status(test_id='test',
                   test_status='success',
                   test_tags=set(['foo']))
     stream = v2.StreamResultToBytes(self.original)
     stream.status(test_id='test',
                   test_status='inprogress',
                   test_tags=set(['foo']))
     stream.status(test_id='test',
                   test_status='success',
                   test_tags=set(['foo', 'bar']))
     self.original.seek(0)
     self.assertEqual(
         0, pysubunit.tag_stream(self.original, self.filtered, ["-bar"]))
     self.assertEqual(reference.getvalue(), self.filtered.getvalue())
예제 #3
0
 def test_route_code_and_file_content(self):
     content = BytesIO()
     v2.StreamResultToBytes(content).status(route_code='0',
                                            mime_type='text/plain',
                                            file_name='bar',
                                            file_bytes=b'foo')
     self.check_event(content.getvalue(),
                      test_id=None,
                      file_name='bar',
                      route_code='0',
                      mime_type='text/plain',
                      file_bytes=b'foo')
예제 #4
0
 def test_default(self):
     byte_stream = compat.BytesIO()
     stream = v2.StreamResultToBytes(byte_stream)
     stream.status(test_id="foo", test_status="inprogress")
     stream.status(test_id="foo", test_status="skip")
     output = self.run_command([], byte_stream.getvalue())
     events = doubles.StreamResult()
     v2.ByteStreamToStreamResult(compat.BytesIO(output)).run(events)
     self.assertEqual([
         ('status', 'foo', 'inprogress'),
         ('status', 'foo', 'skip'),
     ], [event[:3] for event in events._events])
예제 #5
0
 def _list(self, test):
     test_ids, errors = testtools_run.list_test(test)
     try:
         fileno = self.stream.fileno()
     except Exception:
         fileno = None
     if fileno is not None:
         stream = os.fdopen(fileno, 'wb', 0)
     else:
         stream = self.stream
     result = v2.StreamResultToBytes(stream)
     for test_id in test_ids:
         result.status(test_id=test_id, test_status='exists')
     return result, errors
예제 #6
0
def _make_result(output, options, predicate):
    """Make the result that we'll send the test outcomes to."""
    fixup_expected_failures = set()
    for path in options.fixup_expected_failures or ():
        fixup_expected_failures.update(pysubunit.read_test_list(path))
    return testtools.StreamToExtendedDecorator(
        test_results.TestResultFilter(
            testtools.ExtendedToStreamDecorator(
                v2.StreamResultToBytes(output)),
            filter_error=options.error,
            filter_failure=options.failure,
            filter_success=options.success,
            filter_skip=options.skip,
            filter_xfail=options.xfail,
            filter_predicate=predicate,
            fixup_expected_failures=fixup_expected_failures))
예제 #7
0
def tag_stream(original, filtered, tags):
    """Alter tags on a stream.

    :param original: The input stream.
    :param filtered: The output stream.
    :param tags: The tags to apply. As in a normal stream - a list of 'TAG' or
        '-TAG' commands.

        A 'TAG' command will add the tag to the output stream,
        and override any existing '-TAG' command in that stream.
        Specifically:
         * A global 'tags: TAG' will be added to the start of the stream.
         * Any tags commands with -TAG will have the -TAG removed.

        A '-TAG' command will remove the TAG command from the stream.
        Specifically:
         * A 'tags: -TAG' command will be added to the start of the stream.
         * Any 'tags: TAG' command will have 'TAG' removed from it.
        Additionally, any redundant tagging commands (adding a tag globally
        present, or removing a tag globally removed) are stripped as a
        by-product of the filtering.
    :return: 0
    """
    new_tags, gone_tags = tags_to_new_gone(tags)
    source = v2.ByteStreamToStreamResult(original, non_subunit_name='stdout')

    class Tagger(testtools.CopyStreamResult):
        def status(self, **kwargs):
            tags = kwargs.get('test_tags')
            if not tags:
                tags = set()
            tags.update(new_tags)
            tags.difference_update(gone_tags)
            if tags:
                kwargs['test_tags'] = tags
            else:
                kwargs['test_tags'] = None
            super(Tagger, self).status(**kwargs)

    output = Tagger([v2.StreamResultToBytes(filtered)])
    source.run(output)
    return 0
예제 #8
0
 def test_add_tag(self):
     # Literal values to avoid set sort-order dependencies. Python code show
     # derivation.
     # reference = BytesIO()
     # stream = subunit.StreamResultToBytes(reference)
     # stream.status(
     #     test_id='test', test_status='inprogress',
     #     test_tags=set(['quux', 'foo']))
     # stream.status(
     #     test_id='test', test_status='success',
     #     test_tags=set(['bar', 'quux', 'foo']))
     reference = [
         (b'\xb3)\x82\x17\x04test\x02\x04quux\x03foo\x05\x97n\x86\xb3)'
          b'\x83\x1b\x04test\x03\x03bar\x04quux\x03fooqn\xab)'),
         (b'\xb3)\x82\x17\x04test\x02\x04quux\x03foo\x05\x97n\x86\xb3)'
          b'\x83\x1b\x04test\x03\x04quux\x03foo\x03bar\xaf\xbd\x9d\xd6'),
         (b'\xb3)\x82\x17\x04test\x02\x04quux\x03foo\x05\x97n\x86\xb3)'
          b'\x83\x1b\x04test\x03\x04quux\x03bar\x03foo\x03\x04b\r'),
         (b'\xb3)\x82\x17\x04test\x02\x04quux\x03foo\x05\x97n\x86\xb3)'
          b'\x83\x1b\x04test\x03\x03bar\x03foo\x04quux\xd2\x18\x1bC'),
         (b'\xb3)\x82\x17\x04test\x02\x03foo\x04quux\xa6\xe1\xde\xec\xb3)'
          b'\x83\x1b\x04test\x03\x03foo\x04quux\x03bar\x08\xc2X\x83'),
         (b'\xb3)\x82\x17\x04test\x02\x03foo\x04quux\xa6\xe1\xde\xec\xb3)'
          b'\x83\x1b\x04test\x03\x03bar\x03foo\x04quux\xd2\x18\x1bC'),
         (b'\xb3)\x82\x17\x04test\x02\x03foo\x04quux\xa6\xe1\xde\xec\xb3)'
          b'\x83\x1b\x04test\x03\x03foo\x03bar\x04quux:\x05e\x80')
     ]
     stream = v2.StreamResultToBytes(self.original)
     stream.status(test_id='test',
                   test_status='inprogress',
                   test_tags=set(['foo']))
     stream.status(test_id='test',
                   test_status='success',
                   test_tags=set(['foo', 'bar']))
     self.original.seek(0)
     self.assertEqual(
         0, pysubunit.tag_stream(self.original, self.filtered, ["quux"]))
     self.assertThat(reference, matchers.Contains(self.filtered.getvalue()))
예제 #9
0
 def test_tags(self):
     byte_stream = compat.BytesIO()
     stream = v2.StreamResultToBytes(byte_stream)
     stream.status(test_id="foo",
                   test_status="inprogress",
                   test_tags=set(["a"]))
     stream.status(test_id="foo",
                   test_status="success",
                   test_tags=set(["a"]))
     stream.status(test_id="bar", test_status="inprogress")
     stream.status(test_id="bar", test_status="inprogress")
     stream.status(test_id="baz",
                   test_status="inprogress",
                   test_tags=set(["a"]))
     stream.status(test_id="baz",
                   test_status="success",
                   test_tags=set(["a"]))
     output = self.run_command(['-s', '--with-tag', 'a'],
                               byte_stream.getvalue())
     events = doubles.StreamResult()
     v2.ByteStreamToStreamResult(compat.BytesIO(output)).run(events)
     ids = set(event[1] for event in events._events)
     self.assertEqual(set(['foo', 'baz']), ids)
예제 #10
0
 def test_smoke(self):
     output = os.path.join(
         self.useFixture(fixtures.TempDir()).path, 'output')
     stdin = io.BytesIO()
     stdout = io.StringIO()
     writer = v2.StreamResultToBytes(stdin)
     writer.startTestRun()
     writer.status('foo',
                   'success',
                   set(['tag']),
                   file_name='fred',
                   file_bytes=b'abcdefg',
                   eof=True,
                   mime_type='text/plain')
     writer.stopTestRun()
     stdin.seek(0)
     _to_disk.to_disk(['-d', output], stdin=stdin, stdout=stdout)
     self.expectThat(
         os.path.join(output, 'foo/test.json'),
         matchers.FileContains(
             '{"details": ["fred"], "id": "foo", "start": null, '
             '"status": "success", "stop": null, "tags": ["tag"]}'))
     self.expectThat(os.path.join(output, 'foo/fred'),
                     matchers.FileContains('abcdefg'))
예제 #11
0
def run_tests_from_stream(input_stream,
                          result,
                          passthrough_stream=None,
                          forward_stream=None,
                          protocol_version=1,
                          passthrough_subunit=True):
    """Run tests from a subunit input stream through 'result'.

    Non-test events - top level file attachments - are expected to be
    dropped by v2 StreamResults at the present time (as all the analysis code
    is in ExtendedTestResult API's), so to implement passthrough_stream they
    are diverted and copied directly when that is set.

    :param input_stream: A stream containing subunit input.
    :param result: A TestResult that will receive the test events.
        NB: This should be an ExtendedTestResult for v1 and a StreamResult for
        v2.
    :param passthrough_stream: All non-subunit input received will be
        sent to this stream.  If not provided, uses the ``TestProtocolServer``
        default, which is ``sys.stdout``.
    :param forward_stream: All subunit input received will be forwarded
        to this stream. If not provided, uses the ``TestProtocolServer``
        default, which is to not forward any input. Do not set this when
        transforming the stream - items would be double-reported.
    :param protocol_version: What version of the subunit protocol to expect.
    :param passthrough_subunit: If True, passthrough should be as subunit
        otherwise unwrap it. Only has effect when forward_stream is None.
        (when forwarding as subunit non-subunit input is always turned into
        subunit)
    """
    if 1 == protocol_version:
        test = pysubunit.ProtocolTestCase(input_stream,
                                          passthrough=passthrough_stream,
                                          forward=forward_stream)
    elif 2 == protocol_version:
        # In all cases we encapsulate unknown inputs.
        if forward_stream is not None:
            # Send events to forward_stream as subunit.
            forward_result = v2.StreamResultToBytes(forward_stream)
            # If we're passing non-subunit through, copy:
            if passthrough_stream is None:
                # Not passing non-test events - split them off to nothing.
                router = testtools.StreamResultRouter(forward_result)
                router.add_rule(testtools.StreamResult(),
                                'test_id',
                                test_id=None)
                result = testtools.CopyStreamResult([router, result])
            else:
                # otherwise, copy all events to forward_result
                result = testtools.CopyStreamResult([forward_result, result])
        elif passthrough_stream is not None:
            # Route non-test events to passthrough_stream, unwrapping them for
            # display.
            if not passthrough_subunit:
                passthrough_result = test_results.CatFiles(passthrough_stream)
            else:
                passthrough_result = v2.StreamResultToBytes(passthrough_stream)
            result = testtools.StreamResultRouter(result)
            result.add_rule(passthrough_result, 'test_id', test_id=None)
        test = v2.ByteStreamToStreamResult(input_stream,
                                           non_subunit_name='stdout')
    else:
        raise Exception("Unknown protocol version.")
    result.startTestRun()
    test.run(result)
    result.stopTestRun()
예제 #12
0
def TAP2SubUnit(tap, output_stream):
    """Filter a TAP pipe into a subunit pipe.

    This should be invoked once per TAP script, as TAP scripts get
    mapped to a single runnable case with multiple components.

    :param tap: A tap pipe/stream/file object - should emit unicode strings.
    :param subunit: A pipe/stream/file object to write subunit results to.
    :return: The exit code to exit with.
    """
    output = v2.StreamResultToBytes(output_stream)
    UTF8_TEXT = 'text/plain; charset=UTF8'
    BEFORE_PLAN = 0
    AFTER_PLAN = 1
    SKIP_STREAM = 2
    state = BEFORE_PLAN
    plan_start = 1
    plan_stop = 0
    # Test data for the next test to emit
    test_name = None
    log = []
    result = None

    def missing_test(plan_start):
        output.status(test_id='test %d' % plan_start,
                      test_status='fail',
                      runnable=False,
                      mime_type=UTF8_TEXT,
                      eof=True,
                      file_name="tap meta",
                      file_bytes=b"test missing from TAP output")

    def _emit_test():
        "write out a test"
        if test_name is None:
            return
        if log:
            log_bytes = b'\n'.join(log_line.encode('utf8') for log_line in log)
            mime_type = UTF8_TEXT
            file_name = 'tap comment'
            eof = True
        else:
            log_bytes = None
            mime_type = None
            file_name = None
            eof = True
        del log[:]
        output.status(test_id=test_name,
                      test_status=result,
                      file_bytes=log_bytes,
                      mime_type=mime_type,
                      eof=eof,
                      file_name=file_name,
                      runnable=False)

    for line in tap:
        if state == BEFORE_PLAN:
            match = re.match("(\d+)\.\.(\d+)\s*(?:\#\s+(.*))?\n", line)
            if match:
                state = AFTER_PLAN
                _, plan_stop, comment = match.groups()
                plan_stop = int(plan_stop)
                if plan_start > plan_stop and plan_stop == 0:
                    # skipped file
                    state = SKIP_STREAM
                    output.status(test_id='file skip',
                                  test_status='skip',
                                  file_bytes=comment.encode('utf8'),
                                  eof=True,
                                  file_name='tap comment')
                continue
        # not a plan line, or have seen one before
        match = re.match(
            "(ok|not ok)(?:\s+(\d+)?)?(?:\s+([^#]*[^#\s]+)\s*)?(?:\s+#\s+"
            "(TODO|SKIP|skip|todo)(?:\s+(.*))?)?\n", line)
        if match:
            # new test, emit current one.
            _emit_test()
            hits = match.groups()
            status, number, description, directive, directive_comment = hits
            if status == 'ok':
                result = 'success'
            else:
                result = "fail"
            if description is None:
                description = ''
            else:
                description = ' ' + description
            if directive is not None:
                if directive.upper() == 'TODO':
                    result = 'xfail'
                elif directive.upper() == 'SKIP':
                    result = 'skip'
                if directive_comment is not None:
                    log.append(directive_comment)
            if number is not None:
                number = int(number)
                while plan_start < number:
                    missing_test(plan_start)
                    plan_start += 1
            test_name = "test %d%s" % (plan_start, description)
            plan_start += 1
            continue
        match = re.match("Bail out\!(?:\s*(.*))?\n", line)
        if match:
            reason, = match.groups()
            if reason is None:
                extra = ''
            else:
                extra = ' %s' % reason
            _emit_test()
            test_name = "Bail out!%s" % extra
            result = "fail"
            state = SKIP_STREAM
            continue
        match = re.match("\#.*\n", line)
        if match:
            log.append(line[:-1])
            continue
        # Should look at buffering status and binding this to the prior result.
        output.status(file_bytes=line.encode('utf8'),
                      file_name='stdout',
                      mime_type=UTF8_TEXT)
    _emit_test()
    while plan_start <= plan_stop:
        # record missed tests
        missing_test(plan_start)
        plan_start += 1
    return 0
예제 #13
0
 def _make_result(self):
     output = BytesIO()
     return v2.StreamResultToBytes(output), output
예제 #14
0
 def _make_result(self):
     return v2.StreamResultToBytes(BytesIO())
예제 #15
0
 def test_passthrough(self):
     output = self.run_command([], b'hi thar')
     byte_stream = compat.BytesIO()
     stream = v2.StreamResultToBytes(byte_stream)
     stream.status(file_name="stdout", file_bytes=b'hi thar')
     self.assertEqual(byte_stream.getvalue(), output)