public void WhenAssemblyPropertyContainer_ReflectionJsonSchemaGenerator_ReturnsAValidJson()
        {
            string assemblyFilePath = string.Empty;
            string errors           = string.Empty;

            string code = @"
                using System.Collections.Generic;
                using Unity.Properties;
                
                namespace Unity.Properties.TestCases {

                public partial class HelloWorld : IPropertyContainer
                {
                    public static IPropertyBag bag { get; } = new PropertyBag(new List<IProperty> {}.ToArray());

                    public IVersionStorage VersionStorage { get; }
                    public IPropertyBag PropertyBag => bag;

                    private MyContainer m_MyContainer;
                    private static readonly ContainerProperty<HelloWorld, MyContainer> s_MyContainer =
                        new ContainerProperty<HelloWorld, MyContainer>(
                            ""MyContainer"",
                        c => c.m_MyContainer,
                        (c, v) => c.m_MyContainer = v);

                    public class MyContainer : IPropertyContainer
                    {
                        public static IPropertyBag bag { get; } = new PropertyBag(new List<IProperty> {}.ToArray());

                        public IVersionStorage VersionStorage { get; }
                        public IPropertyBag PropertyBag => bag;
                    }
                };
                
                }
            ";

            Assert.IsTrue(CompileTestUtils.TryCompileToFile(code, out assemblyFilePath, out errors), errors);

            using (new FileDisposer(assemblyFilePath))
            {
                var result = JsonSchema.FromJson(
                    JsonSchema.ToJson(
                        new JsonSchema()
                {
                    PropertyTypeNodes = ReflectionPropertyTree.Read(assemblyFilePath)
                }
                        )
                    );

                var containers = new List <PropertyTypeNode>();

                VisitContainer(result.PropertyTypeNodes, c => { containers.Add(c); });

                Assert.True(containers.Count == 2);
                Assert.True(containers[0].TypeName == "HelloWorld");
                Assert.True(containers[1].TypeName == "MyContainer");
            }
        }
        public void WhenBlankPropertyContainer_CecilGenerationBackend_ReturnsAnEmptyContainerList()
        {
            var cecilBackend = new CecilGenerationBackend();

            string assemblyFilePath;
            string errors;

            const string code = @"
            using System.Collections.Generic;
            using Unity.Properties;
            public class HelloWorld : IPropertyContainer
            {
                public IVersionStorage VersionStorage => PassthroughVersionStorage.Instance;

                private static PropertyBag sBag = new PropertyBag(IntValueProperty);
                public IPropertyBag PropertyBag => sBag;
            };
            ";

            Assert.IsTrue(
                CompileTestUtils.TryCompileToFile(
                    code, out assemblyFilePath, out errors)
                , errors);

            var types = new List <string>();
            {
                var assembly = Assembly.LoadFrom(assemblyFilePath);

                // var container = (IPropertyContainer) Activator.CreateInstance(type);
                // Assert.IsNotNull(container);

                var modules = assembly.Modules.ToList();
                foreach (var module in modules)
                {
                    types.AddRange(module.GetTypes().Select(t => t.Name).ToList());
                }

                var nodes = ReflectionPropertyTree.Read(assemblyFilePath);
                Assert.NotZero(nodes.Count);

                cecilBackend.AssemblyFilePath = assemblyFilePath;
                cecilBackend.GenerateContainer(nodes.First());

                Assert.NotNull(cecilBackend.GeneratedContainerTypeDefinition);

                Assert.NotNull(
                    cecilBackend.GeneratedContainerTypeDefinition.Module.Types.FirstOrDefault(
                        t => t.Name == "HelloWorldPropertyContainer"));
            }
        }
        public void WhenAssemblyContainsPropertyContainer_ReflectionJsonSchemaGenerator_ReturnsAValidJson()
        {
            string assemblyFilePath = string.Empty;
            string errors           = string.Empty;

            string code = @"
                using System.Collections.Generic;
                using Unity.Properties;
                
                namespace Unity.Properties.TestCases {

                public partial class HelloWorld : IPropertyContainer
                {
                    public static IPropertyBag bag { get; } = new PropertyBag(new List<IProperty> {}.ToArray());

                    public IVersionStorage VersionStorage { get; }
                    public IPropertyBag PropertyBag => bag;

                    public class Foo
                    {
                        public int Data;
                        public List<float> Floats = new List<float>();
                    }
                    public Foo foo { get; } = new Foo();
                };
                }
            ";

            Assert.IsTrue(CompileTestUtils.TryCompileToFile(code, out assemblyFilePath, out errors), errors);

            using (new FileDisposer(assemblyFilePath))
            {
                var result = JsonSchema.FromJson(
                    JsonSchema.ToJson(
                        new JsonSchema()
                {
                    PropertyTypeNodes = ReflectionPropertyTree.Read(assemblyFilePath)
                }
                        )
                    );

                var containers = new List <PropertyTypeNode>();

                VisitContainer(result.PropertyTypeNodes, c => { containers.Add(c); });

                Assert.True(containers.Count == 1);
                Assert.True(containers[0].TypeName == "HelloWorld");
            }
        }
        private static void TestFullCircle(string json, string rootPropertyContainerTypeName)
        {
            // json -> csharp

            var g = new CSharpGenerationBackend();

            g.Generate(JsonSchema.FromJson(json).PropertyTypeNodes);

            // csharp -> assembly

            var assemblyFilePath = string.Empty;
            var errors           = string.Empty;

            Assert.IsTrue(
                CompileTestUtils.TryCompileToFile(
                    g.Code.ToString(),
                    out assemblyFilePath,
                    out errors));

            // assembly -> property visitor

            var assembly = Assembly.LoadFile(assemblyFilePath);

            Assert.NotNull(assembly);

            var type      = assembly.GetType(rootPropertyContainerTypeName);
            var container = (IPropertyContainer)Activator.CreateInstance(type);
            var visitor   = new PropertyLeafVisitor();

            container.Visit(visitor);

            Assert.NotZero(visitor.Properties.Count);

            //  -> json

            var generatedJson = JsonSchema.ToJson(
                new JsonSchema()
            {
                PropertyTypeNodes = ReflectionPropertyTree.Read(assemblyFilePath)
            }
                );

            Assert.NotNull(generatedJson.Length);
        }
        public string TestContainsPropertyContainerNestedInsidePlainStructOrClass(string parentType)
        {
            string assemblyFilePath = string.Empty;
            string errors           = string.Empty;

            string code = $@"
                using System.Collections.Generic;
                using Unity.Properties;
                public {parentType} HelloWorld
                {{
                    public class Foo : IPropertyContainer
                    {{
                        public static IPropertyBag bag {{ get; }} = new PropertyBag(new List<IProperty> {{}}.ToArray());

                        public IVersionStorage VersionStorage {{ get; }}
                        public IPropertyBag PropertyBag => bag;
                    }}
                    public Foo foo {{ get; }}
                }};
            ";

            Assert.IsTrue(CompileTestUtils.TryCompileToFile(code, out assemblyFilePath, out errors), errors);

            using (new FileDisposer(assemblyFilePath))
            {
                var result = JsonSchema.FromJson(
                    JsonSchema.ToJson(
                        new JsonSchema()
                {
                    PropertyTypeNodes = ReflectionPropertyTree.Read(assemblyFilePath)
                }
                        )
                    );

                var containers = new List <PropertyTypeNode>();

                VisitContainer(result.PropertyTypeNodes, c => { containers.Add(c); });

                Assert.True(containers.Count == 1);

                return(containers[0].TypeName);
            }
        }
        public void WhenAssemblyDoesNotContainPropertyContainers_ReflectionJsonSchemaGenerator_ReturnsAnEmptyJson()
        {
            string assemblyFilePath = string.Empty;
            string errors           = string.Empty;

            string code = @"
                using System.Collections.Generic;
                public partial class HelloWorld
                {
                    public class Foo
                    {
                        public int Data;
                        public List<float> Floats = new List<float>();
                    }
                    public Foo foo { get; } = new Foo();
                };
            ";

            Assert.IsTrue(CompileTestUtils.TryCompileToFile(code, out assemblyFilePath, out errors), errors);

            using (new FileDisposer(assemblyFilePath))
            {
                var result = JsonSchema.FromJson(
                    JsonSchema.ToJson(
                        new JsonSchema()
                {
                    PropertyTypeNodes = ReflectionPropertyTree.Read(assemblyFilePath)
                }
                        )
                    );

                var containers = new List <PropertyTypeNode>();

                VisitContainer(result.PropertyTypeNodes, c => { containers.Add(c); });

                Assert.Zero(containers.Count);
            }
        }
        public void WhenPropertyIsPublic_ReflectionJsonSchemaGenerator_SetsThePropertyAsPublicInTypeTree()
        {
            string assemblyFilePath = string.Empty;
            string errors           = string.Empty;

            string code = @"
                using System.Collections.Generic;
                using Unity.Properties;
                
                namespace Unity.Properties.TestCases {

                public partial class HelloWorld : IPropertyContainer
                {
                    public static IPropertyBag bag { get; } = new PropertyBag(new List<IProperty> {}.ToArray());

                    public IVersionStorage VersionStorage { get; }
                    public IPropertyBag PropertyBag => bag;

                    private int m_MyContainer;
                    public static readonly Property<HelloWorld, int> s_MyField =
                        new Property<HelloWorld, int>(
                            ""MyField"",
                            c => c.m_MyContainer,
                            (c, v) => c.m_MyContainer = v);
                    };
                }
            ";

            Assert.IsTrue(CompileTestUtils.TryCompileToFile(code, out assemblyFilePath, out errors), errors);

            using (new FileDisposer(assemblyFilePath))
            {
                var result = ReflectionPropertyTree.Read(assemblyFilePath);
                Assert.True(result[0].Properties[0].IsPublicProperty);
            }
        }
        public void WhenAssemblyContainsNestedPropertyContainers_ReflectionJsonSchemaGenerator_ReturnsAValidJson()
        {
            string assemblyFilePath = string.Empty;
            string errors           = string.Empty;

            string code = @"
                using System.Collections.Generic;
                using Unity.Properties;

                namespace Unity.Properties.TestCases {

                public partial class HelloWorld : IPropertyContainer
                {
                    public static IPropertyBag bag { get; } = new PropertyBag(new List<IProperty> {}.ToArray());

                    public IVersionStorage VersionStorage { get; }
                    public IPropertyBag PropertyBag => bag;

                    public class Foo : IPropertyContainer
                    {
                        public static IPropertyBag bag { get; } = new PropertyBag(new List<IProperty> {}.ToArray());

                        public IVersionStorage VersionStorage { get; }
                        public IPropertyBag PropertyBag => bag;

                        public class Bar : IPropertyContainer
                        {
                            public static IPropertyBag bag { get; } = new PropertyBag(new List<IProperty> {}.ToArray());

                            public IVersionStorage VersionStorage { get; }
                            public IPropertyBag PropertyBag => bag;
                        }
                    }
                };

                }
            ";

            Assert.IsTrue(CompileTestUtils.TryCompileToFile(code, out assemblyFilePath, out errors), errors);

            using (new FileDisposer(assemblyFilePath))
            {
                var result = JsonSchema.FromJson(
                    JsonSchema.ToJson(
                        new JsonSchema()
                {
                    PropertyTypeNodes = ReflectionPropertyTree.Read(assemblyFilePath)
                }
                        )
                    );

                var containers = new List <PropertyTypeNode>();

                VisitContainer(result.PropertyTypeNodes, c => { containers.Add(c); });

                var containerNames = containers.Select(c => c.TypeName).ToList();

                Assert.AreEqual(
                    new System.Collections.Generic.List <string>
                {
                    "HelloWorld", "Foo", "Bar"
                },
                    containerNames
                    );
            }
        }