예제 #1
0
        public void Pretty([Values(BehaviorMode.RewrittenBare, BehaviorMode.RewrittenPretty)] BehaviorMode mode)
        {
            Dec.Database.Create <StubDec>("Hello");

            var output = new Dec.Composer().ComposeXml(mode == BehaviorMode.RewrittenPretty);

            Assert.AreEqual(mode == BehaviorMode.RewrittenPretty, output.Contains("\n"));
        }
예제 #2
0
        public void NonSerialized([Values(BehaviorMode.RewrittenBare, BehaviorMode.RewrittenPretty)] BehaviorMode mode)
        {
            var ephemeral = Dec.Database.Create <NonSerializedDec>("TestDec");

            ephemeral.serializedValue    = 35;
            ephemeral.nonSerializedValue = 45;

            var    writer = new Dec.Composer();
            string data   = writer.ComposeXml(mode == BehaviorMode.RewrittenPretty);

            Assert.IsTrue(data.Contains("serializedValue"));
            Assert.IsFalse(data.Contains("nonSerializedValue"));
        }
예제 #3
0
        public void Enum([Values(BehaviorMode.RewrittenBare, BehaviorMode.RewrittenPretty)] BehaviorMode mode)
        {
            var enums = Dec.Database.Create <EnumContainerDec>("TestDec");

            enums.alph = EnumContainerDec.Enum.Alpha;
            enums.bet  = EnumContainerDec.Enum.Beta;
            enums.gam  = EnumContainerDec.Enum.Gamma;

            var    writer = new Dec.Composer();
            string data   = writer.ComposeXml(mode == BehaviorMode.RewrittenPretty);

            Assert.IsTrue(data.Contains("Alpha"));
            Assert.IsTrue(data.Contains("Beta"));
            Assert.IsTrue(data.Contains("Gamma"));

            Assert.IsFalse(data.Contains("__value"));
        }
예제 #4
0
        public void DoBehavior(BehaviorMode mode,
                               bool rewrite_expectWriteErrors     = false,
                               bool rewrite_expectParseErrors     = false,
                               bool validation_expectWriteErrors  = false,
                               Assembly[] validation_assemblies   = null,
                               Func <string, bool> errorValidator = null)
        {
            if (mode == BehaviorMode.Bare)
            {
                // we actually have nothing to do here, we're good
            }
            else if (mode == BehaviorMode.RewrittenBare || mode == BehaviorMode.RewrittenPretty)
            {
                string data = null;
                void RunComposer()
                {
                    var composer = new Dec.Composer();

                    data = composer.ComposeXml(mode == BehaviorMode.RewrittenPretty);
                }

                if (rewrite_expectWriteErrors)
                {
                    ExpectErrors(() => RunComposer(), errorValidator: errorValidator);
                }
                else
                {
                    RunComposer();
                }

                Dec.Database.Clear();

                // This is a janky hack; it resets the type caches so we also generate errors again properly.
                Dec.Config.UsingNamespaces = Dec.Config.UsingNamespaces;

                void RunParser()
                {
                    var parser = new Dec.Parser();

                    parser.AddString(data);
                    parser.Finish();
                }

                if (rewrite_expectParseErrors)
                {
                    ExpectErrors(() => RunParser(), errorValidator: errorValidator);
                }
                else
                {
                    RunParser();
                }
            }
            else if (mode == BehaviorMode.Validation)
            {
                string code = null;
                void RunComposer()
                {
                    var composer = new Dec.Composer();

                    code = composer.ComposeValidation();
                }

                if (validation_expectWriteErrors)
                {
                    ExpectErrors(() => RunComposer(), errorValidator: errorValidator);
                }
                else
                {
                    RunComposer();
                }

                var assemblies = new Assembly[] { this.GetType().Assembly };
                if (validation_assemblies != null)
                {
                    assemblies = assemblies.Concat(validation_assemblies).ToArray();
                }

                CompileAndRun($"public static void Test() {{\n{code}\n}}", assemblies, "Test", null);
            }
            else if (mode == BehaviorMode.Null)
            {
                void RunComposer()
                {
                    var composer = new Dec.Composer();

                    composer.ComposeNull();
                }

                if (rewrite_expectWriteErrors)
                {
                    // We don't really insist on an error, but we tolerate one.
                    ExpectErrors(() =>
                    {
                        RunComposer();
                        handledError = true; // good enough, just continue
                    }, errorValidator: errorValidator);
                }
                else
                {
                    RunComposer();
                }

                // may as well just stop here
                Assert.Pass();
            }
            else
            {
                Assert.IsTrue(false, "Bad case for behavior mode!");
            }
        }
