#[cfg(feature = "test-utils")]
#[cfg(test)]
mod tests {
    mod fp_tiny_tests {
        // p = 3*2**11 - 1
        const MODULUS: [u64; 1] = [6143];
        fp2::define_fp_core!(typename = FpTiny, modulus = MODULUS,);
        fp2::define_fp2_from_type!(typename = FpTinyExt, base_field = FpTiny,);
        fp2::define_fp_tests!(FpTiny);
        fp2::define_fp2_tests!(FpTinyExt, MODULUS, 2);
    }

    mod fp_small_tests {
        // p = 2^61 - 1
        const MODULUS: [u64; 1] = [0x1FFFFFFFFFFFFFFF];
        fp2::define_fp_core!(typename = FpSml, modulus = MODULUS,);
        fp2::define_fp2_from_type!(typename = FpSmlExt, base_field = FpSml,);
        fp2::define_fp_tests!(FpSml);
        fp2::define_fp2_tests!(FpSmlExt, MODULUS, 4);
    }
    // Random prime with no nice properties for Montgomery friendliness
    mod fp_ugly_tests {
        // Field modulus
        const MODULUS: [u64; 2] = [0x5A0E852097C48043, 0x7EA2A3A646684E9D];

        // Contents are opaque, all functions are constant-time.
        // Macro input generated with scripts/gen_fp.sage
        fp2::define_fp_core!(typename = FpUgly, modulus = MODULUS,);
        fp2::define_fp_tests!(FpUgly);

        // FpUglyExt: a finite field element GF(p^2) with modulus x^2 + 1.
        // Contents are opaque, all functions are constant-time.
        // Macro input generated with scripts/gen_fp.sage
        fp2::define_fp2_from_modulus!(typename = FpUglyExt, base_typename = Fp, modulus = MODULUS,);
        fp2::define_fp2_tests!(FpUglyExt, MODULUS, 1);

        #[test]
        fn check_sum_of_products_flag() {
            assert!(!FpUgly::SUM_OF_PRODUCTS_ADDITIONAL_SUB);
        }
    }

    mod fp127_no_sop_tests {
        // Field modulus
        const MODULUS: [u64; 2] = [0xFFFFFFFFFFFFFFFF, 0x7FFFFFFFFFFFFFFF];

        fp2::define_fp_core!(typename = Fp127, modulus = MODULUS,);
        fp2::define_fp_tests!(Fp127);

        fp2::define_fp2_from_type!(
            typename = Fp127Ext,
            base_field = Fp127,
            use_sum_of_products = false,
        );
        fp2::define_fp2_tests!(Fp127Ext, MODULUS, 2);

        #[test]
        #[should_panic(expected = "not implemented")]
        fn test_any_panic() {
            let a = Fp127Ext::ONE;
            let b = Fp127Ext::ONE;
            Fp127Ext::mul_sum_of_products(&a, &b);
        }
    }

    mod fp127_tests {
        // Field modulus
        const MODULUS: [u64; 2] = [0xFFFFFFFFFFFFFFFF, 0x7FFFFFFFFFFFFFFF];

        // Fp139: a finite field element GF(p) with p = 3 mod 4.
        // Contents are opaque, all functions are constant-time.
        // Macro input generated with scripts/gen_fp.sage
        // p = 2^127 - 1
        fp2::define_fp_core!(typename = Fp127, modulus = MODULUS,);
        fp2::define_fp_tests!(Fp127);

        // Fp127Ext: a finite field element GF(p^2) with modulus x^2 + 1.
        // Contents are opaque, all functions are constant-time.
        // Macro input generated with scripts/gen_fp.sage
        fp2::define_fp2_from_modulus!(typename = Fp127Ext, base_typename = Fp, modulus = MODULUS,);
        fp2::define_fp2_tests!(Fp127Ext, MODULUS, 2);

        #[test]
        fn check_sum_of_products_flag() {
            assert!(!Fp127::SUM_OF_PRODUCTS_ADDITIONAL_SUB);
        }
    }

    mod fp251_tests {
        // Field modulus
        const MODULUS: [u64; 4] = [
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0x04FFFFFFFFFFFFFF,
        ];

        // Fp251: a finite field element GF(p) with p = 3 mod 4.
        // Contents are opaque, all functions are constant-time.
        // Macro input generated with scripts/gen_fp.sage
        // p = 5*2^248 - 1
        fp2::define_fp_core!(typename = Fp251, modulus = MODULUS,);

        // Fp251Ext: a finite field element GF(p^2) with modulus x^2 + 1.
        // Contents are opaque, all functions are constant-time.
        // Macro input generated with scripts/gen_fp.sage
        fp2::define_fp2_from_type!(typename = Fp251Ext, base_field = Fp251,);

        fp2::define_fp_tests!(Fp251);
        fp2::define_fp2_tests!(Fp251Ext, MODULUS, 5);

