예제 #1
0
    def test_is_built_errback(self):
        tor = FakeTorController()
        a = FakeRouter('$E11D2B2269CC25E67CA6C9FB5843497539A74FD0', 'a')
        tor.routers['$E11D2B2269CC25E67CA6C9FB5843497539A74FD0'] = a

        state = TorState(tor)
        circuit = Circuit(tor)
        circuit.listen(tor)

        circuit.update(
            '123 EXTENDED $E11D2B2269CC25E67CA6C9FB5843497539A74FD0=eris PURPOSE=GENERAL'
            .split())
        state.circuit_new(circuit)
        d = circuit.when_built()

        called = []

        def err(f):
            called.append(f)
            return None

        d.addErrback(err)

        state.circuit_closed(circuit, REASON='testing')

        self.assertEqual(1, len(called))
        self.assertTrue(isinstance(called[0], Failure))
        self.assertTrue('testing' in str(called[0].value))
        return d
예제 #2
0
    def test_extend_messages(self):
        tor = FakeTorController()
        a = FakeRouter('$E11D2B2269CC25E67CA6C9FB5843497539A74FD0', 'a')
        b = FakeRouter('$50DD343021E509EB3A5A7FD0D8A4F8364AFBDCB5', 'b')
        c = FakeRouter('$253DFF1838A2B7782BE7735F74E50090D46CA1BC', 'c')
        tor.routers['$E11D2B2269CC25E67CA6C9FB5843497539A74FD0'] = a
        tor.routers['$50DD343021E509EB3A5A7FD0D8A4F8364AFBDCB5'] = b
        tor.routers['$253DFF1838A2B7782BE7735F74E50090D46CA1BC'] = c

        circuit = Circuit(tor)
        circuit.listen(tor)

        circuit.update('365 LAUNCHED PURPOSE=GENERAL'.split())
        self.assertEqual(tor.extend, [])
        circuit.update('365 EXTENDED $E11D2B2269CC25E67CA6C9FB5843497539A74FD0=eris PURPOSE=GENERAL'.split())
        self.assertEqual(len(tor.extend), 1)
        self.assertEqual(tor.extend[0], (circuit, a))

        circuit.update('365 EXTENDED $E11D2B2269CC25E67CA6C9FB5843497539A74FD0=eris,$50DD343021E509EB3A5A7FD0D8A4F8364AFBDCB5=venus PURPOSE=GENERAL'.split())
        self.assertEqual(len(tor.extend), 2)
        self.assertEqual(tor.extend[0], (circuit, a))
        self.assertEqual(tor.extend[1], (circuit, b))

        circuit.update('365 EXTENDED $E11D2B2269CC25E67CA6C9FB5843497539A74FD0=eris,$50DD343021E509EB3A5A7FD0D8A4F8364AFBDCB5=venus,$253DFF1838A2B7782BE7735F74E50090D46CA1BC=chomsky PURPOSE=GENERAL'.split())
        self.assertEqual(len(tor.extend), 3)
        self.assertEqual(tor.extend[0], (circuit, a))
        self.assertEqual(tor.extend[1], (circuit, b))
        self.assertEqual(tor.extend[2], (circuit, c))
예제 #3
0
    def test_when_closed(self):
        tor = FakeTorController()
        a = FakeRouter('$E11D2B2269CC25E67CA6C9FB5843497539A74FD0', 'a')
        b = FakeRouter('$50DD343021E509EB3A5A7FD0D8A4F8364AFBDCB5', 'b')
        c = FakeRouter('$253DFF1838A2B7782BE7735F74E50090D46CA1BC', 'c')
        tor.routers['$E11D2B2269CC25E67CA6C9FB5843497539A74FD0'] = a
        tor.routers['$50DD343021E509EB3A5A7FD0D8A4F8364AFBDCB5'] = b
        tor.routers['$253DFF1838A2B7782BE7735F74E50090D46CA1BC'] = c

        circuit = Circuit(tor)
        circuit.listen(tor)

        circuit.update(
            '123 EXTENDED $E11D2B2269CC25E67CA6C9FB5843497539A74FD0=eris,$50DD343021E509EB3A5A7FD0D8A4F8364AFBDCB5=venus,$253DFF1838A2B7782BE7735F74E50090D46CA1BC=chomsky PURPOSE=GENERAL'
            .split())
        d0 = circuit.when_closed()

        self.assertFalse(d0.called)

        circuit.update(
            '123 BUILT $E11D2B2269CC25E67CA6C9FB5843497539A74FD0=eris,$50DD343021E509EB3A5A7FD0D8A4F8364AFBDCB5=venus,$253DFF1838A2B7782BE7735F74E50090D46CA1BC=chomsky PURPOSE=GENERAL'
            .split())
        circuit.update('123 CLOSED'.split())

        d1 = circuit.when_closed()

        self.assertTrue(d0 is not d1)
        self.assertTrue(d0.called)
        self.assertTrue(d1.called)
