def test_decode(mock_dictionary_byte_hash: MagicMock):
    mock_dictionary_byte_hash.return_value = 120
    # We're mocking the database hash to avoid breaking tests every single time we change the database

    # This test should break whenever we change how permalinks are created
    # When this happens, we must bump the permalink version and change the tests
    encoded = "gAAAfReLCAAC4wAAAOaANg=="

    expected = Permalink(
        seed_number=1000,
        spoiler=True,
        patcher_configuration=PatcherConfiguration(
            menu_mod=True,
            warp_to_start=False,
        ),
        layout_configuration=LayoutConfiguration.from_params(
            trick_level_configuration=TrickLevelConfiguration(
                LayoutTrickLevel.HARD),
            elevators=LayoutElevators.RANDOMIZED,
        ),
    )

    # Uncomment this line to quickly get the new encoded permalink
    # assert expected.as_str == ""
    # print(expected.as_str)

    # Run
    link = Permalink.from_str(encoded)

    # Assert
    assert link == expected
def test_create_permalink_logic(mock_print: MagicMock, ):
    # Setup
    args = MagicMock()
    args.trick_level = LayoutTrickLevel.HARD.value
    args.major_items_mode = False
    args.sky_temple_keys = LayoutSkyTempleKeyMode.ALL_BOSSES.value
    args.skip_item_loss = True
    args.seed = 15000
    args.menu_mod = False
    args.warp_to_start = False

    # Run
    randovania.cli.commands.create_permalink.create_permalink_logic(args)

    # Assert
    permalink = Permalink(
        seed_number=args.seed,
        spoiler=True,
        patcher_configuration=PatcherConfiguration(
            menu_mod=args.menu_mod,
            warp_to_start=args.warp_to_start,
        ),
        layout_configuration=LayoutConfiguration.from_params(
            trick_level_configuration=TrickLevelConfiguration(
                LayoutTrickLevel.HARD),
            sky_temple_keys=LayoutSkyTempleKeyMode.ALL_BOSSES,
            elevators=LayoutElevators.VANILLA,
            starting_location=StartingLocation.default(),
        ),
    )

    # Assert
    mock_print.assert_called_once_with(permalink)
Example #3
0
def test_distribute_command_logic(mock_generate_list: MagicMock, ):
    # Setup
    args = MagicMock()
    args.trick_level = LayoutTrickLevel.HARD.value
    args.major_items_mode = False
    args.sky_temple_keys = LayoutSkyTempleKeyMode.ALL_BOSSES.value
    args.skip_item_loss = True
    args.seed = 15000
    args.output_file = "asdfasdf/qwerqwerqwer/zxcvzxcv.json"

    # Run
    echoes.distribute_command_logic(args)

    # Assert
    mock_generate_list.assert_called_once_with(permalink=Permalink(
        seed_number=args.seed,
        spoiler=True,
        patcher_configuration=PatcherConfiguration.default(),
        layout_configuration=LayoutConfiguration.from_params(
            trick_level=LayoutTrickLevel.HARD,
            sky_temple_keys=LayoutSkyTempleKeyMode.ALL_BOSSES,
            elevators=LayoutRandomizedFlag.VANILLA,
            pickup_quantities={},
            starting_location=StartingLocation.default(),
            starting_resources=StartingResources.from_non_custom_configuration(
                StartingResourcesConfiguration.VANILLA_ITEM_LOSS_DISABLED),
        ),
    ),
                                               status_update=ANY)

    save_file_mock: MagicMock = mock_generate_list.return_value.save_to_file
    save_file_mock.assert_called_once_with(Path(args.output_file))
Example #4
0
def batch_distribute_helper(
    base_permalink: Permalink,
    seed_number: int,
    timeout: int,
    validate: bool,
    output_dir: Path,
) -> float:
    permalink = Permalink(
        seed_number=seed_number,
        spoiler=True,
        patcher_configuration=base_permalink.patcher_configuration,
        layout_configuration=base_permalink.layout_configuration,
    )

    start_time = time.perf_counter()
    description = generator.generate_description(
        permalink=permalink,
        status_update=None,
        validate_after_generation=validate,
        timeout=timeout)
    delta_time = time.perf_counter() - start_time

    description.save_to_file(output_dir.joinpath(
        "{}.json".format(seed_number)))
    return delta_time
