Exemple #1
0
    async def test_tasks(self):
        s = SyntheticBackend(mocks.Context())

        async def f():
            await imbroglio.sleep(0)
        t = await imbroglio.spawn(f())
        s.tasks.append(t)
        await t

        self.assertTrue(s.tasks)
        s.reap_tasks()
        self.assertFalse(s.tasks)

        t = await imbroglio.spawn(f())
        s.tasks.append(t)
        await s.shutdown()

        self.assertFalse(s.tasks)
        self.assertTrue(t.is_done())

        async def g():
            raise Exception('exception')

        t = await imbroglio.spawn(g())
        s.tasks.append(g)
        with self.assertLogs(s.log.name, level='ERROR'):
            await s.shutdown()
        self.assertFalse(s.tasks)
        self.assertTrue(t.is_done())
Exemple #2
0
    def test_tasks(self):
        s = SyntheticBackend(mocks.Context())

        loop = asyncio.get_event_loop()

        @asyncio.coroutine
        def f():
            yield from asyncio.sleep(0)

        t = asyncio.Task(f())
        s.tasks.append(t)
        loop.run_until_complete(t)

        self.assertTrue(s.tasks)
        s.reap_tasks()
        self.assertFalse(s.tasks)

        t = asyncio.Task(f())
        s.tasks.append(t)
        loop.run_until_complete(s.shutdown())
        self.assertFalse(s.tasks)
        self.assertTrue(t.done())

        @asyncio.coroutine
        def g():
            raise Exception('exception')

        t = asyncio.Task(g())
        s.tasks.append(g)
        with self.assertLogs(s.log.name, level='ERROR'):
            loop.run_until_complete(s.shutdown())
        self.assertFalse(s.tasks)
        self.assertTrue(t.done())
Exemple #3
0
    async def test_unsubscribe(self):
        r = roost.Roost(mocks.Context())
        r.subunify = True

        w = Mock()
        w.read_string.return_value = mocks.promise('a')

        r.r.unsubscribe = Mock(return_value=mocks.promise())

        await r.unsubscribe(w)

        r.r.unsubscribe.assert_called_with([
            ('a', '*', ''),
            ('a.d', '*', ''),
            ('a.d.d', '*', ''),
            ('a.d.d.d', '*', ''),
            ('una', '*', ''),
            ('una.d', '*', ''),
            ('una.d.d', '*', ''),
            ('una.d.d.d', '*', ''),
            ('ununa', '*', ''),
            ('ununa.d', '*', ''),
            ('ununa.d.d', '*', ''),
            ('ununa.d.d.d', '*', ''),
            ('unununa', '*', ''),
            ('unununa.d', '*', ''),
            ('unununa.d.d', '*', ''),
            ('unununa.d.d.d', '*', ''),
            ])
Exemple #4
0
    async def test_Backend(self):
        context = mocks.Context()
        synth = SyntheticBackend(context)
        await synth.start()
        self.assertEqual(str(synth), synth.name)
        self.assertEqual(len(list(synth.walk(synth.earliest()))), 1)
        self.assertEqual(len(list(synth.walk(synth.latest(), False))), 1)

        synth = SyntheticBackend(context, conf={'count': 3})
        await synth.start()
        self.assertEqual(len(list(synth.walk(synth.earliest()))), 3)
        self.assertEqual(len(list(synth.walk(synth.latest(), False))), 3)

        self.assertEqual(len(list(synth.walk(synth.earliest()))), 3)
        self.assertEqual(len(list(synth.walk(synth.latest(), False))), 3)
        self.assertEqual(
            list(synth.walk(synth.messages[1], True)),
            [synth.messages[1], synth.messages[2]])
        self.assertEqual(
            list(synth.walk(synth.messages[1], False)),
            [synth.messages[1], synth.messages[0]])
        self.assertEqual(
            list(synth.walk(synth.messages[0], False)),
            [synth.messages[0]])

        self.assertFalse(synth.senders())
        self.assertFalse(synth.destinations())

        self.assertRaises(
            NotImplementedError, lambda: synth.send(None, None).send(None))

        self.assertEqual(messages.BackendState.IDLE, synth.state())