예제 #4
0
    def test_close_circuit(self):
        tor = FakeTorController()
        a = FakeRouter('$E11D2B2269CC25E67CA6C9FB5843497539A74FD0', 'a')
        b = FakeRouter('$50DD343021E509EB3A5A7FD0D8A4F8364AFBDCB5', 'b')
        c = FakeRouter('$253DFF1838A2B7782BE7735F74E50090D46CA1BC', 'c')
        tor.routers['$E11D2B2269CC25E67CA6C9FB5843497539A74FD0'] = a
        tor.routers['$50DD343021E509EB3A5A7FD0D8A4F8364AFBDCB5'] = b
        tor.routers['$253DFF1838A2B7782BE7735F74E50090D46CA1BC'] = c

        circuit = Circuit(tor)
        circuit.listen(tor)

        circuit.update('123 EXTENDED $E11D2B2269CC25E67CA6C9FB5843497539A74FD0=eris,$50DD343021E509EB3A5A7FD0D8A4F8364AFBDCB5=venus,$253DFF1838A2B7782BE7735F74E50090D46CA1BC=chomsky PURPOSE=GENERAL'.split())

        self.assertEqual(3, len(circuit.path))
        d = circuit.close()
        # we already pretended that Tor answered "OK" to the
        # CLOSECIRCUIT call (see close_circuit() in FakeTorController
        # above) however the circuit isn't "really" closed yet...
        self.assertTrue(not d.called)
        # not unit-test-y? shouldn't probably delve into internals I
        # suppose...
        self.assertTrue(circuit._closing_deferred is not None)

        # simulate that Tor has really closed the circuit for us
        # this should cause our Deferred to callback
        circuit.update('123 CLOSED $E11D2B2269CC25E67CA6C9FB5843497539A74FD0=eris,$50DD343021E509EB3A5A7FD0D8A4F8364AFBDCB5=venus,$253DFF1838A2B7782BE7735F74E50090D46CA1BC=chomsky PURPOSE=GENERAL REASON=FINISHED'.split())

        # confirm that our circuit callback has been triggered already
        self.assertRaises(
            defer.AlreadyCalledError,
            d.callback,
            "should have been called already"
        )
        return d
예제 #5
0
 def test_wrong_update(self):
     tor = FakeTorController()
     circuit = Circuit(tor)
     circuit.listen(tor)
     circuit.update('1 LAUNCHED PURPOSE=GENERAL'.split())
     self.assertRaises(Exception, circuit.update,
                       '2 LAUNCHED PURPOSE=GENERAL'.split())
예제 #6
0
    def test_close_circuit_with_circuit(self):
        circuit = Circuit(self.state)
        circuit.id = 1

        self.state.circuits[1] = circuit
        self.state.close_circuit(circuit)
        self.assertEqual(self.transport.value(), 'CLOSECIRCUIT 1\r\n')
