gcmole

-- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-- This is main driver for gcmole tool. See README for more details.
-- Usage: CLANG_BIN=clang-bin-dir lua tools/gcmole/gcmole.lua [arm|ia32|x64]
local DIR = arg[0]:match("^(.+)/[^/]+$")
local FLAGS = {
   -- Do not build gcsuspects file and reuse previously generated one.
   reuse_gcsuspects = false;
   -- Print commands to console before executing them.
   verbose = false;
   -- Perform dead variable analysis (generates many false positives).
   -- TODO add some sort of whiteliste to filter out false positives.
   dead_vars = false;
   -- When building gcsuspects whitelist certain functions as if they
   -- can be causing GC. Currently used to reduce number of false
   -- positives in dead variables analysis. See TODO for WHITELIST
   -- below.
   whitelist = true;
}
local ARGS = {}
for i = 1, #arg do
   local flag = arg[i]:match "^%-%-([%w_-]+)$"
   if flag then
      local no, real_flag = flag:match "^(no)([%w_-]+)$"
      if real_flag then flag = real_flag end
      flag = flag:gsub("%-", "_")
      if FLAGS[flag] ~= nil then
         FLAGS[flag] = (no ~= "no")
      else
         error("Unknown flag: " .. flag)
      end
   else
      table.insert(ARGS, arg[i])
   end
end
local ARCHS = ARGS[1] and { ARGS[1] } or { 'ia32', 'arm', 'x64' }
local io = require "io"
local os = require "os"
function log(...)
   io.stderr:write(string.format(...))
   io.stderr:write "\n"
end
-------------------------------------------------------------------------------
-- Clang invocation
local CLANG_BIN = os.getenv "CLANG_BIN"
if not CLANG_BIN or CLANG_BIN == "" then
   error "CLANG_BIN not set"
end
local function MakeClangCommandLine(plugin, plugin_args, triple, arch_define)
   if plugin_args then
     for i = 1, #plugin_args do
        plugin_args[i] = "-plugin-arg-" .. plugin .. " " .. plugin_args[i]
     end
     plugin_args = " " .. table.concat(plugin_args, " ")
   end
   return CLANG_BIN .. "/clang -cc1 -load " .. DIR .. "/libgcmole.so"
      .. " -plugin "  .. plugin
      .. (plugin_args or "")
      .. " -triple " .. triple
      .. " -D" .. arch_define
      .. " -DENABLE_DEBUGGER_SUPPORT"
      .. " -Isrc"
end
function InvokeClangPluginForEachFile(filenames, cfg, func)
   local cmd_line = MakeClangCommandLine(cfg.plugin,
                                         cfg.plugin_args,
                                         cfg.triple,
                                         cfg.arch_define)
   for _, filename in ipairs(filenames) do
      log("-- %s", filename)
      local action = cmd_line .. " src/" .. filename .. " 2>&1"
      if FLAGS.verbose then print('popen ', action) end
      local pipe = io.popen(action)
      func(filename, pipe:lines())
      pipe:close()
   end
end
-------------------------------------------------------------------------------
-- SConscript parsing
local function ParseSConscript()
   local f = assert(io.open("src/SConscript"), "failed to open SConscript")
   local sconscript = f:read('*a')
   f:close()
   local SOURCES = sconscript:match "SOURCES = {(.-)}";
   local sources = {}
   for condition, list in
      SOURCES:gmatch "'([^']-)': Split%(\"\"\"(.-)\"\"\"%)" do
      local files = {}
      for file in list:gmatch "[^%s]+" do table.insert(files, file) end
      sources[condition] = files
   end
   for condition, list in SOURCES:gmatch "'([^']-)': %[(.-)%]" do
      local files = {}
      for file in list:gmatch "'([^']-)'" do table.insert(files, file) end
      sources[condition] = files
   end
   return sources
end
local function EvaluateCondition(cond, props)
   if cond == 'all' then return true end
   local p, v = cond:match "(%w+):(%w+)"
   assert(p and v, "failed to parse condition: " .. cond)
   assert(props[p] ~= nil, "undefined configuration property: " .. p)
   return props[p] == v
end
local function BuildFileList(sources, props)
   local list = {}
   for condition, files in pairs(sources) do
      if EvaluateCondition(condition, props) then
         for i = 1, #files do table.insert(list, files[i]) end
      end
   end
   return list
end
local sources = ParseSConscript()
local function FilesForArch(arch)
   return BuildFileList(sources, { os = 'linux',
                                   arch = arch,
                                   mode = 'debug',
                                   simulator = ''})
end
local mtConfig = {}
mtConfig.__index = mtConfig
local function config (t) return setmetatable(t, mtConfig) end
function mtConfig:extend(t)
   local e = {}
   for k, v in pairs(self) do e[k] = v end
   for k, v in pairs(t) do e[k] = v end
   return config(e)
end
local ARCHITECTURES = {
   ia32 = config { triple = "i586-unknown-linux",
                   arch_define = "V8_TARGET_ARCH_IA32" },
   arm = config { triple = "i586-unknown-linux",
                  arch_define = "V8_TARGET_ARCH_ARM" },
   x64 = config { triple = "x86_64-unknown-linux",
                  arch_define = "V8_TARGET_ARCH_X64" }
}
-------------------------------------------------------------------------------
-- GCSuspects Generation
local gc, gc_caused, funcs
local WHITELIST = {
   -- The following functions call CEntryStub which is always present.
   "MacroAssembler.*CallExternalReference",
   "MacroAssembler.*CallRuntime",
   "CompileCallLoadPropertyWithInterceptor",
   "CallIC.*GenerateMiss",
   -- DirectCEntryStub is a special stub used on ARM.
   -- It is pinned and always present.
   "DirectCEntryStub.*GenerateCall",
   -- TODO GCMole currently is sensitive enough to understand that certain
   --      functions only cause GC and return Failure simulataneously.
   --      Callsites of such functions are safe as long as they are properly
   --      check return value and propagate the Failure to the caller.
   --      It should be possible to extend GCMole to understand this.
   "Heap.*AllocateFunctionPrototype"
};
local function AddCause(name, cause)
   local t = gc_caused[name]
   if not t then
      t = {}
      gc_caused[name] = t
   end
   table.insert(t, cause)
end
local function resolve(name)
   local f = funcs[name]
   if not f then
      f = {}
      funcs[name] = f
      if name:match "Collect.*Garbage" then
         gc[name] = true
         AddCause(name, "<GC>")
      end
      if FLAGS.whitelist then
         for i = 1, #WHITELIST do
            if name:match(WHITELIST[i]) then
               gc[name] = false
            end
         end
      end
   end
    return f
end
local function parse (filename, lines)
   local scope
   for funcname in lines do
      if funcname:sub(1, 1) ~= '\t' then
         resolve(funcname)
         scope = funcname
      else
         local name = funcname:sub(2)
         resolve(name)[scope] = true
      end
   end
end
local function propagate ()
   log "** Propagating GC information"
   local function mark(from, callers)
      for caller, _ in pairs(callers) do
         if gc[caller] == nil then
            gc[caller] = true
            mark(caller, funcs[caller])
         end
         AddCause(caller, from)
      end
   end
   for funcname, callers in pairs(funcs) do
      if gc[funcname] then mark(funcname, callers) end
   end
end
local function GenerateGCSuspects(arch, files, cfg)
   -- Reset the global state.
   gc, gc_caused, funcs = {}, {}, {}
   log ("** Building GC Suspects for %s", arch)
   InvokeClangPluginForEachFile (files,
                                 cfg:extend { plugin = "dump-callees" },
                                 parse)
   propagate()
   local out = assert(io.open("gcsuspects", "w"))
   for name, value in pairs(gc) do if value then out:write (name, '\n') end end
   out:close()
   local out = assert(io.open("gccauses", "w"))
   out:write "GC = {"
   for name, causes in pairs(gc_caused) do
      out:write("['", name, "'] = {")
      for i = 1, #causes do out:write ("'", causes[i], "';") end
      out:write("};\n")
   end
   out:write "}"
   out:close()
   log ("** GCSuspects generated for %s", arch)
end
--------------------------------------------------------------------------------
-- Analysis
local function CheckCorrectnessForArch(arch)
   local files = FilesForArch(arch)
   local cfg = ARCHITECTURES[arch]
   if not FLAGS.reuse_gcsuspects then
      GenerateGCSuspects(arch, files, cfg)
   end
   local processed_files = 0
   local errors_found = false
   local function SearchForErrors(filename, lines)
      processed_files = processed_files + 1
      for l in lines do
         errors_found = errors_found or
            l:match "^[^:]+:%d+:%d+:" or
            l:match "error" or
            l:match "warning"
         print(l)
      end
   end
   log("** Searching for evaluation order problems%s for %s",
       FLAGS.dead_vars and " and dead variables" or "",
       arch)
   local plugin_args
   if FLAGS.dead_vars then plugin_args = { "--dead-vars" } end
   InvokeClangPluginForEachFile(files,
                                cfg:extend { plugin = "find-problems",
                                             plugin_args = plugin_args },
                                SearchForErrors)
   log("** Done processing %d files. %s",
       processed_files,
       errors_found and "Errors found" or "No errors found")
   return errors_found
end
local function SafeCheckCorrectnessForArch(arch)
   local status, errors = pcall(CheckCorrectnessForArch, arch)
   if not status then
      print(string.format("There was an error: %s", errors))
      errors = true
   end
   return errors
end
local errors = false
for _, arch in ipairs(ARCHS) do
   if not ARCHITECTURES[arch] then
      error ("Unknown arch: " .. arch)
   end
   errors = SafeCheckCorrectnessForArch(arch, report) or errors
end
os.exit(errors and 1 or 0)


gccause

-- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-- This is an auxiliary tool that reads gccauses file generated by
-- gcmole.lua and prints tree of the calls that can potentially cause a GC
-- inside a given function.
--
-- Usage: lua tools/gcmole/gccause.lua <function-name-pattern>
--
assert(loadfile "gccauses")()
local P = ...
local T = {}
local function TrackCause(name, lvl)
   io.write(("  "):rep(lvl or 0), name, "\n")
   if GC[name] then
      local causes = GC[name]
      for i = 1, #causes do
	 local f = causes[i]
	 if not T[f] then
	    T[f] = true
	    TrackCause(f, (lvl or 0) + 1)
	 end
	 if f == '<GC>' then break end
      end
   end
end
for name, _ in pairs(GC) do
   if name:match(P) then
      T = {}
      TrackCause(name)
   end
end


gcmole

-- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-- This is main driver for gcmole tool. See README for more details.
-- Usage: CLANG_BIN=clang-bin-dir lua tools/gcmole/gcmole.lua [arm|ia32|x64]
local DIR = arg[0]:match("^(.+)/[^/]+$")
local FLAGS = {
   -- Do not build gcsuspects file and reuse previously generated one.
   reuse_gcsuspects = false;
   -- Print commands to console before executing them.
   verbose = false;
   -- Perform dead variable analysis (generates many false positives).
   -- TODO add some sort of whiteliste to filter out false positives.
   dead_vars = false;
   -- When building gcsuspects whitelist certain functions as if they
   -- can be causing GC. Currently used to reduce number of false
   -- positives in dead variables analysis. See TODO for WHITELIST
   -- below.
   whitelist = true;
}
local ARGS = {}
for i = 1, #arg do
   local flag = arg[i]:match "^%-%-([%w_-]+)$"
   if flag then
      local no, real_flag = flag:match "^(no)([%w_-]+)$"
      if real_flag then flag = real_flag end
      flag = flag:gsub("%-", "_")
      if FLAGS[flag] ~= nil then
         FLAGS[flag] = (no ~= "no")
      else
         error("Unknown flag: " .. flag)
      end
   else
      table.insert(ARGS, arg[i])
   end
end
local ARCHS = ARGS[1] and { ARGS[1] } or { 'ia32', 'arm', 'x64' }
local io = require "io"
local os = require "os"
function log(...)
   io.stderr:write(string.format(...))
   io.stderr:write "\n"
end
-------------------------------------------------------------------------------
-- Clang invocation
local CLANG_BIN = os.getenv "CLANG_BIN"
if not CLANG_BIN or CLANG_BIN == "" then
   error "CLANG_BIN not set"
end
local function MakeClangCommandLine(plugin, plugin_args, triple, arch_define)
   if plugin_args then
     for i = 1, #plugin_args do
        plugin_args[i] = "-plugin-arg-" .. plugin .. " " .. plugin_args[i]
     end
     plugin_args = " " .. table.concat(plugin_args, " ")
   end
   return CLANG_BIN .. "/clang -cc1 -load " .. DIR .. "/libgcmole.so"
      .. " -plugin "  .. plugin
      .. (plugin_args or "")
      .. " -triple " .. triple
      .. " -D" .. arch_define
      .. " -DENABLE_DEBUGGER_SUPPORT"
      .. " -Isrc"
end
function InvokeClangPluginForEachFile(filenames, cfg, func)
   local cmd_line = MakeClangCommandLine(cfg.plugin,
                                         cfg.plugin_args,
                                         cfg.triple,
                                         cfg.arch_define)
   for _, filename in ipairs(filenames) do
      log("-- %s", filename)
      local action = cmd_line .. " src/" .. filename .. " 2>&1"
      if FLAGS.verbose then print('popen ', action) end
      local pipe = io.popen(action)
      func(filename, pipe:lines())
      pipe:close()
   end