Exemple #5
0
    def test_set_get0(self):
        val = ''

        def setter(c, v):
            nonlocal val
            val = v

        c = TConfigurable('foo',
                          default='foo',
                          oneof={'foo', 'bar'},
                          action=setter)

        o = HasContext()

        self.assertIs(c.__get__(None, None), c)

        self.assertEqual(c.__get__(o, None), 'foo')

        o.context = mocks.Context()

        c.__set__(o, 'bar')

        self.assertEqual(c.__get__(o, None), 'bar')

        self.assertEqual(val, 'bar')

        self.assertRaises(ValueError, lambda: c.__set__(o, 'baz'))

        o.context.conf['set'] = {'foo': 'foo'}
        self.assertEqual(c.__get__(o, None), 'foo')
        TConfigurable.immanentize(o.context)
        self.assertEqual(val, 'foo')
Exemple #6
0
    def test_set_get1(self):
        c = TConfigurable('foo', default=0, coerce=int)
        o = HasContext()
        o.context = mocks.Context()

        c.__set__(o, '5')

        self.assertEqual(c.__get__(o, None), 5)
Exemple #7
0
    def test_set_get2(self):
        c = TConfigurable('foo')  # noqa: F841

        o = HasContext()
        o.context = mocks.Context()

        TConfigurable.set(o, 'foo', 'bar')
        self.assertEqual(TConfigurable.get(o, 'foo'), 'bar')
Exemple #8
0
 def test(self):
     s = SyntheticBackend(mocks.Context(), 'synthetic')
     m = messages.SnipeErrorMessage(s, 'error', 'traceback')
     self.assertTrue(m.error)
     self.assertEqual(str(m.filter()), 'backend == "synthetic" and error')
     self.assertEqual(
         str(m.filter(1)),
         'backend == "synthetic" and error and body == "error"')
Exemple #9
0
 def test_redisplay(self):
     s = SyntheticBackend(mocks.Context())
     s.context.ui = mocks.FE()
     self.assertNotIn('redisplay', s.context.ui.called)
     s.redisplay(None, None)
     self.assertIn('redisplay', s.context.ui.called)
     s.context.ui.redisplay = lambda: None
     with self.assertLogs(s.log.name, level='ERROR'):
         s.redisplay(None, None)
Exemple #10
0
    async def test_error_message(self):
        r = roost.Roost(mocks.Context())

        async def raises():
            raise Exception('foo')

        r.add_message = Mock()
        await r.error_message('activity', raises)
        m = r.add_message.call_args[0][0]
        self.assertEqual('activity: foo', m.body.splitlines()[0])
Exemple #11
0
    def test_body(self):
        context = mocks.Context()
        s = SyntheticBackend(context, 'synthetic')
        m = messages.SnipeMessage(s, 'foo', 0.0)
        self.assertEqual(str(m.sender), 'synthetic')

        self.assertEqual(m.OnelineDecor.body(m), [])
        self.assertEqual(m.Decor.body(m), [(set(), 'foo\n')])
        s.indent = 'X '
        self.assertEqual(m.Decor.body(m), [(set(), 'X foo\n')])
Exemple #12
0
    async def test_new_message(self):
        r = roost.Roost(mocks.Context())

        o = object()
        r.construct_and_maybe_decrypt = Mock(return_value=mocks.promise(o))
        r.add_message = Mock()

        await r.new_message({})
        r.construct_and_maybe_decrypt.assert_called_with({})
        r.add_message.assert_called_with(o)
Exemple #13
0
    async def test_subscribe_fie(self):
        r = roost.Roost(mocks.Context())

        w = Mock()
        w.read_filename.return_value = mocks.promise('filename')

        r.load_subs = Mock(return_value=mocks.promise())

        with patch('os.path.exists', return_value=False):
            await r.subscribe_file(w)

        r.load_subs.assert_called_with('filename')
Exemple #14
0
    async def test_dump_subscriptions(self):
        r = roost.Roost(mocks.Context())

        r.r.subscriptions = Mock(return_value=mocks.promise([{
            'class': 'class',
            'instance': 'instance',
            'recipient': '',
            }]))
        w = Mock()

        await r.dump_subscriptions(w)
        w.show.assert_called_with('class instance *')
Exemple #15
0
    def test(self):
        a = messages.SnipeAddress(None)
        self.assertEqual(a.address, [None])

        context = mocks.Context()
        s = SyntheticBackend(context, 'synthetic')

        a = messages.SnipeAddress(s, ['foo'])
        self.assertEqual(str(a), 'synthetic;foo')
        self.assertEqual(a.short(), str(a))
        self.assertEqual(a.reply(), str(a))
        self.assertEqual(repr(a), '<SnipeAddress synthetic foo>')