Example #5
0
    def from_json_dict(cls, json_dict: dict) -> "LayoutDescription":
        json_dict = migrate_description(json_dict)

        has_spoiler = "game_modifications" in json_dict
        if not has_spoiler:
            raise ValueError(
                "Unable to read details of seed log with spoiler disabled")

        permalink = Permalink(
            seed_number=json_dict["info"]["seed"],
            spoiler=has_spoiler,
            presets={
                index: VersionedPreset(preset).get_preset()
                for index, preset in enumerate(json_dict["info"]["presets"])
            },
        )

        return LayoutDescription(
            version=json_dict["info"]["version"],
            permalink=permalink,
            all_patches=game_patches_serializer.decode(
                json_dict["game_modifications"], {
                    index: preset.configuration
                    for index, preset in permalink.presets.items()
                }),
            item_order=json_dict["item_order"],
        )
    def from_json_dict(cls, json_dict: dict) -> "LayoutDescription":
        version = json_dict.get("schema_version")
        if version != cls.schema_version():
            raise RuntimeError("Unsupported log file version '{}'. Expected {}.".format(version, cls.schema_version()))

        has_spoiler = "game_modifications" in json_dict
        if not has_spoiler:
            raise ValueError("Unable to read details of seed log with spoiler disabled")

        permalink = Permalink(
            seed_number=json_dict["info"]["seed"],
            spoiler=has_spoiler,
            presets={
                index: VersionedPreset(preset).get_preset()
                for index, preset in enumerate(json_dict["info"]["presets"])
            },
        )

        return LayoutDescription(
            version=json_dict["info"]["version"],
            permalink=permalink,
            all_patches=game_patches_serializer.decode(
                json_dict["game_modifications"], {
                    index: preset.layout_configuration
                    for index, preset in permalink.presets.items()
                }),
            item_order=json_dict["item_order"],
        )
Example #7
0
def batch_distribute_helper(
    base_permalink,
    seed_number: int,
    timeout: int,
    validate: bool,
    output_dir: Path,
) -> float:
    from randovania.generator import generator
    from randovania.layout.permalink import Permalink

    permalink = Permalink(
        seed_number=seed_number,
        spoiler=True,
        presets=typing.cast(Permalink, base_permalink).presets,
    )

    start_time = time.perf_counter()
    description = asyncio.run(
        generator.generate_and_validate_description(
            permalink=permalink,
            status_update=None,
            validate_after_generation=validate,
            timeout=timeout,
            attempts=0,
        ))
    delta_time = time.perf_counter() - start_time

    description.save_to_file(
        output_dir.joinpath("{}.{}".format(seed_number,
                                           description.file_extension())))
    return delta_time
Example #8
0
def _create_test_layout_description(
        configuration: LayoutConfiguration,
        pickup_mapping: Iterable[int],
) -> LayoutDescription:
    """
    Creates a LayoutDescription for the given configuration, with the patches being for the given pickup_mapping
    :param configuration:
    :param pickup_mapping:
    :return:
    """
    game = data_reader.decode_data(configuration.game_data)
    pickup_database = game.pickup_database

    return LayoutDescription(
        version=VERSION,
        permalink=Permalink(
            seed_number=0,
            spoiler=True,
            patcher_configuration=PatcherConfiguration.default(),
            layout_configuration=configuration,
        ),
        patches=GamePatches.with_game(game).assign_new_pickups([
            (PickupIndex(i), pickup_database.original_pickup_mapping[PickupIndex(new_index)])
            for i, new_index in enumerate(pickup_mapping)
        ]),
        solver_path=())
def test_round_trip_generated_patches(echoes_game_data, preset_manager):
    # Setup
    preset = dataclasses.replace(
        preset_manager.default_preset,
        layout_configuration=dataclasses.replace(
            preset_manager.default_preset.layout_configuration,
            trick_level_configuration=TrickLevelConfiguration(
                global_level=LayoutTrickLevel.MINIMAL_RESTRICTIONS,
                specific_levels={},
            )))

    all_patches = generator._async_create_description(
        permalink=Permalink(
            seed_number=1000,
            spoiler=True,
            presets={0: preset},
        ),
        status_update=lambda x: None,
    ).all_patches

    # Run
    encoded = game_patches_serializer.serialize(all_patches,
                                                {0: echoes_game_data})
    decoded = game_patches_serializer.decode(encoded,
                                             {0: preset.layout_configuration})

    # Assert
    assert all_patches == decoded