end
-------------------------------------------------------------------------------
-- SConscript parsing
local function ParseSConscript()
   local f = assert(io.open("src/SConscript"), "failed to open SConscript")
   local sconscript = f:read('*a')
   f:close()
   local SOURCES = sconscript:match "SOURCES = {(.-)}";
   local sources = {}
   for condition, list in
      SOURCES:gmatch "'([^']-)': Split%(\"\"\"(.-)\"\"\"%)" do
      local files = {}
      for file in list:gmatch "[^%s]+" do table.insert(files, file) end
      sources[condition] = files
   end
   for condition, list in SOURCES:gmatch "'([^']-)': %[(.-)%]" do
      local files = {}
      for file in list:gmatch "'([^']-)'" do table.insert(files, file) end
      sources[condition] = files
   end
   return sources
end
local function EvaluateCondition(cond, props)
   if cond == 'all' then return true end
   local p, v = cond:match "(%w+):(%w+)"
   assert(p and v, "failed to parse condition: " .. cond)
   assert(props[p] ~= nil, "undefined configuration property: " .. p)
   return props[p] == v
end
local function BuildFileList(sources, props)
   local list = {}
   for condition, files in pairs(sources) do
      if EvaluateCondition(condition, props) then
         for i = 1, #files do table.insert(list, files[i]) end
      end
   end
   return list
end
local sources = ParseSConscript()
local function FilesForArch(arch)
   return BuildFileList(sources, { os = 'linux',
                                   arch = arch,
                                   mode = 'debug',
                                   simulator = ''})
end
local mtConfig = {}
mtConfig.__index = mtConfig
local function config (t) return setmetatable(t, mtConfig) end
function mtConfig:extend(t)
   local e = {}
   for k, v in pairs(self) do e[k] = v end
   for k, v in pairs(t) do e[k] = v end
   return config(e)
end
local ARCHITECTURES = {
   ia32 = config { triple = "i586-unknown-linux",
                   arch_define = "V8_TARGET_ARCH_IA32" },
   arm = config { triple = "i586-unknown-linux",
                  arch_define = "V8_TARGET_ARCH_ARM" },
   x64 = config { triple = "x86_64-unknown-linux",
                  arch_define = "V8_TARGET_ARCH_X64" }
}
-------------------------------------------------------------------------------
-- GCSuspects Generation
local gc, gc_caused, funcs
local WHITELIST = {
   -- The following functions call CEntryStub which is always present.
   "MacroAssembler.*CallExternalReference",
   "MacroAssembler.*CallRuntime",
   "CompileCallLoadPropertyWithInterceptor",
   "CallIC.*GenerateMiss",
   -- DirectCEntryStub is a special stub used on ARM.
   -- It is pinned and always present.
   "DirectCEntryStub.*GenerateCall",
   -- TODO GCMole currently is sensitive enough to understand that certain
   --      functions only cause GC and return Failure simulataneously.
   --      Callsites of such functions are safe as long as they are properly
   --      check return value and propagate the Failure to the caller.
   --      It should be possible to extend GCMole to understand this.
   "Heap.*AllocateFunctionPrototype",
   -- Ignore all StateTag methods.
   "StateTag",
   -- Ignore printing of elements transition.
   "PrintElementsTransition"
};
local function AddCause(name, cause)
   local t = gc_caused[name]
   if not t then
      t = {}
      gc_caused[name] = t
   end
   table.insert(t, cause)
end
local function resolve(name)
   local f = funcs[name]
   if not f then
      f = {}
      funcs[name] = f
      if name:match "Collect.*Garbage" then
         gc[name] = true
         AddCause(name, "<GC>")
      end
      if FLAGS.whitelist then
         for i = 1, #WHITELIST do
            if name:match(WHITELIST[i]) then
               gc[name] = false
            end
         end
      end
   end
    return f
end
local function parse (filename, lines)
   local scope
   for funcname in lines do
      if funcname:sub(1, 1) ~= '\t' then
         resolve(funcname)
         scope = funcname
      else
         local name = funcname:sub(2)
         resolve(name)[scope] = true
      end
   end
end
local function propagate ()
   log "** Propagating GC information"
   local function mark(from, callers)
      for caller, _ in pairs(callers) do
         if gc[caller] == nil then
            gc[caller] = true
            mark(caller, funcs[caller])
         end
         AddCause(caller, from)
      end
   end
   for funcname, callers in pairs(funcs) do
      if gc[funcname] then mark(funcname, callers) end
   end
end
local function GenerateGCSuspects(arch, files, cfg)
   -- Reset the global state.
   gc, gc_caused, funcs = {}, {}, {}
   log ("** Building GC Suspects for %s", arch)
   InvokeClangPluginForEachFile (files,
                                 cfg:extend { plugin = "dump-callees" },
                                 parse)
   propagate()
   local out = assert(io.open("gcsuspects", "w"))
   for name, value in pairs(gc) do if value then out:write (name, '\n') end end
   out:close()
   local out = assert(io.open("gccauses", "w"))
   out:write "GC = {"
   for name, causes in pairs(gc_caused) do
      out:write("['", name, "'] = {")
      for i = 1, #causes do out:write ("'", causes[i], "';") end
      out:write("};\n")
   end
   out:write "}"
   out:close()
   log ("** GCSuspects generated for %s", arch)
end
--------------------------------------------------------------------------------
-- Analysis
local function CheckCorrectnessForArch(arch)
   local files = FilesForArch(arch)
   local cfg = ARCHITECTURES[arch]
   if not FLAGS.reuse_gcsuspects then
      GenerateGCSuspects(arch, files, cfg)
   end
   local processed_files = 0
   local errors_found = false
   local function SearchForErrors(filename, lines)
      processed_files = processed_files + 1
      for l in lines do
         errors_found = errors_found or
            l:match "^[^:]+:%d+:%d+:" or
            l:match "error" or
            l:match "warning"
         print(l)
      end
   end
   log("** Searching for evaluation order problems%s for %s",
       FLAGS.dead_vars and " and dead variables" or "",
       arch)
   local plugin_args
   if FLAGS.dead_vars then plugin_args = { "--dead-vars" } end
   InvokeClangPluginForEachFile(files,
                                cfg:extend { plugin = "find-problems",
                                             plugin_args = plugin_args },
                                SearchForErrors)
   log("** Done processing %d files. %s",
       processed_files,
       errors_found and "Errors found" or "No errors found")
   return errors_found
end
local function SafeCheckCorrectnessForArch(arch)
   local status, errors = pcall(CheckCorrectnessForArch, arch)
   if not status then
      print(string.format("There was an error: %s", errors))
      errors = true
   end
   return errors
end
local errors = false
for _, arch in ipairs(ARCHS) do
   if not ARCHITECTURES[arch] then
      error ("Unknown arch: " .. arch)
   end
   errors = SafeCheckCorrectnessForArch(arch, report) or errors
end
os.exit(errors and 1 or 0)


-- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-- This is main driver for gcmole tool. See README for more details.
-- Usage: CLANG_BIN=clang-bin-dir lua tools/gcmole/gcmole.lua [arm|ia32|x64]
local DIR = arg[0]:match("^(.+)/[^/]+$")
local FLAGS = {
   -- Do not build gcsuspects file and reuse previously generated one.
   reuse_gcsuspects = false;
   -- Print commands to console before executing them.
   verbose = false;
   -- Perform dead variable analysis (generates many false positives).
   -- TODO add some sort of whiteliste to filter out false positives.
   dead_vars = false;
   -- When building gcsuspects whitelist certain functions as if they
   -- can be causing GC. Currently used to reduce number of false
   -- positives in dead variables analysis. See TODO for WHITELIST
   -- below.
   whitelist = true;
}
local ARGS = {}
for i = 1, #arg do
   local flag = arg[i]:match "^%-%-([%w_-]+)$"
   if flag then
      local no, real_flag = flag:match "^(no)([%w_-]+)$"
      if real_flag then flag = real_flag end
      flag = flag:gsub("%-", "_")
      if FLAGS[flag] ~= nil then
         FLAGS[flag] = (no ~= "no")
      else
         error("Unknown flag: " .. flag)
      end
   else
      table.insert(ARGS, arg[i])
   end
end
local ARCHS = ARGS[1] and { ARGS[1] } or { 'ia32', 'arm', 'x64', 'arm64' }
local io = require "io"
local os = require "os"
function log(...)
   io.stderr:write(string.format(...))
   io.stderr:write "\n"
end
-------------------------------------------------------------------------------
-- Clang invocation
local CLANG_BIN = os.getenv "CLANG_BIN"
local CLANG_PLUGINS = os.getenv "CLANG_PLUGINS"
if not CLANG_BIN or CLANG_BIN == "" then
   error "CLANG_BIN not set"
end
if not CLANG_PLUGINS or CLANG_PLUGINS == "" then
   CLANG_PLUGINS = DIR
end
local function MakeClangCommandLine(plugin, plugin_args, triple, arch_define)
   if plugin_args then
     for i = 1, #plugin_args do
        plugin_args[i] = "-Xclang -plugin-arg-" .. plugin
           .. " -Xclang " .. plugin_args[i]
     end
     plugin_args = " " .. table.concat(plugin_args, " ")
   end
   return CLANG_BIN .. "/clang++ -std=c++11 -c "
      .. " -Xclang -load -Xclang " .. CLANG_PLUGINS .. "/libgcmole.so"
      .. " -Xclang -plugin -Xclang "  .. plugin
      .. (plugin_args or "")
      .. " -Xclang -triple -Xclang " .. triple
      .. " -D" .. arch_define
      .. " -DENABLE_DEBUGGER_SUPPORT"
      .. " -DV8_I18N_SUPPORT"
      .. " -I./"
      .. " -Ithird_party/icu/source/common"
      .. " -Ithird_party/icu/source/i18n"
end
function InvokeClangPluginForEachFile(filenames, cfg, func)
   local cmd_line = MakeClangCommandLine(cfg.plugin,
                                         cfg.plugin_args,
                                         cfg.triple,
                                         cfg.arch_define)
   for _, filename in ipairs(filenames) do
      log("-- %s", filename)
      local action = cmd_line .. " " .. filename .. " 2>&1"
      if FLAGS.verbose then print('popen ', action) end
      local pipe = io.popen(action)
      func(filename, pipe:lines())
      local success = pipe:close()
      if not success then error("Failed to run: " .. action) end
   end
end
-------------------------------------------------------------------------------
-- GYP file parsing
local function ParseGYPFile()
   local gyp = ""
   local gyp_files = { "tools/gyp/v8.gyp", "test/cctest/cctest.gyp" }
   for i = 1, #gyp_files do
      local f = assert(io.open(gyp_files[i]), "failed to open GYP file")
      local t = f:read('*a')
      gyp = gyp .. t
      f:close()
   end
   local result = {}
   for condition, sources in
      gyp:gmatch "'sources': %[.-### gcmole%((.-)%) ###(.-)%]" do
      if result[condition] == nil then result[condition] = {} end
      for file in sources:gmatch "'%.%./%.%./src/([^']-%.cc)'" do
         table.insert(result[condition], "src/" .. file)
      end
      for file in sources:gmatch "'(test-[^']-%.cc)'" do
         table.insert(result[condition], "test/cctest/" .. file)
      end
   end
   return result
end
local function EvaluateCondition(cond, props)
   if cond == 'all' then return true end
   local p, v = cond:match "(%w+):(%w+)"
   assert(p and v, "failed to parse condition: " .. cond)
   assert(props[p] ~= nil, "undefined configuration property: " .. p)
   return props[p] == v
end
local function BuildFileList(sources, props)
   local list = {}
   for condition, files in pairs(sources) do
      if EvaluateCondition(condition, props) then
         for i = 1, #files do table.insert(list, files[i]) end
      end
   end
   return list
end
local sources = ParseGYPFile()
local function FilesForArch(arch)
   return BuildFileList(sources, { os = 'linux',
                                   arch = arch,
                                   mode = 'debug',
                                   simulator = ''})
end
local mtConfig = {}
mtConfig.__index = mtConfig
local function config (t) return setmetatable(t, mtConfig) end
function mtConfig:extend(t)
   local e = {}
   for k, v in pairs(self) do e[k] = v end
   for k, v in pairs(t) do e[k] = v end
   return config(e)
end
local ARCHITECTURES = {
   ia32 = config { triple = "i586-unknown-linux",
                   arch_define = "V8_TARGET_ARCH_IA32" },
   arm = config { triple = "i586-unknown-linux",
                  arch_define = "V8_TARGET_ARCH_ARM" },
   x64 = config { triple = "x86_64-unknown-linux",
                  arch_define = "V8_TARGET_ARCH_X64" },
   arm64 = config { triple = "x86_64-unknown-linux",
                    arch_define = "V8_TARGET_ARCH_ARM64" },
}
-------------------------------------------------------------------------------
-- GCSuspects Generation
local gc, gc_caused, funcs
local WHITELIST = {
   -- The following functions call CEntryStub which is always present.
   "MacroAssembler.*CallExternalReference",
   "MacroAssembler.*CallRuntime",
   "CompileCallLoadPropertyWithInterceptor",
   "CallIC.*GenerateMiss",
   -- DirectCEntryStub is a special stub used on ARM.
   -- It is pinned and always present.
   "DirectCEntryStub.*GenerateCall",
   -- TODO GCMole currently is sensitive enough to understand that certain
   --      functions only cause GC and return Failure simulataneously.
   --      Callsites of such functions are safe as long as they are properly
   --      check return value and propagate the Failure to the caller.
   --      It should be possible to extend GCMole to understand this.
   "Heap.*AllocateFunctionPrototype",
   -- Ignore all StateTag methods.
   "StateTag",
   -- Ignore printing of elements transition.
   "PrintElementsTransition"
};
local function AddCause(name, cause)
   local t = gc_caused[name]
   if not t then
      t = {}
      gc_caused[name] = t
   end
   table.insert(t, cause)