Exemple #16
0
    def test(self):
        os.environ['TZ'] = 'GMT'
        context = mocks.Context()
        s = SyntheticBackend(context, 'synthetic')
        m = messages.SnipeMessage(s, 'foo', 0.0)
        self.assertEqual(str(m.sender), 'synthetic')
        self.assertEqual(str(m), '00:00 synthetic\nfoo')
        self.assertEqual(
            m.display({}), [
                ({'bold'}, 'synthetic'),
                ({'right'}, ' 00:00:00'),
                (set(), 'foo\n'),
                ])
        self.assertIsNone(m.canon('foo', None))
        self.assertEqual(m.field('foo'), '')
        m.data['bar'] = 5
        self.assertEqual(m.field('bar'), 5)
        m.data['baz'] = 'quux'
        self.assertEqual(m.field('baz'), 'quux')

        timeything = collections.namedtuple('TimeyThing', ['time'])(0.0)
        self.assertEqual(m._coerce(timeything), 0.0)

        class IntyThing:
            __int__ = lambda self: 0  # noqa: E731
        intything = IntyThing()
        self.assertEqual(m._coerce(intything), 0)

        class FloatyThing:
            __float__ = lambda self: 0.0  # noqa: E731
        floatything = FloatyThing()
        self.assertEqual(m._coerce(floatything), 0.0)
        self.assertEqual(m._coerce('foo'), 'foo')

        self.assertEqual(m.reply(), s.name)
        self.assertEqual(m.followup(), s.name)

        self.assertEqual(m.filter(), filters.Compare('==', 'backend', s.name))

        self.assertEqual(float(m), m.time)

        m.transform('foo', 'bar')
        self.assertEqual(m.transformed, 'foo')
        self.assertEqual(m.body, 'bar')

        self.assertIs(
            m.get_decor({'decor': 'test_messages.TestMessage'}),
            TestMessage)

        self.assertIs(
            m.get_decor({'decor': 'nonexistent.object'}),
            messages.SnipeMessage.Decor)
Exemple #17
0
    async def test_reconnect(self):
        r = roost.Roost(mocks.Context())

        r.new_task = Mock()
        r.new_task.is_done.return_value = False

        r.disconnect = Mock(return_value=mocks.promise())
        r.start = Mock(return_value=mocks.promise())

        await r.reconnect()

        r.disconnect.assert_called()
        r.start.assert_called()
Exemple #18
0
    async def test_load_subs(self):
        r = roost.Roost(mocks.Context())

        r.r.subscribe = Mock(return_value=mocks.promise())

        with patch('os.path.exists', return_value=False), \
                patch('snipe.roost.open', return_value=io.StringIO(
                    'class,instance,*\n')) as o:
            await r.load_subs('foo')
            o.assert_not_called()

        with patch('os.path.exists', return_value=True), \
                patch('snipe.roost.open', return_value=io.StringIO(
                    'class,instance,@ATHENA.MIT.EDU\n')):
            await r.load_subs('foo')
        r.r.subscribe.assert_called_with([['class', 'instance', '*']])
Exemple #19
0
    async def test_disconnect(self):
        cancelled = False

        class Tusk:
            def cancel(self):
                nonlocal cancelled
                cancelled = True

            def __await__(self):
                yield ('sleep',)

        r = roost.Roost(mocks.Context())
        r.new_task = Tusk()
        r.tasks.append(r.new_task)
        await r.disconnect()
        self.assertTrue(cancelled)
Exemple #20
0
    def test_add_message(self):
        r = roost.Roost(mocks.Context())

        r.drop_cache = Mock()
        r.redisplay = Mock()

        m = messages.SnipeMessage(r, 'foo', 1.0)
        r.add_message(m)

        r.drop_cache.assert_called()
        r.redisplay.assert_called_with(m, m)

        m = messages.SnipeMessage(r, 'bar', 1.0)
        r.add_message(m)

        self.assertEqual(2, len(r.messages))
        self.assertEqual(1.00001, r.messages[-1].time)
