public void SortEnums()
        {
            var rand   = new Random(42);
            var values = Enumerable.Range(0, 128).OrderBy(_ => rand.Next()).ToArray();
            var sorted = StringEnum.SortValues(values, true);

            Array.Sort(values);

            Assert.Equal(values, sorted.Select(kvp => (int)kvp.Key));

            var empty  = new KeyValuePair <ulong, string> [0];
            var buffer = new byte[256];

            fixed(byte *ptr = buffer)
            {
                Assert.Null(StringEnum.GenerateIndexedLookup(empty, ptr, buffer.Length));
                Assert.Null(StringEnum.GenerateIndexedLookup(sorted, ptr, buffer.Length));

                Assert.Null(StringEnum.GenerateSortedLookup(empty, ptr, buffer.Length));
                Assert.Null(StringEnum.GenerateSortedLookup(sorted, ptr, buffer.Length));

                Assert.Null(StringEnum.GenerateVerboseLookup(empty, ptr, buffer.Length));
                Assert.Null(StringEnum.GenerateVerboseLookup(sorted, ptr, buffer.Length));
            }
        }
        void ApproveEnumCommon <T>(string label, StringBuilder sb, bool expectGenerated, GenerateLookup generateLookup, FindString findString)
        {
            var buffer = new byte[1024];

            for (int i = 0; i < buffer.Length; i++)
            {
                buffer[i] = 255;
            }
            var values = StringEnum.SortValues(typeof(T));

            fixed(byte *ptr = buffer)
            {
                var lookup = generateLookup(values, ptr, buffer.Length);

                if (!expectGenerated)
                {
                    Assert.False(lookup.HasValue, "lookup must not have been generated");
                    return;
                }

                Assert.True(lookup.HasValue, "lookup must have been generated");
                var stringStart = (int)(lookup.Value.StringStart - ptr);


                sb.AppendLine("# " + label + " " + SchemaTest.HumanName(typeof(T)));
                sb.AppendLine();
                sb.AppendLine(String.Format("GetLookupType: {0}", StringEnum.GetLookupType(values)));
                sb.AppendLine(String.Format("Values count: {0}", values.Length));
                sb.AppendLine(String.Format("Max value: {0}", values.LastOrDefault().Key));
                sb.AppendLine();
                sb.AppendLine("## Lookups");
                Util.Hex.Dump(sb, buffer.Take(stringStart));
                sb.AppendLine();
                sb.AppendLine();
                sb.AppendLine("## Strings");
                Util.Hex.Dump(sb, buffer.Skip(stringStart).Take((int)lookup.Value.StringLength));


                bool signed = false;

                switch (Type.GetTypeCode(typeof(T)))
                {
                case TypeCode.SByte:
                case TypeCode.Int16:
                case TypeCode.Int32:
                case TypeCode.Int64:
                    signed = true;
                    break;
                }

                var chars = new char[64];

                foreach (T dow in Enum.GetValues(typeof(T)))
                {
                    byte *str;
                    int   len;
                    ulong enumValue = signed ? (ulong)Convert.ToInt64(dow) : Convert.ToUInt64(dow);
                    findString(lookup.Value, enumValue, out str, out len);
                    Assert.True(str != null, "string must not be null");
                    var dowString = dow.ToString();
                    Assert.Equal(Encoding.UTF8.GetByteCount(dowString), len);

                    string actualString;
                    fixed(char *ch = chars)
                    {
                        var strLen = Encoding.UTF8.GetChars(str, len, ch, chars.Length);

                        actualString = new string(ch, 0, strLen);
                    }

                    Assert.Equal(dowString, actualString);
                }
            }
        }