end
local function resolve(name)
   local f = funcs[name]
   if not f then
      f = {}
      funcs[name] = f
      if name:match "Collect.*Garbage" then
         gc[name] = true
         AddCause(name, "<GC>")
      end
      if FLAGS.whitelist then
         for i = 1, #WHITELIST do
            if name:match(WHITELIST[i]) then
               gc[name] = false
            end
         end
      end
   end
    return f
end
local function parse (filename, lines)
   local scope
   for funcname in lines do
      if funcname:sub(1, 1) ~= '\t' then
         resolve(funcname)
         scope = funcname
      else
         local name = funcname:sub(2)
         resolve(name)[scope] = true
      end
   end
end
local function propagate ()
   log "** Propagating GC information"
   local function mark(from, callers)
      for caller, _ in pairs(callers) do
         if gc[caller] == nil then
            gc[caller] = true
            mark(caller, funcs[caller])
         end
         AddCause(caller, from)
      end
   end
   for funcname, callers in pairs(funcs) do
      if gc[funcname] then mark(funcname, callers) end
   end
end
local function GenerateGCSuspects(arch, files, cfg)
   -- Reset the global state.
   gc, gc_caused, funcs = {}, {}, {}
   log ("** Building GC Suspects for %s", arch)
   InvokeClangPluginForEachFile (files,
                                 cfg:extend { plugin = "dump-callees" },
                                 parse)
   propagate()
   local out = assert(io.open("gcsuspects", "w"))
   for name, value in pairs(gc) do if value then out:write (name, '\n') end end
   out:close()
   local out = assert(io.open("gccauses", "w"))
   out:write "GC = {"
   for name, causes in pairs(gc_caused) do
      out:write("['", name, "'] = {")
      for i = 1, #causes do out:write ("'", causes[i], "';") end
      out:write("};\n")
   end
   out:write "}"
   out:close()
   log ("** GCSuspects generated for %s", arch)
end
--------------------------------------------------------------------------------
-- Analysis
local function CheckCorrectnessForArch(arch)
   local files = FilesForArch(arch)
   local cfg = ARCHITECTURES[arch]
   if not FLAGS.reuse_gcsuspects then
      GenerateGCSuspects(arch, files, cfg)
   end
   local processed_files = 0
   local errors_found = false
   local function SearchForErrors(filename, lines)
      processed_files = processed_files + 1
      for l in lines do
         errors_found = errors_found or
            l:match "^[^:]+:%d+:%d+:" or
            l:match "error" or
            l:match "warning"
         print(l)
      end
   end
   log("** Searching for evaluation order problems%s for %s",
       FLAGS.dead_vars and " and dead variables" or "",
       arch)
   local plugin_args
   if FLAGS.dead_vars then plugin_args = { "--dead-vars" } end
   InvokeClangPluginForEachFile(files,
                                cfg:extend { plugin = "find-problems",
                                             plugin_args = plugin_args },
                                SearchForErrors)
   log("** Done processing %d files. %s",
       processed_files,
       errors_found and "Errors found" or "No errors found")
   return errors_found
end
local function SafeCheckCorrectnessForArch(arch)
   local status, errors = pcall(CheckCorrectnessForArch, arch)
   if not status then
      print(string.format("There was an error: %s", errors))
      errors = true
   end
   return errors
end
local errors = false
for _, arch in ipairs(ARCHS) do
   if not ARCHITECTURES[arch] then
      error ("Unknown arch: " .. arch)
   end
   errors = SafeCheckCorrectnessForArch(arch, report) or errors
end
os.exit(errors and 1 or 0)


-- Box2D premake script.
-- http://industriousone.com/premake

local action = _ACTION or ""

solution "Box2D"
	location ( "Build/" .. action )
	configurations { "Debug", "Release" }

	configuration "vs*"
		defines { "_CRT_SECURE_NO_WARNINGS" }

	configuration "Debug"
		targetdir ( "Build/" .. action .. "/bin/Debug" )
		flags { "Symbols" }

   configuration "Release"
		targetdir ( "Build/" .. action .. "/bin/Release" )
		defines { "NDEBUG" }
		flags { "Optimize" }

	project "Box2D"
		kind "StaticLib"
		language "C++"
		files { "Box2D/**.h", "Box2D/**.cpp" }
		vpaths { [""] = "Box2D" }
		includedirs { "." }

	if os.get == "windows" then
		project "FreeGLUT"
			kind "StaticLib"
			language "C"
			files { "freeglut/*.h", "freeglut/*.c" }
			vpaths { ["Headers"] = "**.h",  ["Sources"] = "**.c" }
	end

	project "GLUI"
		kind "StaticLib"
		language "C++"
		files { "glui/*.h", "glui/*.cpp" }
		vpaths { ["Headers"] = "**.h",  ["Sources"] = "**.cpp" }
		includedirs { "." }
		configuration { "windows" }
			 buildoptions { "/W1" }

	project "HelloWorld"
		kind "ConsoleApp"
		language "C++"
		files { "HelloWorld/Helloworld.cpp" }
		vpaths { [""] = "HelloWorld" }
		includedirs { "." }
		links { "Box2D" }

	project "Testbed"
		kind "ConsoleApp"
		language "C++"
		files { "Testbed/**.h", "Testbed/**.cpp" }
		vpaths { [""] = "Testbed" }
		includedirs { "." }
		links { "Box2D", "GLUI" }
		configuration { "windows" }
			links { "FreeGLUT", "glu32", "opengl32", "winmm" }
		configuration { "macosx" }
			linkoptions { "-framework OpenGL -framework GLUT" }
		configuration { "not windows", "not macosx" }
			links { "X11", "GL", "GLU", "GLUT" }


scimark

------------------------------------------------------------------------------
-- Lua SciMark (2010-12-20).
--
-- A literal translation of SciMark 2.0a, written in Java and C.
-- Credits go to the original authors Roldan Pozo and Bruce Miller.
-- See: http://math.nist.gov/scimark2/
------------------------------------------------------------------------------
local SCIMARK_VERSION = "2010-12-10"
local MIN_TIME = 0.8
local RANDOM_SEED = 101009 -- Must be odd.
local SIZE_SELECT = "small"
local benchmarks = {
  "FFT", "SOR", "MC", "SPARSE", "LU",
  small = {
    FFT		= { 1024 },
    SOR		= { 100 },
    MC		= { },
    SPARSE	= { 1000, 5000 },
    LU		= { 100 },
  },
  large = {
    FFT		= { 1048576 },
    SOR		= { 1000 },
    MC		= { },
    SPARSE	= { 100000, 1000000 },
    LU		= { 1000 },
  },
}
local abs, log, sin, floor = math.abs, math.log, math.sin, math.floor
local pi, clock = math.pi, os.clock
local format = string.format
------------------------------------------------------------------------------
-- Select array type: Lua tables or native (FFI) arrays
------------------------------------------------------------------------------
local darray, iarray
local function array_init()
  if jit and jit.status and jit.status() then
    local ok, ffi = pcall(require, "ffi")
    if ok then
      darray = ffi.typeof("double[?]")
      iarray = ffi.typeof("int[?]")
      return
    end
  end
  function darray(n) return {} end
  iarray = darray
end
------------------------------------------------------------------------------
-- This is a Lagged Fibonacci Pseudo-random Number Generator with
-- j, k, M = 5, 17, 31. Pretty weak, but same as C/Java SciMark.
------------------------------------------------------------------------------
local rand, rand_init
if jit and jit.status and jit.status() then
  -- LJ2 has bit operations and zero-based arrays (internally).
  local bit = require("bit")
  local band, sar = bit.band, bit.arshift
  function rand_init(seed)
    local Rm, Rj, Ri = iarray(17), 16, 11
    for i=0,16 do Rm[i] = 0 end
    for i=16,0,-1 do
      seed = band(seed*9069, 0x7fffffff)
      Rm[i] = seed
    end
    function rand()
      local i = band(Ri+1, sar(Ri-16, 31))
      local j = band(Rj+1, sar(Rj-16, 31))
      Ri, Rj = i, j
      local k = band(Rm[i] - Rm[j], 0x7fffffff)
      Rm[j] = k
      return k * (1.0/2147483647.0)
    end
  end
else
  -- Better for standard Lua with one-based arrays and without bit operations.
  function rand_init(seed)
    local Rm, Rj = {}, 1
    for i=1,17 do Rm[i] = 0 end
    for i=17,1,-1 do
      seed = (seed*9069) % (2^31)
      Rm[i] = seed
    end
    function rand()
      local j, m = Rj, Rm
      local h = j - 5
      if h < 1 then h = h + 17 end
      local k = m[h] - m[j]
      if k < 0 then k = k + 2147483647 end
      m[j] = k
      if j < 17 then Rj = j + 1 else Rj = 1 end
      return k * (1.0/2147483647.0)
    end
  end
end
local function random_vector(n)
  local v = darray(n+1)
  for x=1,n do v[x] = rand() end
  return v
end
local function random_matrix(m, n)
  local a = {}
  for y=1,m do
    local v = darray(n+1)
    a[y] = v
    for x=1,n do v[x] = rand() end
  end
  return a
end
------------------------------------------------------------------------------
-- FFT: Fast Fourier Transform.
------------------------------------------------------------------------------
local function fft_bitreverse(v, n)
  local j = 0
  for i=0,2*n-4,2 do
    if i < j then
      v[i+1], v[i+2], v[j+1], v[j+2] = v[j+1], v[j+2], v[i+1], v[i+2]
    end
    local k = n
    while k <= j do j = j - k; k = k / 2 end
    j = j + k
  end
end
local function fft_transform(v, n, dir)
  if n <= 1 then return end
  fft_bitreverse(v, n)
  local dual = 1
  repeat
    local dual2 = 2*dual
    for i=1,2*n-1,2*dual2 do
      local j = i+dual2
      local ir, ii = v[i], v[i+1]
      local jr, ji = v[j], v[j+1]
      v[j], v[j+1] = ir - jr, ii - ji
      v[i], v[i+1] = ir + jr, ii + ji
    end
    local theta = dir * pi / dual
    local s, s2 = sin(theta), 2.0 * sin(theta * 0.5)^2
    local wr, wi = 1.0, 0.0
    for a=3,dual2-1,2 do
      wr, wi = wr - s*wi - s2*wr, wi + s*wr - s2*wi
      for i=a,a+2*(n-dual2),2*dual2 do
	local j = i+dual2
	local jr, ji = v[j], v[j+1]
	local dr, di = wr*jr - wi*ji, wr*ji + wi*jr
	local ir, ii = v[i], v[i+1]
	v[j], v[j+1] = ir - dr, ii - di
	v[i], v[i+1] = ir + dr, ii + di
      end
    end
    dual = dual2
  until dual >= n
end
function benchmarks.FFT(n)
  local l2n = log(n)/log(2)
  if l2n % 1 ~= 0 then
    io.stderr:write("Error: FFT data length is not a power of 2\n")
    os.exit(1)
  end
  local v = random_vector(n*2)
  return function(cycles)
    local norm = 1.0 / n
    for p=1,cycles do
      fft_transform(v, n, -1)
      fft_transform(v, n, 1)
      for i=1,n*2 do v[i] = v[i] * norm end
    end
    return ((5*n-2)*l2n + 2*(n+1)) * cycles
  end
end
------------------------------------------------------------------------------
-- SOR: Jacobi Successive Over-Relaxation.
------------------------------------------------------------------------------
local function sor_run(mat, m, n, cycles, omega)
  local om4, om1 = omega*0.25, 1.0-omega
  m = m - 1
  n = n - 1
  for i=1,cycles do
    for y=2,m do
      local v, vp, vn = mat[y], mat[y-1], mat[y+1]
      for x=2,n do
	v[x] = om4*((vp[x]+vn[x])+(v[x-1]+v[x+1])) + om1*v[x]
      end
    end
  end
end
function benchmarks.SOR(n)
  local mat = random_matrix(n, n)
  return function(cycles)
    sor_run(mat, n, n, cycles, 1.25)
    return (n-1)*(n-1)*cycles*6
  end
end
------------------------------------------------------------------------------
-- MC: Monte Carlo Integration.
------------------------------------------------------------------------------
local function mc_integrate(cycles)
  local under_curve = 0
  local rand = rand
  for i=1,cycles do
    local x = rand()
    local y = rand()
    if x*x + y*y <= 1.0 then under_curve = under_curve + 1 end
  end
  return (under_curve/cycles) * 4
end
function benchmarks.MC()
  return function(cycles)
    local res = mc_integrate(cycles)
    assert(math.sqrt(cycles)*math.abs(res-math.pi) < 5.0, "bad MC result")
    return cycles * 4 -- Way off, but same as SciMark in C/Java.
  end
end
------------------------------------------------------------------------------
-- Sparse Matrix Multiplication.
------------------------------------------------------------------------------
local function sparse_mult(n, cycles, vy, val, row, col, vx)
  for p=1,cycles do
    for r=1,n do
      local sum = 0
      for i=row[r],row[r+1]-1 do sum = sum + vx[col[i]] * val[i] end
      vy[r] = sum
    end
  end