Example #10
0
def test_decode_mock_other(encoded, num_players, mocker):
    preset = MagicMock()

    def read_values(decoder: BitPackDecoder, metadata):
        decoder.decode(100, 100)
        return preset

    mock_preset_unpack: MagicMock = mocker.patch(
        "randovania.layout.preset.Preset.bit_pack_unpack",
        side_effect=read_values)

    expected = Permalink(
        seed_number=1000,
        spoiler=True,
        presets={i: preset
                 for i in range(num_players)},
    )
    preset.bit_pack_encode.return_value = [(0, 100), (5, 100)]

    # Uncomment this line to quickly get the new encoded permalink
    # assert expected.as_base64_str == ""
    # print(expected.as_base64_str)

    # Run
    round_trip = expected.as_base64_str
    link = Permalink.from_str(encoded)

    # Assert
    assert link == expected
    assert round_trip == encoded
    mock_preset_unpack.assert_called_once_with(ANY, {"manager": ANY})
Example #11
0
def distribute_command_logic(args):
    debug._DEBUG_LEVEL = args.debug

    def status_update(s):
        pass

    seed_number = args.seed
    if seed_number is None:
        seed_number = random.randint(0, 2**31)

    print("Using seed: {}".format(seed_number))
    permalink = Permalink(
        seed_number=seed_number,
        spoiler=True,
        patcher_configuration=PatcherConfiguration.default(),
        layout_configuration=get_layout_configuration_from_args(args),
    )

    before = time.perf_counter()
    layout_description = generator.generate_list(permalink=permalink,
                                                 status_update=status_update)
    after = time.perf_counter()
    print("Took {} seconds. Hash: {}".format(
        after - before,
        hash(tuple(layout_description.pickup_assignment.items()))))
    layout_description.save_to_file(Path(args.output_file))
Example #12
0
def test_round_trip(spoiler: bool, layout: dict, default_preset, mocker):
    # Setup
    random_uuid = uuid.uuid4()
    mocker.patch("uuid.uuid4", return_value=random_uuid)

    preset = Preset(
        name="{} Custom".format(default_preset.name),
        description="A customized preset.",
        uuid=random_uuid,
        base_preset_uuid=default_preset.uuid,
        game=default_preset.game,
        configuration=dataclasses.replace(default_preset.configuration,
                                          **layout),
    )

    link = Permalink(
        seed_number=1000,
        spoiler=spoiler,
        presets={0: preset},
    )

    # Run
    after = Permalink.from_str(link.as_base64_str)

    # Assert
    assert link == after
def test_round_trip_generated_patches(echoes_game_data, default_preset):
    # Setup
    preset = dataclasses.replace(
        default_preset,
        base_preset_name=default_preset.name,
        configuration=dataclasses.replace(
            default_preset.configuration,
            trick_level=TrickLevelConfiguration(
                minimal_logic=True,
                specific_levels={},
                game=RandovaniaGame.PRIME2,
            )
        )
    )

    all_patches = generator._async_create_description(
        permalink=Permalink(
            seed_number=1000,
            spoiler=True,
            presets={0: preset},
        ),
        status_update=lambda x: None,
        attempts=0,
    ).all_patches

    # Run
    encoded = game_patches_serializer.serialize(all_patches, {0: echoes_game_data})
    decoded = game_patches_serializer.decode(encoded, {0: preset.configuration})

    # Assert
    assert all_patches == decoded
Example #14
0
def test_decode_mock_other(
    mock_packer_unpack: MagicMock,
    mock_layout_unpack: MagicMock,
):

    encoded = "gAAAfRggLQ=="
    patcher_configuration = mock_packer_unpack.return_value
    layout_configuration = mock_layout_unpack.return_value

    expected = Permalink(
        seed_number=1000,
        spoiler=True,
        patcher_configuration=patcher_configuration,
        layout_configuration=layout_configuration,
    )
    patcher_configuration.bit_pack_encode.return_value = []
    layout_configuration.bit_pack_encode.return_value = []
    mock_layout_unpack.return_value.game_data = {"test": True}

    # Uncomment this line to quickly get the new encoded permalink
    # assert expected.as_str == ""
    # print(expected.as_str)

    # Run
    link = Permalink.from_str(encoded)
    round_trip = expected.as_str

    # Assert
    assert link == expected
    assert encoded == round_trip
    mock_packer_unpack.assert_called_once()
    mock_layout_unpack.assert_called_once()
    patcher_configuration.bit_pack_encode.assert_called_once_with({})
    layout_configuration.bit_pack_encode.assert_called_once_with({})
