def test_invalid_input_vocab_size(self):
        r"""Raise exception when input `vocab_size` is invalid."""
        msg1 = (
            'Must raise `TypeError` or `ValueError` when input `vocab_size` '
            'is invalid.')
        msg2 = 'Inconsistent error message.'
        examples = (False, 0, 0.0, 1.0, math.nan, -math.nan,
                    math.inf, -math.inf, 0j, 1j, '', b'', (), [], {}, set(),
                    object(), lambda x: x, type, None, NotImplemented, ...)

        for invalid_input in examples:
            with self.assertRaises((TypeError, ValueError),
                                   msg=msg1) as ctx_man:
                GRUModel(d_emb=1,
                         d_hid=1,
                         dropout=0.1,
                         num_linear_layers=1,
                         num_rnn_layers=1,
                         pad_token_id=0,
                         vocab_size=invalid_input)

            if isinstance(ctx_man.exception, TypeError):
                self.assertEqual(ctx_man.exception.args[0],
                                 '`vocab_size` must be an instance of `int`.',
                                 msg=msg2)
            else:
                self.assertEqual(
                    ctx_man.exception.args[0],
                    '`vocab_size` must be bigger than or equal to `1`.',
                    msg=msg2)
    def setUp(self):
        r"""Setup hyperparameters and construct `GRUModel`."""
        self.model_objs = []
        cls = self.__class__
        for d_emb in cls.d_emb_range:
            for d_hid in cls.d_hid_range:
                for dropout in cls.dropout_range:
                    for num_linear_layers in cls.num_linear_layers_range:
                        for num_rnn_layers in cls.num_rnn_layers_range:
                            for pad_token_id in cls.pad_token_id_range:
                                for vocab_size in cls.vocab_size_range:
                                    # skip invalid construct.
                                    if vocab_size <= pad_token_id:
                                        continue

                                    model = GRUModel(
                                        d_emb=d_emb,
                                        d_hid=d_hid,
                                        dropout=dropout,
                                        num_linear_layers=num_linear_layers,
                                        num_rnn_layers=num_rnn_layers,
                                        pad_token_id=pad_token_id,
                                        vocab_size=vocab_size)
                                    self.model_objs.append({
                                        'd_emb':
                                        d_emb,
                                        'd_hid':
                                        d_hid,
                                        'dropout':
                                        dropout,
                                        'model':
                                        model,
                                        'num_linear_layers':
                                        num_linear_layers,
                                        'num_rnn_layers':
                                        num_rnn_layers,
                                        'pad_token_id':
                                        pad_token_id,
                                        'vocab_size':
                                        vocab_size,
                                    })
def gru_model(
        tknzr: BaseTknzr,
        d_emb: int,
        d_hid: int,
        n_hid_lyr: int,
        n_pre_hid_lyr: int,
        n_post_hid_lyr: int,
        p_emb: float,
        p_hid: float,
) -> GRUModel:
    r"""Example ``GRUModel`` instance."""
    return GRUModel(
        d_emb=d_emb,
        d_hid=d_hid,
        n_hid_lyr=n_hid_lyr,
        n_pre_hid_lyr=n_pre_hid_lyr,
        n_post_hid_lyr=n_post_hid_lyr,
        p_emb=p_emb,
        p_hid=p_hid,
        tknzr=tknzr,
    )
    def test_invalid_input_pad_token_id_and_vocab_size(self):
        r"""Raise `ValueError` when input `vocab_size <= pad_token_id`."""
        msg1 = (
            'Must raise `ValueError` when input `vocab_size <= pad_token_id`.')
        msg2 = 'Inconsistent error message.'
        examples = ((2, 1), (3, 2), (4, 3), (10, 1))

        for pad_token_id, vocab_size in examples:
            with self.assertRaises(ValueError, msg=msg1) as ctx_man:
                GRUModel(
                    d_emb=1,
                    d_hid=1,
                    dropout=0.1,
                    num_linear_layers=1,
                    num_rnn_layers=1,
                    pad_token_id=pad_token_id,
                    vocab_size=vocab_size,
                )

            self.assertEqual(
                ctx_man.exception.args[0],
                '`pad_token_id` must be smaller than `vocab_size`.',
                msg=msg2)
def test_save_and_load(tknzr: BaseTknzr, ckpt: int, exp_name: str,
                       clean_model):
    r"""Saved parameters are the same as loaded."""
    model = GRUModel(
        d_emb=1,
        d_hid=1,
        n_hid_lyr=1,
        n_pre_hid_lyr=1,
        n_post_hid_lyr=1,
        p_emb=0.5,
        p_hid=0.5,
        tknzr=tknzr,
    )

    # Save model parameters.
    model.save(
        ckpt=ckpt,
        exp_name=exp_name,
    )

    # Load model parameters.
    load_model = GRUModel.load(
        ckpt=ckpt,
        exp_name=exp_name,
        d_emb=1,
        d_hid=1,
        n_hid_lyr=1,
        n_pre_hid_lyr=1,
        n_post_hid_lyr=1,
        p_emb=0.5,
        p_hid=0.5,
        tknzr=tknzr,
    )

    # Ensure parameters are the same.
    for p_1, p_2 in zip(model.parameters(), load_model.parameters()):
        assert torch.equal(p_1, p_2)