Пример #1
0
def push_instruction_and_record_prefix(instructions, op, op_args, path,
                                       dir_index, random, subspace):
    if not op.endswith('_DATABASE'):
        instructions.push_args(1, *test_util.with_length(path))
        instructions.append('DIRECTORY_EXISTS')

    # This op must leave the stack in the state it is in at this point, with the exception
    # that it may leave an error on the stack
    instructions.push_args(*op_args)
    instructions.append(op)

    if not op.endswith('_DATABASE'):
        instructions.push_args(dir_index)
        instructions.append('DIRECTORY_CHANGE')

        instructions.push_args(1, b'', random.random_string(16), b'')
        instructions.append('DIRECTORY_PACK_KEY')
        test_util.to_front(
            instructions,
            3)  # move the existence result up to the front of the stack

        t = util.subspace_to_tuple(subspace)
        instructions.push_args(len(t) + 3, *t)

        instructions.append(
            'TUPLE_PACK'
        )  # subspace[<exists>][<packed_key>][random.random_string(16)] = b''
        instructions.append('SET')

        instructions.push_args(DEFAULT_DIRECTORY_INDEX)
        instructions.append('DIRECTORY_CHANGE')
    def generate(self, args, thread_number):
        instructions = InstructionSet()

        instructions.append('NEW_TRANSACTION')

        default_path = unicode('default%d' % self.next_path)
        self.next_path += 1
        dir_list = directory_util.setup_directories(instructions, default_path,
                                                    self.random)
        num_dirs = len(dir_list)

        instructions.push_args(directory_util.DEFAULT_DIRECTORY_INDEX)
        instructions.append('DIRECTORY_CHANGE')

        instructions.setup_complete()

        current_op = 0

        while current_op < args.num_ops:
            if args.concurrency > 1:
                self.barrier(instructions, thread_number)

            instructions.push_args(random.choice(self.transactions))
            instructions.append('USE_TRANSACTION')

            if thread_number == 0 and args.concurrency > 1:
                num_directories = 1
            else:
                num_directories = int(
                    max(
                        1,
                        pow(random.random(), 4) *
                        min(self.max_directories_per_transaction,
                            args.num_ops - current_op)))

            for i in range(num_directories):
                path = (self.random.random_unicode_str(16), )
                op_args = test_util.with_length(path) + ('', None)
                directory_util.push_instruction_and_record_prefix(
                    instructions, 'DIRECTORY_CREATE', op_args, path, num_dirs,
                    self.random, self.prefix_log)
                num_dirs += 1

            current_op += num_directories

            if args.concurrency > 1:
                self.barrier(instructions,
                             thread_number,
                             thread_ending=(current_op >= args.num_ops))

            if thread_number == 0:
                self.commit_transactions(instructions, args)

        return instructions