Example #15
0
def test_batch_distribute_helper(
    mock_perf_counter: MagicMock,
    mock_generate_description: MagicMock,
):
    # Setup
    base_permalink = MagicMock()
    seed_number = 5000
    validate = MagicMock()
    output_dir = MagicMock()

    expected_permalink = Permalink(
        seed_number=seed_number,
        spoiler=True,
        patcher_configuration=base_permalink.patcher_configuration,
        layout_configuration=base_permalink.layout_configuration,
    )

    mock_perf_counter.side_effect = [1000, 5000]

    # Run
    delta_time = batch_distribute.batch_distribute_helper(
        base_permalink, seed_number, validate, output_dir)

    # Assert
    mock_generate_description.assert_called_once_with(expected_permalink, None,
                                                      validate)
    assert delta_time == 4000
    output_dir.joinpath.assert_called_once_with("{}.json".format(seed_number))
    mock_generate_description.return_value.save_to_file.assert_called_once_with(
        output_dir.joinpath.return_value)
async def test_generate_game(window, mocker, preset_manager):
    mock_generate_layout: MagicMock = mocker.patch("randovania.interface_common.simplified_patcher.generate_layout")
    mock_randint: MagicMock = mocker.patch("random.randint", return_value=5000)

    spoiler = True
    game_session = MagicMock()
    game_session.presets = [preset_manager.default_preset, preset_manager.default_preset]

    window._game_session = game_session
    window._upload_layout_description = AsyncMock()
    window._admin_global_action = AsyncMock()

    # Run
    await window.generate_game(spoiler)

    # Assert
    mock_randint.assert_called_once_with(0, 2 ** 31)
    mock_generate_layout.assert_called_once_with(
        progress_update=ANY,
        permalink=Permalink(
            seed_number=mock_randint.return_value,
            spoiler=spoiler,
            presets={
                0: preset_manager.default_preset.get_preset(),
                1: preset_manager.default_preset.get_preset(),
            },
        ),
        options=window._options
    )
    window._upload_layout_description.assert_awaited_once_with(mock_generate_layout.return_value)
def test_round_trip_generated_patches(echoes_game_data):
    # Setup
    configuration = LayoutConfiguration.from_params(
        trick_level_configuration=TrickLevelConfiguration(
            global_level=LayoutTrickLevel.MINIMAL_RESTRICTIONS,
            specific_levels={},
        ))

    patches = generator._create_randomized_patches(
        permalink=Permalink(
            seed_number=1000,
            spoiler=True,
            patcher_configuration=PatcherConfiguration.default(),
            layout_configuration=configuration,
        ),
        game=data_reader.decode_data(echoes_game_data),
        status_update=lambda x: None,
    )

    # Run
    encoded = game_patches_serializer.serialize(patches, echoes_game_data)
    decoded = game_patches_serializer.decode(encoded, configuration)

    # Assert
    assert patches == decoded
Example #18
0
 def _generate_new_seed(self, spoiler: bool):
     self.generate_seed_from_permalink(
         Permalink(
             seed_number=random.randint(0, 2**31),
             spoiler=spoiler,
             preset=self._current_preset_data,
         ))
async def test_round_trip_generated_patches(default_preset):
    # Setup
    preset = dataclasses.replace(
        default_preset,
        uuid=uuid.UUID('b41fde84-1f57-4b79-8cd6-3e5a78077fa6'),
        base_preset_uuid=default_preset.uuid,
        configuration=dataclasses.replace(default_preset.configuration,
                                          trick_level=TrickLevelConfiguration(
                                              minimal_logic=True,
                                              specific_levels={},
                                              game=default_preset.game,
                                          )))

    description = await generator._create_description(
        permalink=Permalink(
            seed_number=1000,
            spoiler=True,
            presets={0: preset},
        ),
        status_update=lambda x: None,
        attempts=0,
    )
    all_patches = description.all_patches

    # Run
    encoded = game_patches_serializer.serialize(all_patches,
                                                {0: default_preset.game})
    decoded = game_patches_serializer.decode(encoded,
                                             {0: preset.configuration})

    # Assert
    assert all_patches == decoded