예제 #7
0
    def test_close_circuit(self):
        tor = FakeTorController()
        a = FakeRouter('$E11D2B2269CC25E67CA6C9FB5843497539A74FD0', 'a')
        b = FakeRouter('$50DD343021E509EB3A5A7FD0D8A4F8364AFBDCB5', 'b')
        c = FakeRouter('$253DFF1838A2B7782BE7735F74E50090D46CA1BC', 'c')
        tor.routers['$E11D2B2269CC25E67CA6C9FB5843497539A74FD0'] = a
        tor.routers['$50DD343021E509EB3A5A7FD0D8A4F8364AFBDCB5'] = b
        tor.routers['$253DFF1838A2B7782BE7735F74E50090D46CA1BC'] = c

        circuit = Circuit(tor, self.protocol)
        circuit.listen(tor)

        circuit.update(
            '123 EXTENDED $E11D2B2269CC25E67CA6C9FB5843497539A74FD0=eris,$50DD343021E509EB3A5A7FD0D8A4F8364AFBDCB5=venus,$253DFF1838A2B7782BE7735F74E50090D46CA1BC=chomsky PURPOSE=GENERAL'
            .split())

        self.assertEqual(3, len(circuit.path))
        d = circuit.close()
        self.assertTrue(self.protocol.deferred is not None)
        # simulate the success of the CIRCUITCLOSED call"
        self.protocol.deferred.callback("it went swimmingly")
        # simulate that Tor has really closed the circuit for us (via failing it, in this case)
        circuit.update(
            '123 CLOSED $E11D2B2269CC25E67CA6C9FB5843497539A74FD0=eris,$50DD343021E509EB3A5A7FD0D8A4F8364AFBDCB5=venus,$253DFF1838A2B7782BE7735F74E50090D46CA1BC=chomsky PURPOSE=GENERAL REASON=FINISHED'
            .split())

        # confirm that our circuit callback has been triggered already
        self.assertRaises(defer.AlreadyCalledError, d.callback,
                          "should have been called already")
        return d
예제 #8
0
    def test_is_built(self):
        tor = FakeTorController()
        a = FakeRouter('$E11D2B2269CC25E67CA6C9FB5843497539A74FD0', 'a')
        b = FakeRouter('$50DD343021E509EB3A5A7FD0D8A4F8364AFBDCB5', 'b')
        c = FakeRouter('$253DFF1838A2B7782BE7735F74E50090D46CA1BC', 'c')
        tor.routers['$E11D2B2269CC25E67CA6C9FB5843497539A74FD0'] = a
        tor.routers['$50DD343021E509EB3A5A7FD0D8A4F8364AFBDCB5'] = b
        tor.routers['$253DFF1838A2B7782BE7735F74E50090D46CA1BC'] = c

        circuit = Circuit(tor)
        circuit.listen(tor)

        circuit.update('123 EXTENDED $E11D2B2269CC25E67CA6C9FB5843497539A74FD0=eris,$50DD343021E509EB3A5A7FD0D8A4F8364AFBDCB5=venus,$253DFF1838A2B7782BE7735F74E50090D46CA1BC=chomsky PURPOSE=GENERAL'.split())
        built0 = circuit.is_built
        built1 = circuit.when_built()

        self.assertTrue(built0 is not built1)
        self.assertFalse(built0.called)
        self.assertFalse(built1.called)

        circuit.update('123 BUILT $E11D2B2269CC25E67CA6C9FB5843497539A74FD0=eris,$50DD343021E509EB3A5A7FD0D8A4F8364AFBDCB5=venus,$253DFF1838A2B7782BE7735F74E50090D46CA1BC=chomsky PURPOSE=GENERAL'.split())

        # create callback when we're alread in BUILT; should be
        # callback'd already
        built2 = circuit.when_built()

        self.assertTrue(built2 is not built1)
        self.assertTrue(built2 is not built0)
        self.assertTrue(built0.called)
        self.assertTrue(built1.called)
        self.assertTrue(built2.called)
        self.assertTrue(built0.result == circuit)
        self.assertTrue(built1.result == circuit)
        self.assertTrue(built2.result == circuit)
예제 #9
0
    def test_updates(self):
        tor = FakeTorController()
        circuit = Circuit(tor)
        circuit.listen(tor)
        tor.routers['$E11D2B2269CC25E67CA6C9FB5843497539A74FD0'] = FakeRouter(
            '$E11D2B2269CC25E67CA6C9FB5843497539A74FD0', 'a'
        )
        tor.routers['$50DD343021E509EB3A5A7FD0D8A4F8364AFBDCB5'] = FakeRouter(
            '$50DD343021E509EB3A5A7FD0D8A4F8364AFBDCB5', 'b'
        )
        tor.routers['$253DFF1838A2B7782BE7735F74E50090D46CA1BC'] = FakeRouter(
            '$253DFF1838A2B7782BE7735F74E50090D46CA1BC', 'c'
        )

        for ex in examples[:-1]:
            circuit.update(ex.split()[1:])
            self.assertEqual(circuit.state, ex.split()[2])
            self.assertEqual(circuit.purpose, 'GENERAL')
            if '$' in ex:
                self.assertEqual(
                    len(circuit.path),
                    len(ex.split()[3].split(','))
                )
                for (r, p) in zip(ex.split()[3].split(','), circuit.path):
                    d = r.split('=')[0]
                    self.assertEqual(d, p.id_hash)
