Exemplo n.º 1
0
def test_round_trip(spoiler: bool, layout: dict, default_echoes_preset,
                    mocker):
    # Setup
    random_uuid = uuid.uuid4()
    mocker.patch("uuid.uuid4", return_value=random_uuid)

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

    params = GeneratorParameters(
        seed_number=1000,
        spoiler=spoiler,
        presets=[preset],
    )

    # Run
    after = GeneratorParameters.from_bytes(params.as_bytes)

    # Assert
    assert params == after
Exemplo n.º 2
0
def test_decode(default_echoes_preset, mocker, extra_data):
    # We're mocking the database hash to avoid breaking tests every single time we change the database
    mocker.patch("randovania.layout.generator_parameters._game_db_hash",
                 autospec=True,
                 return_value=120)

    random_uuid = uuid.uuid4()
    mocker.patch("uuid.uuid4", return_value=random_uuid)

    # 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 = b'$\x00\x00\x1fD\x00\x000\xff\xbc\x00'
    if extra_data:
        encoded += b"="

    expected = GeneratorParameters(
        seed_number=1000,
        spoiler=True,
        presets=[
            dataclasses.replace(
                default_echoes_preset,
                name="{} Custom".format(default_echoes_preset.game.long_name),
                description="A customized preset.",
                uuid=random_uuid,
                base_preset_uuid=default_echoes_preset.uuid,
            )
        ],
    )

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

    # Run
    if extra_data:
        expectation = pytest.raises(ValueError)
    else:
        expectation = contextlib.nullcontext()

    with expectation:
        link = GeneratorParameters.from_bytes(encoded)

    # Assert
    if not extra_data:
        assert link == expected
Exemplo n.º 3
0
    def from_str(cls, param: str) -> "Permalink":
        encoded_param = param.encode("utf-8")
        encoded_param += b"=" * ((4 - len(encoded_param)) % 4)

        try:
            b = base64.b64decode(encoded_param, altchars=b'-_', validate=True)
            if len(b) < 4:
                raise ValueError("String too short")

            cls.validate_version(b)
            data = PermalinkBinary.parse(b).value

        except construct.core.TerminatedError:
            raise ValueError("Extra text at the end")

        except construct.core.StreamError:
            raise ValueError("Missing text at the end")

        except construct.core.ChecksumError:
            raise ValueError("Incorrect checksum")

        except (binascii.Error, bitstruct.Error,
                construct.ConstructError) as e:
            raise ValueError(str(e))

        try:
            return Permalink(
                parameters=GeneratorParameters.from_bytes(
                    data.generator_params),
                seed_hash=data.seed_hash,
                randovania_version=data.randovania_version,
            )
        except Exception as e:
            games = generator_parameters.try_decode_game_list(
                data.generator_params)

            if data.randovania_version != cls.current_randovania_version():
                msg = "Detected version {}, current version is {}".format(
                    data.randovania_version.hex(),
                    cls.current_randovania_version().hex())
            else:
                msg = f"Error decoding parameters - {e}"
            raise UnsupportedPermalink(msg, data.seed_hash,
                                       data.randovania_version, games) from e
Exemplo n.º 4
0
def test_decode_mock_other(encoded, num_players, mocker):
    # We're mocking the database hash to avoid breaking tests every single time we change the database
    mocker.patch("randovania.layout.generator_parameters._game_db_hash",
                 autospec=True,
                 return_value=120)

    preset = MagicMock()
    preset.game = RandovaniaGame.METROID_PRIME_ECHOES

    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 = GeneratorParameters(
        seed_number=1000,
        spoiler=True,
        presets=[preset] * 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_bytes == b""
    # print(expected.as_bytes)

    # Run
    round_trip = expected.as_bytes
    link = GeneratorParameters.from_bytes(encoded)

    # Assert
    assert link == expected
    assert round_trip == encoded
    mock_preset_unpack.assert_has_calls([
        call(ANY, {
            "manager": ANY,
            "game": RandovaniaGame.METROID_PRIME_ECHOES
        }) for _ in range(num_players)
    ])