Exemple #21
0
    def test(self):
        c = TLevel('foo', logger='foo', default=logging.ERROR)  # noqa: F841
        o = HasContext()
        o.context = mocks.Context()

        TLevel.immanentize(o.context)

        self.assertEqual(logging.getLogger('foo').level, logging.ERROR)

        TLevel.set(o, 'foo', '10')
        self.assertEqual(logging.getLogger('foo').level, 10)

        TLevel.set(o, 'foo', 'warning')
        self.assertEqual(logging.getLogger('foo').level, logging.WARNING)

        self.assertRaises(ValueError, lambda: TLevel.set(o, 'foo', object()))
        self.assertRaises(ValueError, lambda: TLevel.set(o, 'foo', 'zog'))
Exemple #22
0
    def test(self):
        d = messages.DateBackend(mocks.Context())
        d.context.backends.eldest = lambda: None
        self.assertFalse(list(d.walk(d.earliest(), True)))
        self.assertFalse(list(d.walk(d.latest(), False)))

        d.context.backends.eldest = lambda: (
            datetime.datetime.now() - datetime.timedelta(days=1)).timestamp()
        self.assertTrue(list(d.walk(d.earliest(), True)))
        self.assertFalse(list(d.walk(d.earliest(), True, search=True)))

        self.assertFalse(list(d.walk(float('Inf'), True)))
        self.assertTrue(list(d.walk(float('Inf'), False)))
        self.assertTrue(list(d.walk(-float('Inf'), True)))

        self.assertTrue(list(d.walk(d.starting_at.timestamp() + .1, True)))

        self.assertEqual(d.count(), 0)

        self.assertIsNone(d.eldest())
Exemple #23
0
    async def test_send(self):
        r = roost.Roost(mocks.Context())

        r.r.send = Mock(return_value=mocks.promise())
        await r.send('-c class -i instance -s sig -O opcode', 'body')

        self.assertEqual(
            r.r.send.call_args[0][0],
            {
                'class': 'class',
                'instance': 'instance',
                'recipient': '',
                'opcode': 'opcode',
                'signature': 'sig',
                'message': 'body',
            })

        r.r.send = Mock(return_value=mocks.promise())
        await r.send('-c class -R -s sig recipient', 'body')

        self.assertEqual(
            r.r.send.call_args[0][0],
            {
                'class': 'class',
                'instance': 'PERSONAL',
                'recipient': 'recipient',
                'opcode': '',
                'signature': 'sig',
                'message': 'obql',
            })

        r.r.send = Mock(return_value=mocks.promise())
        with self.assertRaises(RuntimeError):
            await r.send('-c class -s sig -C r1 r2', 'body')

        self.assertEqual(
            r.r.send.call_args[0][0],
            {
                'class': 'class',
                'instance': 'PERSONAL',
                'recipient': 'r2',
                'opcode': '',
                'signature': 'sig',
                'message': 'CC: r1 r2\nbody',
            })

        with patch(
                'snipe.imbroglio.process_filter',
                return_value=mocks.promise((0, 'foo'))):
            r.r.send = Mock(return_value=mocks.promise())
            await r.send('-c class -x -s sig recipient', 'body')

            self.assertEqual(
                {
                    'class': 'class',
                    'instance': 'PERSONAL',
                    'recipient': 'recipient',
                    'opcode': 'crypt',
                    'signature': 'sig',
                    'message': 'foo',
                }, r.r.send.call_args[0][0])

        with patch(
                'snipe.imbroglio.process_filter',
                return_value=mocks.promise((1, 'foo'))), \
                self.assertRaises(Exception):
            r.r.send = Mock(return_value=mocks.promise())
            await r.send('-c class -x -s sig recipient', 'body')