예제 #10
0
 def test_str(self):
     tor = FakeTorController()
     circuit = Circuit(tor)
     circuit.id = 1
     str(circuit)
     router = Router(tor)
     circuit.path.append(router)
     str(circuit)
예제 #11
0
    def test_circuit_web_agent(self):
        tor = FakeTorController()
        a = FakeRouter('$E11D2B2269CC25E67CA6C9FB5843497539A74FD0', 'a')
        tor.routers['$E11D2B2269CC25E67CA6C9FB5843497539A74FD0'] = a

        circuit = Circuit(tor)
        reactor = Mock()

        # just testing this doesn't cause an exception
        circuit.web_agent(reactor, Mock())
예제 #12
0
 def test_path_update(self):
     cp = TorControlProtocol()
     state = TorState(cp, False)
     circuit = Circuit(state)
     circuit.update('1 EXTENDED $E11D2B2269CC25E67CA6C9FB5843497539A74FD0=eris PURPOSE=GENERAL'.split())
     self.assertEqual(1, len(circuit.path))
     self.assertEqual(
         '$E11D2B2269CC25E67CA6C9FB5843497539A74FD0',
         circuit.path[0].id_hex
     )
     self.assertEqual('eris', circuit.path[0].name)
예제 #13
0
    def test_close_circuit_with_flags(self):
        circuit = Circuit(self.state)
        circuit.id = 1
        # try:
        #     self.state.close_circuit(circuit.id, IfUnused=True)
        #     self.assertTrue(False)
        # except KeyError:
        #     pass

        self.state.circuits[1] = circuit
        self.state.close_circuit(circuit.id, IfUnused=True)
        self.assertEqual(self.transport.value(), 'CLOSECIRCUIT 1 IfUnused\r\n')
예제 #14
0
    def test_no_age_yet(self):
        """
        make sure age doesn't explode if there's no TIME_CREATED flag.
        """
        tor = FakeTorController()

        circuit = Circuit(tor)
        now = datetime.datetime.now()
        circuit.update('1 LAUNCHED PURPOSE=GENERAL'.split())
        self.assertTrue(circuit.time_created is None)
        diff = circuit.age(now=now)
        self.assertEquals(diff, None)
예제 #15
0
 def test_failed_reason(self):
     tor = FakeTorController()
     circuit = Circuit(tor)
     circuit.listen(tor)
     circuit.update('1 FAILED $E11D2B2269CC25E67CA6C9FB5843497539A74FD0=eris PURPOSE=GENERAL REASON=TIMEOUT'.split())
     self.assertEqual(len(tor.failed), 1)
     circ, kw = tor.failed[0]
     self.assertEqual(circ, circuit)
     self.assertTrue('PURPOSE' in kw)
     self.assertTrue('REASON' in kw)
     self.assertEqual(kw['PURPOSE'], 'GENERAL')
     self.assertEqual(kw['REASON'], 'TIMEOUT')
예제 #16
0
    def test_age(self):
        """
        make sure age does something sensible at least once.
        """
        tor = FakeTorController()

        circuit = Circuit(tor)
        now = datetime.datetime.now()
        update = '1 LAUNCHED PURPOSE=GENERAL TIME_CREATED=%s' % time.strftime('%Y-%m-%dT%H:%M:%S')
        circuit.update(update.split())
        diff = circuit.age(now=now)
        self.assertEquals(diff, 0)
        self.assertTrue(circuit.time_created is not None)
예제 #17
0
    def test_stream_success(self):
        tor = FakeTorController()
        a = FakeRouter('$E11D2B2269CC25E67CA6C9FB5843497539A74FD0', 'a')
        tor.routers['$E11D2B2269CC25E67CA6C9FB5843497539A74FD0'] = a

        circuit = Circuit(tor)
        reactor = Mock()

        circuit.stream_via(
            reactor, 'torproject.org', 443,
            Mock(),
            use_tls=True,
        )