end
function benchmarks.SPARSE(n, nz)
  local nr = floor(nz/n)
  local anz = nr*n
  local vx = random_vector(n)
  local val = random_vector(anz)
  local vy, col, row = darray(n+1), iarray(nz+1), iarray(n+2)
  row[1] = 1
  for r=1,n do
    local step = floor(r/nr)
    if step < 1 then step = 1 end
    local rr = row[r]
    row[r+1] = rr+nr
    for i=0,nr-1 do col[rr+i] = 1+i*step end
  end
  return function(cycles)
    sparse_mult(n, cycles, vy, val, row, col, vx)
    return anz*cycles*2
  end
end
------------------------------------------------------------------------------
-- LU: Dense Matrix Factorization.
------------------------------------------------------------------------------
local function lu_factor(a, pivot, m, n)
  local min_m_n = m < n and m or n
  for j=1,min_m_n do
    local jp, t = j, abs(a[j][j])
    for i=j+1,m do
      local ab = abs(a[i][j])
      if ab > t then
	jp = i
	t = ab
      end
    end
    pivot[j] = jp
    if a[jp][j] == 0 then error("zero pivot") end
    if jp ~= j then a[j], a[jp] = a[jp], a[j] end
    if j < m then
      local recp = 1.0 / a[j][j]
      for k=j+1,m do
	local v = a[k]
	v[j] = v[j] * recp
      end
    end
    if j < min_m_n then
      for i=j+1,m do
	local vi, vj = a[i], a[j]
	local eij = vi[j]
	for k=j+1,n do vi[k] = vi[k] - eij * vj[k] end
      end
    end
  end
end
local function matrix_alloc(m, n)
  local a = {}
  for y=1,m do a[y] = darray(n+1) end
  return a
end
local function matrix_copy(dst, src, m, n)
  for y=1,m do
    local vd, vs = dst[y], src[y]
    for x=1,n do vd[x] = vs[x] end
  end
end
function benchmarks.LU(n)
  local mat = random_matrix(n, n)
  local tmp = matrix_alloc(n, n)
  local pivot = iarray(n+1)
  return function(cycles)
    for i=1,cycles do
      matrix_copy(tmp, mat, n, n)
      lu_factor(tmp, pivot, n, n)
    end
    return 2.0/3.0*n*n*n*cycles
  end
end
------------------------------------------------------------------------------
-- Main program.
------------------------------------------------------------------------------
local function printf(...)
  io.write(format(...))
end
local function fmtparams(p1, p2)
  if p2 then return format("[%d, %d]", p1, p2)
  elseif p1 then return format("[%d]", p1) end
  return ""
end
local function measure(min_time, name, ...)
  array_init()
  rand_init(RANDOM_SEED)
  local run = benchmarks[name](...)
  local cycles = 1
  repeat
    local tm = clock()
    local flops = run(cycles, ...)
    tm = clock() - tm
    if tm >= min_time then
      local res = flops / tm * 1.0e-6
      local p1, p2 = ...
      printf("%-7s %8.2f  %s\n", name, res, fmtparams(...))
      return res
    end
    cycles = cycles * 2
  until false
end
--printf("Lua SciMark %s based on SciMark 2.0a. %s.\n\n",
--while arg and arg[1] do
--  local a = table.remove(arg, 1)
--  if a == "-noffi" then
--    package.preload.ffi = nil
--  elseif a == "-small" then
--    SIZE_SELECT = "small"
--  elseif a == "-large" then
--    SIZE_SELECT = "large"
--  elseif benchmarks[a] then
--    local p = benchmarks[SIZE_SELECT][a]
--    measure(MIN_TIME, a, tonumber(arg[1]) or p[1], tonumber(arg[2]) or p[2])
--    return
--  else
--    printf("Usage: scimark [-noffi] [-small|-large] [BENCH params...]\n\n")
--    printf("BENCH   -small         -large\n")
--    printf("---------------------------------------\n")
--    for _,name in ipairs(benchmarks) do
--      printf("%-7s %-13s %s\n", name,
--	     fmtparams(unpack(benchmarks.small[name])),
--	     fmtparams(unpack(benchmarks.large[name])))
--    end
--    printf("\n")
--    os.exit(1)
--  end
--end
local params = benchmarks[SIZE_SELECT]
local sum = 0
for _,name in ipairs(benchmarks) do
  sum = sum + measure(MIN_TIME, name, unpack(params[name]))
end
printf("\nSciMark %8.2f  [%s problem sizes]\n", sum / #benchmarks, SIZE_SELECT)
io.flush()


binarytrees

-- The Computer Language Benchmarks Game
-- http://benchmarksgame.alioth.debian.org/
-- contributed by Mike Pall

local function BottomUpTree(item, depth)
  if depth > 0 then
    local i = item + item
    depth = depth - 1
    local left, right = BottomUpTree(i-1, depth), BottomUpTree(i, depth)
    return { item, left, right }
  else
    return { item }
  end
end

local function ItemCheck(tree)
  if tree[2] then
    return tree[1] + ItemCheck(tree[2]) - ItemCheck(tree[3])
  else
    return tree[1]
  end
end

-- we don't look at commandline arguments anyhow
local N = 4

if N == 0 then
  N = 0
elseif N == 1 then
  N = 9.5
elseif N == 2 then
  N = 11.99
elseif N == 3 then
  N = 12.85
elseif N == 4 then
  N = 14.72
elseif N == 5 then
  N = 15.82
end

local mindepth = 4
local maxdepth = mindepth + 2
if maxdepth < N then maxdepth = N end

do
  local stretchdepth = maxdepth + 1
  local stretchtree = BottomUpTree(0, stretchdepth)
  io.write(string.format("stretch tree of depth %d\t check: %d\n",
    stretchdepth, ItemCheck(stretchtree)))
end

local longlivedtree = BottomUpTree(0, maxdepth)

for depth=mindepth,maxdepth,2 do
  local iterations = 2 ^ (maxdepth - depth + mindepth)
  local check = 0
  for i=1,iterations do
    check = check + ItemCheck(BottomUpTree(1, depth)) +
            ItemCheck(BottomUpTree(-1, depth))
  end
  io.write(string.format("%d\t trees of depth %d\t check: %d\n",
    iterations*2, depth, check))
end

io.write(string.format("long lived tree of depth %d\t check: %d\n",
  maxdepth, ItemCheck(longlivedtree)))


require("import")	-- the import fn
import("smart_pointer_templatemethods")	-- import lib into global
spt=smart_pointer_templatemethods --alias

-- catching undefined variables
local env = _ENV -- Lua 5.2
if not env then env = getfenv () end -- Lua 5.1
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})

o1 = spt.Objct()

iid = spt.InterfaceId()

po2 = o1:QueryInterfaceObjct(iid)
-- we can't call po2:DisposeObjct, because smart pointer Ptr<T> always return 0 when dereferencing
-- (see interface file). So we only check that po2 has necessary method
assert(po2.DisposeObjct ~= nil)
assert(po2.QueryInterfaceObjct ~= nil)


require("import") -- the import fn
import("lua_lightuserdata") -- import lib

local t = lua_lightuserdata
local d = t.get_lightuserdata()
local r = t.check_lighuserdata(d)
assert(r)


require("import")	-- the import fn
import("cpp11_move_typemaps")	-- import code

-- catch "undefined" global variables
local env = _ENV -- Lua 5.2
if not env then env = getfenv () end -- Lua 5.1
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})

cpp11_move_typemaps.Counter.reset_counts()
mo = cpp11_move_typemaps.MoveOnly(111)
cpp11_move_typemaps.Counter.check_counts(1, 0, 0, 0, 0, 0)
cpp11_move_typemaps.MoveOnly.take(mo)
cpp11_move_typemaps.Counter.check_counts(1, 0, 0, 1, 0, 2)
mo = nil
cpp11_move_typemaps.Counter.check_counts(1, 0, 0, 1, 0, 2)

cpp11_move_typemaps.Counter.reset_counts()
mo = cpp11_move_typemaps.MovableCopyable(111)
cpp11_move_typemaps.Counter.check_counts(1, 0, 0, 0, 0, 0)
cpp11_move_typemaps.MovableCopyable.take(mo)
cpp11_move_typemaps.Counter.check_counts(1, 0, 0, 1, 0, 2)
mo = nil
cpp11_move_typemaps.Counter.check_counts(1, 0, 0, 1, 0, 2)

mo = cpp11_move_typemaps.MoveOnly(222)
cpp11_move_typemaps.MoveOnly.take(mo)
s, msg = pcall(function() cpp11_move_typemaps.MoveOnly.take(mo) end)
assert(s == false and msg:find("Cannot release ownership as memory is not owned", 1, true))


require("import")	-- the import fn
import("overload_template")	-- import code
for k,v in pairs(overload_template) do _G[k]=v end -- move to global

-- lua has only one numeric type, so maximum(int,int) and maximum(double,double) are the same
-- whichever one was wrapper first will be used (which is int)

f = foo()

a = maximum(3,4)

-- mix 1
assert(mix1("hi") == 101)
assert(mix1(1.0, 1.0) == 102)
assert(mix1(1.0) == 103)

-- mix 2
assert(mix2("hi") == 101)
assert(mix2(1.0, 1.0) == 102)
assert(mix2(1.0) == 103)

-- mix 3
assert(mix3("hi") == 101)
assert(mix3(1.0, 1.0) == 102)
assert(mix3(1.0) == 103)

-- Combination 1
assert(overtparams1(100) == 10)
assert(overtparams1(100.0, 100) == 20)

-- Combination 2
assert(overtparams2(100.0, 100) == 40)

-- Combination 3
assert(overloaded() == 60)
assert(overloaded(100.0, 100) == 70)

-- Combination 4
assert(overloadedagain("hello") == 80)
assert(overloadedagain() == 90)

-- specializations
assert(specialization(10) == 202 or specialization(10.0) == 203) -- only one works
assert(specialization(10, 10) == 204 or specialization(10.0, 10.0) == 205) -- ditto
assert(specialization("hi", "hi") == 201)

-- simple specialization
xyz()
xyz_int()
xyz_double()

-- a bit of everything
assert(overload("hi") == 0)
assert(overload(1) == 10)
assert(overload(1, 1) == 20)
assert(overload(1, "hello") == 30)

k = Klass()
assert(overload(k) == 10)
assert(overload(k, k) == 20)
assert(overload(k, "hello") == 30)
-- this one is incorrect: it mactches overload(10.0, "hi") with int overload(T t, const char *c)
--print(overload(10.0, "hi"))
--assert(overload(10.0, "hi") == 40)
assert(overload() == 50)

-- everything put in a namespace
assert(nsoverload("hi") == 1000,"nsoverload()")
assert(nsoverload(1) == 1010,"nsoverload(int t)")
assert(nsoverload(1, 1) == 1020,"nsoverload(int t, const int &)")
assert(nsoverload(1, "hello") == 1030,"nsoverload(int t, const char *)")
assert(nsoverload(k) == 1010,"nsoverload(Klass t)")
assert(nsoverload(k, k) == 1020,"nsoverload(Klass t, const Klass &)")
assert(nsoverload(k, "hello") == 1030,"nsoverload(Klass t, const char *)")
-- again this one fails
--assert(nsoverload(10.0, "hi") == 1040,"nsoverload(double t, const char *)")
assert(nsoverload() == 1050,"nsoverload(const char *)")

A_foo(1)
b = B()
b:foo(1)


require("import")	-- the import fn
import("extend_placement")	-- import lib into global
ep=extend_placement --alias

-- catching undefined variables
local env = _ENV -- Lua 5.2
if not env then env = getfenv () end -- Lua 5.1
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})

function test_obj(main, suppl)
  assert(main:spam() == 1)
  assert(main:spam("this_is_string") == 2)
  assert(main:spam(5) == 5)
  assert(main:spam(5,6) == 11)
  assert(main:spam(7,8,9) == 15)
  assert(main:spam(suppl,12.0) == 0)
  assert(main:spam(suppl) == 0)
end

foo1 = ep.Foo(0)
foo2 = ep.Foo(1,2)
foo3 = ep.Foo()
test_obj(foo1,foo2)

bar1 = ep.Bar()
bar2 = ep.Bar(5)
test_obj(bar1,bar2)

fti1 = ep.FooTi(0)
fti2 = ep.FooTi(1,2)
fti3 = ep.FooTi()
test_obj(fti1,foo1)

bti1 = ep.BarTi()
bti2 = ep.BarTi(5)
test_obj(bti1,bar1)


require("import")	-- the import fn
import("grouping")	-- import lib into global
g=grouping --alias

-- catching undefined variables
local env = _ENV -- Lua 5.2
if not env then env = getfenv () end -- Lua 5.1
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})

assert(g.test1(5) == 5)
g.test2(42) -- Return value is int* packed into userdata. We can't do anything with it

assert(g.test3 == 37)
g.test3 = 42
assert(g.test3 == 42)

assert(g.NEGATE ~= nil)
assert(g.do_unary(5, g.NEGATE) == -5)


require("import")	-- the import fn
import("static_const_member")	-- import lib into global
scm=static_const_member --alias

-- catching undefined variables
local env = _ENV -- Lua 5.2
if not env then env = getfenv () end -- Lua 5.1
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})

assert(scm.X.PN == 0)
assert(scm.X.CN == 1)
assert(scm.X.EN == 2)
assert(scm.X.CHARTEST == "A")