Exemple #24
0
    def test(self):
        context = mocks.Context()
        synth = SyntheticBackend(context)
        startup = messages.StartupBackend(context)
        sink = messages.SinkBackend(context)
        a = messages.AggregatorBackend(context, [startup, synth, sink])
        a.start()
        self.assertEqual(startup.count(), 1)
        self.assertEqual(synth.count(), 1)
        self.assertEqual(a.count(), 3)
        self.assertEqual(len(list(a.walk(None, False))), 3)
        list(a.send('sink', 'a message'))
        self.assertEqual(a.count(), 4)
        self.assertEqual(len(list(a.walk(None, False))), 4)
        self.assertEqual(len(list(a.walk(None))), 4)
        self.assertEqual(len(list(a.walk(None, search=True))), 3)
        self.assertEqual(
            len(list(a.walk(None, filter=filters.makefilter('yes')))), 4)
        self.assertEqual(
            len(
                list(
                    a.walk(None,
                           filter=filters.makefilter('backend == "sink"'),
                           search=True))), 1)
        self.assertEqual(
            len(list(a.walk(
                float('Inf'),
                forward=False,
                backfill_to=0.0,
            ))), 4)
        self.assertEqual(len(list(a.walk(float('-Inf')))), 4)

        for i in range(2):  # because caching?
            forward = list(a.walk(None, True))
            for (x, y) in list(zip([None] + forward, forward + [None]))[1:-1]:
                self.assertLess(x, y)

            backward = list(a.walk(None, False))
            for (x, y) in list(zip([None] + backward,
                                   backward + [None]))[1:-1]:
                self.assertGreater(x, y)

        self.assertTrue(a.walk(forward[0], True))

        self.assertEqual(a.eldest(), synth.messages[0].time)

        self.assertRaises(util.SnipeException,
                          lambda: a.send('nope', None).send(None))

        count = 0

        @asyncio.coroutine
        def mock_shutdown():
            nonlocal count
            count += 1

        for backend in a:
            backend.shutdown = mock_shutdown

        loop = asyncio.get_event_loop()
        loop.run_until_complete(a.shutdown())

        self.assertGreater(count, 0)

        count = 0

        def mock_backfill(filter, target):
            nonlocal count
            count += 1

        for backend in a:
            backend.backfill = mock_backfill

        a.backfill(None, None)

        self.assertGreater(count, 0)

        self.assertEqual(a.destinations(), set())
        self.assertEqual(a.senders(), set())

        self.assertEqual(a.count(), 4)
        synth2 = SyntheticBackend(context)
        a.add(synth2)
        self.assertEqual(a.count(), 5)
Exemple #25
0
    async def test(self):
        context = mocks.Context()
        synth = SyntheticBackend(context)
        startup = messages.StartupBackend(context)
        sink = messages.SinkBackend(context)
        a = messages.AggregatorBackend(context, [startup, synth, sink])
        await a.start()
        self.assertEqual(startup.count(), 1)
        self.assertEqual(synth.count(), 1)
        self.assertEqual(a.count(), 3)
        self.assertEqual(len(list(a.walk(a.latest(), False))), 3)
        self.assertEqual(sink.count(), 0)
        await a.send('sink', 'a message')
        self.assertEqual(sink.count(), 1)
        self.assertEqual(sink.messages[0].body, 'a message')
        await a.send('sink', 'a message\x0bwith a vt')
        self.assertEqual(sink.messages[1].body, 'a message\nwith a vt')
        sink.SOFT_NEWLINES = True
        await a.send('sink', 'another message\x0bwith a vt')
        self.assertEqual(sink.messages[2].body, 'another message with a vt')
        with self.assertRaises(util.SnipeException):
            await a.send('', 'a message')
        with self.assertRaises(util.SnipeException):
            await a.send('fnord', 'a message')
        with self.assertRaises(util.SnipeException):
            await a.send('s', 'a message')
        self.assertEqual(a.count(), 6)
        self.assertEqual(len(list(a.walk(a.latest(), False))), 6)
        self.assertEqual(len(list(a.walk(a.earliest()))), 6)
        self.assertEqual(len(list(a.walk(a.earliest(), search=True))), 5)
        self.assertEqual(
            len(list(a.walk(a.earliest(), mfilter=filters.makefilter('yes')))),
            6)
        self.assertEqual(
            len(list(a.walk(
                a.earliest(),
                mfilter=filters.makefilter('backend == "sink"'),
                search=True))),
            3)
        self.assertEqual(len(list(a.walk(
            float('Inf'),
            forward=False,
            backfill_to=0.0,
            ))), 6)
        self.assertEqual(len(list(a.walk(float('-Inf')))), 6)

        for i in range(2):  # because caching?
            forward = list(a.walk(a.earliest(), True))
            for (x, y) in list(zip([None] + forward, forward + [None]))[1:-1]:
                self.assertLess(x, y)

            backward = list(a.walk(a.latest(), False))
            for (x, y) in list(
                    zip([None] + backward, backward + [None]))[1:-1]:
                self.assertGreater(x, y)

        self.assertTrue(a.walk(forward[0], True))

        self.assertEqual(a.eldest(), synth.messages[0].time)

        with self.assertRaises(util.SnipeException):
            await a.send('nope', None)

        count = 0

        async def mock_shutdown():
            nonlocal count
            count += 1

        for backend in a:
            backend.shutdown = mock_shutdown

        await a.shutdown()

        self.assertGreater(count, 0)

        count = 0

        def mock_backfill(filter, target):
            nonlocal count
            count += 1

        for backend in a:
            backend.backfill = mock_backfill

        a.backfill(None, None)

        self.assertGreater(count, 0)

        self.assertEqual(a.destinations(), set())
        self.assertEqual(a.senders(), set())

        self.assertEqual(a.count(), 6)
        synth2 = SyntheticBackend(context)
        a.backends.append(synth2)
        await synth2.start()
        self.assertEqual(a.count(), 7)

        self.assertEqual(a.statusline(), '')

        synth2.context.ui = mocks.FE()
        synth2.state_set(messages.BackendState.BACKFILLING)

        self.assertEqual(a.statusline(), '[synthetic BACKFILLING]')
