Example #1
0
        public void LuaCollectsObjectsAfterReferencesAreDisposed()
        {
            // In this test we repeatedly create and destroy table references to make sure the Lua GC is able to collect
            // them.  We create a multiple of 1,000 tables since the runtime rewrites the reference table every 1,000
            // reference destructions.  This should return the runtime to exactly the same state as it was at the
            // beginning of the test.
            using (var runtime = new MemoryConstrainedLuaRuntime()) {
                using (var collect = (LuaFunction)runtime.Globals["collectgarbage"]) {
                    collect.Call().Dispose();

                    var begin = runtime.MemoryUse;

                    // Stress the GC a bit by creating and disposing tables, in batches of 100.
                    for (int i = 0; i < 1000; ++i) {
                        foreach (var t in Enumerable.Range(1, 100).Select(j => runtime.CreateTable()).ToList()) {
                            t.Dispose();
                        }
                    }

                    // Now create a whole bunch of tables all at once.
                    foreach (var t in Enumerable.Range(1, 10000).Select(j => runtime.CreateTable()).ToList()) {
                        t.Dispose();
                    }

                    collect.Call().Dispose();

                    Assert.AreEqual(begin, runtime.MemoryUse);
                }
            }
        }
Example #2
0
        public void LuaCollectsObjectsAfterReferencesAreDisposed()
        {
            // In this test we repeatedly create and destroy table references to make sure the Lua GC is able to collect
            // them.  We create a multiple of 1,000 tables since the runtime rewrites the reference table every 1,000
            // reference destructions.  This should return the runtime to exactly the same state as it was at the
            // beginning of the test.
            using (var runtime = new MemoryConstrainedLuaRuntime()) {
                using (var collect = (LuaFunction)runtime.Globals["collectgarbage"]) {
                    collect.Call().Dispose();

                    var begin = runtime.MemoryUse;

                    // Stress the GC a bit by creating and disposing tables, in batches of 100.
                    for (int i = 0; i < 1000; ++i)
                    {
                        foreach (var t in Enumerable.Range(1, 100).Select(j => runtime.CreateTable()).ToList())
                        {
                            t.Dispose();
                        }
                    }

                    // Now create a whole bunch of tables all at once.
                    foreach (var t in Enumerable.Range(1, 10000).Select(j => runtime.CreateTable()).ToList())
                    {
                        t.Dispose();
                    }

                    collect.Call().Dispose();

                    Assert.AreEqual(begin, runtime.MemoryUse);
                }
            }
        }
Example #3
0
        public void NoMemoryErrorWhileInClr()
        {
            if (LuaRuntime.LUAJIT && IntPtr.Size == 8)
            {
                Assert.Ignore();
            }

            using (var runtime = new MemoryConstrainedLuaRuntime()) {
                Action fn = () => {
                    runtime.MaxMemoryUse = runtime.MemoryUse + 1;

                    using (var x = runtime.CreateTable()) {
                        x[1] = "This is a string that is way more than one byte long.";
                    }

                    runtime.MaxMemoryUse = long.MaxValue;
                };

                using (var callback = runtime.CreateFunctionFromDelegate(fn)) {
                    runtime.Globals["callback"] = callback;
                }

                runtime.DoString("callback()").Dispose();
            }
        }
Example #4
0
        public void BasicMemoryConstraint()
        {
            using (var runtime = new MemoryConstrainedLuaRuntime()) {
                runtime.MaxMemoryUse = runtime.MemoryUse + 10 * 1024 * 1024;

                // Exponentially allocate memory.
                runtime.DoString("x = '.' while true do x = x .. x end");
            }
        }
Example #5
0
        public void BasicMemoryConstraint()
        {
            using (var runtime = new MemoryConstrainedLuaRuntime()) {
                runtime.MaxMemoryUse = runtime.MemoryUse + 10 * 1024 * 1024;

                // Exponentially allocate memory.
                runtime.DoString("x = '.' while true do x = x .. x end");
            }
        }
Example #6
0
        public void BasicMemoryConstraint()
        {
            if (LuaRuntime.LUAJIT && IntPtr.Size == 8)
            {
                Assert.Ignore();
            }

            using (var runtime = new MemoryConstrainedLuaRuntime()) {
                runtime.MaxMemoryUse = runtime.MemoryUse + 10 * 1024 * 1024;

                // Exponentially allocate memory.
                runtime.DoString("x = '.' while true do x = x .. x end");
            }
        }
Example #7
0
        public void NoMemoryErrorWhileInClr()
        {
            using (var runtime = new MemoryConstrainedLuaRuntime()) {
                Action fn = () => {
                    runtime.MaxMemoryUse = runtime.MemoryUse + 1;

                    using (var x = runtime.CreateTable()) {
                        x[1] = "This is a string that is way more than one byte long.";
                    }

                    runtime.MaxMemoryUse = long.MaxValue;
                };

                using (var callback = runtime.CreateFunctionFromDelegate(fn)) {
                    runtime.Globals["callback"] = callback;
                }

                runtime.DoString("callback()").Dispose();
            }
        }