-- Old-style bindings
assert(scm.X_PN == 0)
assert(scm.X_CN == 1)
assert(scm.X_EN == 2)
assert(scm.X_CHARTEST == "A")


require("import")	-- the import fn
import("import_nomodule")	-- import code

-- catch "undefined" global variables
local env = _ENV -- Lua 5.2
if not env then env = getfenv () end -- Lua 5.1
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})

f = import_nomodule.create_Foo()
import_nomodule.test1(f,42)
import_nomodule.delete_Foo(f)

b = import_nomodule.Bar()
import_nomodule.test1(b,37)

collectgarbage()


require("import")	-- the import fn
import("newobject1")	-- import code

foo1 = newobject1.Foo_makeFoo()
assert(newobject1.Foo_fooCount() == 1)

foo2 = foo1:makeMore()
assert(newobject1.Foo_fooCount() == 2)

foo1 = nil
collectgarbage()
assert(newobject1.Foo_fooCount() == 1)

foo2 = nil
collectgarbage()
assert(newobject1.Foo_fooCount() == 0)


require("import")	-- the import fn
import("cpp_namespace")	-- import lib into global
cn=cpp_namespace --alias

-- catching undefined variables
local env = _ENV -- Lua 5.2
if not env then env = getfenv () end -- Lua 5.1
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})

assert(cn.fact(4) == 24)
assert(cn.Foo == 42)

t1 = cn.Test()
assert(t1:method() == "Test::method")

cn.weird("t1", 4)

assert(cn.do_method(t1) == "Test::method")
assert(cn.do_method2(t1) == "Test::method")

t2 = cn.Test2()
assert(t2:method() == "Test2::method")

assert(cn.foo3(5) == 5)

assert(cn.do_method3(t2, 7) == "Test2::method")


require("import")	-- the import fn
import("exception_partial_info")	-- import code

-- catch "undefined" global variables
setmetatable(getfenv(),{__index=function (t,i) error("undefined global variable `"..i.."'",2) end})

imp=exception_partial_info.Impl()

-- trying to call throwing methods
-- should fail
assert(pcall(function() imp:f1() end)==false)
assert(pcall(function() imp:f2() end)==false)


require("import")	-- the import fn
import("equality")	-- import code
eq=equality    -- renaming import

-- catch "undefined" global variables
local env = _ENV -- Lua 5.2
if not env then env = getfenv () end -- Lua 5.1
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})

-- === No equality operator ===

-- logically same data without equality operator are not equal
p1 = eq.MakePoint(10,9);
p2 = eq.MakePoint(10,9);

assert( p1 ~= p2 );

-- different wrappers for same Point* are equal
p3 = eq.GetZeroPointPtr()
p4 = eq.GetZeroPointPtr()

assert( p3 == p4 )

-- === Logically correct equality operator ===

ed1 = eq.EqualOpDefined(10)
ed2 = eq.EqualOpDefined(10)
ed3 = eq.EqualOpDefined(15)

assert( ed1 == ed2 )
assert( ed1 ~= ed3 )

-- === Logically incorrect equality operator ===

ew1 = eq.EqualOpWrong()
ew2 = eq.EqualOpWrong()

assert( ew1 ~= ew2 );

ew3 = eq.EqualOpWrong.GetStaticObject()
ew4 = eq.EqualOpWrong.GetStaticObject()

-- Even though these are pointers to same object, operator== overload should
-- state that they are not equal
assert( ew3 ~= ew4 )


require("import")	-- the import fn
-- need to load two modules
import("imports_a")	-- import code
import("imports_b")	-- import code

b=imports_b.B()
b:hello() -- call member function in A which is in a different SWIG generated library.
b:bye()

assert (b:member_virtual_test(imports_a.A_memberenum1) == imports_a.A_memberenum2)
assert (b:global_virtual_test(imports_a.globalenum1) == imports_a.globalenum2)

imports_b.global_test(imports_a.A_memberenum1)

--[[    B b = new B();
    b.hello(); //call member function in A which is in a different SWIG generated library.

            B b = new B();
        b.hello(); //call member function in A which is in a different SWIG generated library.
        b.bye();

        if (b.member_virtual_test(A.MemberEnum.memberenum1) != A.MemberEnum.memberenum2)
          throw new Exception("Test 1 failed");
        if (b.global_virtual_test(GlobalEnum.globalenum1) != GlobalEnum.globalenum2)
          throw new Exception("Test 2 failed");

        imports_b.global_test(A.MemberEnum.memberenum1);
]]


require("import")	-- the import fn
import("li_std_vector")	-- import code

for k,v in pairs(li_std_vector) do _G[k]=v end -- move to global

iv = IntVector(4)
for i=0,3 do
    iv[i] = i
end

for i=0,3 do assert(iv[i]==i) end

x = average(iv)

function near(x,y) return math.abs(x-y)<0.001 end

assert(near(x,1.5))

rv = RealVector()
rv:push_back(10)
rv:push_back(10.5)
rv:push_back(11)
rv:push_back(11.5)

a=half(rv)
for i=0,rv:size()-1 do
	assert(near(a[i],rv[i]/2))
end

dv = DoubleVector(10)
for i=0,9 do dv[i] = i/2.0 end

halve_in_place(dv)

for i=0,9 do
	assert(near(dv[i],i/4))
end

sv=StructVector(4)

for i=0,3 do
	sv[i]=Struct(i)
end

for i=0,3 do
	assert(swig_type(sv[i]) =='Struct *' and sv[i].num==i)
end

-- range checking
idx=0
function test_set() iv[idx]=0 end
function test_get() iv[idx]=0 end

idx=0 --ok
assert(pcall(test_get)==true)
assert(pcall(test_set)==true)
idx=-1 --should error
assert(pcall(test_get)==false)
assert(pcall(test_set)==false)
idx=3 --ok
assert(pcall(test_get)==true)
assert(pcall(test_set)==true)
idx=4 --should error
assert(pcall(test_get)==false)
assert(pcall(test_set)==false)


require("import")	-- the import fn
import("cpp_typedef")	-- import lib into global
ct = cpp_typedef --alias

-- catching undefined variables
local env = _ENV -- Lua 5.2
if not env then env = getfenv () end -- Lua 5.1
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})

foo1 = ct.Foo()
bar1 = foo1:bar()
bar2 = ct.Foo.sbar()

u1 = ct.UnnamedStruct()
n1 = ct.TypedefNamedStruct()

test = ct.Test()

u2 = test:test1(u1)
n2 = test:test2(n1)
n3 = test:test3(n1)
n4 = test:test4(n1)


require("import")	-- the import fn
import("char_strings")	-- import code

assert (char_strings.CharPingPong("hi there") == "hi there")
assert (char_strings.CharPingPong(nil) == nil)

assert (char_strings.CharArrayPingPong("hi there") == "hi there")
assert (char_strings.CharArrayPingPong(nil) == nil)

assert (char_strings.CharArrayDimsPingPong("hi there") == "hi there")
assert (char_strings.CharArrayDimsPingPong(nil) == nil)


require("import")	-- the import fn
import("li_typemaps")	-- import code

-- catch "undefined" global variables
local env = _ENV -- Lua 5.2
if not env then env = getfenv () end -- Lua 5.1
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})

-- Check double INPUT typemaps
assert(li_typemaps.in_double(22.22) == 22.22)
assert(li_typemaps.inr_double(22.22) == 22.22)

-- Check double OUTPUT typemaps
assert(li_typemaps.out_double(22.22) == 22.22)
assert(li_typemaps.outr_double(22.22) == 22.22)

-- Check double INOUT typemaps
assert(li_typemaps.inout_double(22.22) == 22.22)
assert(li_typemaps.inoutr_double(22.22) == 22.22)

-- check long long
assert(li_typemaps.in_ulonglong(20)==20)
assert(li_typemaps.inr_ulonglong(20)==20)
assert(li_typemaps.out_ulonglong(20)==20)
assert(li_typemaps.outr_ulonglong(20)==20)
assert(li_typemaps.inout_ulonglong(20)==20)
assert(li_typemaps.inoutr_ulonglong(20)==20)

-- check bools
assert(li_typemaps.in_bool(true)==true)
assert(li_typemaps.inr_bool(false)==false)
assert(li_typemaps.out_bool(true)==true)
assert(li_typemaps.outr_bool(false)==false)
assert(li_typemaps.inout_bool(true)==true)
assert(li_typemaps.inoutr_bool(false)==false)

-- the others
a,b=li_typemaps.inoutr_int2(1,2)
assert(a==1 and b==2)

f,i,i2=li_typemaps.out_foo(10)
assert(f.a==10 and i==20 and i2==30)


require("import")	-- the import fn
import("exception_memory_leak")	-- import code
eml=exception_memory_leak --alias

-- catch "undefined" global variables
local env = _ENV -- Lua 5.2
if not env then env = getfenv () end -- Lua 5.1
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})

a = eml.Foo()
assert(eml.Foo_get_count() == 1)
b = eml.Foo()
assert(eml.Foo_get_count() == 2)

-- Normal behaviour
eml.trigger_internal_swig_exception("no problem", a)
assert(eml.Foo_get_count() == 2)
assert(eml.Foo_get_freearg_count() == 1)

-- SWIG exception triggered and handled (return new object case)
ok,ex=pcall(eml.trigger_internal_swig_exception, "null", b)
assert(ok==false)
assert(eml.Foo_get_count() == 2)
assert(eml.Foo_get_freearg_count() == 2)

-- SWIG exception triggered and handled (return by value case).
ok,ex=pcall(eml.trigger_internal_swig_exception, "null")
assert(ok==false)
assert(eml.Foo_get_count() == 2)


require("import")	-- the import fn
import("template_construct")	-- import lib into global
tc=template_construct --alias

-- catching undefined variables
local env = _ENV -- Lua 5.2
if not env then env = getfenv () end -- Lua 5.1
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})

foo = tc.Foo_int(1)


require("import")	-- the import fn
import("static_const_member_2")	-- import lib
scm=static_const_member_2

-- catch "undefined" global variables
local env = _ENV -- Lua 5.2
if not env then env = getfenv () end -- Lua 5.1
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})

assert(scm.CavityPackFlags.forward_field == 1)
assert(scm.CavityPackFlags.backward_field == 2)
assert(scm.CavityPackFlags.cavity_flags == 3)

assert(scm.CavityPackFlags.flags == 0)
scm.CavityPackFlags.flags = 91
assert(scm.CavityPackFlags.flags == 91)
assert(scm.CavityPackFlags_flags == 91) -- old style bindings

assert(scm.CavityPackFlags.reftest == 42)

assert(scm.Test_int.LeftIndex ~= nil)
assert(scm.Test_int.current_profile == 4)

assert(scm.Foo.BAR.val == 1)
assert(scm.Foo.BAZ.val == 2)

assert(scm.Foo_BAR.val == 1)
assert(scm.Foo_BAZ.val == 2)

scm.Foo.BAR.val = 4
scm.Foo.BAZ.val = 5

assert(scm.Foo.BAR.val == 4)
assert(scm.Foo.BAZ.val == 5)

assert(scm.Foo_BAR.val == 4)
assert(scm.Foo_BAZ.val == 5)


require("import")	-- the import fn
import("smart_pointer_extend")	-- import lib into global
spe=smart_pointer_extend --alias

-- catching undefined variables
local env = _ENV -- Lua 5.2
if not env then env = getfenv () end -- Lua 5.1
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})

assert(spe.CBase.hello() == 1)
assert(spe.CBase.z == 1)

base1 = spe.CBase()
base1.x = 7

p1 = spe.CPtr()

assert(spe.get_hello(p1) == 1)
assert(p1:foo() == 1)
assert(p1:bar() == 2)
assert(p1:boo(5) == 5)

foo = spe.Foo()
bar = spe.Bar(foo)

assert(bar:extension(5,7) == 5)
assert(bar:extension(7) == 7)
assert(bar:extension() == 1)

dfoo = spe.DFoo()
dptr = spe.DPtrFoo(dfoo)

assert(dptr:Ext() == 2)
assert(dptr:Ext(5) == 5)


require("import")	-- the import fn
import("sizet")	-- import code

s = 2000
s = sizet.test1(s+1)
s = sizet.test2(s+1)
s = sizet.test3(s+1)
s = sizet.test4(s+1)
assert(s == 2004)


require("import")	-- the import fn
import("cpp_basic")	-- import code
cb=cpp_basic    -- renaming import

-- catch "undefined" global variables
local env = _ENV -- Lua 5.2
if not env then env = getfenv () end -- Lua 5.1
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})

f=cb.Foo(4)
assert(f.num==4)
f.num=-17
assert(f.num==-17)

b=cb.Bar()

b.fptr=f
assert(b.fptr.num==-17)
assert(b:test(-3,b.fptr)==-5)
f.num=12
assert(b.fptr.num==12)

assert(b.fref.num==-4)
assert(b:test(12,b.fref)==23)

-- references don't take ownership, so if we didn't define this here it might get garbage collected
f2=cb.Foo(23)
b.fref=f2
assert(b.fref.num==23)
assert(b:test(-3,b.fref)==35)

assert(b.fval.num==15)
assert(b:test(3,b.fval)==33)
b.fval=cb.Foo(-15)  -- this is safe as it is copied into the C++
assert(b.fval.num==-15)
assert(b:test(3,b.fval)==-27)

f3=b:testFoo(12,b.fref)
assert(f3.num==32)