Exemple #26
0
 async def test_do_auto_fill_long(self):
     e = snipe.editor.Editor(mocks.Context())
     await e.set_fill_column(5)
     for c in 'sassa fras ':
         e.input_char(c)
     self.assertEqual('sassa\x0bfras ', str(e.buf))
Exemple #27
0
    async def test_construct_and_maybe_decrypt(self):
        r = roost.Roost(mocks.Context())

        self.assertEqual(0, len(r._destinations))
        self.assertEqual(0, len(r._senders))

        m = await r.construct_and_maybe_decrypt({
                'message': 'body',
                'receiveTime': 0.0,
                'sender': 'sender',
                'class': 'class',
                'instance': 'instance',
                'recipient': '',
                'opcode': '',
                'signature': 'sig',
                'time': 0.0,
                })

        self.assertEqual('body', m.body)
        self.assertEqual(2, len(r._destinations))
        self.assertEqual(1, len(r._senders))

        with patch(
                'snipe.imbroglio.process_filter',
                return_value=mocks.promise((0, 'foo\n**END**\n'))):
            m = await r.construct_and_maybe_decrypt({
                    'message': 'body',
                    'receiveTime': 0.0,
                    'sender': 'sender',
                    'class': 'class',
                    'instance': 'instance',
                    'recipient': '',
                    'opcode': 'crypt',
                    'signature': 'sig',
                    'time': 0.0,
                    })
            self.assertEqual('zcrypt', m.transformed)
            self.assertEqual('foo\n', m.body)

        with patch(
                'snipe.imbroglio.process_filter',
                return_value=mocks.promise((1, 'foo\n**END**\n'))), \
                self.assertLogs() as l:
            m = await r.construct_and_maybe_decrypt({
                    'message': 'body',
                    'receiveTime': 0.0,
                    'sender': 'sender',
                    'class': 'class',
                    'instance': 'instance',
                    'recipient': '',
                    'opcode': 'crypt',
                    'signature': 'sig',
                    'time': 0.0,
                    })
        (m,) = l.output
        self.assertRegex(
            m,
            r'ERROR:Roost.[0-9a-f]+:roost: zcrypt -D -c class returned 1')

        with patch(
                'snipe.imbroglio.process_filter',
                return_value=mocks.promise(exception=Exception)), \
                self.assertLogs() as l:
            m = await r.construct_and_maybe_decrypt({
                    'message': 'body',
                    'receiveTime': 0.0,
                    'sender': 'sender',
                    'class': 'class',
                    'instance': 'instance',
                    'recipient': '',
                    'opcode': 'crypt',
                    'signature': 'sig',
                    'time': 0.0,
                    })
        (m,) = l.output
        m = m.splitlines()[0]
        self.assertRegex(
            m,
            'ERROR:Roost.[0-9a-f]+:zcrypt, decrypting')
Exemple #28
0
 def test(self):
     context = mocks.Context()
     startup = messages.StartupBackend(context)
     self.assertEqual(len(list(startup.walk(startup.earliest()))), 1)
     self.assertEqual(len(list(startup.walk(startup.latest(), False))), 1)