def test_batch_distribute_helper(
    mock_perf_counter: MagicMock,
    mock_generate_description: MagicMock,
):
    # Setup
    base_permalink = MagicMock()
    seed_number = 5000
    validate = MagicMock()
    output_dir = MagicMock()
    timeout = 67

    expected_permalink = Permalink(
        seed_number=seed_number,
        spoiler=True,
        presets=base_permalink.presets,
    )

    mock_perf_counter.side_effect = [1000, 5000]

    # Run
    delta_time = batch_distribute.batch_distribute_helper(
        base_permalink, seed_number, timeout, validate, output_dir)

    # Assert
    mock_generate_description.assert_called_once_with(
        permalink=expected_permalink,
        status_update=None,
        validate_after_generation=validate,
        timeout=timeout)
    assert delta_time == 4000
    output_dir.joinpath.assert_called_once_with("{}.json".format(seed_number))
    mock_generate_description.return_value.save_to_file.assert_called_once_with(
        output_dir.joinpath.return_value)
Example #21
0
def test_round_trip_generated_patches(echoes_game_data, preset_manager):
    # Setup
    preset = dataclasses.replace(
        preset_manager.default_preset,
        layout_configuration=dataclasses.replace(
            preset_manager.default_preset.layout_configuration,
            trick_level_configuration=TrickLevelConfiguration(
                global_level=LayoutTrickLevel.MINIMAL_RESTRICTIONS,
                specific_levels={},
            )
        )
    )

    patches = generator._create_randomized_patches(
        permalink=Permalink(
            seed_number=1000,
            spoiler=True,
            preset=preset,
        ),
        game=data_reader.decode_data(echoes_game_data),
        status_update=lambda x: None,
    )

    # Run
    encoded = game_patches_serializer.serialize(patches, echoes_game_data)
    decoded = game_patches_serializer.decode(encoded, preset.layout_configuration)

    # Assert
    assert patches == decoded
def test_apply_layout(
    mock_ensure_no_menu_mod: MagicMock,
    mock_create_pak_backups: MagicMock,
    mock_add_menu_mod_to_files: MagicMock,
    mock_modern_api: MagicMock,
    mock_create_progress_update_from_successive_messages: MagicMock,
    mock_save_to_file: MagicMock,
    include_menu_mod: bool,
    has_backup_path: bool,
):
    # Setup
    cosmetic_patches = MagicMock()
    description = LayoutDescription(
        version=randovania.VERSION,
        permalink=Permalink(seed_number=1,
                            spoiler=False,
                            patcher_configuration=PatcherConfiguration(
                                menu_mod=include_menu_mod,
                                warp_to_start=MagicMock(),
                            ),
                            layout_configuration=MagicMock()),
        patches=MagicMock(),
        solver_path=(),
    )

    game_root = MagicMock(spec=Path())
    backup_files_path = MagicMock() if has_backup_path else None
    progress_update = MagicMock()
    status_update = mock_create_progress_update_from_successive_messages.return_value

    # Run
    claris_randomizer.apply_layout(description, cosmetic_patches,
                                   backup_files_path, progress_update,
                                   game_root)

    # Assert
    mock_create_progress_update_from_successive_messages.assert_called_once_with(
        progress_update, 400 if include_menu_mod else 100)
    mock_ensure_no_menu_mod.assert_called_once_with(game_root,
                                                    backup_files_path,
                                                    status_update)
    if has_backup_path:
        mock_create_pak_backups.assert_called_once_with(
            game_root, backup_files_path, status_update)
    else:
        mock_create_pak_backups.assert_not_called()
    game_root.joinpath.assert_called_once_with("files", "randovania.json")
    mock_save_to_file.assert_called_once_with(description,
                                              game_root.joinpath.return_value)

    mock_modern_api.assert_called_once_with(game_root, status_update,
                                            description, cosmetic_patches)

    if include_menu_mod:
        mock_add_menu_mod_to_files.assert_called_once_with(
            game_root, status_update)
    else:
        mock_add_menu_mod_to_files.assert_not_called()
Example #23
0
    def permalink(self) -> Optional[Permalink]:
        if self.seed_number is None:
            return None

        return Permalink(
            seed_number=self.seed_number,
            spoiler=self.create_spoiler,
            patcher_configuration=self.patcher_configuration,
            layout_configuration=self.layout_configuration,
        )