-- now test global
f4=cb.Foo(6)
cb.Bar_global_fptr=f4
assert(cb.Bar_global_fptr.num==6)
assert(cb.Bar.global_fptr.num==6)
f4.num=8
assert(cb.Bar_global_fptr.num==8)
assert(cb.Bar.global_fptr.num==8)

assert(cb.Bar_global_fref.num==23)
assert(cb.Bar.global_fref.num==23)
cb.Bar_global_fref=cb.Foo(-7) -- this will set the value
assert(cb.Bar_global_fref.num==-7)
assert(cb.Bar.global_fref.num==-7)

assert(cb.Bar_global_fval.num==3)
assert(cb.Bar.global_fval.num==3)
cb.Bar_global_fval=cb.Foo(-34)
assert(cb.Bar_global_fval.num==-34)
assert(cb.Bar.global_fval.num==-34)

assert(cb.Bar.global_cint == -4)
assert(cb.Bar_global_cint == -4)

-- Now test member function pointers
func1_ptr=cb.get_func1_ptr()
func2_ptr=cb.get_func2_ptr()
f.num=4
assert(f:func1(2)==16)
assert(f:func2(2)==-8)

f.func_ptr=func1_ptr
assert(cb.test_func_ptr(f,2)==16)
f.func_ptr=func2_ptr
assert(cb.test_func_ptr(f,2)==-8)

-- Test that __tostring metamethod produce no internal asserts
f2_name = tostring(f2)

f3 = cb.FooSub()
f3_name = tostring(f3)

f4 = cb.FooSubSub()
f4_name = tostring(f4)

assert( f2_name == "Foo" )
assert( f3_name == "Foo" )
assert( f4_name == "FooSubSub" )

-- Test __eq implementation supplied by default

-- eq_f1 and eq_f2 must be different userdata with same Foo* pointer. If eq_f1 and eq_f2 are the same userdata (e.g.)
-- > eq_f1 = smth
-- > eq_f2 = eq_f1
-- then default Lua equality comparison kicks in and considers them equal. Access to global_fptr is actually a
-- function call (internally) and it returns new userdata each time.
eq_f1 = cb.Bar.global_fptr
eq_f2 = cb.Bar.global_fptr
assert( eq_f1 == eq_f2 )


require("import")	-- the import fn
import("cpp11_rvalue_reference_move")	-- import code

-- catch "undefined" global variables
local env = _ENV -- Lua 5.2
if not env then env = getfenv () end -- Lua 5.1
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})

-- Function containing rvalue reference parameter
cpp11_rvalue_reference_move.Counter.reset_counts()
mo = cpp11_rvalue_reference_move.MovableCopyable(222)
cpp11_rvalue_reference_move.Counter.check_counts(1, 0, 0, 0, 0, 0)
cpp11_rvalue_reference_move.MovableCopyable.movein(mo)
cpp11_rvalue_reference_move.Counter.check_counts(1, 0, 0, 1, 0, 2)
if not (cpp11_rvalue_reference_move.MovableCopyable_is_nullptr(mo)) then
  error("is_nullptr failed")
end
mo = nil
cpp11_rvalue_reference_move.Counter.check_counts(1, 0, 0, 1, 0, 2)

-- Move constructor test
cpp11_rvalue_reference_move.Counter.reset_counts()
mo = cpp11_rvalue_reference_move.MovableCopyable(222)
cpp11_rvalue_reference_move.Counter.check_counts(1, 0, 0, 0, 0, 0)
mo_moved = cpp11_rvalue_reference_move.MovableCopyable(mo)
cpp11_rvalue_reference_move.Counter.check_counts(1, 0, 0, 1, 0, 1)
if not (cpp11_rvalue_reference_move.MovableCopyable_is_nullptr(mo)) then
  error("is_nullptr failed")
end
mo = nil
cpp11_rvalue_reference_move.Counter.check_counts(1, 0, 0, 1, 0, 1)
mo_moved = nil
collectgarbage() -- gc nudge needed here
cpp11_rvalue_reference_move.Counter.check_counts(1, 0, 0, 1, 0, 2)

-- Move assignment operator test
cpp11_rvalue_reference_move.Counter.reset_counts()
mo111 = cpp11_rvalue_reference_move.MovableCopyable(111)
mo222 = cpp11_rvalue_reference_move.MovableCopyable(222)
cpp11_rvalue_reference_move.Counter.check_counts(2, 0, 0, 0, 0, 0)
mo111:MoveAssign(mo222)
cpp11_rvalue_reference_move.Counter.check_counts(2, 0, 0, 0, 1, 1)
if not (cpp11_rvalue_reference_move.MovableCopyable_is_nullptr(mo222)) then
  error("is_nullptr failed")
end
mo222 = nil
cpp11_rvalue_reference_move.Counter.check_counts(2, 0, 0, 0, 1, 1)
mo111 = nil
collectgarbage() -- gc nudge needed here
cpp11_rvalue_reference_move.Counter.check_counts(2, 0, 0, 0, 1, 2)

-- null check
cpp11_rvalue_reference_move.Counter.reset_counts()
s, msg = pcall(function() cpp11_rvalue_reference_move.MovableCopyable.movein(nil) end)
assert(s == false and msg:find("Error in MovableCopyable::movein (arg 1), expected 'MovableCopyable &&' got 'nil'", 1, true))
cpp11_rvalue_reference_move.Counter.check_counts(0, 0, 0, 0, 0, 0)

-- output
cpp11_rvalue_reference_move.Counter.reset_counts()
mc = cpp11_rvalue_reference_move.MovableCopyable.moveout(1234)
cpp11_rvalue_reference_move.Counter.check_counts(2, 0, 0, 0, 1, 1)
cpp11_rvalue_reference_move.MovableCopyable.check_numbers_match(mc, 1234)

s, msg = pcall(function() cpp11_rvalue_reference_move.MovableCopyable.movein(mc) end)
assert(s == false and msg:find("Cannot release ownership as memory is not owned", 1, true))
cpp11_rvalue_reference_move.Counter.check_counts(2, 0, 0, 0, 1, 1)


require("import")	-- the import fn
import("friends")	-- import lib into global
f=friends --alias

-- catching undefined variables
local env = _ENV -- Lua 5.2
if not env then env = getfenv () end -- Lua 5.1
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})

f.globalscope()

b1 = f.B(5)
a1 = f.A(10)

assert(f.get_val1(a1) == 10)
assert(f.get_val1(a1, 2) == 12)
assert(f.get_val2(a1) == 20)
assert(f.get_val3(a1) == 30)

assert(f.get_val1(100, 1, 2) == 100)

assert(f.mix(a1,b1) == 15);

d1 = f.D_i(7)
assert(f.get_val1(d1) == 7)
f.set(d1,9)
assert(f.get_val1(d1) == 9)


require("import")	-- the import fn
import("catches_strings")	-- import code

-- catch "undefined" global variables
local env = _ENV -- Lua 5.2
if not env then env = getfenv () end -- Lua 5.1
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})

s, msg = pcall(function() catches_strings.StringsThrower.charstring() end)
assert(s == false and msg:find("charstring message", 1, true))

s, msg = pcall(function() catches_strings.StringsThrower.stdstring() end)
assert(s == false and msg:find("stdstring message", 1, true))


require("import")	-- the import fn
import("inherit_missing")	-- import lib
im=inherit_missing

-- catch "undefined" global variables
local env = _ENV -- Lua 5.2
if not env then env = getfenv () end -- Lua 5.1
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})

bar = im.Bar()
spam = im.Spam()

assert(im.do_blah(bar) == "Bar::blah")
assert(im.do_blah(spam) == "Spam::blah")


require("import")	-- the import fn
import("extend_constructor_destructor")	-- import lib into global
ecd=extend_constructor_destructor --alias

-- catching undefined variables
local env = _ENV -- Lua 5.2
if not env then env = getfenv () end -- Lua 5.1
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})

a1 = ecd.AStruct(101)
assert(a1.ivar == 101)
assert(ecd.globalVar == 101)

b1 = ecd.BStruct(201)
assert(b1.ivar == 201)
assert(ecd.globalVar == 201)

c1 = ecd.CStruct(301)
assert(c1.ivar == 301)
assert(ecd.globalVar == 301)

d1 = ecd.DStruct(401)
assert(d1.ivar == 401)
assert(ecd.globalVar == 401)

e1 = ecd.EStruct(501)
assert(e1.ivar == 501)
assert(ecd.globalVar == 501)

f1 = ecd.FStruct(601)
assert(f1.ivar == 601)
assert(ecd.globalVar == 601)


require("import")	-- the import fn
import("cpp17_string_view")	-- import lib

for k,v in pairs(cpp17_string_view) do _G[k]=v end -- move to global

-- catch "undefined" global variables
local env = _ENV -- Lua 5.2
if not env then env = getfenv () end -- Lua 5.1
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})

-- Checking expected use of %typemap(in) std::string_view {}
test_value("Fee")

-- Checking expected result of %typemap(out) std::string_view {}
s=test_value("Fi")
assert(type(s)=="string" and s =="Fi")

-- Checking expected use of %typemap(in) const std::string_view & {}
test_const_reference("Fo")

-- Checking expected result of %typemap(out) const std::string_view& {}
s=test_const_reference("Fum")
assert(type(s)=="string" and s =="Fum")

-- Input and output typemaps for pointers and non-const references to
-- std::string_view are *not* supported; the following tests confirm
-- that none of these cases are slipping through.

stringPtr = test_pointer_out()

test_pointer(stringPtr)

stringPtr = test_const_pointer_out()

test_const_pointer(stringPtr)

stringPtr = test_reference_out()

test_reference(stringPtr)

-- Global variables
assert(cpp17_string_view.ConstGlobalString=="const global string")

-- Member variables
myStructure = Structure()
assert(myStructure.ConstMemberString=="const member string")

assert(Structure.ConstStaticMemberString=="const static member string")

test_const_reference_returning_void("foo")


require("import")	-- the import fn
import("template_inherit")	-- import lib into global
ti=template_inherit --alias

-- catching undefined variables
local env = _ENV -- Lua 5.2
if not env then env = getfenv () end -- Lua 5.1
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})

fi = ti.FooInt()
assert(fi:blah() == "Foo")
assert(fi:foomethod() == "foomethod")

bi = ti.BarInt()
assert(bi:blah() == "Bar")
assert(bi:foomethod() == "foomethod")

assert(ti.invoke_blah_int(fi) == "Foo")
assert(ti.invoke_blah_int(bi) == "Bar")

bd = ti.BarDouble()
success = pcall(ti.invoke_blah_int, bd)
assert(not success)


require("import")	-- the import fn
import("pointer_reference",true)	-- import code

s=pointer_reference.get()
assert(s.value == 10)

ss = pointer_reference.Struct(20);
pointer_reference.set(ss);
assert(pointer_reference.Struct_instance.value == 20)

assert(pointer_reference.overloading(1) == 111)
assert(pointer_reference.overloading(ss) == 222)


-- require is only available in Lua 5.1

if string.sub(_VERSION,1,7)=='Lua 5.1' then

        -- Initially the package should not be loaded
        assert(package.loaded["lua_no_module_global"] == nil)

        -- Load the module
        the_module = require "lua_no_module_global"

        -- require should return the module table
        assert(the_module.hi_mom ~= nil)
        assert(the_module.hi_mom() == "hi mom!")

        -- But it should not end up in the global table _G, subject to
        -- the -nomoduleglobal swig option.
        assert(_G["lua_no_module_global"] == nil)

        -- According to the Lua 5.1 reference manual, require should also
        -- store the module table into package.loaded["name"]
        assert(package.loaded["lua_no_module_global"] == the_module)
        assert(package.loaded["lua_no_module_global"].hi_mom() == "hi mom!")

end


require("import")	-- the import fn
import("template_extend1")	-- import lib into global
te=template_extend1 --alias

-- catching undefined variables
local env = _ENV -- Lua 5.2
if not env then env = getfenv () end -- Lua 5.1
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})

lb = te.lBaz()
assert(lb:foo() == "lBaz::foo")

db = te.dBaz()
assert(db:foo() == "dBaz::foo")


require("import")  -- the import fn
import("li_factory") -- import code

-- moving to global
for k,v in pairs(li_factory) do _G[k]=v end

-- catch "undefined" global variables
setmetatable(getfenv(),{__index=function (t,i) error("undefined global variable `"..i.."'",2) end})

circle = Geometry_create(Geometry_CIRCLE)
r = circle:radius()
assert(r == 1.5)

point = Geometry_create(Geometry_POINT)
w = point:width()
assert(w == 1.0)


require("import")	-- the import fn
import("smart_pointer_inherit")	-- import lib into global
spi=smart_pointer_inherit --alias

-- catching undefined variables
local env = _ENV -- Lua 5.2
if not env then env = getfenv () end -- Lua 5.1
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})

der = spi.Derived(7)

ptr = spi.SmartDerived(der)

assert(ptr.val == 7)
assert(ptr:value() == 7)
assert(ptr:value2() == 7)
assert(ptr:value3() == 7)
assert(ptr:valuehide() == -1)


require("import")	-- the import fn
import("enum_template")	-- import lib
et=enum_template

-- catch "undefined" global variables
local env = _ENV -- Lua 5.2
if not env then env = getfenv () end -- Lua 5.1
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})

assert(et.eTest0 ~= nil)
assert(et.eTest1 ~= nil)