예제 #18
0
    def test_closed_remaining_streams(self):
        tor = FakeTorController()
        circuit = Circuit(tor)
        circuit.listen(tor)
        circuit.update('1 LAUNCHED PURPOSE=GENERAL'.split())
        stream = Stream(tor)
        stream.update("1 NEW 0 94.23.164.42.$43ED8310EB968746970896E8835C2F1991E50B69.exit:9001 SOURCE_ADDR=(Tor_internal):0 PURPOSE=DIR_FETCH".split())
        circuit.streams.append(stream)
        self.assertEqual(len(circuit.streams), 1)

        circuit.update('1 CLOSED $E11D2B2269CC25E67CA6C9FB5843497539A74FD0=eris,$50DD343021E509EB3A5A7FD0D8A4F8364AFBDCB5=venus,$253DFF1838A2B7782BE7735F74E50090D46CA1BC=chomsky PURPOSE=GENERAL REASON=FINISHED'.split())
        circuit.update('1 FAILED $E11D2B2269CC25E67CA6C9FB5843497539A74FD0=eris,$50DD343021E509EB3A5A7FD0D8A4F8364AFBDCB5=venus,$253DFF1838A2B7782BE7735F74E50090D46CA1BC=chomsky PURPOSE=GENERAL REASON=TIMEOUT'.split())
        errs = self.flushLoggedErrors()
        self.assertEqual(len(errs), 2)
예제 #19
0
    def test_age_default(self, fake_datetime):
        """
        age() w/ defaults works properly
        """
        from datetime import datetime
        now = datetime.fromtimestamp(60.0)
        fake_datetime.return_value = now
        fake_datetime.utcnow = Mock(return_value=now)
        tor = FakeTorController()

        circuit = Circuit(tor)
        circuit._time_created = datetime.fromtimestamp(0.0)
        self.assertEquals(circuit.age(), 60)
        self.assertTrue(circuit.time_created is not None)
예제 #20
0
    def test_unlisten(self):
        tor = FakeTorController()
        tor.routers['$E11D2B2269CC25E67CA6C9FB5843497539A74FD0'] = FakeRouter(
            '$E11D2B2269CC25E67CA6C9FB5843497539A74FD0', 'a')

        circuit = Circuit(tor, self.protocol)
        circuit.listen(tor)
        circuit.update('1 LAUNCHED PURPOSE=GENERAL'.split())
        circuit.unlisten(tor)
        circuit.update(
            '1 EXTENDED $E11D2B2269CC25E67CA6C9FB5843497539A74FD0=eris PURPOSE=GENERAL'
            .split())
        self.assertEqual(len(tor.circuits), 1)
        self.assertTrue(1 in tor.circuits)
        self.assertEqual(len(tor.extend), 0)
예제 #21
0
    def test_extends_no_path(self):
        '''
        without connectivity, it seems you get EXTENDS messages with no
        path update.
        '''
        tor = FakeTorController()
        circuit = Circuit(tor)
        circuit.listen(tor)

        circuit.update('753 EXTENDED BUILD_FLAGS=IS_INTERNAL,NEED_CAPACITY,NEED_UPTIME PURPOSE=MEASURE_TIMEOUT TIME_CREATED=2012-07-30T18:23:18.956704'.split())
        self.assertEqual(tor.extend, [])
        self.assertEqual(circuit.path, [])
        self.assertTrue('IS_INTERNAL' in circuit.build_flags)
        self.assertTrue('NEED_CAPACITY' in circuit.build_flags)
        self.assertTrue('NEED_UPTIME' in circuit.build_flags)
