/// <summary>
        /// Writes a single test for a specific opcode variant.
        /// </summary>
        /// <param name="spec">The opcode spec.</param>
        /// <param name="variant">The opcode variant.</param>
        /// <param name="writer">The text writer to write to.</param>
        void WriteTest(X86OpcodeSpec spec, X86OpcodeVariantSpec variant, TextWriter writer)
        {
            var operandStrings = from o in variant.Operands.Cast<X86OperandSpec>()
                                 select GetOperandStrings(o.Type, o.Size, o.FixedRegister, GetRandom(variant));
            string operands = string.Join(", ", from o in operandStrings select o.Item1);

            string instruction = spec.Mnemonic.ToUpperInvariant();
            if (operandStrings.Any())
                instruction += " " + string.Join(", ", from o in operandStrings select o.Item2);

            string feedback16;
            byte[] bytes16 = GetEncodedInstruction(DataSize.Bit16, instruction, out feedback16);
            string feedback32;
            byte[] bytes32 = GetEncodedInstruction(DataSize.Bit32, instruction, out feedback32);
            string feedback64;
            byte[] bytes64 = GetEncodedInstruction(DataSize.Bit64, instruction, out feedback64);

            string methodName = spec.Mnemonic.ToUpperInvariant();
            if (variant.Operands.Any())
            {
                methodName += "_" + string.Join("_", from o in variant.Operands.Cast<X86OperandSpec>()
                                                     select IdentifierValidation.Replace(GetOperandManualName(o), ""));
            }

            writer.WriteLine(T + T + "[Test]");
            writer.WriteLine(T + T + "public void {0}()", AsValidIdentifier(methodName));
            writer.WriteLine(T + T + "{");
            writer.WriteLine(T + T + T + "var instruction = Instr.{0}({1});", AsValidIdentifier(spec.Name), operands);
            writer.WriteLine();
            writer.WriteLine(T + T + T + "// " + instruction);
            if (bytes16 != null)
                writer.WriteLine(T + T + T + "AssertInstruction(instruction, DataSize.Bit16, new byte[] { " +
                    string.Join(", ", from b in bytes16 select string.Format("0x{0:X2}", b)) + " });");
            else
                writer.WriteLine(T + T + T + "AssertInstructionFail(instruction, DataSize.Bit16);");
            if (bytes32 != null)
                writer.WriteLine(T + T + T + "AssertInstruction(instruction, DataSize.Bit32, new byte[] { " +
                    string.Join(", ", from b in bytes32 select string.Format("0x{0:X2}", b)) + " });");
            else
                writer.WriteLine(T + T + T + "AssertInstructionFail(instruction, DataSize.Bit32);");
            if (bytes64 != null)
                writer.WriteLine(T + T + T + "AssertInstruction(instruction, DataSize.Bit64, new byte[] { " +
                    string.Join(", ", from b in bytes64 select string.Format("0x{0:X2}", b)) + " });");
            else
                writer.WriteLine(T + T + T + "AssertInstructionFail(instruction, DataSize.Bit64);");

            if (bytes16 == null && bytes32 == null && bytes64 == null)
            {

                throw new ScriptException(string.Format("Assembling {0} for the tests failed with the following messages:\n" +
                    "16-bit: {1}\n32-bit: {2}\n64-bit: {3}",
                    instruction, ProcessFeedback(feedback16), ProcessFeedback(feedback32), ProcessFeedback(feedback64)));
            }

            writer.WriteLine(T + T + "}");
        }
 /// <summary>
 /// Gets a random number generator.
 /// </summary>
 /// <param name="variant">The opcode variant.</param>
 /// <returns>A <see cref="Random"/> object.</returns>
 /// <remarks>
 /// The seed of the RNG depends on the operands used by the opcode variant,
 /// but is constant across uses.
 /// </remarks>
 Random GetRandom(X86OpcodeVariantSpec variant)
 {
     string name = string.Join("_", from o in variant.Operands.Cast<X86OperandSpec>()
                                    select GetOperandManualName(o));
     return new Random(name.GetHashCode());
 }