et.TakeETest(et.eTest0)

res = et.MakeETest()
et.TakeETest(res)


-- Run file
require("import")	-- the import fn
import("cpp_nodefault")	-- import lib into global
cn=cpp_nodefault --alias

-- catching undefined variables
local env = _ENV -- Lua 5.2
if not env then env = getfenv () end -- Lua 5.1
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})

foo1 = cn.Foo(1,2)
foo1.a = 5
assert(foo1.a == 5)

foo2 = cn.create(1,2)

cn.consume(foo1,foo2)

bar1 = cn.Bar()
bar1:consume(cn.gvar, foo2)
foo3 = bar1:create(1,2)

foo3.a = 6
assert(foo3.a == 6)


require("import")	-- the import fn
import("nested_workaround")	-- import lib
nw=nested_workaround

-- catch "undefined" global variables
local env = _ENV -- Lua 5.2
if not env then env = getfenv () end -- Lua 5.1
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})

i1 = nw.Inner(5)
assert(i1:getValue() == 5)
i1:setValue(7)
assert(i1:getValue() == 7)

o1 = nw.Outer()
i2 = o1:createInner(9)
assert(i2:getValue() == 9)
i2:setValue(11)
assert(o1:getInnerValue(i2) == 11)

i3 = o1:doubleInnerValue(i2)
assert(i3:getValue() == 22)


require("import")	-- the import fn
import("array_member")	-- import lib
am = array_member

-- catch "undefined" global variables
local env = _ENV -- Lua 5.2
if not env then env = getfenv () end -- Lua 5.1
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})

assert(am.get_value(am.global_data,0) == 0)
assert(am.get_value(am.global_data,7) == 7)

foo = am.Foo()
foo.data = am.global_data
assert(am.get_value(foo.data,0) == 0)

for i = 0, 7 do
  assert(am.get_value(foo.data,i) == am.get_value(am.global_data,i))
end

for i = 0, 7 do
  am.set_value(am.global_data,i,-i)
end

am.global_data = foo.data

for i = 0, 7 do
  assert(am.get_value(foo.data,i) == am.get_value(am.global_data,i))
end


require("import")	-- the import fn
import("enum_rename")	-- import lib
er=enum_rename

-- catch "undefined" global variables
local env = _ENV -- Lua 5.2
if not env then env = getfenv () end -- Lua 5.1
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})

assert(er.M_Jan ~= nil)
assert(er.May ~= nil)


require("import")	-- the import fn
import("cpp11_std_unique_ptr")	-- import code

-- catch "undefined" global variables
local env = _ENV -- Lua 5.2
if not env then env = getfenv () end -- Lua 5.1
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})

function checkCount(expected_count)
  -- call gc to make unused objects are collected
  collectgarbage()
  actual_count = cpp11_std_unique_ptr.Klass.getTotal_count()
  if not (actual_count == expected_count) then
    error("Counts incorrect, expected:"..expected_count.." actual:"..actual_count)
  end
end

--Test raw pointer handling involving virtual inheritance
kini = cpp11_std_unique_ptr.KlassInheritance("KlassInheritanceInput")
checkCount(1)
s = cpp11_std_unique_ptr.useKlassRawPtr(kini)
if not (s == "KlassInheritanceInput") then
  error("Incorrect string: "..s)
end
kini = nil
checkCount(0)

-- unique_ptr as input
kin = cpp11_std_unique_ptr.Klass("KlassInput")
checkCount(1)
s = cpp11_std_unique_ptr.takeKlassUniquePtr(kin)
checkCount(0)
if not (s == "KlassInput") then
  error("Incorrect string: "..s)
end
if not (cpp11_std_unique_ptr.is_nullptr(kin)) then
  error("is_nullptr failed")
end
kin = nil -- Should not fail, even though already deleted
checkCount(0)

kin = cpp11_std_unique_ptr.Klass("KlassInput")
checkCount(1)
s = cpp11_std_unique_ptr.takeKlassUniquePtr(kin)
checkCount(0)
if not (s == "KlassInput") then
  error("Incorrect string: "..s)
end
if not (cpp11_std_unique_ptr.is_nullptr(kin)) then
  error("is_nullptr failed")
end
s, msg = pcall(function() cpp11_std_unique_ptr.takeKlassUniquePtr(kin) end)
assert(s == false and msg == "Cannot release ownership as memory is not owned for argument 1 of type 'Klass *' in takeKlassUniquePtr")

kin = nil -- Should not fail, even though already deleted
checkCount(0)

kin = cpp11_std_unique_ptr.Klass("KlassInput")
notowned = cpp11_std_unique_ptr.get_not_owned_ptr(kin)
s, msg = pcall(function() cpp11_std_unique_ptr.takeKlassUniquePtr(notowned) end)
assert(s == false and msg == "Cannot release ownership as memory is not owned for argument 1 of type 'Klass *' in takeKlassUniquePtr")
checkCount(1)
kin = nil
checkCount(0)

kini = cpp11_std_unique_ptr.KlassInheritance("KlassInheritanceInput")
checkCount(1)
s = cpp11_std_unique_ptr.takeKlassUniquePtr(kini)
checkCount(0)
if not (s == "KlassInheritanceInput") then
  error("Incorrect string: "..s)
end
if not (cpp11_std_unique_ptr.is_nullptr(kini)) then
  error("is_nullptr failed")
end
kini = nil -- Should not fail, even though already deleted
checkCount(0)

cpp11_std_unique_ptr.takeKlassUniquePtr(nil);
cpp11_std_unique_ptr.takeKlassUniquePtr(cpp11_std_unique_ptr.make_null());
checkCount(0);

-- overloaded parameters
if not (cpp11_std_unique_ptr.overloadTest() == 0) then
  error("overloadTest failed")
end
if not (cpp11_std_unique_ptr.overloadTest(nil) == 1) then
  error("overloadTest failed")
end
if not (cpp11_std_unique_ptr.overloadTest(cpp11_std_unique_ptr.Klass("over")) == 1) then
  error("overloadTest failed")
end
checkCount(0)

-- unique_ptr as output
k1 = cpp11_std_unique_ptr.makeKlassUniquePtr("first")
k2 = cpp11_std_unique_ptr.makeKlassUniquePtr("second")
checkCount(2)

k1 = nil
checkCount(1)

if not (k2:getLabel() == "second") then
  error("wrong object label")
end

k2 = nil
checkCount(0)

assert(cpp11_std_unique_ptr.makeNullUniquePtr() == nil)


require("import")	-- the import fn
import("template_static")	-- import lib
ts=template_static

-- catch "undefined" global variables
local env = _ENV -- Lua 5.2
if not env then env = getfenv () end -- Lua 5.1
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})

assert(ts.foo_i.test == 0)
ts.foo_i.test = 42
assert(ts.foo_i.test == 42)
assert(ts.foo_i_test == 42)
ts.foo_i_test = 57
assert(ts.foo_i.test == 57)
assert(ts.foo_i_test == 57)
assert(ts.foo_d.test == 0)

assert(ts.Foo.bar_double(4) == 1.0)
assert(ts.Foo_bar_double(4) == 1.0)


require('import')       -- the import fn
import('li_constraints') -- import lib into global
cn=li_constraints --alias

function check_func(except, f, val, name)
  actual, err = pcall(f, val);
  assert(actual == except, 'function perform exception wrongly');
  if name == nil then
    r = 'SWIG_ValueError:Received a NULL pointer.';
  else
    r = 'SWIG_ValueError:Expected a ' .. name .. ' value.';
  end
  if not actual then
    assert(err == r, 'function perform the wrong exception');
  end
end

check_func(true, cn.test_nonnegative, 10, 'non-negative');
check_func(true, cn.test_nonnegative, 0, 'non-negative');
check_func(false, cn.test_nonnegative, -10, 'non-negative');

check_func(false, cn.test_nonpositive, 10, 'non-positive');
check_func(true, cn.test_nonpositive, 0, 'non-positive');
check_func(true, cn.test_nonpositive, -10, 'non-positive');

check_func(true, cn.test_positive, 10, 'positive');
check_func(false, cn.test_positive, 0, 'positive');
check_func(false, cn.test_positive, -10, 'positive');

check_func(false, cn.test_negative, 10, 'negative');
check_func(false, cn.test_negative, 0, 'negative');
check_func(true, cn.test_negative, -10, 'negative');

check_func(true, cn.test_nonzero, 10, 'nonzero');
check_func(false, cn.test_nonzero, 0, 'nonzero');
check_func(true, cn.test_nonzero, -10, 'nonzero');

check_func(false, cn.test_nonnull, nil);
nonnull = cn.get_nonnull();
check_func(true, cn.test_nonnull, nonnull);


require("import")	-- the import fn
import("ret_by_value")	-- import code

a = ret_by_value.get_test()
assert(a.myInt == 100)
assert(a.myShort == 200)


require("import")   -- the import fn
import("chartest")   -- import code

function char_assert(char, code)
  assert(type(char) == 'string')
  assert(char:len() == 1)
  assert(char:byte() == code)
end

char_assert(chartest.GetPrintableChar(), 0x61)
char_assert(chartest.GetUnprintableChar(), 0x7F)

char_assert(chartest.printable_global_char, 0x61)
char_assert(chartest.unprintable_global_char, 0x7F)


require("import")	-- the import fn
import("cpp11_strongly_typed_enumerations")	-- import lib

-- catch "undefined" global variables
local env = _ENV -- Lua 5.2
if not env then env = getfenv () end -- Lua 5.1
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})

function enumCheck(actual, expected)
  if not (actual == expected) then
    error("Enum value mismatch. Expected: "..expected.." Actual: "..actual)
  end
  return expected + 1
end

--val = 0
--val = enumCheck(cpp11_strongly_typed_enumerations.cpp11_strongly_typed_enumerations.Enum1_Val1, val)
local val = 0
val = enumCheck(cpp11_strongly_typed_enumerations.Enum1_Val1, val)
val = enumCheck(cpp11_strongly_typed_enumerations.Enum1_Val2, val)
val = enumCheck(cpp11_strongly_typed_enumerations.Enum1_Val3, 13)
val = enumCheck(cpp11_strongly_typed_enumerations.Enum1_Val4, val)
val = enumCheck(cpp11_strongly_typed_enumerations.Enum1_Val5a, 13)
val = enumCheck(cpp11_strongly_typed_enumerations.Enum1_Val6a, val)

val = 0
val = enumCheck(cpp11_strongly_typed_enumerations.Enum2_Val1, val)
val = enumCheck(cpp11_strongly_typed_enumerations.Enum2_Val2, val)
val = enumCheck(cpp11_strongly_typed_enumerations.Enum2_Val3, 23)
val = enumCheck(cpp11_strongly_typed_enumerations.Enum2_Val4, val)
val = enumCheck(cpp11_strongly_typed_enumerations.Enum2_Val5b, 23)
val = enumCheck(cpp11_strongly_typed_enumerations.Enum2_Val6b, val)

val = 0
val = enumCheck(cpp11_strongly_typed_enumerations.Val1, val)
val = enumCheck(cpp11_strongly_typed_enumerations.Val2, val)
val = enumCheck(cpp11_strongly_typed_enumerations.Val3, 43)
val = enumCheck(cpp11_strongly_typed_enumerations.Val4, val)

val = 0
val = enumCheck(cpp11_strongly_typed_enumerations.Enum5_Val1, val)
val = enumCheck(cpp11_strongly_typed_enumerations.Enum5_Val2, val)
val = enumCheck(cpp11_strongly_typed_enumerations.Enum5_Val3, 53)
val = enumCheck(cpp11_strongly_typed_enumerations.Enum5_Val4, val)

val = 0
val = enumCheck(cpp11_strongly_typed_enumerations.Enum6_Val1, val)
val = enumCheck(cpp11_strongly_typed_enumerations.Enum6_Val2, val)
val = enumCheck(cpp11_strongly_typed_enumerations.Enum6_Val3, 63)
val = enumCheck(cpp11_strongly_typed_enumerations.Enum6_Val4, val)

val = 0
val = enumCheck(cpp11_strongly_typed_enumerations.Enum7td_Val1, val)
val = enumCheck(cpp11_strongly_typed_enumerations.Enum7td_Val2, val)
val = enumCheck(cpp11_strongly_typed_enumerations.Enum7td_Val3, 73)
val = enumCheck(cpp11_strongly_typed_enumerations.Enum7td_Val4, val)

val = 0
val = enumCheck(cpp11_strongly_typed_enumerations.Enum8_Val1, val)
val = enumCheck(cpp11_strongly_typed_enumerations.Enum8_Val2, val)
val = enumCheck(cpp11_strongly_typed_enumerations.Enum8_Val3, 83)
val = enumCheck(cpp11_strongly_typed_enumerations.Enum8_Val4, val)

val = 0
val = enumCheck(cpp11_strongly_typed_enumerations.Enum10_Val1, val)
val = enumCheck(cpp11_strongly_typed_enumerations.Enum10_Val2, val)
val = enumCheck(cpp11_strongly_typed_enumerations.Enum10_Val3, 103)
val = enumCheck(cpp11_strongly_typed_enumerations.Enum10_Val4, val)