Example #24
0
    async def _create_permalink(args_) -> Permalink:
        from randovania.interface_common.preset_manager import PresetManager

        preset_manager = PresetManager(None)
        preset = preset_manager.included_preset_with(RandovaniaGame(args_.game), args_.preset_name).get_preset()

        return Permalink(
            args_.seed_number,
            spoiler=True,
            presets={i: preset for i in range(args_.player_count)},
        )
Example #25
0
def test_encode(fake_generator_parameters):
    # Setup
    link = Permalink(parameters=fake_generator_parameters,
                     seed_hash=None,
                     randovania_version=b"0123")

    # Run
    encoded = link.as_base64_str

    # Assert
    assert encoded == "DX4wMTIzAx6sOvRw"
Example #26
0
    def _generate_new_seed(self, spoiler: bool):
        preset = self._current_preset_data
        num_players = self.window.num_players_spin_box.value()

        self.generate_seed_from_permalink(
            Permalink(
                seed_number=random.randint(0, 2**31),
                spoiler=spoiler,
                presets={i: preset.get_preset()
                         for i in range(num_players)},
            ))
Example #27
0
async def _create_permalink(args) -> Permalink:
    from randovania.interface_common import persistence
    preset_manager = PresetManager(persistence.user_data_dir())
    await preset_manager.load_user_presets()
    preset = preset_manager.preset_for_name(args.preset_name).get_preset()

    return Permalink(
        args.seed_number,
        spoiler=True,
        presets={i: preset
                 for i in range(args.player_count)},
    )
def run_bootstrap(preset: Preset):
    game = data_reader.decode_data(preset.configuration.game_data)
    permalink = Permalink(
        seed_number=15000,
        spoiler=True,
        presets={0: preset},
    )
    patches = base_patches_factory.create_base_patches(preset.configuration,
                                                       Random(15000), game,
                                                       False)
    _, state = logic_bootstrap(preset.configuration, game, patches)

    return game, state, permalink
Example #29
0
def test_create_patches(
    mock_random: MagicMock,
    mock_calculate_item_pool: MagicMock,
    mock_create_base_patches: MagicMock,
    mock_retcon_playthrough_filler: MagicMock,
    mock_indices_for_unassigned_pickups: MagicMock,
):
    # Setup
    seed_number: int = 91319
    game = default_prime2_game_description()
    status_update: Union[MagicMock, Callable[[str], None]] = MagicMock()
    configuration = LayoutConfiguration.from_params(
        trick_level=LayoutTrickLevel.NO_TRICKS,
        sky_temple_keys=LayoutSkyTempleKeyMode.FULLY_RANDOM,
        elevators=LayoutRandomizedFlag.VANILLA,
        pickup_quantities={},
        starting_location=StartingLocation.default(),
        starting_resources=StartingResources.from_item_loss(False),
    )
    permalink = Permalink(
        seed_number=seed_number,
        spoiler=True,
        patcher_configuration=PatcherConfiguration.default(),
        layout_configuration=configuration,
    )
    mock_calculate_item_pool.return_value = list(
        sorted(game.pickup_database.original_pickup_mapping.values()))
    mock_create_base_patches.return_value.starting_location = game.starting_location
    mock_create_base_patches.return_value.custom_initial_items = None

    filler_patches = mock_retcon_playthrough_filler.return_value

    # Run
    result = generator._create_patches(permalink, game, status_update)

    # Assert
    mock_random.assert_called_once_with(permalink.as_str)
    mock_calculate_item_pool.assert_called_once_with(permalink, game)

    mock_create_base_patches.assert_called_once_with(mock_random.return_value,
                                                     game, permalink, ANY)

    mock_retcon_playthrough_filler.assert_called_once_with(
        ANY, ANY, ANY, mock_random.return_value, status_update)

    mock_indices_for_unassigned_pickups.assert_called_once_with(
        mock_random.return_value, game, filler_patches.pickup_assignment, ANY)
    filler_patches.assign_new_pickups.assert_called_once_with(
        mock_indices_for_unassigned_pickups.return_value)

    assert result == filler_patches.assign_new_pickups.return_value
Example #30
0
def test_round_trip(spoiler: bool, patcher: PatcherConfiguration,
                    layout: LayoutConfiguration):
    # Setup
    link = Permalink(
        seed_number=1000,
        spoiler=spoiler,
        patcher_configuration=patcher,
        layout_configuration=layout,
    )

    # Run
    after = Permalink.from_str(link.as_str)

    # Assert
    assert link == after