        #[test]
        fn check_sum_of_products_flag() {
            assert!(!Fp251::SUM_OF_PRODUCTS_ADDITIONAL_SUB);
        }
    }

    mod fp383_tests {
        // Field modulus
        const MODULUS: [u64; 6] = [
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0x40FFFFFFFFFFFFFF,
        ];

        // Fp383: a finite field element GF(p) with p = 3 mod 4.
        // Contents are opaque, all functions are constant-time.
        // Macro input generated with scripts/gen_fp.sage
        // p = 65 * 2**376 - 1
        fp2::define_fp_core!(typename = Fp383, modulus = MODULUS,);

        // Fp383Ext: a finite field element GF(p^2) with modulus x^2 + 1.
        // Contents are opaque, all functions are constant-time.
        // Macro input generated with scripts/gen_fp.sage
        fp2::define_fp2_from_type!(typename = Fp383Ext, base_field = Fp383,);

        // For define_fp2_tests we must include a u64 nqr_re such that
        // nqr_re + i is a non-quadratic residue in Fp2
        fp2::define_fp_tests!(Fp383);
        fp2::define_fp2_tests!(Fp383Ext, MODULUS, 6);

        #[test]
        fn check_sum_of_products_flag() {
            assert!(!Fp383::SUM_OF_PRODUCTS_ADDITIONAL_SUB);
        }
    }

    mod fp434_tests {
        // NIST lvl 1 SIKE prime: p = 2^216 * 3^137 - 1
        // Fp434Ext: a finite field element GF(p^2) with modulus x^2 + 1.
        const MODULUS: [u64; 7] = [
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFDC1767AE2FFFFFF,
            0x7BC65C783158AEA3,
            0x6CFC5FD681C52056,
            0x0002341F27177344,
        ];

        fp2::define_fp2_from_modulus!(
            typename = Fp434Ext,
            base_typename = Fp434,
            modulus = MODULUS,
        );

        // For define_fp2_tests we must include a u64 nqr_re such that
        // nqr_re + i is a non-quadratic residue in Fp2
        fp2::define_fp_tests!(Fp434);
        fp2::define_fp2_tests!(Fp434Ext, MODULUS, 2);

        #[test]
        fn check_sum_of_products_flag() {
            assert!(!Fp434::SUM_OF_PRODUCTS_ADDITIONAL_SUB);
        }
    }

    // This modulus is very close to the value R = 2^(64 * 14) and so
    // needs an extra conditional subtraction in the sum of products
    // method.
    mod fp896_tests {
        const MODULUS: [u64; 14] = [
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xA7FFFFFFFFFFFFFF,
        ];
        // Fp896: a finite field element GF(p) with p = 3 mod 4.
        // Contents are opaque, all functions are constant-time.
        fp2::define_fp_core!(typename = Fp896, modulus = MODULUS,);

        // Fp896Ext: a finite field element GF(p^2) with modulus x^2 + 1.
        // Contents are opaque, all functions are constant-time.
        fp2::define_fp2_from_type!(typename = Fp896Ext, base_field = Fp896,);

        fp2::define_fp_tests!(Fp896);
        fp2::define_fp2_tests!(Fp896Ext, MODULUS, 2);

        #[test]
        fn check_sum_of_products_flag() {
            assert!(Fp896::SUM_OF_PRODUCTS_ADDITIONAL_SUB);
        }
    }

    // When the word length is larger than 20, we slightly modify set_mul
    mod fp1554_tests {
        static MODULUS: [u64; 25] = [
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0x0000000000047FFF,
        ];
        // Fp896: a finite field element GF(p) with p = 3 mod 4.
        // Contents are opaque, all functions are constant-time.
        fp2::define_fp_core!(typename = Fp1554, modulus = MODULUS,);
        fp2::define_fp_tests!(Fp1554);

        #[test]
        fn check_sum_of_products_flag() {
            assert!(!Fp1554::SUM_OF_PRODUCTS_ADDITIONAL_SUB);
        }
    }

    mod fp648_tests {
        static MODULUS: [u64; 11] = [
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xFFFFFFFFFFFFFFFF,
            0xAB4C1EC4E9A4421A,
            0xA1A751E0FF03064A,
            0x5C5381A82432B77B,
            0x74F54CC513A36773,
            0x152EF0C01F75CCD4,
            0xA53054622A07450C,
            0xF81DCB46FD3F8B4D,
            0x00000000000000DA,
        ];

        // Fp648: a finite field element GF(p) with p = 3 mod 4.
        // Contents are opaque, all functions are constant-time.
        fp2::define_fp_core!(typename = Fp648, modulus = MODULUS,);

        // Fp648Ext: a finite field element GF(p^2) with modulus x^2 + 1.
        // Contents are opaque, all functions are constant-time.
        fp2::define_fp2_from_type!(typename = Fp648Ext, base_field = Fp648,);

        fp2::define_fp_tests!(Fp648);
        fp2::define_fp2_tests!(Fp648Ext, MODULUS, 6);
    }
}