val = 0
val = enumCheck(cpp11_strongly_typed_enumerations.Class1.Enum12_Val1, 1121)
val = enumCheck(cpp11_strongly_typed_enumerations.Class1.Enum12_Val2, 1122)
val = enumCheck(cpp11_strongly_typed_enumerations.Class1.Enum12_Val3, val)
val = enumCheck(cpp11_strongly_typed_enumerations.Class1.Enum12_Val4, val)
val = enumCheck(cpp11_strongly_typed_enumerations.Class1.Enum12_Val5c, 1121)
val = enumCheck(cpp11_strongly_typed_enumerations.Class1.Enum12_Val6c, val)

val = 0
val = enumCheck(cpp11_strongly_typed_enumerations.Class1.Val1, 1131)
val = enumCheck(cpp11_strongly_typed_enumerations.Class1.Val2, 1132)
val = enumCheck(cpp11_strongly_typed_enumerations.Class1.Val3, val)
val = enumCheck(cpp11_strongly_typed_enumerations.Class1.Val4, val)
val = enumCheck(cpp11_strongly_typed_enumerations.Class1.Val5d, 1131)
val = enumCheck(cpp11_strongly_typed_enumerations.Class1.Val6d, val)

val = 0
val = enumCheck(cpp11_strongly_typed_enumerations.Class1.Enum14_Val1, 1141)
val = enumCheck(cpp11_strongly_typed_enumerations.Class1.Enum14_Val2, 1142)
val = enumCheck(cpp11_strongly_typed_enumerations.Class1.Enum14_Val3, val)
val = enumCheck(cpp11_strongly_typed_enumerations.Class1.Enum14_Val4, val)
val = enumCheck(cpp11_strongly_typed_enumerations.Class1.Enum14_Val5e, 1141)
val = enumCheck(cpp11_strongly_typed_enumerations.Class1.Enum14_Val6e, val)

-- Requires nested class support to work
--val = 0
--val = enumCheck(cpp11_strongly_typed_enumerations.Class1.Struct1.Enum12_Val1, 3121)
--val = enumCheck(cpp11_strongly_typed_enumerations.Class1.Struct1.Enum12_Val2, 3122)
--val = enumCheck(cpp11_strongly_typed_enumerations.Class1.Struct1.Enum12_Val3, val)
--val = enumCheck(cpp11_strongly_typed_enumerations.Class1.Struct1.Enum12_Val4, val)
--val = enumCheck(cpp11_strongly_typed_enumerations.Class1.Struct1.Enum12_Val5f, 3121)
--val = enumCheck(cpp11_strongly_typed_enumerations.Class1.Struct1.Enum12_Val6f, val)
--
--val = 0
--val = enumCheck(cpp11_strongly_typed_enumerations.Class1.Struct1.Val1, 3131)
--val = enumCheck(cpp11_strongly_typed_enumerations.Class1.Struct1.Val2, 3132)
--val = enumCheck(cpp11_strongly_typed_enumerations.Class1.Struct1.Val3, val)
--val = enumCheck(cpp11_strongly_typed_enumerations.Class1.Struct1.Val4, val)
--
--val = 0
--val = enumCheck(cpp11_strongly_typed_enumerations.Class1.Struct1.Enum14_Val1, 3141)
--val = enumCheck(cpp11_strongly_typed_enumerations.Class1.Struct1.Enum14_Val2, 3142)
--val = enumCheck(cpp11_strongly_typed_enumerations.Class1.Struct1.Enum14_Val3, val)
--val = enumCheck(cpp11_strongly_typed_enumerations.Class1.Struct1.Enum14_Val4, val)
--val = enumCheck(cpp11_strongly_typed_enumerations.Class1.Struct1.Enum14_Val5g, 3141)
--val = enumCheck(cpp11_strongly_typed_enumerations.Class1.Struct1.Enum14_Val6g, val)

val = 0
val = enumCheck(cpp11_strongly_typed_enumerations.Class2.Enum12_Val1, 2121)
val = enumCheck(cpp11_strongly_typed_enumerations.Class2.Enum12_Val2, 2122)
val = enumCheck(cpp11_strongly_typed_enumerations.Class2.Enum12_Val3, val)
val = enumCheck(cpp11_strongly_typed_enumerations.Class2.Enum12_Val4, val)
val = enumCheck(cpp11_strongly_typed_enumerations.Class2.Enum12_Val5h, 2121)
val = enumCheck(cpp11_strongly_typed_enumerations.Class2.Enum12_Val6h, val)

val = 0
val = enumCheck(cpp11_strongly_typed_enumerations.Class2.Val1, 2131)
val = enumCheck(cpp11_strongly_typed_enumerations.Class2.Val2, 2132)
val = enumCheck(cpp11_strongly_typed_enumerations.Class2.Val3, val)
val = enumCheck(cpp11_strongly_typed_enumerations.Class2.Val4, val)
val = enumCheck(cpp11_strongly_typed_enumerations.Class2.Val5i, 2131)
val = enumCheck(cpp11_strongly_typed_enumerations.Class2.Val6i, val)

val = 0
val = enumCheck(cpp11_strongly_typed_enumerations.Class2.Enum14_Val1, 2141)
val = enumCheck(cpp11_strongly_typed_enumerations.Class2.Enum14_Val2, 2142)
val = enumCheck(cpp11_strongly_typed_enumerations.Class2.Enum14_Val3, val)
val = enumCheck(cpp11_strongly_typed_enumerations.Class2.Enum14_Val4, val)
val = enumCheck(cpp11_strongly_typed_enumerations.Class2.Enum14_Val5j, 2141)
val = enumCheck(cpp11_strongly_typed_enumerations.Class2.Enum14_Val6j, val)

-- Requires nested class support to work
--val = 0
--val = enumCheck(cpp11_strongly_typed_enumerations.Class2.Struct1.Enum12_Val1, 4121)
--val = enumCheck(cpp11_strongly_typed_enumerations.Class2.Struct1.Enum12_Val2, 4122)
--val = enumCheck(cpp11_strongly_typed_enumerations.Class2.Struct1.Enum12_Val3, val)
--val = enumCheck(cpp11_strongly_typed_enumerations.Class2.Struct1.Enum12_Val4, val)
--val = enumCheck(cpp11_strongly_typed_enumerations.Class2.Struct1.Enum12_Val5k, 4121)
--val = enumCheck(cpp11_strongly_typed_enumerations.Class2.Struct1.Enum12_Val6k, val)
--
--val = 0
--val = enumCheck(cpp11_strongly_typed_enumerations.Class2.Struct1.Val1, 4131)
--val = enumCheck(cpp11_strongly_typed_enumerations.Class2.Struct1.Val2, 4132)
--val = enumCheck(cpp11_strongly_typed_enumerations.Class2.Struct1.Val3, val)
--val = enumCheck(cpp11_strongly_typed_enumerations.Class2.Struct1.Val4, val)
--val = enumCheck(cpp11_strongly_typed_enumerations.Class2.Struct1.Val5l, 4131)
--val = enumCheck(cpp11_strongly_typed_enumerations.Class2.Struct1.Val6l, val)
--
--val = 0
--val = enumCheck(cpp11_strongly_typed_enumerations.Class2.Struct1.Enum14_Val1, 4141)
--val = enumCheck(cpp11_strongly_typed_enumerations.Class2.Struct1.Enum14_Val2, 4142)
--val = enumCheck(cpp11_strongly_typed_enumerations.Class2.Struct1.Enum14_Val3, val)
--val = enumCheck(cpp11_strongly_typed_enumerations.Class2.Struct1.Enum14_Val4, val)
--val = enumCheck(cpp11_strongly_typed_enumerations.Class2.Struct1.Enum14_Val5m, 4141)
--val = enumCheck(cpp11_strongly_typed_enumerations.Class2.Struct1.Enum14_Val6m, val)

class1 = cpp11_strongly_typed_enumerations.Class1()
enumCheck(class1:class1Test1(cpp11_strongly_typed_enumerations.Enum1_Val5a), 13)
enumCheck(class1:class1Test2(cpp11_strongly_typed_enumerations.Class1.Enum12_Val5c), 1121)
--enumCheck(class1:class1Test3(cpp11_strongly_typed_enumerations.Class1.Struct1.Enum12_Val5f), 3121)

enumCheck(cpp11_strongly_typed_enumerations.globalTest1(cpp11_strongly_typed_enumerations.Enum1_Val5a), 13)
enumCheck(cpp11_strongly_typed_enumerations.globalTest2(cpp11_strongly_typed_enumerations.Class1.Enum12_Val5c), 1121)
--enumCheck(globalTest3(cpp11_strongly_typed_enumerations.Class1.Struct1.Enum12_Val5f), 3121)


require("import")	-- the import fn
import("li_std_string")	-- import lib

for k,v in pairs(li_std_string) do _G[k]=v end -- move to global

-- catch "undefined" global variables
local env = _ENV -- Lua 5.2
if not env then env = getfenv () end -- Lua 5.1
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})

-- helper to check type
function is_std_string(s)
	return type(s)=='userdata' and swig_type(s)=='std::string *'
end

-- std::string by value is just a Lua string
s=test_value("foo")
assert(type(s)=="string" and s=="foo")

-- std::string by const ref is also just a Lua string
s=test_const_reference("foo")
assert(type(s)=="string" and s=="foo")

-- std:string* is an object
obj=test_pointer_out()
assert(is_std_string(obj) and obj:c_str()=="x")	-- check type & value

test_pointer(obj)	-- this wants an object

cobj=test_const_pointer_out()
assert(is_std_string(cobj) and cobj:c_str()=="x")	-- check type & value

test_const_pointer(cobj)

-- this shouldn't work, but it does
-- swig doesn't appear to diff between const object ptrs & object ptrs very well
test_pointer(cobj)	-- this wants an non const object (give it a const one!)

-- refs are also wrapped as ptrs (unless the correct typemaps are applied)
robj=test_reference_out()
assert(is_std_string(robj) and robj:c_str()=="test_reference_out message")	-- check type & value

test_reference(robj)
test_reference(obj)	-- object ptr is ok
test_reference(cobj)	-- obj const ptr is also ok

-- Test INPUT, INOUT and OUTPUT string& typemaps:
assert(test_reference_input("hello")=="hello")
s=test_reference_inout("hello")
assert(s=="hellohello")
assert(test_reference_output()=="output")

-- throwing string
ok,ex=pcall(test_throw)
assert(ok==false and type(ex)=="string")	-- failed & threw string

ok,ex=pcall(test_const_reference_throw)
assert(ok==false and type(ex)=="string")	-- failed & threw string

-- const ptrs are now converted to lua strings
-- they used to be std::string*
ok,ex=pcall(test_const_pointer_throw)
assert(ok==false and type(ex)=="string")	-- failed & threw object

-- ditto non const ptrs
ok,ex=pcall(test_pointer_throw)
assert(ok==false and type(ex)=="string")	-- failed & threw object

-- testing std::string variables
-- Global variables
s = "initial string"
assert (li_std_string.GlobalString2 == "global string 2")
li_std_string.GlobalString2 = s
assert (li_std_string.GlobalString2 == s)
assert (li_std_string.ConstGlobalString == "const global string")

-- Member variables
myStructure = Structure()
assert(myStructure.MemberString2 == "member string 2")
myStructure.MemberString2 = s
assert (myStructure.MemberString2 == s)
assert (myStructure.ConstMemberString == "const member string")

assert (li_std_string.Structure_StaticMemberString2 == "static member string 2")
li_std_string.Structure_StaticMemberString2 = s
assert (li_std_string.Structure_StaticMemberString2 == s)
assert (li_std_string.Structure_ConstStaticMemberString == "const static member string")

-- testing the structure (these are some old tests which predated the std::string variable tests above)
struc=Structure()

assert(type(struc.MemberString2)=="string") -- typemaps make this a string
assert(type(struc.ConstMemberString)=="string")

-- set a const (should fail with error)
assert(pcall(function () struc.ConstMemberString="c" end)==false)
--print(struc.MemberString:data(),struc.MemberString2,struc.ConstMemberString:data())

--check type again
assert(type(struc.MemberString2)=="string") -- typemaps make this a string
assert(type(struc.ConstMemberString)=="string")

-- for static types: they are really variables,
-- so we must still use the module name

-- check static type
assert(type(li_std_string.Structure_StaticMemberString2)=="string")
assert(type(li_std_string.Structure_ConstStaticMemberString)=="string")

-- try setting (should fail with error)
--li_std_string.Structure_StaticMemberString2='e'
assert(pcall(function () li_std_string.Structure_ConstStaticMemberString='f' end)==false)
--[[print(li_std_string.Structure_StaticMemberString:data(),
		li_std_string.Structure_StaticMemberString2,
		li_std_string.Structure_ConstStaticMemberString:data())]]

-- check static type again
assert(type(li_std_string.Structure_StaticMemberString)=="string")
assert(type(li_std_string.Structure_StaticMemberString2)=="string")
assert(type(li_std_string.Structure_ConstStaticMemberString)=="string")

assert(stdstring_empty()=="")
assert(c_empty()=="")
assert(c_null()==nil)
assert(get_null(c_null())==nil)
assert(get_null(c_empty())=="non-null")
assert(get_null(stdstring_empty())=="non-null")


require("import")	-- the import fn
import("newobject2",true)	-- import code

foo1 = newobject2.makeFoo()	-- lua doesn't yet support static fns properly
assert(newobject2.fooCount() == 1)	-- lua doesn't yet support static fns properly

foo2 = newobject2.makeFoo()
assert(newobject2.fooCount() == 2)

foo1 = nil
collectgarbage()
assert(newobject2.fooCount() == 1)

foo2 = nil
collectgarbage()
assert(newobject2.fooCount() == 0)