Пример #3
0
    def generate(self, args, thread_number):
        instructions = InstructionSet()

        op_choices = ['NEW_TRANSACTION', 'COMMIT']

        general = ['DIRECTORY_CREATE_SUBSPACE', 'DIRECTORY_CREATE_LAYER']

        op_choices += general

        directory_mutations = ['DIRECTORY_CREATE_OR_OPEN', 'DIRECTORY_CREATE', 'DIRECTORY_MOVE', 'DIRECTORY_MOVE_TO',
                               'DIRECTORY_REMOVE', 'DIRECTORY_REMOVE_IF_EXISTS']
        directory_reads = ['DIRECTORY_EXISTS', 'DIRECTORY_OPEN', 'DIRECTORY_LIST']

        directory_db_mutations = [x + '_DATABASE' for x in directory_mutations]
        directory_db_reads = [x + '_DATABASE' for x in directory_reads]
        directory_snapshot_reads = [x + '_SNAPSHOT' for x in directory_reads]

        directory = []
        directory += directory_mutations
        directory += directory_reads
        directory += directory_db_mutations
        directory += directory_db_reads

        if not args.no_directory_snapshot_ops:
            directory += directory_snapshot_reads

        subspace = ['DIRECTORY_PACK_KEY', 'DIRECTORY_UNPACK_KEY', 'DIRECTORY_RANGE', 'DIRECTORY_CONTAINS', 'DIRECTORY_OPEN_SUBSPACE']

        instructions.append('NEW_TRANSACTION')

        default_path = unicode('default%d' % self.next_path)
        self.next_path += 1
        self.dir_list = directory_util.setup_directories(instructions, default_path, self.random)
        self.root = self.dir_list[0]

        instructions.push_args(0)
        instructions.append('DIRECTORY_CHANGE')

        # Generate some directories that we are going to create in advance. This tests that other bindings
        # are compatible with the Python implementation
        self.prepopulated_dirs = [(generate_path(min_length=1), self.generate_layer()) for i in range(5)]

        for path, layer in self.prepopulated_dirs:
            instructions.push_args(layer)
            instructions.push_args(*test_util.with_length(path))
            instructions.append('DIRECTORY_OPEN')
            self.dir_list.append(self.root.add_child(path, DirectoryStateTreeNode(True, True, has_known_prefix=False, is_partition=(layer=='partition'))))
            # print('%d. Selected %s, dir=%s, dir_id=%s, has_known_prefix=%s, dir_list_len=%d' \
            #       % (len(instructions), 'DIRECTORY_OPEN', repr(self.dir_index), self.dir_list[-1].dir_id, False, len(self.dir_list)-1))

        instructions.setup_complete()

        for i in range(args.num_ops):
            if random.random() < 0.5:
                while True:
                    self.dir_index = random.randrange(0, len(self.dir_list))
                    if not self.dir_list[self.dir_index].state.is_partition or not self.dir_list[self.dir_index].state.deleted:
                        break

                instructions.push_args(self.dir_index)
                instructions.append('DIRECTORY_CHANGE')

            dir_entry = self.dir_list[self.dir_index]

            choices = op_choices[:]
            if dir_entry.state.is_directory:
                choices += directory
            if dir_entry.state.is_subspace:
                choices += subspace

            op = random.choice(choices)

            # print('%d. Selected %s, dir=%d, dir_id=%d, has_known_prefix=%d, dir_list_len=%d' \
            #       % (len(instructions), op, self.dir_index, dir_entry.dir_id, dir_entry.state.has_known_prefix, len(self.dir_list)))

            if op.endswith('_DATABASE') or op.endswith('_SNAPSHOT'):
                root_op = op[0:-9]
            else:
                root_op = op

            if root_op == 'NEW_TRANSACTION':
                instructions.append(op)

            elif root_op == 'COMMIT':
                test_util.blocking_commit(instructions)

            elif root_op == 'DIRECTORY_CREATE_SUBSPACE':
                path = generate_path()
                instructions.push_args(generate_prefix(require_unique=False, is_partition=True))
                instructions.push_args(*test_util.with_length(path))
                instructions.append(op)
                self.dir_list.append(DirectoryStateTreeNode(False, True, has_known_prefix=True))

            elif root_op == 'DIRECTORY_CREATE_LAYER':
                indices = []
                
                prefixes = [generate_prefix(require_unique=args.concurrency==1, is_partition=True) for i in range(2)]
                for i in range(2):
                    instructions.push_args(prefixes[i])
                    instructions.push_args(*test_util.with_length(generate_path()))
                    instructions.append('DIRECTORY_CREATE_SUBSPACE')
                    indices.append(len(self.dir_list))
                    self.dir_list.append(DirectoryStateTreeNode(False, True, has_known_prefix=True))

                instructions.push_args(random.choice([0, 1]))
                instructions.push_args(*indices)
                instructions.append(op)
                self.dir_list.append(DirectoryStateTreeNode.get_layer(prefixes[0]))

            elif root_op == 'DIRECTORY_CREATE_OR_OPEN':
                # Because allocated prefixes are non-deterministic, we cannot have overlapping
                # transactions that allocate/remove these prefixes in a comparison test
                if op.endswith('_DATABASE') and args.concurrency == 1:
                    test_util.blocking_commit(instructions)

                path = generate_path()
                op_args = test_util.with_length(path) + (self.generate_layer(),)
                directory_util.push_instruction_and_record_prefix(instructions, op, op_args, path, len(self.dir_list), self.random, self.prefix_log)

                if not op.endswith('_DATABASE') and args.concurrency == 1:
                    test_util.blocking_commit(instructions)

                child_entry = dir_entry.get_descendent(path)
                if child_entry is None:
                    child_entry = DirectoryStateTreeNode(True, True)

                child_entry.state.has_known_prefix = False  
                self.dir_list.append(dir_entry.add_child(path, child_entry))

            elif root_op == 'DIRECTORY_CREATE':
                layer = self.generate_layer()
                is_partition = layer == 'partition'

                prefix = generate_prefix(require_unique=is_partition and args.concurrency==1, is_partition=is_partition, min_length=0)

                # Because allocated prefixes are non-deterministic, we cannot have overlapping
                # transactions that allocate/remove these prefixes in a comparison test
                if op.endswith('_DATABASE') and args.concurrency == 1:  # and allow_empty_prefix:
                    test_util.blocking_commit(instructions)

                path = generate_path()
                op_args = test_util.with_length(path) + (layer, prefix)
                if prefix is None:
                    directory_util.push_instruction_and_record_prefix(
                        instructions, op, op_args, path, len(self.dir_list), self.random, self.prefix_log)
                else:
                    instructions.push_args(*op_args)
                    instructions.append(op)

                if not op.endswith('_DATABASE') and args.concurrency == 1:  # and allow_empty_prefix:
                    test_util.blocking_commit(instructions)

                child_entry = dir_entry.get_descendent(path)
                if child_entry is None:
                    child_entry = DirectoryStateTreeNode(True, True, has_known_prefix=bool(prefix))
                elif not bool(prefix):
                    child_entry.state.has_known_prefix = False

                if is_partition:
                    child_entry.state.is_partition = True

                self.dir_list.append(dir_entry.add_child(path, child_entry))

            elif root_op == 'DIRECTORY_OPEN':
                path = generate_path()
                instructions.push_args(self.generate_layer())
                instructions.push_args(*test_util.with_length(path))
                instructions.append(op)

                child_entry = dir_entry.get_descendent(path)
                if child_entry is None:
                    self.dir_list.append(DirectoryStateTreeNode(False, False, has_known_prefix=False))
                else:
                    self.dir_list.append(dir_entry.add_child(path, child_entry))

            elif root_op == 'DIRECTORY_MOVE':
                old_path = generate_path()
                new_path = generate_path()
                instructions.push_args(*(test_util.with_length(old_path) + test_util.with_length(new_path)))
                instructions.append(op)

                child_entry = dir_entry.get_descendent(old_path)
                if child_entry is None:
                    self.dir_list.append(DirectoryStateTreeNode(False, False, has_known_prefix=False))
                else:
                    self.dir_list.append(dir_entry.add_child(new_path, child_entry))

                # Make sure that the default directory subspace still exists after moving the specified directory
                if dir_entry.state.is_directory and not dir_entry.state.is_subspace and old_path == (u'',):
                    self.ensure_default_directory_subspace(instructions, default_path)

            elif root_op == 'DIRECTORY_MOVE_TO':
                new_path = generate_path()
                instructions.push_args(*test_util.with_length(new_path))
                instructions.append(op)

                child_entry = dir_entry.get_descendent(())
                if child_entry is None:
                    self.dir_list.append(DirectoryStateTreeNode(False, False, has_known_prefix=False))
                else:
                    self.dir_list.append(dir_entry.add_child(new_path, child_entry))

                # Make sure that the default directory subspace still exists after moving the current directory
                self.ensure_default_directory_subspace(instructions, default_path)

            elif root_op == 'DIRECTORY_REMOVE' or root_op == 'DIRECTORY_REMOVE_IF_EXISTS':
                # Because allocated prefixes are non-deterministic, we cannot have overlapping
                # transactions that allocate/remove these prefixes in a comparison test
                if op.endswith('_DATABASE') and args.concurrency == 1:
                    test_util.blocking_commit(instructions)

                path = ()
                count = random.randint(0, 1)
                if count == 1:
                    path = generate_path()
                    instructions.push_args(*test_util.with_length(path))

                instructions.push_args(count)
                instructions.append(op)

                dir_entry.delete(path)

                # Make sure that the default directory subspace still exists after removing the specified directory
                if path == () or (dir_entry.state.is_directory and not dir_entry.state.is_subspace and path == (u'',)):
                    self.ensure_default_directory_subspace(instructions, default_path)

            elif root_op == 'DIRECTORY_LIST' or root_op == 'DIRECTORY_EXISTS':
                path = ()
                count = random.randint(0, 1)
                if count == 1:
                    path = generate_path()
                    instructions.push_args(*test_util.with_length(path))
                instructions.push_args(count)
                instructions.append(op)

            elif root_op == 'DIRECTORY_PACK_KEY':
                t = self.random.random_tuple(5)
                instructions.push_args(*test_util.with_length(t))
                instructions.append(op)
                instructions.append('DIRECTORY_STRIP_PREFIX')

            elif root_op == 'DIRECTORY_UNPACK_KEY' or root_op == 'DIRECTORY_CONTAINS':
                if not dir_entry.state.has_known_prefix or random.random() < 0.2 or root_op == 'DIRECTORY_UNPACK_KEY':
                    t = self.random.random_tuple(5)
                    instructions.push_args(*test_util.with_length(t))
                    instructions.append('DIRECTORY_PACK_KEY')
                    instructions.append(op)
                else:
                    instructions.push_args(fdb.tuple.pack(self.random.random_tuple(5)))
                    instructions.append(op)

            elif root_op == 'DIRECTORY_RANGE' or root_op == 'DIRECTORY_OPEN_SUBSPACE':
                t = self.random.random_tuple(5)
                instructions.push_args(*test_util.with_length(t))
                instructions.append(op)
                if root_op == 'DIRECTORY_OPEN_SUBSPACE':
                    self.dir_list.append(DirectoryStateTreeNode(False, True, dir_entry.state.has_known_prefix))
                else:
                    test_util.to_front(instructions, 1)
                    instructions.append('DIRECTORY_STRIP_PREFIX')
                    test_util.to_front(instructions, 1)
                    instructions.append('DIRECTORY_STRIP_PREFIX')

        instructions.begin_finalization()

        test_util.blocking_commit(instructions)

        instructions.append('NEW_TRANSACTION')

        for i, dir_entry in enumerate(self.dir_list):
            instructions.push_args(i)
            instructions.append('DIRECTORY_CHANGE')
            if dir_entry.state.is_directory:
                instructions.push_args(self.directory_log.key())
                instructions.append('DIRECTORY_LOG_DIRECTORY')
            if dir_entry.state.has_known_prefix and dir_entry.state.is_subspace:
                # print('%d. Logging subspace: %d' % (i, dir_entry.dir_id))
                instructions.push_args(self.subspace_log.key())
                instructions.append('DIRECTORY_LOG_SUBSPACE')
            if (i + 1) % 100 == 0:
                test_util.blocking_commit(instructions)

        test_util.blocking_commit(instructions)

        instructions.push_args(self.stack_subspace.key())
        instructions.append('LOG_STACK')

        test_util.blocking_commit(instructions)
        return instructions