예제 #22
0
    def test_close_circuit(self):
        tor = FakeTorController()
        a = FakeRouter('$E11D2B2269CC25E67CA6C9FB5843497539A74FD0', 'a')
        b = FakeRouter('$50DD343021E509EB3A5A7FD0D8A4F8364AFBDCB5', 'b')
        c = FakeRouter('$253DFF1838A2B7782BE7735F74E50090D46CA1BC', 'c')
        tor.routers['$E11D2B2269CC25E67CA6C9FB5843497539A74FD0'] = a
        tor.routers['$50DD343021E509EB3A5A7FD0D8A4F8364AFBDCB5'] = b
        tor.routers['$253DFF1838A2B7782BE7735F74E50090D46CA1BC'] = c

        circuit = Circuit(tor)
        circuit.listen(tor)

        circuit.update(
            '123 EXTENDED $E11D2B2269CC25E67CA6C9FB5843497539A74FD0=eris,$50DD343021E509EB3A5A7FD0D8A4F8364AFBDCB5=venus,$253DFF1838A2B7782BE7735F74E50090D46CA1BC=chomsky PURPOSE=GENERAL'
            .split())

        self.assertEqual(3, len(circuit.path))
        d0 = circuit.close()
        # we already pretended that Tor answered "OK" to the
        # CLOSECIRCUIT call (see close_circuit() in FakeTorController
        # above) however the circuit isn't "really" closed yet...
        self.assertTrue(not d0.result.called)
        # not unit-test-y? shouldn't probably delve into internals I
        # suppose...
        self.assertTrue(circuit._closing_deferred is not None)

        # if we try to close it again (*before* the actual close has
        # succeeded!) we should also still be waiting.
        d1 = circuit.close()
        self.assertTrue(not d1.called)
        # ...and this Deferred should *not* be the same as the first
        self.assertTrue(d0 is not d1)

        # simulate that Tor has really closed the circuit for us
        # this should cause our Deferred to callback
        circuit.update(
            '123 CLOSED $E11D2B2269CC25E67CA6C9FB5843497539A74FD0=eris,$50DD343021E509EB3A5A7FD0D8A4F8364AFBDCB5=venus,$253DFF1838A2B7782BE7735F74E50090D46CA1BC=chomsky PURPOSE=GENERAL REASON=FINISHED'
            .split())

        # if we close *after* the close has succeeded, then we should
        # immediately "succeed"
        d2 = circuit.close()
        self.assertTrue(d1.called)

        # confirm that our circuit callback has been triggered already
        self.assertRaises(defer.AlreadyCalledError, d0.callback,
                          "should have been called already")
        return defer.DeferredList([d0, d1, d2])
예제 #23
0
    def test_is_built_errback(self):
        tor = FakeTorController()
        a = FakeRouter('$E11D2B2269CC25E67CA6C9FB5843497539A74FD0', 'a')
        tor.routers['$E11D2B2269CC25E67CA6C9FB5843497539A74FD0'] = a

        state = TorState(tor)
        circuit = Circuit(tor)
        circuit.listen(tor)

        circuit.update('123 EXTENDED $E11D2B2269CC25E67CA6C9FB5843497539A74FD0=eris PURPOSE=GENERAL'.split())
        state.circuit_new(circuit)
        d = circuit.when_built()

        state.circuit_closed(circuit)

        self.assertTrue(d.called)
        self.assertTrue(isinstance(d.result, Failure))
예제 #24
0
    def _test_attacher_both_apis(self):
        """
        similar to above, but first set_attacher is implicit via
        Circuit.stream_via
        """
        reactor = Mock()
        directlyProvides(reactor, IReactorCore)

        @implementer(IStreamAttacher)
        class MyAttacher(object):
            pass

        circ = Circuit(self.state)
        circ.state = 'BUILT'

        # use the "preferred" API, which will set an attacher
        factory = Mock()
        proto = Mock()
        proto.when_done = Mock(return_value=defer.succeed(None))
        factory.connect = Mock(return_value=defer.succeed(proto))
        ep = circ.stream_via(reactor, 'meejah.ca', 443, factory)
        addr = Mock()
        addr.host = '10.0.0.1'
        addr.port = 1011
        ep._target_endpoint._get_address = Mock(
            return_value=defer.succeed(addr))
        print("EP", ep)
        attacher = yield _get_circuit_attacher(reactor, self.state)
        print("attacher", attacher)
        d = ep.connect('foo')
        print("doin' it")
        stream = Mock()
        import ipaddress
        stream.source_addr = ipaddress.IPv4Address(u'10.0.0.1')
        stream.source_port = 1011
        attacher.attach_stream(stream, [])
        yield d

        # ...now use the low-level API (should be an error)
        with self.assertRaises(RuntimeError) as ctx:
            self.state.set_attacher(MyAttacher(), FakeReactor(self))
        self.assertTrue("already have an attacher" in str(ctx.exception))
예제 #25
0
 def test_str(self):
     tor = FakeTorController()
     circuit = Circuit(tor)
     circuit.id = 1
     str(circuit)
예제 #26
0
 def test_str(self):
     tor = FakeTorController()
     circuit = Circuit(tor, self.protocol)
     circuit.id = 1
     str(circuit)