예제 #5
0
        private static void Main()
        {
            Init();

            var env = new Env();

            // Generate initial composites
            for (int i = 0; i < 100; ++i)
            {
                var c = new Composite();
                c.name = Rand.NextString();

                c.type = CompositeTypeDistribution.Distribution.Choose();
                if (c.type == Composite.Type.Dec)
                {
                    c.name += "Dec";
                }

                env.types.Add(c);
            }

            // Generate parameters
            foreach (var c in env.types)
            {
                int parameterCount = Rand.WeightedDistribution();

                for (int i = 0; i < parameterCount; ++i)
                {
                    c.members.Add(new Member(env, c, Rand.NextString(), MemberTypeDistribution.Distribution.Choose()));
                }
            }

            // Generate instances
            foreach (var c in env.types)
            {
                if (c.type != Composite.Type.Dec)
                {
                    continue;
                }

                int creations = Rand.WeightedDistribution();
                for (int i = 0; i < creations; ++i)
                {
                    env.instances.Add(new Instance(env, c));
                }
            }

            string GenerateTestHarness(string testData)
            {
                string testHarness = File.ReadAllText("data/TestHarness.cs.template");

                var csComposites = new StringBuilder();

                foreach (var c in env.types)
                {
                    csComposites.Append(Util.Indent(c.WriteCsharpDefinition(), 2));
                }

                var types    = string.Join(", ", env.types.Select(c => $"typeof({c.name})"));
                var filename = "data/Fuzzgen.FuzzgenTest.xml";

                return(testHarness
                       .Replace("<<COMPOSITES>>", csComposites.ToString())
                       .Replace("<<TYPES>>", types)
                       .Replace("<<FILENAME>>", $"\"{filename}\"")
                       .Replace("<<TESTS>>", testData));
            }

            string testCode = GenerateTestHarness("");

            string xmlCode;

            // Output xml
            {
                var sb = new StringBuilder();
                sb.AppendLine("<Decs>");

                foreach (var i in env.instances)
                {
                    sb.AppendLine(Util.Indent(i.WriteXmlDec()));
                }

                sb.AppendLine("</Decs>");

                xmlCode = sb.ToString();
            }

            // This is a bit janky; we want to use Dec features when doing generation, but now we need to blow it away to generate the .cs code
            // So I guess maybe it would be nice to have non-global state right now :V

            Dec.Database.Clear();

            var bootstrapAssembly = DecUtilLib.Compilation.Compile(testCode, new System.Reflection.Assembly[] { });

            bootstrapAssembly.GetType("DecTest.Harness").GetMethod("Setup").Invoke(null, null);

            var parser = new Dec.Parser();

            parser.AddString(xmlCode);
            parser.Finish();

            var composer = new Dec.Composer();
            var tests    = composer.ComposeValidation();

            string finalCode = GenerateTestHarness(tests);

            string path = $"../../test/data/golden/parser/{System.DateTimeOffset.Now:yyyyMMddhhmmss}";

            System.IO.Directory.CreateDirectory(path);

            DecUtilLib.Compress.WriteToFile(System.IO.Path.Combine(path, "Harness.cs"), finalCode);
            DecUtilLib.Compress.WriteToFile(System.IO.Path.Combine(path, "data.xml"), xmlCode);
        }