Пример #4
0
    def generate(self, args, thread_number):
        self.results = []

        test_instructions = ThreadedInstructionSet()
        main_thread = test_instructions.create_thread()

        foo = [self.workspace.pack(('foo%d' % i, )) for i in range(0, 6)]

        main_thread.append('NEW_TRANSACTION')
        main_thread.push_args(1020)
        main_thread.append('ON_ERROR')
        self.add_result(main_thread, args, 'RESULT_NOT_PRESENT')
        main_thread.append('GET_READ_VERSION')
        main_thread.push_args(foo[1], 'bar')
        main_thread.append('SET')
        main_thread.push_args(foo[1])
        main_thread.append('GET')
        self.add_result(main_thread, args, 'bar')
        test_util.blocking_commit(main_thread)
        self.add_result(main_thread, args, 'RESULT_NOT_PRESENT')

        main_thread.push_args(2000)
        main_thread.append('ON_ERROR')
        self.add_result(main_thread, args, test_util.error_string(2000))

        main_thread.append('NEW_TRANSACTION')
        main_thread.push_args(0)
        main_thread.append('ON_ERROR')
        self.add_result(main_thread, args, test_util.error_string(2000))

        main_thread.append('NEW_TRANSACTION')
        main_thread.push_args(foo[1])
        main_thread.append('DUP')
        main_thread.append('DUP')
        main_thread.append('GET')
        self.add_result(main_thread, args, 'bar')
        main_thread.append('CLEAR')
        main_thread.append('GET_SNAPSHOT')
        self.add_result(main_thread, args, 'RESULT_NOT_PRESENT')
        main_thread.push_args(foo[1])
        main_thread.append('GET_DATABASE')
        self.add_result(main_thread, args, 'bar')
        test_util.blocking_commit(main_thread)
        self.add_result(main_thread, args, 'RESULT_NOT_PRESENT')

        main_thread.append('SET_READ_VERSION')
        main_thread.push_args(foo[1])
        main_thread.append('DUP')
        main_thread.append('GET')
        self.add_result(main_thread, args, 'RESULT_NOT_PRESENT')
        main_thread.append('CLEAR')
        test_util.blocking_commit(main_thread)
        self.add_result(main_thread, args, test_util.error_string(1020))

        main_thread.push_args(foo[1])
        main_thread.append('GET_SNAPSHOT')
        self.add_result(main_thread, args, 'RESULT_NOT_PRESENT')
        main_thread.push_args(foo[1])
        main_thread.append('CLEAR')
        main_thread.append('COMMIT')
        main_thread.append('WAIT_FUTURE')
        self.add_result(main_thread, args, 'RESULT_NOT_PRESENT')
        main_thread.append('GET_COMMITTED_VERSION')
        main_thread.append('RESET')
        main_thread.append('EMPTY_STACK')

        main_thread.append('NEW_TRANSACTION')
        main_thread.push_args(1, 'bar', foo[1], foo[2], 'bar2', foo[3], 'bar3',
                              foo[4], 'bar4', foo[5], 'bar5')
        main_thread.append('SWAP')
        main_thread.append('SET')
        main_thread.append('SET')
        main_thread.append('SET')
        main_thread.append('SET')
        main_thread.append('SET_DATABASE')
        test_util.blocking_commit(main_thread)
        self.add_result(main_thread, args, 'RESULT_NOT_PRESENT')

        main_thread.append('SET_READ_VERSION')
        main_thread.push_args(foo[2])
        main_thread.append('GET')
        self.add_result(main_thread, args, 'RESULT_NOT_PRESENT')

        main_thread.append('NEW_TRANSACTION')
        main_thread.push_args('', 0, -1, '')
        main_thread.append('GET_KEY')
        self.add_result(main_thread, args, '')

        main_thread.append('NEW_TRANSACTION')
        main_thread.append('GET_READ_VERSION_SNAPSHOT')
        main_thread.push_args('random', foo[1], foo[3], 0, 1, 1)
        main_thread.append('POP')
        main_thread.append('GET_RANGE')
        self.add_result(main_thread, args,
                        fdb.tuple.pack((foo[2], 'bar2', foo[1], 'bar')))
        main_thread.push_args(foo[1], foo[3], 1, 1, 0)
        main_thread.append('GET_RANGE_SNAPSHOT')
        self.add_result(main_thread, args, fdb.tuple.pack((foo[2], 'bar2')))
        main_thread.push_args(foo[1], foo[3], 0, 0, 4)
        main_thread.append('GET_RANGE_DATABASE')
        self.add_result(main_thread, args,
                        fdb.tuple.pack((foo[1], 'bar', foo[2], 'bar2')))
        test_util.blocking_commit(main_thread)
        self.add_result(main_thread, args, 'RESULT_NOT_PRESENT')

        main_thread.push_args(foo[3], foo[5])
        main_thread.append('CLEAR_RANGE')
        main_thread.push_args(foo[1], 0, 3, '')
        main_thread.append('GET_KEY')
        self.add_result(main_thread, args, foo[5])
        main_thread.push_args(foo[1], 1, 2, '')
        main_thread.append('GET_KEY_SNAPSHOT')
        self.add_result(main_thread, args, foo[5])
        main_thread.push_args(foo[5], 0, -2, '')
        main_thread.append('GET_KEY_DATABASE')
        self.add_result(main_thread, args, foo[2])
        main_thread.push_args(self.workspace.key(), 2, 0, 2)
        main_thread.append('GET_RANGE_STARTS_WITH')
        self.add_result(main_thread, args,
                        fdb.tuple.pack((foo[1], 'bar', foo[2], 'bar2')))
        main_thread.push_args(self.workspace.key(), 4, 0, 3)
        main_thread.append('GET_RANGE_STARTS_WITH_SNAPSHOT')
        self.add_result(
            main_thread, args,
            fdb.tuple.pack((foo[1], 'bar', foo[2], 'bar2', foo[5], 'bar5')))
        main_thread.push_args(self.workspace.key(), 3, 1, -1)
        main_thread.append('GET_RANGE_STARTS_WITH_DATABASE')
        self.add_result(
            main_thread, args,
            fdb.tuple.pack((foo[5], 'bar5', foo[4], 'bar4', foo[3], 'bar3')))
        main_thread.push_args(foo[1], 0, 1, foo[1], 0, 3, 0, 0, -1, '')
        main_thread.append('GET_RANGE_SELECTOR')
        self.add_result(main_thread, args,
                        fdb.tuple.pack((foo[1], 'bar', foo[2], 'bar2')))
        main_thread.push_args(foo[1], 1, 0, foo[1], 1, 3, 0, 0, -1, '')
        main_thread.append('GET_RANGE_SELECTOR_SNAPSHOT')
        self.add_result(
            main_thread, args,
            fdb.tuple.pack((foo[1], 'bar', foo[2], 'bar2', foo[5], 'bar5')))
        main_thread.push_args(foo[1], 0, 1, foo[1], 1, 3, 0, 0, -1, '')
        main_thread.append('GET_RANGE_SELECTOR_DATABASE')
        self.add_result(
            main_thread, args,
            fdb.tuple.pack((foo[1], 'bar', foo[2], 'bar2', foo[3], 'bar3')))
        test_util.blocking_commit(main_thread)
        self.add_result(main_thread, args, 'RESULT_NOT_PRESENT')

        main_thread.push_args(self.workspace.key())
        main_thread.append('CLEAR_RANGE_STARTS_WITH')
        main_thread.push_args(self.workspace.key(), 0, 0, -1)
        main_thread.append('GET_RANGE_STARTS_WITH')
        self.add_result(main_thread, args, '')
        test_util.blocking_commit(main_thread)
        self.add_result(main_thread, args, 'RESULT_NOT_PRESENT')

        main_thread.append('SET_READ_VERSION')
        main_thread.push_args(foo[1])
        main_thread.append('GET')
        self.add_result(main_thread, args, 'bar')
        test_util.blocking_commit(main_thread)
        self.add_result(main_thread, args, 'RESULT_NOT_PRESENT')

        main_thread.push_args(foo[1], 'bar', foo[2], 'bar2', foo[3], 'bar3',
                              foo[4], 'bar4', foo[5], 'bar5')
        main_thread.append('SET')
        main_thread.append('SET')
        main_thread.append('SET')
        main_thread.append('SET')
        main_thread.append('SET')
        test_util.blocking_commit(main_thread)
        self.add_result(main_thread, args, 'RESULT_NOT_PRESENT')

        main_thread.push_args(foo[2])
        main_thread.append('CLEAR_DATABASE')
        main_thread.append('WAIT_FUTURE')
        main_thread.push_args(self.workspace.key(), 0, 0, -1)
        main_thread.append('GET_RANGE_STARTS_WITH_DATABASE')
        self.add_result(
            main_thread, args,
            fdb.tuple.pack((foo[1], 'bar', foo[3], 'bar3', foo[4], 'bar4',
                            foo[5], 'bar5')))

        main_thread.push_args(foo[3], foo[5])
        main_thread.append('CLEAR_RANGE_DATABASE')
        main_thread.append('WAIT_FUTURE')
        main_thread.push_args(self.workspace.key(), 0, 0, -1)
        main_thread.append('GET_RANGE_STARTS_WITH_DATABASE')
        self.add_result(main_thread, args,
                        fdb.tuple.pack((foo[1], 'bar', foo[5], 'bar5')))

        main_thread.push_args(self.workspace.key())
        main_thread.append('CLEAR_RANGE_STARTS_WITH_DATABASE')
        main_thread.append('WAIT_FUTURE')
        main_thread.push_args(self.workspace.key(), 0, 0, -1)
        main_thread.append('GET_RANGE_STARTS_WITH_DATABASE')
        self.add_result(main_thread, args, '')

        test_util.blocking_commit(main_thread)
        self.add_result(main_thread, args, 'RESULT_NOT_PRESENT')

        main_thread.append('NEW_TRANSACTION')
        main_thread.push_args(foo[1], foo[5], 0, 0, 0)
        main_thread.append('GET_RANGE')
        self.add_result(main_thread, args, test_util.error_string(2210))
        main_thread.push_args(foo[1], foo[5], 0, 0, 0)
        main_thread.append('GET_RANGE_DATABASE')
        self.add_result(main_thread, args, test_util.error_string(2210))

        self.append_range_test(main_thread, args, 100, 256)
        self.append_range_test(main_thread, args, 1000, 8)

        main_thread.append('EMPTY_STACK')
        tup = (0, 'foo', -1093, u'unicode\u9348test', 0xffffffff + 100,
               'bar\x00\xff')
        main_thread.push_args(*test_util.with_length(tup))
        main_thread.append('TUPLE_PACK')
        main_thread.append('DUP')
        self.add_result(main_thread, args, fdb.tuple.pack(tup))
        main_thread.append('TUPLE_UNPACK')
        for item in reversed(tup):
            self.add_result(main_thread, args, fdb.tuple.pack((item, )))

        main_thread.push_args(0xffffffff, -100)
        main_thread.append('SUB')
        main_thread.push_args(1)
        main_thread.append('TUPLE_PACK')
        self.add_result(main_thread, args, fdb.tuple.pack(
            (0xffffffff + 100, )))

        main_thread.append('EMPTY_STACK')
        main_thread.push_args(*test_util.with_length(tup))
        main_thread.append('TUPLE_RANGE')
        rng = fdb.tuple.range(tup)
        self.add_result(main_thread, args, rng.stop)
        self.add_result(main_thread, args, rng.start)

        stampKey = 'stampedXXXXXXXXXXsuffix'
        stampKeyIndex = stampKey.find('XXXXXXXXXX')
        main_thread.push_args(u'SET_VERSIONSTAMPED_KEY',
                              self.versionstamp_key(stampKey, stampKeyIndex),
                              'stampedBar')
        main_thread.append('ATOMIC_OP')
        main_thread.push_args(u'SET_VERSIONSTAMPED_VALUE', 'stampedValue',
                              self.versionstamp_value('XXXXXXXXXX'))
        main_thread.append('ATOMIC_OP')

        if self.api_version >= 520:
            stampValue = 'stampedXXXXXXXXXXsuffix'
            stampValueIndex = stampValue.find('XXXXXXXXXX')
            main_thread.push_args(
                u'SET_VERSIONSTAMPED_VALUE', 'stampedValue2',
                self.versionstamp_value(stampValue, stampValueIndex))
            main_thread.append('ATOMIC_OP')

        main_thread.push_args('suffix')
        main_thread.append('GET_VERSIONSTAMP')
        test_util.blocking_commit(main_thread)
        self.add_result(main_thread, args, 'RESULT_NOT_PRESENT')
        main_thread.push_args('stamped')
        main_thread.append('CONCAT')
        main_thread.append('CONCAT')
        main_thread.append('GET')
        self.add_result(main_thread, args, 'stampedBar')

        main_thread.push_args('stampedValue', 'suffix')
        main_thread.append('GET')
        main_thread.push_args('stamped')
        main_thread.append('CONCAT')
        main_thread.append('CONCAT')
        main_thread.append('GET')
        self.add_result(main_thread, args, 'stampedBar')

        if self.api_version >= 520:
            main_thread.push_args('stampedValue2')
            main_thread.append('GET')
            main_thread.append('GET')
            self.add_result(main_thread, args, 'stampedBar')

        main_thread.append('GET_VERSIONSTAMP')
        test_util.blocking_commit(main_thread)
        self.add_result(main_thread, args, 'RESULT_NOT_PRESENT')
        self.add_result(main_thread, args, test_util.error_string(2021))

        main_thread.push_args('sentinel')
        main_thread.append('UNIT_TESTS')
        self.add_result(main_thread, args, 'sentinel')

        if not args.no_threads:
            wait_key = 'waitKey'
            # threads = [self.thread_subspace[i] for i in range(0, 2)]
            threads = ['thread_spec%d' % i for i in range(0, 2)]
            for thread_spec in threads:
                main_thread.push_args(
                    self.workspace.pack((wait_key, thread_spec)), '')
                main_thread.append('SET_DATABASE')
                main_thread.append('WAIT_FUTURE')

            for thread_spec in threads:
                main_thread.push_args(thread_spec)
                # if len(main_thread) < args.num_ops:
                main_thread.append('START_THREAD')
                thread = test_instructions.create_thread(
                    fdb.Subspace((thread_spec, )))
                thread.append('NEW_TRANSACTION')
                thread.push_args(foo[1], foo[1], 'bar%s' % thread_spec,
                                 self.workspace.pack((wait_key, thread_spec)),
                                 self.workspace.pack((wait_key, thread_spec)))
                thread.append('GET')
                thread.append('POP')
                thread.append('SET')
                thread.append('CLEAR')
                test_util.blocking_commit(thread)
                thread.append('POP')
                thread.append('CLEAR_DATABASE')
                thread.push_args(self.workspace.pack((wait_key, )))
                thread.append('WAIT_EMPTY')

                thread.append('NEW_TRANSACTION')
                thread.push_args(foo[1])
                thread.append('GET')
                self.add_result(thread, args, 'barthread_spec0',
                                'barthread_spec1')

        main_thread.append('EMPTY_STACK')
        # if len(main_thread) > args.num_ops:
        #     main_thread[args.num_ops:] = []

        return test_instructions