Example #8
0
        public ScriptContext(World world, WorldRenderer worldRenderer,
                             IEnumerable <string> scripts)
        {
            runtime = new MemoryConstrainedLuaRuntime();

            World              = world;
            WorldRenderer      = worldRenderer;
            knownActorCommands = Game.modData.ObjectCreator
                                 .GetTypesImplementing <ScriptActorProperties>()
                                 .ToArray();

            ActorCommands  = new Cache <ActorInfo, Type[]>(FilterActorCommands);
            PlayerCommands = Game.modData.ObjectCreator
                             .GetTypesImplementing <ScriptPlayerProperties>()
                             .ToArray();

            runtime.DoBuffer(GlobalFileSystem.Open(Path.Combine("lua", "scriptwrapper.lua")).ReadAllText(), "scriptwrapper.lua").Dispose();
            tick = (LuaFunction)runtime.Globals["Tick"];

            // Register globals
            using (var fn = runtime.CreateFunctionFromDelegate((Action <string>)FatalError))
                runtime.Globals["FatalError"] = fn;

            runtime.Globals["MaxUserScriptInstructions"] = MaxUserScriptInstructions;

            using (var registerGlobal = (LuaFunction)runtime.Globals["RegisterSandboxedGlobal"])
            {
                using (var fn = runtime.CreateFunctionFromDelegate((Action <string>)Console.WriteLine))
                    registerGlobal.Call("print", fn).Dispose();

                // Register global tables
                var bindings = Game.modData.ObjectCreator.GetTypesImplementing <ScriptGlobal>();
                foreach (var b in bindings)
                {
                    var ctor = b.GetConstructors(BindingFlags.Public | BindingFlags.Instance).FirstOrDefault(c =>
                    {
                        var p = c.GetParameters();
                        return(p.Length == 1 && p.First().ParameterType == typeof(ScriptContext));
                    });

                    if (ctor == null)
                    {
                        throw new InvalidOperationException("{0} must define a constructor that takes a ScriptContext context parameter".F(b.Name));
                    }

                    var binding = (ScriptGlobal)ctor.Invoke(new[] { this });
                    using (var obj = binding.ToLuaValue(this))
                        registerGlobal.Call(binding.Name, obj).Dispose();
                }
            }

            // System functions do not count towards the memory limit
            runtime.MaxMemoryUse = runtime.MemoryUse + MaxUserScriptMemory;

            using (var loadScript = (LuaFunction)runtime.Globals["ExecuteSandboxedScript"])
            {
                foreach (var s in scripts)
                {
                    loadScript.Call(s, GlobalFileSystem.Open(s).ReadAllText()).Dispose();
                }
            }
        }
Example #9
0
        public ScriptContext(World world, WorldRenderer worldRenderer, IEnumerable <string> scripts)
        {
            LuaRuntime.LoadAndroidAsset += (string filename) =>
            {
                using (StreamReader sr = new StreamReader(Android.App.Application.Context.Assets.Open(Platform.ResolvePath(".", "lua", filename))))
                {
                    var luaContent = sr.ReadToEnd();
                    if (!string.IsNullOrEmpty(luaContent))
                    {
                        runtime.LoadBuffer(luaContent, filename);
                    }
                }
            };
            runtime = new MemoryConstrainedLuaRuntime();

            this.World         = world;
            this.WorldRenderer = worldRenderer;

            knownActorCommands = WarGame.ModData.ObjectCreator.GetTypesImplementing <ScriptActorProperties>().ToArray();

            ActorCommands = new Cache <ActorInfo, Type[]>(FilterActorCommands);


            var knownPlayerCommands = WarGame.ModData.ObjectCreator.GetTypesImplementing <ScriptPlayerProperties>().ToArray();

            PlayerCommands = FilterCommands(world.Map.Rules.Actors["player"], knownPlayerCommands);

            runtime.Globals["GameDir"] = Platform.SupportDir;

            //var directory = Directory.GetCurrentDirectory();
            //var directory = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
            //var directory = Android.App.Application.Context.ApplicationContext.PackageResourcePath;
            var    directory = Platform.ResolvePath(".", "lua", "scriptwrapper.lua");
            string content;

            using (StreamReader sr = new StreamReader(Android.App.Application.Context.Assets.Open(Platform.ResolvePath(".", "lua", "scriptwrapper.lua"))))
            {
                content = sr.ReadToEnd();
            }
            //runtime.DoBuffer(File.Open(directory, FileMode.Open, FileAccess.Read).ReadAllText(), "scriptwrapper.lua").Dispose();
            runtime.DoBuffer(content, "scriptwrapper.lua").Dispose();
            tick = (LuaFunction)runtime.Globals["Tick"];

            //Register globals
            using (var fatalError = runtime.CreateFunctionFromDelegate((Action <string>)FatalError))
            {
                runtime.Globals["FatalError"] = fatalError;
            }
            runtime.Globals["MaxUserScriptInstructions"] = MaxUserScriptInstructions;

            using (var registerGlobal = (LuaFunction)runtime.Globals["RegisterSandboxedGlobal"])
            {
                using (var log = runtime.CreateFunctionFromDelegate((Action <string>)LogDebugMessage))
                {
                    registerGlobal.Call("print", log).Dispose();
                }

                //Register global tables
                var bindings = WarGame.ModData.ObjectCreator.GetTypesImplementing <ScriptGlobal>();
                foreach (var bind in bindings)
                {
                    var ctor = bind.GetConstructors(BindingFlags.Public | BindingFlags.Instance).FirstOrDefault(c => {
                        var p = c.GetParameters();
                        return(p.Length == 1 && p.First().ParameterType == typeof(ScriptContext));
                    });


                    if (ctor == null)
                    {
                        throw new InvalidOperationException("{0} must define a constructor that takes a ScriptContext context parameter");
                    }

                    var binding = (ScriptGlobal)ctor.Invoke(new[] { this });
                    using (var obj = binding.ToLuaValue(this))
                        registerGlobal.Call(binding.Name, obj).Dispose();
                }
            }

            //System functions do not count towards the memory limit
            //系统函数不计入内存限制
            runtime.MaxMemoryUse = runtime.MemoryUse + MaxUserScriptMemory;
            using (var loadScript = (LuaFunction)runtime.Globals["ExecuteSandboxedScript"])
            {
                foreach (var s in scripts)
                {
                    loadScript.Call(s, world.Map.Open(s).ReadAllText()).Dispose();
                }
            }
        }