Initial community commit

This commit is contained in:
Jef 2024-09-24 14:54:57 +02:00
parent 537bcbc862
commit fc06254474
16440 changed files with 4239995 additions and 2 deletions

View file

@ -0,0 +1,67 @@
return {
-- Base API tests
"test_string.lua",
"base/test_aliasing.lua",
"base/test_binmodules.lua",
"base/test_configset.lua",
"base/test_context.lua",
"base/test_criteria.lua",
"base/test_detoken.lua",
"base/test_include.lua",
"base/test_module_loader.lua",
"base/test_option.lua",
"base/test_os.lua",
"base/test_override.lua",
"base/test_path.lua",
"base/test_premake_command.lua",
"base/test_table.lua",
"base/test_tree.lua",
"base/test_rule.lua",
"base/test_uuid.lua",
"base/test_versions.lua",
"base/test_http.lua",
"base/test_json.lua",
-- Workspace object tests
"workspace/test_eachconfig.lua",
"workspace/test_location.lua",
"workspace/test_objdirs.lua",
-- Project object tests
"project/test_config_maps.lua",
"project/test_eachconfig.lua",
"project/test_getconfig.lua",
"project/test_location.lua",
"project/test_sources.lua",
"project/test_vpaths.lua",
-- Configuration object tests
"config/test_linkinfo.lua",
"config/test_links.lua",
"config/test_targetinfo.lua",
-- Baking tests
"oven/test_filtering.lua",
"oven/test_objdirs.lua",
-- API tests
"api/test_boolean_kind.lua",
"api/test_containers.lua",
"api/test_directory_kind.lua",
"api/test_list_kind.lua",
"api/test_path_kind.lua",
"api/test_register.lua",
"api/test_string_kind.lua",
"api/test_table_kind.lua",
"api/test_deprecations.lua",
-- Control system tests
"test_premake.lua",
"base/test_validation.lua",
-- -- Toolset tests
"tools/test_dotnet.lua",
"tools/test_gcc.lua",
"tools/test_clang.lua",
"tools/test_msc.lua",
}

View file

@ -0,0 +1,80 @@
--
-- tests/api/test_boolean_kind.lua
-- Tests the boolean API value type.
-- Copyright (c) 2014 Jason Perkins and the Premake project
--
local p = premake
local suite = test.declare("api_boolean_kind")
local api = p.api
--
-- Setup and teardown
--
function suite.setup()
api.register {
name = "testapi",
kind = "boolean",
scope = "project",
}
test.createWorkspace()
end
function suite.teardown()
testapi = nil
end
--
-- Check setting of true values.
--
function suite.setsTrue_onYes()
testapi "yes"
test.istrue(api.scope.project.testapi)
end
function suite.setsTrue_onBooleanTrue()
testapi (true)
test.istrue(api.scope.project.testapi)
end
function suite.setsTrue_onNonZero()
testapi (1)
test.istrue(api.scope.project.testapi)
end
--
-- Check setting of false values.
--
function suite.setsFalse_onNo()
testapi "no"
test.isfalse(api.scope.project.testapi)
end
function suite.setsFalse_onBooleanFalse()
testapi (false)
test.isfalse(api.scope.project.testapi)
end
function suite.setsFalse_onZero()
testapi (0)
test.isfalse(api.scope.project.testapi)
end
--
-- Raise an error on an invalid string value.
--
function suite.raisesError_onDisallowedValue()
ok, err = pcall(function ()
testapi "maybe"
end)
test.isfalse(ok)
end

View file

@ -0,0 +1,94 @@
--
-- tests/api/test_containers.lua
-- Tests the API's workspace() and project() container definitions.
-- Copyright (c) 2013-2014 Jason Perkins and the Premake project
--
local p = premake
local suite = test.declare("api_containers")
local api = p.api
--
-- Setup and teardown
--
local wks
function suite.setup()
wks = workspace("MyWorkspace")
end
--
-- The first time a name is encountered, a new container should be created.
--
function suite.workspace_createsOnFirstUse()
test.isnotnil(p.global.getWorkspace("MyWorkspace"))
end
function suite.project_createsOnFirstUse()
project("MyProject")
test.isnotnil(test.getproject(wks, "MyProject"))
end
--
-- When a container is created, it should become the active scope.
--
function suite.workspace_setsActiveScope()
test.issame(api.scope.workspace, wks)
end
function suite.project_setsActiveScope()
local prj = project("MyProject")
test.issame(api.scope.project, prj)
end
--
-- When container function is called with no arguments, that should
-- become the current scope.
--
function suite.workspace_setsActiveScope_onNoArgs()
project("MyProject")
group("MyGroup")
workspace()
test.issame(wks, api.scope.workspace)
test.isnil(api.scope.project)
test.isnil(api.scope.group)
end
function suite.project_setsActiveScope_onNoArgs()
local prj = project("MyProject")
group("MyGroup")
project()
test.issame(prj, api.scope.project)
end
--
-- The "*" name should activate the parent scope.
--
function suite.workspace_onStar()
project("MyProject")
group("MyGroup")
filter("Debug")
workspace("*")
test.isnil(api.scope.workspace)
test.isnil(api.scope.project)
test.isnil(api.scope.group)
end
function suite.project_onStar()
project("MyProject")
group("MyGroup")
filter("Debug")
project "*"
test.issame(wks, api.scope.workspace)
test.isnil(api.scope.project)
end

View file

@ -0,0 +1,66 @@
--
-- tests/api/test_table_kind.lua
-- Tests the table API value type.
-- Copyright (c) 2012-2014 Jason Perkins and the Premake project
--
local p = premake
local suite = test.declare("api_deprecations")
local api = p.api
function suite.setup()
workspace("MyWorkspace")
configurations { "Debug", "Release" }
end
function suite.setsNewValue_whenOldValueIsRemovedViaWildcard_inSubConfig()
local prj = project "MyProject"
filter { "configurations:Debug" }
flags { "Symbols" }
filter { "*" }
removeflags { "*" }
-- test output.
local cfg = test.getconfig(prj, "Debug", platform)
test.isequal("Default", cfg.Symbols)
end
function suite.setsNewValue_whenOldValueIsRemovedInOtherConfig_inSubConfig()
local prj = project "MyProject"
flags { "Symbols" }
filter { "configurations:Release" }
removeflags { "*" }
-- test output.
test.isequal("On", test.getconfig(prj, "Debug", platform).Symbols)
test.isequal("Default", test.getconfig(prj, "Release", platform).Symbols)
end
function suite.dontRemoveFlagIfSetThroughNewApi()
local prj = project "MyProject"
floatingpoint "Fast"
removeflags "*"
-- test output.
local cfg = test.getconfig(prj, "Debug", platform)
test.isequal("Fast", cfg.floatingpoint)
end
function suite.setsNewValue_whenOldValueFromParentIsRemovedInOtherConfig_inSubConfig()
flags { "Symbols" }
local prj = project "MyProject"
filter { "configurations:Release" }
removeflags { "*" }
-- test output.
test.isequal("On", test.getconfig(prj, "Debug", platform).Symbols)
test.isequal("Default", test.getconfig(prj, "Release", platform).Symbols)
end

View file

@ -0,0 +1,49 @@
--
-- tests/api/test_directory_kind.lua
-- Tests the directory API value type.
-- Copyright (c) 2013 Jason Perkins and the Premake project
--
local p = premake
local suite = test.declare("api_directory_kind")
local api = p.api
--
-- Setup and teardown
--
function suite.setup()
api.register {
name = "testapi",
kind = "directory",
list = true,
scope = "project"
}
test.createWorkspace()
end
function suite.teardown()
testapi = nil
end
--
-- Values should be converted to absolute paths, relative to
-- the currently running script.
--
function suite.convertsToAbsolute()
testapi "self/local"
test.isequal({os.getcwd() .. "/self/local"}, api.scope.project.testapi)
end
--
-- Check expansion of wildcards.
--
function suite.expandsWildcards()
testapi (_TESTS_DIR .. "/*")
test.istrue(table.contains(api.scope.project.testapi, _TESTS_DIR .. "/api"))
end

View file

@ -0,0 +1,86 @@
--
-- tests/api/test_list_kind.lua
-- Tests the list API value type.
-- Copyright (c) 2012 Jason Perkins and the Premake project
--
local p = premake
local suite = test.declare("api_list_kind")
local api = p.api
--
-- Setup and teardown
--
function suite.setup()
api.register {
name = "testapi",
kind = "string",
list = true,
scope = "project",
allowed = { "first", "second", "third" }
}
test.createWorkspace()
end
function suite.teardown()
testapi = nil
end
--
-- Table values should be stored as-is.
--
function suite.storesTable_onArrayValue()
testapi { "first", "second" }
test.isequal({ "first", "second" }, api.scope.project.testapi)
end
--
-- String values should be converted into a table.
--
function suite.storesTable_onStringValue()
testapi "first"
test.isequal({ "first" }, api.scope.project.testapi)
end
--
-- New values should be appended to any previous values.
--
function suite.overwrites_onNewValue()
testapi "first"
testapi "second"
test.isequal({ "first", "second" }, api.scope.project.testapi)
end
--
-- Nested lists should be flattened.
--
function suite.flattensValues_onNestedLists()
testapi { { "first" }, { "second" } }
test.isequal({ "first", "second" }, api.scope.project.testapi)
end
--
-- If an allowed values list is present, make sure it gets applied.
--
function suite.raisesError_onDisallowedValue()
ok, err = pcall(function ()
testapi "NotAllowed"
end)
test.isfalse(ok)
end
function suite.convertsCase_onAllowedValue()
testapi "seCOnd"
test.isequal({ "second" }, api.scope.project.testapi)
end

View file

@ -0,0 +1,38 @@
--
-- tests/api/test_path_kind.lua
-- Tests the path API value type.
-- Copyright (c) 2012 Jason Perkins and the Premake project
--
local p = premake
local suite = test.declare("api_path_kind")
local api = p.api
--
-- Setup and teardown
--
function suite.setup()
api.register {
name = "testapi",
kind = "path",
scope = "project"
}
test.createWorkspace()
end
function suite.teardown()
testapi = nil
end
--
-- Values should be converted to absolute paths, relative to
-- the currently running script.
--
function suite.convertsToAbsolute()
testapi "self/local.h"
test.isequal(os.getcwd() .. "/self/local.h", api.scope.project.testapi)
end

View file

@ -0,0 +1,88 @@
--
-- tests/api/test_register.lua
-- Tests the new API registration function.
-- Copyright (c) 2012 Jason Perkins and the Premake project
--
local p = premake
local suite = test.declare("api_register")
local api = p.api
--
-- Setup and teardown
--
function suite.teardown()
testapi = nil
end
--
-- Verify that the function exists.
--
function suite.registerFunctionExists()
test.isequal("function", type(p.api.register))
end
--
-- When called, a new function with with provided name should
-- added to the global namespace.
--
function suite.createsNewGlobalFunction()
api.register { name = "testapi", kind = "string", scope = "project" }
test.isequal("function", type(testapi));
end
--
-- Verify that an error is raised if no name is provided.
--
function suite.raisesError_onMissingName()
ok, err = pcall(function ()
api.register { kind = "string", scope = "project" }
end)
test.isfalse(ok)
end
--
-- Verify that an error is raised if the name is already in use.
--
function suite.raisesError_onExistingGlobalName()
testapi = "testapi"
ok, err = pcall(function ()
api.register { name = "testapi", kind = "string", scope = "project" }
end)
test.isfalse(ok)
end
--
-- Verify that an error is raised if an invalid kind is used.
--
function suite.raisesError_onInvalidKind()
ok, err = pcall(function ()
api.register { name = "testapi", kind = "bogus", scope = "project" }
end)
test.isfalse(ok)
end
--
-- Verify that key-value forms are accepted.
--
function suite.succeeds_onKeyValueForm()
ok, err = pcall(function ()
api.register { name = "testapi", kind = "string", keyed = true, scope = "project" }
end)
test.istrue(ok)
end

View file

@ -0,0 +1,85 @@
--
-- tests/api/test_string_kind.lua
-- Tests the string API value type.
-- Copyright (c) 2012 Jason Perkins and the Premake project
--
local p = premake
local suite = test.declare("api_string_kind")
local api = p.api
--
-- Setup and teardown
--
function suite.setup()
api.register {
name = "testapi",
kind = "string",
scope = "project",
allowed = { "One", "Two", "Three" },
}
test.createWorkspace()
end
function suite.teardown()
testapi = nil
end
--
-- String values should be stored as-is.
--
function suite.storesString_onStringValue()
testapi "One"
test.isequal("One", api.scope.project.testapi)
end
--
-- New values should overwrite old ones.
--
function suite.overwritesPreviousValues()
testapi "One"
testapi "Two"
test.isequal("Two", api.scope.project.testapi)
end
--
-- An error occurs if a table value is assigned to a string field.
--
function suite.raisesError_onTableValue()
ok, err = pcall(function ()
testapi { "One", "Two" }
end)
test.isfalse(ok)
end
--
-- Raises an error on a disallowed value.
--
function suite.raisesError_onDisallowedValue()
ok, err = pcall(function ()
testapi "NotAllowed"
end)
test.isfalse(ok)
end
--
-- If allowed values present, converts to provided case.
--
function suite.convertsCase_onAllowedValue()
testapi "oNe"
test.isequal("One", api.scope.project.testapi)
end

View file

@ -0,0 +1,54 @@
--
-- tests/api/test_table_kind.lua
-- Tests the table API value type.
-- Copyright (c) 2012-2014 Jason Perkins and the Premake project
--
local p = premake
local suite = test.declare("api_table_kind")
local api = p.api
--
-- Setup and teardown
--
function suite.setup()
api.register { name = "testapi", kind = "table", scope = "project" }
test.createWorkspace()
end
function suite.teardown()
testapi = nil
end
--
-- Array values should be stored as-is.
--
function suite.storesTable_onArrayValue()
testapi { "one", "two" }
test.isequal({ "one", "two" }, api.scope.project.testapi)
end
--
-- String values should be converted into a table.
--
function suite.storesTable_onStringValue()
testapi "myvalue"
test.isequal({ "myvalue" }, api.scope.project.testapi)
end
--
-- New values should overwrite old.
--
function suite.overwrites_onNewValue()
testapi "first"
testapi "second"
test.isequal({ "second" }, api.scope.project.testapi)
end

View file

@ -0,0 +1 @@
This is a test file for os.matchfiles tests.

View file

@ -0,0 +1,65 @@
--
-- tests/base/test_aliasing.lua
-- Verify handling of function aliases.
-- Copyright (c) 2015 Jason Perkins and the Premake project
--
local suite = test.declare("premake_alias")
local m = {}
local p = premake
function suite.setup()
m.testfunc = function()
return 48
end
m.aliased = nil
m.aliased2 = nil
end
function suite.returnsOriginalFunction_onNoAlias()
local scope, f = p.resolveAlias(m, "testfunc")
test.isequal("testfunc", f)
end
function suite.pointsAliasToOriginalFunction()
p.alias(m, "testfunc", "aliased")
test.isequal(48, m.aliased())
end
function suite.returnsOriginalFunction_onAlias()
p.alias(m, "testfunc", "aliased")
local scope, f = p.resolveAlias(m, "aliased")
test.isequal("testfunc", f)
end
function suite.returnsOriginalFunction_onChainedAliases()
p.alias(m, "testfunc", "aliased")
p.alias(m, "aliased", "aliased2")
local scope, f = p.resolveAlias(m, "aliased2")
test.isequal("testfunc", f)
end
function suite.overrideResolvesAliases()
p.alias(m, "testfunc", "aliased")
p.override(m, "aliased", function(base)
return base() + 1
end)
test.isequal(49, m.testfunc())
end
function suite.aliasTracksOverrides()
p.alias(m, "testfunc", "aliased")
p.override(m, "testfunc", function(base)
return base() + 1
end)
test.isequal(49, m.aliased())
end

View file

@ -0,0 +1,19 @@
--
-- tests/base/test_binmodules.lua
-- Verify handling of binary modules.
-- Copyright (c) 2017 Tom van Dijck and the Premake project
--
local suite = test.declare("premake_binmodules")
local p = premake
function suite.setup()
require("example")
end
function suite.testExample()
local result = example.test("world")
test.isequal("hello world", result)
end

View file

@ -0,0 +1,261 @@
--
-- tests/base/test_configset.lua
-- Test suite for the configset API.
-- Copyright (c) 2012-2014 Jason Perkins and the Premake project
--
local p = premake
local suite = test.declare("configset")
local configset = p.configset
local field = p.field
--
-- Setup and teardown
--
local cset, parentset
function suite.setup()
local wks = test.createWorkspace()
parentset = configset.new()
cset = configset.new(parentset)
end
--
-- Make sure that new() returns a valid object.
--
function suite.new_returnsValidObject()
test.isequal("table", type(cset))
end
--
-- Check the default values for different field types.
--
function suite.defaultValue_onString()
test.isnil(configset.fetch(cset, field.get("targetextension")))
end
function suite.defaultValue_onList()
test.isequal({}, configset.fetch(cset, field.get("defines")))
end
--
-- Make sure that I can roundtrip a value stored into the
-- initial, default configuration.
--
function suite.canRoundtrip_onDefaultBlock()
local f = field.get("targetextension")
configset.store(cset, f, ".so")
test.isequal(".so", configset.fetch(cset, f, {}))
end
--
-- Make sure that I can roundtrip a value stored into a block
-- with a simple matching term.
--
function suite.canRoundtrip_onSimpleTermMatch()
local f = field.get("targetextension")
configset.addblock(cset, { "Windows" })
configset.store(cset, f, ".dll")
test.isequal(".dll", configset.fetch(cset, f, { "windows" }))
end
--
-- Make sure that blocks that do not match the context terms
-- do not contribute to the result.
--
function suite.skipsBlock_onTermMismatch()
local f = field.get("targetextension")
configset.store(cset, f, ".so")
configset.addblock(cset, { "Windows" })
configset.store(cset, f, ".dll")
test.isequal(".so", configset.fetch(cset, f, { "linux" }))
end
--
-- Values stored in a parent configuration set should propagate into child.
--
function suite.canRoundtrip_fromParentToChild()
local f = field.get("targetextension")
configset.store(parentset, f, ".so")
test.isequal(".so", configset.fetch(cset, f, {}))
end
--
-- Child should be able to override parent values.
--
function suite.child_canOverrideStringValueFromParent()
local f = field.get("targetextension")
configset.store(parentset, f, ".so")
configset.store(cset, f, ".dll")
test.isequal(".dll", configset.fetch(cset, f, {}))
end
--
-- If a base directory is set, filename tests should be performed
-- relative to this path.
--
function suite.filenameMadeRelative_onBaseDirSet()
local f = field.get("buildaction")
configset.addblock(cset, { "hello.c" }, os.getcwd())
configset.store(cset, f, "Copy")
test.isequal("Copy", configset.fetch(cset, f, { files=path.join(os.getcwd(), "hello.c"):lower() }))
end
--
-- List fields should return an empty list of not set.
--
function suite.lists_returnsEmptyTable_onNotSet()
test.isequal({}, configset.fetch(cset, field.get("buildoptions"), {}))
end
--
-- List fields should merge values fetched from different blocks.
--
function suite.lists_mergeValues_onFetch()
local f = field.get("buildoptions")
configset.store(cset, f, "v1")
configset.addblock(cset, { "windows" })
configset.store(cset, f, "v2")
test.isequal({"v1", "v2"}, configset.fetch(cset, f, {"windows"}))
end
--
-- Multiple adds to a list field in the same block should be merged together.
--
function suite.lists_mergeValues_onAdd()
local f = field.get("buildoptions")
configset.store(cset, f, "v1")
configset.store(cset, f, "v2")
test.isequal({"v1", "v2"}, configset.fetch(cset, f, {"windows"}))
end
--
-- Fetched lists should be both keyed and indexed.
--
function suite.lists_includeValueKeys()
local f = field.get("buildoptions")
configset.store(cset, f, { "v1", "v2" })
local x = configset.fetch(cset, f, {})
test.isequal("v2", x.v2)
end
--
-- Check removing a value with an exact match.
--
function suite.remove_onExactValueMatch()
local f = field.get("flags")
local r, err = configset.store(cset, f, { "Symbols", "WinMain", "MFC" })
test.isnil(err)
configset.remove(cset, f, { "WinMain" })
local result = configset.fetch(cset, f)
test.isequal({ "Symbols", "MFC" }, result)
end
function suite.remove_onMultipleValues()
local f = field.get("flags")
local r, err = configset.store(cset, f, { "Symbols", "Maps", "WinMain", "MFC" })
test.isnil(err)
configset.remove(cset, f, { "Maps", "MFC" })
local result = configset.fetch(cset, f)
test.isequal({ "Symbols", "WinMain" }, result)
end
--
-- Remove should also accept wildcards.
--
function suite.remove_onWildcard()
local f = field.get("defines")
configset.store(cset, f, { "WIN32", "WIN64", "LINUX", "MACOSX" })
configset.remove(cset, f, { "WIN*" })
test.isequal({ "LINUX", "MACOSX" }, configset.fetch(cset, f, {}))
end
--
-- Keyed values should merge keys fetched from different blocks.
--
function suite.keyed_mergesKeys_onFetch()
local f = field.get("configmap")
configset.store(cset, f, { Debug="Debug", Release="Release" })
configset.addblock(cset, { "windows" })
configset.store(cset, f, { Profile="Profile" })
local x = configset.fetch(cset, f, {"windows"})
test.istrue(x[1].Debug and x[1].Release and x[2].Profile)
end
--
-- Multiple adds to a keyed value field in the same block should be merged.
--
function suite.keyed_mergesKeys_onAdd()
local f = field.get("configmap")
configset.store(cset, f, { Debug="Debug", Release="Release" })
configset.store(cset, f, { Profile="Profile" })
local x = configset.fetch(cset, f, {"windows"})
test.istrue(x[1].Debug and x[1].Release and x[2].Profile)
end
--
-- Keyed values should overwrite when non-merged fields are fetched.
--
function suite.keyed_overwritesValues_onNonMergeFetch()
local f = field.get("configmap")
configset.store(cset, f, { Debug="Debug" })
configset.addblock(cset, { "windows" })
configset.store(cset, f, { Debug="Development" })
local x = configset.fetch(cset, f, {"windows"})
test.isequal({"Development"}, x[2].Debug)
end
function suite.keyed_overwritesValues_onNonMergeAdd()
local f = field.get("configmap")
configset.store(cset, f, { Debug="Debug" })
configset.store(cset, f, { Debug="Development" })
local x = configset.fetch(cset, f, {"windows"})
test.isequal({"Development"}, x[2].Debug)
end

View file

@ -0,0 +1,113 @@
--
-- tests/base/test_context.lua
-- Test suite for the configuration context API.
-- Copyright (c) 2012-2014 Jason Perkins and the Premake project
--
local p = premake
local suite = test.declare("context")
local context = p.context
local configset = p.configset
local field = p.field
--
-- Setup and teardown
--
local ctx, cset
function suite.setup()
cset = configset.new()
ctx = context.new(cset)
end
--
-- Make sure that new() returns a valid object.
--
function suite.new_returnsValidObject()
test.isequal("table", type(ctx))
end
--
-- Context should be able to retrieve a default value from
-- the configuration set, using the field name.
--
function suite.returnsConfigValue_onExistingValue()
configset.store(cset, field.get("targetextension"), ".so")
test.isequal(".so", ctx.targetextension)
end
--
-- Tokens encountered in enabled fields should be expanded.
--
function suite.doesExpandTokens()
configset.store(cset, field.get("targetname"), "MyProject%{1 + 1}")
test.isequal("MyProject2", ctx.targetname)
end
--
-- Token environment in extended context overrides context.
--
function suite.extent()
-- set in toplevel context.
configset.store(cset, field.get("targetname"), "%{value}")
-- detoken in toplevel context should result in empty string.
test.isequal("", ctx.targetname)
-- create an extended context with a local environ.
local environ = {
value = "text"
}
local ext = context.extent(ctx, environ)
-- detoken in extended context should result in value set in that environ.
test.isequal("text", ext.targetname)
end
--
-- mergeFilters should behave as expected for tags
--
function suite.mergeFilters()
ctx = { terms = { tags = { "ctxtags" } } }
src = { terms = { tags = { "srctags" } } }
context.mergeFilters(ctx, src)
result = { terms = { tags = { "ctxtags", "srctags" } } }
test.isequal(result, ctx)
end
function suite.mergeFilters_keeptype()
ctx = { terms = { kind = "ConsoleApp" } }
src = { terms = { kind = "ConsoleApp" } }
context.mergeFilters(ctx, src)
test.isequal("string", type(ctx.terms.kind))
end
function suite.mergeFilters_createtable()
ctx = { terms = { tags = "ctxtags" } }
src = { terms = { tags = "srctags" } }
context.mergeFilters(ctx, src)
result = { terms = { tags = { "ctxtags", "srctags" } } }
test.isequal(result, ctx)
end

View file

@ -0,0 +1,362 @@
--
-- tests/base/test_criteria.lua
-- Test suite for the criteria matching API.
-- Copyright (c) 2012-2015 Jason Perkins and the Premake project
--
local p = premake
local suite = test.declare("criteria")
local criteria = p.criteria
--
-- Setup and teardown
--
local crit
--
-- A criteria with no terms should satisfy any context.
--
function suite.matches_alwaysTrue_onNoFilterTerms()
crit = criteria.new {}
test.istrue(criteria.matches(crit, { configurations="Debug", system="Windows" }))
end
--
-- Should not match if any term is missing in the context.
--
function suite.matches_fails_onMissingContext()
crit = criteria.new { "system:Windows", "architecture:x86" }
test.isfalse(criteria.matches(crit, { configurations="Debug", system="Windows" }))
end
--
-- Context terms must match the entire criteria term.
--
function suite.matches_fails_onIncompleteTermMatch()
crit = criteria.new { "platforms:win64" }
test.isfalse(criteria.matches(crit, { platforms="win64 dll dcrt" }))
end
--
-- Wildcard matches should work.
--
function suite.matches_passes_onPatternMatch()
crit = criteria.new { "action:vs*" }
test.istrue(criteria.matches(crit, { action="vs2005" }))
end
--
-- The "not" modifier should fail the test if the term is matched.
--
function suite.matches_fails_onMatchWithNotModifier_afterPrefix()
crit = criteria.new { "system:not windows" }
test.isfalse(criteria.matches(crit, { system="windows" }))
end
function suite.matches_fails_onMatchWithNotModifier_beforePrefix()
crit = criteria.new { "not system:windows" }
test.isfalse(criteria.matches(crit, { system="windows" }))
end
function suite.matches_passes_onMissWithNotModifier_afterPrefix()
crit = criteria.new { "system:not windows" }
test.istrue(criteria.matches(crit, { system="linux" }))
end
function suite.matches_passes_onMissWithNotModifier_beforePrefix()
crit = criteria.new { "not system:windows" }
test.istrue(criteria.matches(crit, { system="linux" }))
end
function suite.matches_passes_onMissWithNotModifier_noPrefix()
crit = criteria.new { "not debug" }
test.istrue(criteria.matches(crit, { configurations="release" }))
end
--
-- The "or" modifier should pass if either term is present.
--
function suite.matches_passes_onFirstOrTermMatched()
crit = criteria.new { "system:windows or linux" }
test.istrue(criteria.matches(crit, { system="windows" }))
end
function suite.matches_passes_onSecondOrTermMatched()
crit = criteria.new { "system:windows or linux" }
test.istrue(criteria.matches(crit, { system="linux" }))
end
function suite.matches_passes_onThirdOrTermMatched()
crit = criteria.new { "system:windows or linux or vs2005" }
test.istrue(criteria.matches(crit, { system="vs2005" }))
end
function suite.matches_fails_onNoOrTermMatched()
crit = criteria.new { "system:windows or linux" }
test.isfalse(criteria.matches(crit, { system="vs2005" }))
end
function suite.matches_passes_onMixedPrefixes_firstTermMatched_projectContext()
crit = criteria.new { "system:windows or files:core*" }
test.istrue(criteria.matches(crit, { system="windows" }))
end
function suite.matches_fails_onMixedPrefixes_firstTermMatched_fileContext()
crit = criteria.new { "system:windows or files:core*" }
test.isfalse(criteria.matches(crit, { system="windows", files="hello.cpp" }))
end
function suite.matches_passes_onMixedPrefixes_secondTermMatched()
crit = criteria.new { "system:windows or files:core*" }
test.istrue(criteria.matches(crit, { system="linux", files="coregraphics.cpp" }))
end
function suite.matches_fails_onMixedPrefixes_noTermMatched()
crit = criteria.new { "system:windows or files:core*" }
test.isfalse(criteria.matches(crit, { system="linux", files="hello.cpp" }))
end
--
-- The "not" modifier should fail on any match with an "or" modifier.
--
function suite.matches_passes_onNotOrMatchesFirst()
crit = criteria.new { "system:not windows or linux" }
test.isfalse(criteria.matches(crit, { system="windows" }))
end
function suite.matches_passes_onNotOrMatchesSecond()
crit = criteria.new { "system:windows or not linux" }
test.isfalse(criteria.matches(crit, { system="linux" }))
end
--
-- The "not" modifier should succeed with "or" if there are no matches.
--
function suite.matches_passes_onNoNotMatch()
crit = criteria.new { "system:not windows or linux" }
test.istrue(criteria.matches(crit, { system="macosx" }))
end
--
-- If the context specifies a filename, the filter must match it explicitly.
--
function suite.matches_passes_onFilenameAndMatchingPattern()
crit = criteria.new { "files:**.c", "system:windows" }
test.istrue(criteria.matches(crit, { system="windows", files="hello.c" }))
end
function suite.matches_fails_onFilenameAndNoMatchingPattern()
crit = criteria.new { "system:windows" }
test.isfalse(criteria.matches(crit, { system="windows", files="hello.c" }))
end
--
-- Test criteria creation through a table.
--
function suite.createCriteriaWithTable()
crit = criteria.new {
files = { "**.c" },
system = "windows"
}
test.istrue(criteria.matches(crit, { system="windows", files="hello.c" }))
end
function suite.createCriteriaWithTable2()
crit = criteria.new {
system = "not windows"
}
test.isfalse(criteria.matches(crit, { system="windows" }))
end
function suite.createCriteriaWithTable3()
crit = criteria.new {
system = "not windows or linux"
}
test.istrue(criteria.matches(crit, { system="macosx" }))
end
function suite.createCriteriaWithTable4()
crit = criteria.new {
system = "windows or linux"
}
test.istrue(criteria.matches(crit, { system="windows" }))
end
--
-- "Not" modifiers can also be used on filenames.
--
function suite.matches_passes_onFilenameMissAndNotModifier()
crit = criteria.new { "files:not **.c", "system:windows" }
test.istrue(criteria.matches(crit, { system="windows", files="hello.h" }))
end
function suite.matches_fails_onFilenameHitAndNotModifier()
crit = criteria.new { "files:not **.c", "system:windows" }
test.isfalse(criteria.matches(crit, { system="windows", files="hello.c" }))
end
--
-- If context provides a list of values, match against them.
--
function suite.matches_passes_termMatchesList()
crit = criteria.new { "options:debug" }
test.istrue(criteria.matches(crit, { options={ "debug", "logging" }}))
end
--
-- If no prefix is specified, default to "configurations".
--
function suite.matches_usesDefaultPrefix_onSingleTerm()
crit = criteria.new { "debug" }
test.istrue(criteria.matches(crit, { configurations="debug" }))
end
--
-- These tests use the older, unprefixed style of filter terms. This
-- approach will get phased out eventually, but are still included here
-- for backward compatibility testing.
--
function suite.matches_onEmptyCriteria_Unprefixed()
crit = criteria.new({}, true)
test.istrue(criteria.matches(crit, { "apple", "orange" }))
end
function suite.fails_onMissingContext_Unprefixed()
crit = criteria.new({ "orange", "pear" }, true)
test.isfalse(criteria.matches(crit, { "apple", "orange" }))
end
function suite.fails_onIncompleteMatch_Unprefixed()
crit = criteria.new({ "win64" }, true)
test.isfalse(criteria.matches(crit, { "win64 dll dcrt" }))
end
function suite.passes_onPatternMatch_Unprefixed()
crit = criteria.new({ "vs*" }, true)
test.istrue(criteria.matches(crit, { "vs2005" }))
end
function suite.fails_onNotMatch_Unprefixed()
crit = criteria.new({ "not windows" }, true)
test.isfalse(criteria.matches(crit, { "windows" }))
end
function suite.passes_onNotUnmatched_Unprefixed()
crit = criteria.new({ "not windows" }, true)
test.istrue(criteria.matches(crit, { "linux" }))
end
function suite.passes_onFirstOrTermMatched_Unprefixed()
crit = criteria.new({ "windows or linux" }, true)
test.istrue(criteria.matches(crit, { "windows" }))
end
function suite.passes_onSecondOrTermMatched_Unprefixed()
crit = criteria.new({ "windows or linux" }, true)
test.istrue(criteria.matches(crit, { "linux" }))
end
function suite.passes_onThirdOrTermMatched_Unprefixed()
crit = criteria.new({ "windows or linux or vs2005" }, true)
test.istrue(criteria.matches(crit, { "vs2005" }))
end
function suite.fails_onNoOrTermMatched_Unprefixed()
crit = criteria.new({ "windows or linux" }, true)
test.isfalse(criteria.matches(crit, { "vs2005" }))
end
function suite.passes_onNotOrMatchesFirst_Unprefixed()
crit = criteria.new({ "not windows or linux" }, true)
test.isfalse(criteria.matches(crit, { "windows" }))
end
function suite.passes_onNotOrMatchesSecond_Unprefixed()
crit = criteria.new({ "windows or not linux" }, true)
test.isfalse(criteria.matches(crit, { "linux" }))
end
function suite.passes_onNoNotMatch_Unprefixed()
crit = criteria.new({ "not windows or linux" }, true)
test.istrue(criteria.matches(crit, { "macosx" }))
end
function suite.passes_onFilenameAndMatchingPattern_Unprefixed()
crit = criteria.new({ "**.c", "windows" }, true)
test.istrue(criteria.matches(crit, { system="windows", files="hello.c" }))
end
function suite.fails_onFilenameAndNoMatchingPattern_Unprefixed()
crit = criteria.new({ "windows" }, true)
test.isfalse(criteria.matches(crit, { system="windows", files="hello.c" }))
end
function suite.fails_onFilenameAndNotModifier_Unprefixed()
crit = criteria.new({ "not linux" }, true)
test.isfalse(criteria.matches(crit, { system="windows", files="hello.c" }))
end
function suite.matches_passes_termMatchesList_Unprefixed()
crit = criteria.new({ "debug" }, true)
test.istrue(criteria.matches(crit, { options={ "debug", "logging" }}))
end
--
-- Should return nil and an error message on an invalid prefix.
--
function suite.returnsNilAndError_onInvalidPrefix()
crit, err = criteria.new { "gibble:Debug" }
test.isnil(crit)
test.isnotnil(err)
end
--
-- Should respect field value aliases, if present.
--
function suite.passes_onAliasedValue()
p.api.addAliases("system", { ["gnu-linux"] = "linux" })
crit = criteria.new { "system:gnu-linux" }
test.istrue(criteria.matches(crit, { system="linux" }))
end
function suite.passes_onAliasedValue_withMixedCase()
p.api.addAliases("system", { ["gnu-linux"] = "linux" })
crit = criteria.new { "System:GNU-Linux" }
test.istrue(criteria.matches(crit, { system="linux" }))
end

View file

@ -0,0 +1,170 @@
--
-- tests/base/test_detoken.lua
-- Test suite for the token expansion API.
-- Copyright (c) 2011-2014 Jason Perkins and the Premake project
--
local p = premake
local suite = test.declare("detoken")
local detoken = p.detoken
--
-- Setup
--
local x, action
local environ = {}
function suite.setup()
action = p.action.get("test")
end
function suite.teardown()
action.pathVars = nil
end
--
-- The contents of the token should be executed and the results returned.
--
function suite.executesTokenContents()
x = detoken.expand("MyProject%{1+1}", environ)
test.isequal("MyProject2", x)
end
--
-- If the value contains more than one token, then should all be expanded.
--
function suite.expandsMultipleTokens()
x = detoken.expand("MyProject%{'X'}and%{'Y'}and%{'Z'}", environ)
test.isequal("MyProjectXandYandZ", x)
end
--
-- If the token replacement values contain tokens themselves, those
-- should also get expanded.
--
function suite.expandsNestedTokens()
environ.wks = { name="MyWorkspace%{'X'}" }
x = detoken.expand("%{wks.name}", environ)
test.isequal("MyWorkspaceX", x)
end
--
-- Verify that the global namespace is still accessible.
--
function suite.canUseGlobalFunctions()
x = detoken.expand("%{iif(true, 'a', 'b')}", environ)
test.isequal("a", x)
end
--
-- If a path field contains a token, and if that token expands to an
-- absolute path itself, that should be returned as the new value.
--
function suite.canExpandToAbsPath()
environ.cfg = { basedir = os.getcwd() }
x = detoken.expand("bin/debug/%{cfg.basedir}", environ, {paths=true})
test.isequal(os.getcwd(), x)
end
--
-- If a non-path field contains a token that expands to a path, that
-- path should be converted to a relative value.
--
function suite.canExpandToRelPath()
local cwd = os.getcwd()
environ.cfg = { basedir = path.getdirectory(cwd) }
x = detoken.expand("cd %{cfg.basedir}", environ, {}, cwd)
test.isequal("cd ..", x)
end
--
-- but not if it is prefixed with a !
--
function suite.canExpandWithExclamationMark()
local cwd = os.getcwd()
environ.cfg = { basedir = path.getdirectory(cwd) }
x = detoken.expand("%{!cfg.basedir}", environ, {}, cwd)
test.isequal(path.getdirectory(os.getcwd()), x)
end
--
-- If a path field contains a token that expands to a deferred join,
-- it should be resolved before performing detoken.
--
function suite.canExpandWithDeferredJoin()
local cwd = os.getcwd()
x = detoken.expand(path.deferredjoin(os.getcwd(), "%{_ACTION}"), environ, {}, cwd)
test.isequal(os.getcwd() .. "/test", x)
end
--
-- If the value being expanded is a table, iterate over all of its values.
--
function suite.expandsAllItemsInList()
x = detoken.expand({ "A%{1}", "B%{2}", "C%{3}" }, environ)
test.isequal({ "A1", "B2", "C3" }, x)
end
--
-- If the field being expanded supports path variable mapping, and the
-- action provides a map, replace tokens with the mapped values.
--
function suite.replacesToken_onSupportedAndMapped()
action.pathVars = { ["cfg.objdir"] = { absolute = true, token = "$(IntDir)" }, }
x = detoken.expand("cmd %{cfg.objdir}/file", environ, {pathVars=true})
test.isequal("cmd $(IntDir)/file", x)
end
function suite.replacesToken_onSupportedAndMapped_inAbsPath()
action.pathVars = { ["cfg.objdir"] = { absolute = true, token = "$(IntDir)" }, }
x = detoken.expand(os.getcwd() .. "/%{cfg.objdir}/file", environ, {paths=true,pathVars=true})
test.isequal("$(IntDir)/file", x)
end
function suite.replacesToken_onSupportedAndMapped_inRelPath()
action.pathVars = { ["cfg.objdir"] = { absolute = false, token = "$(IntDir)" }, }
x = detoken.expand(os.getcwd() .. "/%{cfg.objdir}/file", environ, {paths=true,pathVars=true})
test.isequal(os.getcwd() .. "/$(IntDir)/file", x)
end
--
-- Escapes backslashes correctly.
--
function suite.escapesBackslashes()
environ.foo = "some/path"
x = detoken.expand("%{foo:gsub('/', '\\')}", environ)
test.isequal("some\\path", x)
end
--
-- Escapes backslashes correctly, but not outside tokens.
--
function suite.escapesBackslashes2()
environ.foo = "some/path"
x = detoken.expand("%{foo:gsub('/', '\\')}\\already\\escaped", environ)
test.isequal("some\\path\\already\\escaped", x)
end

View file

@ -0,0 +1,99 @@
--
-- tests/base/test_filename.lua
-- Verify generation of project/workspace/rule filenames.
-- Copyright (c) 2008-2014 Jason Perkins and the Premake project
--
local suite = test.declare("project_filename")
local p = premake
--
-- Setup
--
local wks
function suite.setup()
wks = test.createWorkspace()
end
local function prepare()
prj = test.getproject(wks, 1)
end
--
-- Should return name as an absolute path.
--
function suite.isAbsolutePath()
prepare()
test.isequal(os.getcwd(), path.getdirectory(p.filename(prj)))
end
--
-- Should use the project name, if no filename was specified.
--
function suite.isProjectName_onNoFilename()
prepare()
test.isequal("MyProject", path.getname(p.filename(prj)))
end
--
-- Should use filename, if set via API.
--
function suite.doesUseFilename()
filename "Howdy"
prepare()
test.isequal("Howdy", path.getname(p.filename(prj)))
end
--
-- Appends file extension, if supplied.
--
function suite.doesUseExtension()
prepare()
test.isequal(".xc", path.getextension(p.filename(prj, ".xc")))
end
--
-- Should also work with workspaces.
--
function suite.worksWithWorkspace()
prepare()
test.isequal("MyWorkspace", path.getname(p.filename(wks)))
end
--
-- Value should not propagate down to projects.
--
function suite.doesNotPropagate()
workspace ("MyWorkspace")
filename ("Howdy")
prepare()
test.isequal("MyProject", path.getname(p.filename(prj)))
end
--
-- If extension is provided without a leading dot, it should override any
-- project filename.
--
function suite.canOverrideFilename()
prepare()
test.isequal("Makefile", path.getname(p.filename(prj, "Makefile")))
end

View file

@ -0,0 +1,85 @@
--
-- tests/base/test_http.lua
-- Tests the http API
-- Copyright (c) 2016, 2020 Jason Perkins and the Premake project
--
if http.get ~= nil and _OPTIONS["test-all"] then
local p = premake
local suite = test.declare("premake_http")
function suite.http_get()
local result, err = http.get("http://httpbin.org/user-agent")
if result then
p.out(result)
test.capture(
'{"user-agent": "Premake/' .. _PREMAKE_VERSION .. '"}'
)
else
test.fail(err);
end
end
function suite.https_get()
-- sslverifypeer = 0, so we can test from within companies like here at Blizzard where all HTTPS traffic goes through
-- some strange black box that re-signs all traffic with a custom ssl certificate.
local result, err = http.get("https://httpbin.org/user-agent", { sslverifypeer = 0 })
if result then
p.out(result)
test.capture(
'{"user-agent": "Premake/' .. _PREMAKE_VERSION .. '"}'
)
else
test.fail(err);
end
end
function suite.https_get_verify_peer()
local result, err = http.get("https://httpbin.org/user-agent")
if result then
p.out(result)
test.capture(
'{"user-agent": "Premake/' .. _PREMAKE_VERSION .. '"}'
)
else
test.fail(err);
end
end
function suite.http_responsecode()
local result, err, responseCode = http.get("http://httpbin.org/status/418")
test.isequal(responseCode, 418)
end
-- Disable as httpbin.org returns 404 on this endpoint
-- See: https://github.com/postmanlabs/httpbin/issues/617
--[[
function suite.http_redirect()
local result, err, responseCode = http.get("http://httpbin.org/redirect/3")
if result then
test.isequal(responseCode, 200)
else
test.fail(err);
end
end
]]
function suite.http_headers()
local result, err, responseCode = http.get("http://httpbin.org/headers", {
headers = { 'X-Premake: premake' }
})
if result then
if (not result:find('X-Premake')) then
test.fail("response doens't contain header")
test.print(result)
end
else
test.fail(err);
end
end
end

View file

@ -0,0 +1,67 @@
--
-- tests/base/test_include.lua
-- Test the include() function, for including external scripts
-- Copyright (c) 2011-2014 Jason Perkins and the Premake project
--
local p = premake
local suite = test.declare("include")
--
-- Setup and teardown
--
function suite.teardown()
-- clear the list of included files after each run
io._includedFiles = { }
end
--
-- Tests
--
function suite.include_findsPremakeFile_onFolderNameOnly()
include (_TESTS_DIR .. "/folder")
test.isequal("ok", p.captured())
end
function suite.include_onExactFilename()
include (_TESTS_DIR .. "/folder/premake5.lua")
test.isequal("ok", p.captured())
end
function suite.include_runsOnlyOnce_onMultipleIncludes()
include (_TESTS_DIR .. "/folder/premake5.lua")
include (_TESTS_DIR .. "/folder/premake5.lua")
test.isequal("ok", p.captured())
end
function suite.include_runsOnlyOnce_onMultipleIncludesWithDifferentPaths()
include (_TESTS_DIR .. "/folder/premake5.lua")
include (_TESTS_DIR .. "/../tests/folder/premake5.lua")
test.isequal("ok", p.captured())
end
function suite.includeexternal_runs()
includeexternal (_TESTS_DIR .. "/folder/premake5.lua")
test.isequal("ok", p.captured())
end
function suite.includeexternal_runsAfterInclude()
include (_TESTS_DIR .. "/folder/premake5.lua")
includeexternal (_TESTS_DIR .. "/folder/premake5.lua")
test.isequal("okok", p.captured())
end
function suite.includeexternal_runsTwiceAfterInclude()
include (_TESTS_DIR .. "/folder/premake5.lua")
includeexternal (_TESTS_DIR .. "/folder/premake5.lua")
includeexternal (_TESTS_DIR .. "/folder/premake5.lua")
test.isequal("okokok", p.captured())
end

View file

@ -0,0 +1,32 @@
--
-- tests/base/test_json.lua
-- Tests the json API
-- Copyright (c) 2017 Jason Perkins and the Premake project
--
local p = premake
local suite = test.declare("premake_json")
function suite.json_encode()
local result = json.encode({foo = "bar"})
result = result:gsub('%s*', ''),
test.isequal(result, '{"foo":"bar"}')
end
function suite.json_decode()
local result = json.decode('{ "foo": "bar" }')
test.isequal(result, { foo = "bar" })
end
function suite.json_encode_error()
local result, err = json.encode({ fubar = function() end })
test.isnil(result)
test.isequal(type(err), "string")
end
function suite.json_decode_error()
local result, err = json.decode("fubar string")
test.isnil(result)
test.isequal(type(err), "string")
end

View file

@ -0,0 +1,38 @@
--
-- tests/base/test_module_loader.lua
-- Test the custom module loader.
-- Copyright (c) 2012-2015 Jason Perkins and the Premake project
--
local p = premake
local suite = test.declare("module_loader")
--
-- Setup
--
local loaderIndex
function suite.setup()
table.insert(package.searchers, function (name)
p.out(name)
return load("")
end)
loaderIndex = #package.searchers
end
function suite.teardown()
table.remove(package.searchers, loaderIndex)
end
--
-- Check that premake's module loader let other loaders try
-- when it cannot find a module.
--
function suite.letOtherLoadersTry()
require("foo")
test.capture [[
foo
]]
end

View file

@ -0,0 +1,45 @@
--
-- tests/base/test_option.lua
-- Verify the handling of command line options and the _OPTIONS table.
-- Copyright (c) 2014 Jason Perkins and the Premake project
--
local p = premake
local suite = test.declare("base_option")
--
-- Setup and teardown.
--
function suite.setup()
_OPTIONS["testopt"] = "testopt"
end
function suite.teardown()
_OPTIONS["testopt"] = nil
end
--
-- Because we can't control how the user will type in options on the
-- command line, all key lookups should be case insensitive.
--
function suite.returnsCorrectOption_onMixedCase()
test.isnotnil(_OPTIONS["TestOpt"])
end
--
-- Because we can't control how the user will type in options in the
-- premake script, keys should be stored in lowercase.
--
function suite.storesOptionCorrectly_onMixedCase()
newoption {
trigger = "TestOpt2",
description = "Testing",
}
test.isnotnil(p.option.get("testopt2"))
end

View file

@ -0,0 +1,487 @@
---
-- tests/base/test_os.lua
-- Automated test suite for the new OS functions.
-- Copyright (c) 2008-2017 Jason Perkins and the Premake project
---
local suite = test.declare("base_os")
local cwd
function suite.setup()
cwd = os.getcwd()
os.chdir(_TESTS_DIR)
end
function suite.teardown()
os.chdir(cwd)
end
--
-- os.findlib() tests
--
function suite.findlib_FindSystemLib()
if os.istarget("macosx") then
-- macOS no longer stores system libraries on filesystem; see
-- https://developer.apple.com/documentation/macos-release-notes/macos-big-sur-11_0_1-release-notes
elseif os.istarget("windows") then
test.istrue(os.findlib("user32"))
elseif os.istarget("haiku") then
test.istrue(os.findlib("root"))
else
test.istrue(os.findlib("m"))
end
end
function suite.findlib_FailsOnBadLibName()
test.isfalse(os.findlib("NoSuchLibraryAsThisOneHere"))
end
function suite.findheader_stdheaders()
if not os.istarget("windows") and not os.istarget("macosx") then
test.istrue(os.findheader("stdlib.h"))
end
end
function suite.findheader_failure()
test.isfalse(os.findheader("Knights/who/say/Ni.hpp"))
end
--
-- os.isfile() tests
--
function suite.isfile_ReturnsTrue_OnExistingFile()
test.istrue(os.isfile("_tests.lua"))
end
function suite.isfile_ReturnsFalse_OnNonexistantFile()
test.isfalse(os.isfile("no_such_file.lua"))
end
--
-- os.matchdirs() tests
--
function suite.matchdirs_skipsDottedDirs()
local result = os.matchdirs("*")
test.isfalse(table.contains(result, ".."))
end
--
-- os.matchfiles() tests
--
function suite.matchfiles_OnNonRecursive()
local result = os.matchfiles("*.lua")
test.istrue(table.contains(result, "_tests.lua"))
test.isfalse(table.contains(result, "folder/ok.lua"))
end
function suite.matchfiles_Recursive()
local result = os.matchfiles("**.lua")
test.istrue(table.contains(result, "folder/ok.lua"))
end
function suite.matchfiles_SkipsDotDirs_OnRecursive()
local result = os.matchfiles("**.lua")
test.isfalse(table.contains(result, ".svn/text-base/testfx.lua.svn-base"))
end
function suite.matchfiles_OnSubfolderMatch()
local result = os.matchfiles("**/subfolder/*")
test.istrue(table.contains(result, "folder/subfolder/hello.txt"))
test.isfalse(table.contains(result, "premake4.lua"))
end
function suite.matchfiles_OnDotSlashPrefix()
local result = os.matchfiles("./**.lua")
test.istrue(table.contains(result, "folder/ok.lua"))
end
function suite.matchfiles_OnImplicitEndOfString()
local result = os.matchfiles("folder/*.lua")
test.istrue(table.contains(result, "folder/ok.lua"))
test.isfalse(table.contains(result, "folder/ok.lua.2"))
end
function suite.matchfiles_OnLeadingDotSlashWithPath()
local result = os.matchfiles("./folder/*.lua")
test.istrue(table.contains(result, "folder/ok.lua"))
end
function suite.matchfiles_OnDottedFile()
local result = os.matchfiles("base/.*")
test.istrue(table.contains(result, "base/.testDotFile"))
end
function suite.matchfiles_onComboSearch()
local result = os.matchfiles("folder/**/*.txt")
test.istrue(table.contains(result, "folder/subfolder/hello.txt"))
end
function suite.matchfiles_onSymbolicLink()
if os.istarget("macosx")
or os.istarget("linux")
or os.istarget("solaris")
or os.istarget("bsd")
then
os.execute("cd folder && ln -s subfolder symlinkfolder && cd ..")
local result = os.matchfiles("folder/**/*.txt")
os.execute("rm folder/symlinkfolder")
premake.modules.self_test.print(table.tostring(result))
test.istrue(table.contains(result, "folder/symlinkfolder/hello.txt"))
end
end
--
-- os.pathsearch() tests
--
function suite.pathsearch_ReturnsNil_OnNotFound()
test.istrue(os.pathsearch("nosuchfile", "aaa;bbb;ccc") == nil)
end
function suite.pathsearch_ReturnsPath_OnFound()
test.isequal(_TESTS_DIR, os.pathsearch("_tests.lua", _TESTS_DIR))
end
function suite.pathsearch_FindsFile_OnComplexPath()
test.isequal(_TESTS_DIR, os.pathsearch("_tests.lua", "aaa;" .. _TESTS_DIR .. ";bbb"))
end
function suite.pathsearch_NilPathsAllowed()
test.isequal(_TESTS_DIR, os.pathsearch("_tests.lua", nil, _TESTS_DIR, nil))
end
--
-- os.outputof() tests
--
-- Check if outputof returns the command exit code
-- in addition of the command output
function suite.outputof_commandExitCode()
if os.istarget("macosx")
or os.istarget("linux")
or os.istarget("solaris")
or os.istarget("bsd")
then
-- Assumes 'true' and 'false' commands exist
-- which should be the case on all *nix platforms
for cmd, exitcode in pairs ({
["true"] = 0,
["false"] = 1
})
do
local o, e = os.outputof(cmd)
test.isequal(e, exitcode)
end
end
end
-- Check outputof content
function suite.outputof_streams_output()
if (os.istarget("macosx")
or os.istarget("linux")
or os.istarget("solaris")
or os.istarget("bsd"))
and os.isdir (_TESTS_DIR)
then
local ob, e = os.outputof ("ls " .. _TESTS_DIR .. "/base")
local oo, e = os.outputof ("ls " .. _TESTS_DIR .. "/base", "output")
test.isequal (oo, ob)
local s, e = string.find (oo, "test_os.lua")
test.istrue(s ~= nil)
local o, e = os.outputof ("ls " .. cwd .. "/base", "error")
test.istrue(o == nil or #o == 0)
end
end
--
-- os.translateCommand() tests
--
function suite.translateCommand_onNoToken()
test.isequal("cp a b", os.translateCommands("cp a b"))
end
function suite.translateCommand_callsProcessor()
os.commandTokens.test = {
copy = function(value) return "test " .. value end
}
test.isequal("test a b", os.translateCommands("{COPY} a b", "test"))
end
function suite.translateCommand_callsProcessor_multipleTokens()
os.commandTokens.test = {
copy = function(value) return "test " .. value end
}
test.isequal("test a b; test c d; test e f;", os.translateCommands("{COPY} a b; {COPY} c d; {COPY} e f;", "test"))
end
--
-- os.translateCommand() windows COPY tests
--
function suite.translateCommand_windowsCopyNoDst()
test.isequal('IF EXIST a\\ (xcopy /Q /E /Y /I a > nul) ELSE (xcopy /Q /Y /I a > nul)', os.translateCommands('{COPY} a', "windows"))
end
function suite.translateCommand_windowsCopyNoDst_ExtraSpace()
test.isequal('IF EXIST a\\ (xcopy /Q /E /Y /I a > nul) ELSE (xcopy /Q /Y /I a > nul)', os.translateCommands('{COPY} a ', "windows"))
end
function suite.translateCommand_windowsCopyNoQuotes()
test.isequal('IF EXIST a\\ (xcopy /Q /E /Y /I a b > nul) ELSE (xcopy /Q /Y /I a b > nul)', os.translateCommands('{COPY} a b', "windows"))
end
function suite.translateCommand_windowsCopyNoQuotes_ExtraSpace()
test.isequal('IF EXIST a\\ (xcopy /Q /E /Y /I a b > nul) ELSE (xcopy /Q /Y /I a b > nul)', os.translateCommands('{COPY} a b ', "windows"))
end
function suite.translateCommand_windowsCopyQuotes()
test.isequal('IF EXIST "a a"\\ (xcopy /Q /E /Y /I "a a" "b" > nul) ELSE (xcopy /Q /Y /I "a a" "b" > nul)', os.translateCommands('{COPY} "a a" "b"', "windows"))
end
function suite.translateCommand_windowsCopyQuotes_ExtraSpace()
test.isequal('IF EXIST "a a"\\ (xcopy /Q /E /Y /I "a a" "b" > nul) ELSE (xcopy /Q /Y /I "a a" "b" > nul)', os.translateCommands('{COPY} "a a" "b" ', "windows"))
end
function suite.translateCommand_windowsCopyNoQuotesDst()
test.isequal('IF EXIST "a a"\\ (xcopy /Q /E /Y /I "a a" b > nul) ELSE (xcopy /Q /Y /I "a a" b > nul)', os.translateCommands('{COPY} "a a" b', "windows"))
end
function suite.translateCommand_windowsCopyNoQuotesDst_ExtraSpace()
test.isequal('IF EXIST "a a"\\ (xcopy /Q /E /Y /I "a a" b > nul) ELSE (xcopy /Q /Y /I "a a" b > nul)', os.translateCommands('{COPY} "a a" b ', "windows"))
end
function suite.translateCommand_windowsCopyNoQuotesSrc()
test.isequal('IF EXIST a\\ (xcopy /Q /E /Y /I a "b" > nul) ELSE (xcopy /Q /Y /I a "b" > nul)', os.translateCommands('{COPY} a "b"', "windows"))
end
function suite.translateCommand_windowsCopyNoQuotesSrc_ExtraSpace()
test.isequal('IF EXIST a\\ (xcopy /Q /E /Y /I a "b" > nul) ELSE (xcopy /Q /Y /I a "b" > nul)', os.translateCommands('{COPY} a "b" ', "windows"))
end
--
-- os.getWindowsRegistry windows tests
--
function suite.getreg_nonExistentValue()
if os.ishost("windows") then
local x = os.getWindowsRegistry("HKCU:Should\\Not\\Exist\\At\\All")
test.isequal(nil, x)
end
end
function suite.getreg_nonExistentDefaultValue()
if os.ishost("windows") then
local x = os.getWindowsRegistry("HKCU:Should\\Not\\Exist\\At\\All\\")
test.isequal(nil, x)
end
end
function suite.getreg_noSeparators()
if os.ishost("windows") then
local x = os.getWindowsRegistry("HKCU:ShouldNotExistAtAll")
test.isequal(nil, x)
end
end
function suite.getreg_namedValue()
if os.ishost("windows") then
local x = os.getWindowsRegistry("HKCU:Environment\\TEMP")
test.istrue(x ~= nil)
end
end
function suite.getreg_namedValueOptSeparator()
if os.ishost("windows") then
local x = os.getWindowsRegistry("HKCU:\\Environment\\TEMP")
test.istrue(x ~= nil)
end
end
function suite.getreg_defaultValue()
if os.ishost("windows") then
local x = os.getWindowsRegistry("HKLM:SYSTEM\\CurrentControlSet\\Control\\SafeBoot\\Minimal\\AppInfo\\")
test.isequal("Service", x)
end
end
--
-- os.listWindowsRegistry windows tests
--
function suite.listreg_nonExistentKey()
if os.ishost("windows") then
local x = os.listWindowsRegistry("HKCU:Should\\Not\\Exist\\At\\All")
test.isequal(nil, x)
end
end
function suite.listreg_nonExistentKeyTrailingBackslash()
if os.ishost("windows") then
local x = os.listWindowsRegistry("HKCU:Should\\Not\\Exist\\At\\All\\")
test.isequal(nil, x)
end
end
function suite.listreg_noSeparators()
if os.ishost("windows") then
local x = os.listWindowsRegistry("HKCU:ShouldNotExistAtAll")
test.isequal(nil, x)
end
end
function suite.listreg_noSeparatorExistingPath()
if os.ishost("windows") then
local x = os.listWindowsRegistry("HKCU:Environment")
test.istrue(x ~= nil and x["TEMP"] ~= nil)
end
end
function suite.listreg_optSeparators()
if os.ishost("windows") then
local x = os.listWindowsRegistry("HKCU:\\Environment\\")
test.istrue(x ~= nil and x["TEMP"] ~= nil)
end
end
function suite.listreg_keyDefaultValueAndStringValueFormat()
if os.ishost("windows") then
local x = os.listWindowsRegistry("HKLM:SYSTEM\\CurrentControlSet\\Control\\SafeBoot\\Minimal\\AppInfo")
test.isequal(x[""]["value"], "Service")
test.isequal(x[""]["type"], "REG_SZ")
end
end
function suite.listreg_numericValueFormat()
if os.ishost("windows") then
local x = os.listWindowsRegistry("HKCU:Console")
test.isequal(type(x["FullScreen"]["value"]), "number")
test.isequal(x["FullScreen"]["type"], "REG_DWORD")
end
end
function suite.listreg_subkeyFormat()
if os.ishost("windows") then
local x = os.listWindowsRegistry("HKLM:")
test.isequal(type(x["SOFTWARE"]), "table")
test.isequal(next(x["SOFTWARE"]), nil)
end
end
--
-- os.getversion tests.
--
function suite.getversion()
local version = os.getversion();
test.istrue(version ~= nil)
end
--
-- os.translateCommandsAndPaths.
--
function suite.translateCommandsAndPaths()
test.isequal('cmdtool "../foo/path1"', os.translateCommandsAndPaths("cmdtool %[path1]", '../foo', '.', 'osx'))
end
function suite.translateCommandsAndPaths_PreserveSlash()
test.isequal('cmdtool "../foo/path1/"', os.translateCommandsAndPaths("cmdtool %[path1/]", '../foo', '.', 'osx'))
end
function suite.translateCommandsAndPaths_MultipleTokens()
test.isequal('cmdtool "../foo/path1" "../foo/path2/"', os.translateCommandsAndPaths("cmdtool %[path1] %[path2/]", '../foo', '.', 'osx'))
end
--
-- Helpers
--
local tmpname = function()
local p = os.tmpname()
os.remove(p) -- just needed on POSIX
return p
end
local tmpfile = function()
local p = tmpname()
if os.ishost("windows") then
os.execute("type nul >" .. p)
else
os.execute("touch " .. p)
end
return p
end
local tmpdir = function()
local p = tmpname()
os.mkdir(p)
return p
end
--
-- os.remove() tests.
--
function suite.remove_ReturnsError_OnNonExistingPath()
local ok, err, exitcode = os.remove(tmpname())
test.isnil(ok)
test.isequal("string", type(err))
test.isequal("number", type(exitcode))
test.istrue(0 ~= exitcode)
end
function suite.remove_ReturnsError_OnDirectory()
local ok, err, exitcode = os.remove(tmpdir())
test.isnil(ok)
test.isequal("string", type(err))
test.isequal("number", type(exitcode))
test.istrue(0 ~= exitcode)
end
function suite.remove_ReturnsTrue_OnFile()
local ok, err, exitcode = os.remove(tmpfile())
test.isequal(true, ok)
test.isnil(err)
test.isnil(exitcode)
end
--
-- os.rmdir() tests.
--
function suite.rmdir_ReturnsError_OnNonExistingPath()
local ok, err = os.rmdir(tmpname())
test.isnil(ok)
test.isequal("string", type(err))
end
function suite.rmdir_ReturnsError_OnFile()
local ok, err = os.rmdir(tmpfile())
test.isnil(ok)
test.isequal("string", type(err))
end
function suite.rmdir_ReturnsTrue_OnDirectory()
local ok, err = os.rmdir(tmpdir())
test.isequal(true, ok)
test.isnil(err)
end

View file

@ -0,0 +1,75 @@
--
-- tests/base/test_override.lua
-- Verify function override support.
-- Copyright (c) 2012 Jason Perkins and the Premake project
--
local p = premake
local suite = test.declare("base_override")
--
-- Setup
--
local X = {}
function suite.setup()
X.testfunc = function(value)
return value or "testfunc"
end
end
--
-- Should be able to completely replace the function with one of my own.
--
function suite.canOverride()
p.override(X, "testfunc", function()
return "canOverride"
end)
test.isequal("canOverride", X.testfunc())
end
--
-- Should be able to reference the original implementation.
--
function suite.canCallOriginal()
p.override(X, "testfunc", function(base)
return "canOverride > " .. base()
end)
test.isequal("canOverride > testfunc", X.testfunc())
end
--
-- Arguments should pass through.
--
function suite.canPassThroughArguments()
p.override(X, "testfunc", function(base, value)
return value .. " > " .. base()
end)
test.isequal("testval > testfunc", X.testfunc("testval"))
end
--
-- Can override the same function multiple times.
--
function suite.canOverrideMultipleTimes()
p.override(X, "testfunc", function(base, value)
return string.format("[%s > %s]", value, base("base1"))
end)
p.override(X, "testfunc", function(base, value)
return string.format("{%s > %s}", value, base("base2"))
end)
test.isequal("{base3 > [base2 > base1]}", X.testfunc("base3"))
end

View file

@ -0,0 +1,789 @@
--
-- tests/base/test_path.lua
-- Automated test suite for the action list.
-- Copyright (c) 2008-2013 Jason Perkins and the Premake project
--
local suite = test.declare("path")
--
-- path.getabsolute() tests
--
function suite.getabsolute_worksWithMissingSubdirs()
local expected = os.getcwd() .. "/a/b/c"
test.isequal(expected, path.getabsolute("a/b/c"))
end
function suite.getabsolute_removesDotDots_onWindows()
test.isequal("c:/ProjectB/bin", path.getabsolute("c:/ProjectA/../ProjectB/bin"))
end
function suite.getabsolute_removesDotDots_OnPosix()
test.isequal("/ProjectB/bin", path.getabsolute("/ProjectA/../ProjectB/bin"))
end
function suite.getabsolute_limitsDotDots_onWindows()
test.isequal("c:/ProjectB/bin", path.getabsolute("c:/ProjectA/../../ProjectB/bin"))
end
function suite.getabsolute_limitsDotDots_OnPosix()
test.isequal("/ProjectB/bin", path.getabsolute("/ProjectA/../../ProjectB/bin"))
end
function suite.getabsolute_removesDot()
test.isequal("/ProjectA/ProjectB/bin", path.getabsolute("/ProjectA/./ProjectB/bin"))
end
function suite.getabsolute_removesTrailingSlash()
test.isequal("/a/b/c", path.getabsolute("/a/b/c/"))
end
function suite.getabsolute_onLeadingEnvVar()
test.isequal("$(HOME)/user", path.getabsolute("$(HOME)/user"))
end
function suite.getabsolute_onLeadingEnvVar_dosStyle()
test.isequal("%HOME%/user", path.getabsolute("%HOME%/user"))
end
function suite.getabsolute_onServerPath()
test.isequal("//Server/Volume", path.getabsolute("//Server/Volume"))
end
function suite.getabsolute_onMultipleEnvVar()
test.isequal("$(HOME)/$(USER)", path.getabsolute("$(HOME)/$(USER)"))
end
function suite.getabsolute_onTrailingEnvVar()
test.isequal("/home/$(USER)", path.getabsolute("/home/$(USER)"))
end
function suite.getabsolute_onLeadingEnvVarQuoted()
test.isequal('"$(HOME)/user"', path.getabsolute('"$(HOME)/user"'))
end
function suite.getabsolute_normalizesPaths()
test.isequal("c:/ProjectB/bin", path.getabsolute("c:\\ProjectB\\bin"))
end
function suite.getabsolute_acceptsTables()
test.isequal({ "/a/b", "/c/d" }, path.getabsolute({ "/a/b", "/c/d" }))
end
function suite.getabsolute_withRelativeTo()
local relto = path.getdirectory(os.getcwd())
local expected = relto .. "/a/b/c"
test.isequal(expected, path.getabsolute("a/b/c", relto))
end
function suite.getabsolute_withRelativeTo_withTrailingSlashes()
local relto = path.getdirectory(os.getcwd())
local expected = relto .. "/a/b/c"
test.isequal(expected, path.getabsolute("a/b/c", relto .. "/"))
end
function suite.getabsolute_acceptsTables_withRelativeTo()
local relto = path.getdirectory(os.getcwd())
test.isequal({ relto .. "/a/b", relto .. "/c/d" }, path.getabsolute({ "a/b", "c/d" }, relto))
end
function suite.getabsolute_leavesDotDot_onShellVar()
test.isequal("$ORIGIN/../libs", path.getabsolute("$ORIGIN/../libs"))
end
function suite.getabsolute_leavesDotDot2_onShellVar()
test.isequal("$ORIGIN/../../libs", path.getabsolute("$ORIGIN/../../libs"))
end
--
-- path.deferred_join() tests
--
function suite.deferred_join_OnMaybeAbsolutePath()
test.isequal("p1\a%{foo}", path.deferredjoin("p1", "%{foo}"))
end
function suite.deferred_join_OnValidParts()
test.isequal("p1/p2", path.deferredjoin("p1", "p2"))
end
function suite.deferred_join_OnAbsoluteath()
test.isequal("/p2", path.deferredjoin("p1", "/p2"))
end
--
-- path.has_deferred_join() tests
--
function suite.has_deferred_join_true()
test.istrue(path.hasdeferredjoin("p1\a%{foo}"))
end
function suite.has_deferred_join_false()
test.isfalse(path.hasdeferredjoin("p1/p2"))
end
function suite.has_deferred_join_true_OnPipe()
test.istrue(path.hasdeferredjoin("c1 p1\a%{foo} | c2"))
end
function suite.has_deferred_join_false_OnPipe()
test.isfalse(path.hasdeferredjoin("c1 p1/p2 | c2"))
end
function suite.has_deferred_join_true_OnOr()
test.istrue(path.hasdeferredjoin("c1 p1\a%{foo} || c2"))
end
function suite.has_deferred_join_false_OnOr()
test.isfalse(path.hasdeferredjoin("c1 p1/p2 || c2"))
end
--
-- path.resolvedeferredjoin() tests
--
function suite.resolve_deferred_join_OnNoDelimiter()
test.isequal("p1", path.resolvedeferredjoin("p1"))
end
function suite.resolve_deferred_join_OnValidParts()
test.isequal("p1/p2", path.resolvedeferredjoin("p1\ap2"))
end
function suite.resolve_deferred_join_OnAbsoluteWindowsPath()
test.isequal("C:/p2", path.resolvedeferredjoin("p1\aC:/p2"))
end
function suite.resolve_deferred_join_OnCurrentDirectory()
test.isequal("p2", path.resolvedeferredjoin(".\ap2"))
end
function suite.resolve_deferred_join_OnBackToBasePath()
test.isequal("", path.resolvedeferredjoin("p1/p2/\a../../"))
end
function suite.resolve_deferred_join_OnBackToBasePathWithoutFinalSlash()
test.isequal("", path.resolvedeferredjoin("p1/p2/\a../.."))
end
function suite.resolve_deferred_join_OnBothUpTwoFolders()
test.isequal("../../../../foo", path.resolvedeferredjoin("../../\a../../foo"))
end
function suite.resolve_deferred_join_OnUptwoFolders()
test.isequal("p1/foo", path.resolvedeferredjoin("p1/p2/p3\a../../foo"))
end
function suite.resolve_deferred_join_OnUptoBase()
test.isequal("foo", path.resolvedeferredjoin("p1/p2/p3\a../../../foo"))
end
function suite.resolve_deferred_join_ignoreLeadingDots()
test.isequal("p1/p2/foo", path.resolvedeferredjoin("p1/p2\a././foo"))
end
function suite.resolve_deferred_join_OnUptoParentOfBase()
test.isequal("../../p1", path.resolvedeferredjoin("p1/p2/p3/p4/p5/p6/p7/\a../../../../../../../../../p1"))
end
function suite.resolve_deferred_join_onMoreThanTwoParts()
test.isequal("p1/p2/p3", path.resolvedeferredjoin("p1\ap2\ap3"))
end
function suite.resolve_deferred_join_removesExtraInternalSlashes()
test.isequal("p1/p2", path.resolvedeferredjoin("p1/\ap2"))
end
function suite.resolve_deferred_join_removesTrailingSlash()
test.isequal("p1/p2", path.resolvedeferredjoin("p1\ap2/"))
end
function suite.resolve_deferred_join_ignoresEmptyParts()
test.isequal("p2", path.resolvedeferredjoin("\ap2\a"))
end
function suite.resolve_deferred_join_canJoinBareSlash()
test.isequal("/Users", path.resolvedeferredjoin("/\aUsers"))
end
function suite.resolve_deferred_join_keepsLeadingEnvVar()
test.isequal("$(ProjectDir)/../../Bin", path.resolvedeferredjoin("$(ProjectDir)\a../../Bin"))
end
function suite.resolve_deferred_join_keepsInternalEnvVar()
test.isequal("$(ProjectDir)/$(TargetName)/../../Bin", path.resolvedeferredjoin("$(ProjectDir)/$(TargetName)\a../../Bin"))
end
function suite.resolve_deferred_join_keepsComplexInternalEnvVar()
test.isequal("$(ProjectDir)/myobj_$(Arch)/../../Bin", path.resolvedeferredjoin("$(ProjectDir)/myobj_$(Arch)\a../../Bin"))
end
function suite.resolve_deferred_join_keepsRecursivePattern()
test.isequal("p1/**.lproj/../p2", path.resolvedeferredjoin("p1/**.lproj\a../p2"))
end
function suite.resolve_deferred_join_keepsVSMacros()
test.isequal("p1/%(Filename).ext", path.resolvedeferredjoin("p1\a%(Filename).ext"))
end
function suite.resolve_deferred_join_noCombineSingleDot()
test.isequal("p1/./../p2", path.resolvedeferredjoin("p1/.\a../p2"))
end
function suite.resolve_deferred_join_absolute_second_part()
test.isequal("$ORIGIN", path.resolvedeferredjoin("foo/bar\a$ORIGIN"))
end
function suite.resolve_deferred_join_absolute_second_part1()
test.isequal("$(FOO)/bar", path.resolvedeferredjoin("foo/bar\a$(FOO)/bar"))
end
function suite.resolve_deferred_join_absolute_second_part2()
test.isequal("%ROOT%/foo", path.resolvedeferredjoin("foo/bar\a%ROOT%/foo"))
end
function suite.resolve_deferred_join_token_in_second_part()
test.isequal("foo/bar/%{test}/foo", path.resolvedeferredjoin("foo/bar\a%{test}/foo"))
end
function suite.resolve_deferred_join_ignoresPipe()
test.isequal("c1 p1/p2 | c2", path.resolvedeferredjoin("c1 p1/p2 | c2"))
end
function suite.resolve_deferred_join_OnPipe()
test.isequal("c1 p1/p2 | c2", path.resolvedeferredjoin("c1 p1\ap2 | c2"))
end
function suite.resolve_deferred_join_ignoresOr()
test.isequal("c1 p1/p2 || c2", path.resolvedeferredjoin("c1 p1/p2 || c2"))
end
function suite.resolve_deferred_join_OnOr()
test.isequal("c1 p1/p2 || c2", path.resolvedeferredjoin("c1 p1\ap2 || c2"))
end
--
-- path.getbasename() tests
--
function suite.getbasename_ReturnsCorrectName_OnDirAndExtension()
test.isequal("filename", path.getbasename("folder/filename.ext"))
end
--
-- path.getdirectory() tests
--
function suite.getdirectory_ReturnsEmptyString_OnNoDirectory()
test.isequal(".", path.getdirectory("filename.ext"))
end
function suite.getdirectory_ReturnsDirectory_OnSingleLevelPath()
test.isequal("dir0", path.getdirectory("dir0/filename.ext"))
end
function suite.getdirectory_ReturnsDirectory_OnMultiLeveLPath()
test.isequal("dir0/dir1/dir2", path.getdirectory("dir0/dir1/dir2/filename.ext"))
end
function suite.getdirectory_ReturnsRootPath_OnRootPathOnly()
test.isequal("/", path.getdirectory("/filename.ext"))
end
--
-- path.getdrive() tests
--
function suite.getdrive_ReturnsNil_OnNotWindows()
test.isnil(path.getdrive("/hello"))
end
function suite.getdrive_ReturnsLetter_OnWindowsAbsolute()
test.isequal("x", path.getdrive("x:/hello"))
end
--
-- path.getextension() tests
--
function suite.getextension_ReturnsEmptyString_OnNoExtension()
test.isequal("", path.getextension("filename"))
end
function suite.getextension_ReturnsEmptyString_OnPathWithDotAndNoExtension()
test.isequal("", path.getextension("/.premake/premake"))
end
function suite.getextension_ReturnsExtension()
test.isequal(".txt", path.getextension("filename.txt"))
end
function suite.getextension_ReturnsExtension_OnPathWithDot()
test.isequal(".lua", path.getextension("/.premake/premake.lua"))
end
function suite.getextension_OnMultipleDots()
test.isequal(".txt", path.getextension("filename.mod.txt"))
end
function suite.getextension_OnLeadingNumeric()
test.isequal(".7z", path.getextension("filename.7z"))
end
function suite.getextension_OnUnderscore()
test.isequal(".a_c", path.getextension("filename.a_c"))
end
function suite.getextension_OnHyphen()
test.isequal(".a-c", path.getextension("filename.a-c"))
end
--
-- path.getrelative() tests
--
function suite.getrelative_ReturnsDot_OnMatchingPaths()
test.isequal(".", path.getrelative("/a/b/c", "/a/b/c"))
end
function suite.getrelative_ReturnsDoubleDot_OnChildToParent()
test.isequal("..", path.getrelative("/a/b/c", "/a/b"))
end
function suite.getrelative_ReturnsDoubleDot_OnSiblingToSibling()
test.isequal("../d", path.getrelative("/a/b/c", "/a/b/d"))
end
function suite.getrelative_ReturnsChildPath_OnParentToChild()
test.isequal("d", path.getrelative("/a/b/c", "/a/b/c/d"))
end
function suite.getrelative_ReturnsChildPath_OnWindowsAbsolute()
test.isequal("obj/debug", path.getrelative("C:/Code/Premake4", "C:/Code/Premake4/obj/debug"))
end
function suite.getrelative_ReturnsChildPath_OnServerPath()
test.isequal("../Volume", path.getrelative("//Server/Shared", "//Server/Volume"))
end
function suite.getrelative_ReturnsAbsPath_OnDifferentDriveLetters()
test.isequal("D:/Files", path.getrelative("C:/Code/Premake4", "D:/Files"))
end
function suite.getrelative_ReturnsAbsPath_OnDollarMacro()
test.isequal("$(SDK_HOME)/include", path.getrelative("C:/Code/Premake4", "$(SDK_HOME)/include"))
end
function suite.getrelative_ReturnsAbsPath_OnRootedPath()
test.isequal("/opt/include", path.getrelative("/home/me/src/project", "/opt/include"))
end
function suite.getrelative_ReturnsAbsPath_OnServerPath()
test.isequal("//Server/Volume", path.getrelative("C:/Files", "//Server/Volume"))
end
function suite.getrelative_ReturnsAbsPath_OnDifferentServers()
test.isequal("//Server/Volume", path.getrelative("//Computer/Users", "//Server/Volume"))
end
function suite.getrelative_ignoresExtraSlashes2()
test.isequal("..", path.getrelative("/a//b/c","/a/b"))
end
function suite.getrelative_ignoresExtraSlashes3()
test.isequal("..", path.getrelative("/a///b/c","/a/b"))
end
function suite.getrelative_ignoresTrailingSlashes()
test.isequal("c", path.getrelative("/a/b/","/a/b/c"))
end
function suite.getrelative_returnsAbsPath_onContactWithFileSysRoot()
test.isequal("C:/Boost/Include", path.getrelative("C:/Code/MyApp", "C:/Boost/Include"))
end
--
-- path.isabsolute() tests
--
function suite.isabsolute_ReturnsTrue_OnAbsolutePosixPath()
test.istrue(path.isabsolute("/a/b/c"))
end
function suite.isabsolute_ReturnsTrue_OnAbsoluteWindowsPathWithDrive()
test.istrue(path.isabsolute("C:/a/b/c"))
end
function suite.isabsolute_ReturnsFalse_OnRelativePath()
test.isfalse(path.isabsolute("a/b/c"))
end
function suite.isabsolute_ReturnsTrue_OnDollarToken()
test.istrue(path.isabsolute("$(SDK_HOME)/include"))
end
function suite.isabsolute_ReturnsTrue_OnDotInDollarToken()
test.istrue(path.isabsolute("$(configuration.libs)/include"))
end
function suite.isabsolute_ReturnsTrue_OnJustADollarSign()
test.istrue(path.isabsolute("$foo/include"))
end
function suite.isabsolute_ReturnsFalse_OnIncompleteDollarToken()
test.isfalse(path.isabsolute("$(foo/include"))
end
function suite.isabsolute_ReturnsTrue_OnEnvVar()
test.istrue(path.isabsolute("%FOO%/include"))
end
function suite.isabsolute_ReturnsFalse_OnEmptyEnvVar()
test.isfalse(path.isabsolute("%%/include"))
end
function suite.isabsolute_ReturnsFalse_OnToken()
test.isfalse(path.isabsolute("%{foo}/include"))
end
--
-- path.join() tests
--
function suite.join_OnValidParts()
test.isequal("p1/p2", path.join("p1", "p2"))
end
function suite.join_OnAbsoluteUnixPath()
test.isequal("/p2", path.join("p1", "/p2"))
end
function suite.join_OnAbsoluteWindowsPath()
test.isequal("C:/p2", path.join("p1", "C:/p2"))
end
function suite.join_OnCurrentDirectory()
test.isequal("p2", path.join(".", "p2"))
end
function suite.join_OnBackToBasePath()
test.isequal("", path.join("p1/p2/", "../../"))
end
function suite.join_OnBackToBasePathWithoutFinalSlash()
test.isequal("", path.join("p1/p2/", "../.."))
end
function suite.join_OnBothUpTwoFolders()
test.isequal("../../../../foo", path.join("../../", "../../foo"))
end
function suite.join_OnUptwoFolders()
test.isequal("p1/foo", path.join("p1/p2/p3", "../../foo"))
end
function suite.join_OnUptoBase()
test.isequal("foo", path.join("p1/p2/p3", "../../../foo"))
end
function suite.join_ignoreLeadingDots()
test.isequal("p1/p2/foo", path.join("p1/p2", "././foo"))
end
function suite.join_OnUptoParentOfBase()
test.isequal("../../p1", path.join("p1/p2/p3/p4/p5/p6/p7/", "../../../../../../../../../p1"))
end
function suite.join_OnNilSecondPart()
test.isequal("p1", path.join("p1", nil))
end
function suite.join_onMoreThanTwoParts()
test.isequal("p1/p2/p3", path.join("p1", "p2", "p3"))
end
function suite.join_removesExtraInternalSlashes()
test.isequal("p1/p2", path.join("p1/", "p2"))
end
function suite.join_removesTrailingSlash()
test.isequal("p1/p2", path.join("p1", "p2/"))
end
function suite.join_ignoresNilParts()
test.isequal("p2", path.join(nil, "p2", nil))
end
function suite.join_ignoresEmptyParts()
test.isequal("p2", path.join("", "p2", ""))
end
function suite.join_canJoinBareSlash()
test.isequal("/Users", path.join("/", "Users"))
end
function suite.join_keepsLeadingEnvVar()
test.isequal("$(ProjectDir)/../../Bin", path.join("$(ProjectDir)", "../../Bin"))
end
function suite.join_keepsInternalEnvVar()
test.isequal("$(ProjectDir)/$(TargetName)/../../Bin", path.join("$(ProjectDir)/$(TargetName)", "../../Bin"))
end
function suite.join_keepsComplexInternalEnvVar()
test.isequal("$(ProjectDir)/myobj_$(Arch)/../../Bin", path.join("$(ProjectDir)/myobj_$(Arch)", "../../Bin"))
end
function suite.join_keepsRecursivePattern()
test.isequal("p1/**.lproj/../p2", path.join("p1/**.lproj", "../p2"))
end
function suite.join_noCombineSingleDot()
test.isequal("p1/./../p2", path.join("p1/.", "../p2"))
end
function suite.join_absolute_second_part()
test.isequal("$ORIGIN", path.join("foo/bar", "$ORIGIN"))
end
function suite.join_absolute_second_part1()
test.isequal("$(FOO)/bar", path.join("foo/bar", "$(FOO)/bar"))
end
function suite.join_absolute_second_part2()
test.isequal("%ROOT%/foo", path.join("foo/bar", "%ROOT%/foo"))
end
function suite.join_token_in_second_part()
test.isequal("foo/bar/%{test}/foo", path.join("foo/bar", "%{test}/foo"))
end
--
-- path.rebase() tests
--
function suite.rebase_WithEndingSlashOnPath()
local cwd = os.getcwd()
test.isequal("src", path.rebase("../src/", cwd, path.getdirectory(cwd)))
end
--
-- path.replaceextension() tests
--
function suite.getabsolute_replaceExtension()
test.isequal("/AB.foo", path.replaceextension("/AB.exe","foo"))
end
function suite.getabsolute_replaceExtensionWithDot()
test.isequal("/AB.foo", path.replaceextension("/AB.exe",".foo"))
end
function suite.getabsolute_replaceExtensionWithDotMultipleDots()
test.isequal("/nunit.framework.foo", path.replaceextension("/nunit.framework.dll",".foo"))
end
function suite.getabsolute_replaceExtensionCompletePath()
test.isequal("/nunit/framework/main.foo", path.replaceextension("/nunit/framework/main.cpp",".foo"))
end
function suite.getabsolute_replaceExtensionWithoutExtension()
test.isequal("/nunit/framework/main.foo", path.replaceextension("/nunit/framework/main",".foo"))
end
function suite.getabsolute_replaceExtensionWithEmptyString()
test.isequal("foo", path.replaceextension("foo.lua",""))
end
--
-- path.translate() tests
--
function suite.translate_ReturnsTranslatedPath_OnValidPath()
test.isequal("dir/dir/file", path.translate("dir\\dir\\file", "/"))
end
function suite.translate_returnsCorrectSeparator_onMixedPath()
local actual = path.translate("dir\\dir/file", "/")
test.isequal("dir/dir/file", actual)
end
function suite.translate_ReturnsTargetOSSeparator_Windows()
_OPTIONS["os"] = "windows"
test.isequal("dir\\dir\\file", path.translate("dir/dir\\file"))
end
function suite.translate_ReturnsTargetOSSeparator_Linux()
_OPTIONS["os"] = "linux"
test.isequal("dir/dir/file", path.translate("dir/dir\\file"))
end
--
-- path.wildcards tests
--
function suite.wildcards_MatchesTrailingStar()
local p = path.wildcards("**/xcode/*")
test.isequal(".*/xcode/[^/]*", p)
end
function suite.wildcards_MatchPlusSign()
local patt = path.wildcards("file+name.*")
local name = "file+name.c"
test.isequal(name, name:match(patt))
end
function suite.wildcards_escapeSpecialChars()
test.isequal("%.%-", path.wildcards(".-"))
end
function suite.wildcards_escapeStar()
test.isequal("vs[^/]*", path.wildcards("vs*"))
end
function suite.wildcards_escapeStarStar()
test.isequal("Images/.*%.bmp", path.wildcards("Images/**.bmp"))
end
--
-- path.normalize tests
--
function suite.normalize_Test1()
local p = path.normalize("d:/game/../test")
test.isequal("d:/test", p)
end
function suite.normalize_Test2()
local p = path.normalize("d:/game/../../test")
test.isequal("d:/../test", p)
end
function suite.normalize_Test3()
local p = path.normalize("../../test")
test.isequal("../../test", p)
end
function suite.normalize_Test4()
local p = path.normalize("../../../test/*.h")
test.isequal("../../../test/*.h", p)
end
function suite.normalize_Test5()
test.isequal("test", path.normalize("./test"))
test.isequal("d:/", path.normalize("d:/"))
test.isequal("d:/", path.normalize("d:/./"))
local p = path.normalize("d:/game/..")
test.isequal("d:/", p)
end
function suite.normalize_trailingDots1()
local p = path.normalize("../game/test/..")
test.isequal("../game", p)
end
function suite.normalize_trailingDots2()
local p = path.normalize("../game/..")
test.isequal("..", p)
end
function suite.normalize_singleDot()
local p = path.normalize("../../p1/p2/p3/p4/./a.pb.cc")
test.isequal("../../p1/p2/p3/p4/a.pb.cc", p)
end
function suite.normalize_trailingSingleDot()
local p = path.normalize("../../p1/p2/p3/p4/./.")
test.isequal("../../p1/p2/p3/p4", p)
end
function suite.normalize()
test.isequal("d:/ProjectB/bin", path.normalize("d:/ProjectA/../ProjectB/bin"))
test.isequal("/ProjectB/bin", path.normalize("/ProjectA/../ProjectB/bin"))
end
function suite.normalize_leadingWhitespaces()
test.isequal("d:/game", path.normalize("\t\n d:/game"))
end
function suite.normalize_multPath()
test.isequal("../a/b ../c/d", path.normalize("../a/b ../c/d"))
test.isequal("d:/test ../a/b", path.normalize("d:/game/../test ../a/b"))
test.isequal("d:/game/test ../a/b", path.normalize("d:/game/./test ../a/b"))
test.isequal("d:/test ../a/b", path.normalize(" d:/game/../test ../a/b"))
test.isequal("d:/game ../a/b", path.normalize(" d:/game ../a/./b"))
test.isequal("d:/game ../a/b", path.normalize("d:/game/ ../a/b"))
test.isequal("d:/game", path.normalize("d:/game/ "))
end
function suite.normalize_legitimateDots()
test.isequal("d:/test/test..test", path.normalize("d:/test/test..test"))
test.isequal("d:/test..test/test", path.normalize("d:/test..test/test"))
test.isequal("d:/test/.test", path.normalize("d:/test/.test"))
test.isequal("d:/.test", path.normalize("d:/test/../.test"))
test.isequal("d:/test", path.normalize("d:/test/.test/.."))
test.isequal("d:/test/..test", path.normalize("d:/test/..test"))
test.isequal("d:/..test", path.normalize("d:/test/../..test"))
test.isequal("d:/test", path.normalize("d:/test/..test/.."))
test.isequal("d:/test/.test", path.normalize("d:/test/..test/../.test"))
test.isequal("d:/test/..test/.test", path.normalize("d:/test/..test/test/../.test"))
test.isequal("d:/test", path.normalize("d:/test/..test/../.test/.."))
end
function suite.normalize_serverpath()
test.isequal("//myawesomeserver/test", path.normalize("//myawesomeserver/test/"))
test.isequal("//myawesomeserver/test", path.normalize("///myawesomeserver/test/"))
end
function suite.normalize_quotedpath()
test.isequal("\"../../test/test/\"", path.normalize("\"../../test/test/\""))
test.isequal("\"../../test/\"", path.normalize("\"../../test/../test/\""))
end
function suite.normalize_withTokens()
-- Premake tokens
test.isequal("%{wks.location}../../test", path.normalize("%{wks.location}../../test"))
-- Visual Studio var
test.isequal("$(SolutionDir)../../test", path.normalize("$(SolutionDir)../../test"))
-- Windows env var
test.isequal("%APPDATA%../../test", path.normalize("%APPDATA%../../test"))
-- Unix env var
test.isequal("${HOME}../../test", path.normalize("${HOME}../../test"))
-- Middle
test.isequal("../../${MYVAR}/../test", path.normalize("../../${MYVAR}/../test"))
-- End
test.isequal("../../test/${MYVAR}", path.normalize("../../test/${MYVAR}"))
end
function suite.normalize_quotedpath_withTokens()
-- Premake tokens
test.isequal("\"%{wks.location}../../test\"", path.normalize("\"%{wks.location}../../test\""))
-- Visual Studio var
test.isequal("\"$(SolutionDir)../../test\"", path.normalize("\"$(SolutionDir)../../test\""))
-- Windows env var
test.isequal("\"%APPDATA%../../test\"", path.normalize("\"%APPDATA%../../test\""))
-- Unix env var
test.isequal("\"${HOME}../../test\"", path.normalize("\"${HOME}../../test\""))
-- Middle
test.isequal("\"../../${MYVAR}/../test\"", path.normalize("\"../../${MYVAR}/../test\""))
-- End
test.isequal("\"../../test/${MYVAR}\"", path.normalize("\"../../test/${MYVAR}\""))
end

View file

@ -0,0 +1,12 @@
--
-- tests/base/test_premake_command.lua
-- Test the initialization of the _PREMAKE_COMMAND global.
-- Copyright (c) 2012-2014 Jason Perkins and the Premake project
--
local suite = test.declare("premake_command")
function suite.valueIsSet()
test.istrue(os.isfile(_PREMAKE_COMMAND))
end

View file

@ -0,0 +1,85 @@
--
-- tests/base/test_rule.lua
-- Automated test suite for custom rule.
-- Copyright (c) 2008-2021 Jason Perkins and the Premake project
--
local suite = test.declare("rule")
local p = premake
function suite.setup()
rule "TestRule"
display "Test Rule"
fileextension ".rule"
propertydefinition {
name = "TestPropertyFalse",
kind = "boolean",
value = false,
switch = "-dummy"
}
propertydefinition {
name = "TestPropertyTrue",
kind = "boolean",
value = false,
switch = "-p"
}
propertydefinition {
name = "TestListProperty",
kind = "list"
}
propertydefinition {
name = "TestListPropertyWithSwitch",
kind = "list",
switch = "-S"
}
propertydefinition {
name = "TestListPropertySeparator",
kind = "list",
separator = ","
}
propertydefinition {
name = "TestListPropertySeparatorWithSwitch",
kind = "list",
separator = ",",
switch = "-O"
}
propertydefinition {
name = "TestEnumProperty",
values = { [0] = "V0", [1] = "V1"},
switch = { [0] = "S0", [1] = "S1"},
value = 0
}
end
--
-- rule tests
--
function suite.prepareEnvironment()
local rule = premake.global.getRule("TestRule")
local environ = {}
local cfg = {
["_rule_TestRule_TestPropertyFalse"] = false,
["_rule_TestRule_TestPropertyTrue"] = true,
["_rule_TestRule_TestListProperty"] = {"a", "b"},
["_rule_TestRule_TestListPropertyWithSwitch"] = {"c", "d"},
["_rule_TestRule_TestListPropertySeparator"] = {"e", "f"},
["_rule_TestRule_TestListPropertySeparatorWithSwitch"] = {"1", "2"},
["_rule_TestRule_TestEnumProperty"] = 'V1'
}
p.rule.prepareEnvironment(rule, environ, cfg)
test.isequal(nil, environ["TestPropertyFalse"])
test.isequal("-p", environ["TestPropertyTrue"])
test.isequal("a b", environ["TestListProperty"])
test.isequal("-Sc -Sd", environ["TestListPropertyWithSwitch"])
test.isequal("e,f", environ["TestListPropertySeparator"])
test.isequal("-O1,2", environ["TestListPropertySeparatorWithSwitch"])
test.isequal("S1", environ["TestEnumProperty"])
end

View file

@ -0,0 +1,97 @@
--
-- tests/base/test_table.lua
-- Automated test suite for the new table functions.
-- Copyright (c) 2008-2013 Jason Perkins and the Premake project
--
local suite = test.declare("table")
local t
--
-- table.contains() tests
--
function suite.contains_OnContained()
t = { "one", "two", "three" }
test.istrue( table.contains(t, "two") )
end
function suite.contains_OnNotContained()
t = { "one", "two", "three" }
test.isfalse( table.contains(t, "four") )
end
--
-- table.flatten() tests
--
function suite.flatten_OnMixedValues()
t = { "a", { "b", "c" }, "d" }
test.isequal({ "a", "b", "c", "d" }, table.flatten(t))
end
--
-- table.implode() tests
--
function suite.implode()
t = { "one", "two", "three", "four" }
test.isequal("[one], [two], [three], [four]", table.implode(t, "[", "]", ", "))
end
--
-- table.indexof() tests
--
function suite.indexof_returnsIndexOfValueFound()
local idx = table.indexof({ "a", "b", "c" }, "b")
test.isequal(2, idx)
end
--
-- table.isempty() tests
--
function suite.isempty_ReturnsTrueOnEmpty()
test.istrue(table.isempty({}))
end
function suite.isempty_ReturnsFalseOnNotEmpty()
test.isfalse(table.isempty({ 1 }))
end
function suite.isempty_ReturnsFalseOnNotEmptyMap()
test.isfalse(table.isempty({ name = 'premake' }))
end
function suite.isempty_ReturnsFalseOnNotEmptyMapWithFalseKey()
test.isfalse(table.isempty({ [false] = 0 }))
end
--
-- table.insertsorted() tests
--
function suite.insertsorted()
local t = {}
table.insertsorted(t, 5)
table.insertsorted(t, 2)
table.insertsorted(t, 8)
table.insertsorted(t, 4)
table.insertsorted(t, 1)
test.istrue(#t == 5)
test.istrue(t[1] == 1)
test.istrue(t[2] == 2)
test.istrue(t[3] == 4)
test.istrue(t[4] == 5)
test.istrue(t[5] == 8)
end

View file

@ -0,0 +1,286 @@
--
-- tests/base/test_tree.lua
-- Automated test suite source code tree handling.
-- Copyright (c) 2009-2012 Jason Perkins and the Premake project
--
local p = premake
local suite = test.declare("base_tree")
local tree = p.tree
--
-- Setup/teardown
--
local tr
function suite.setup()
tr = tree.new()
end
local function prepare()
tree.traverse(tr, {
onnode = function(node, depth)
_p(depth + 2, node.name)
end
})
end
--
-- Tests for tree.new()
--
function suite.NewReturnsObject()
test.isnotnil(tr)
end
--
-- Tests for tree.add()
--
function suite.CanAddAtRoot()
tree.add(tr, "Root")
prepare()
test.capture [[
Root
]]
end
function suite.CanAddAtChild()
tree.add(tr, "Root/Child")
prepare()
test.capture [[
Root
Child
]]
end
function suite.CanAddAtGrandchild()
tree.add(tr, "Root/Child/Grandchild")
prepare()
test.capture [[
Root
Child
Grandchild
]]
end
--
-- Tests for tree.getlocalpath()
--
function suite.GetLocalPath_ReturnsPath_OnNoParentPath()
local c = tree.add(tr, "Root/Child")
c.parent.path = nil
test.isequal("Root/Child", tree.getlocalpath(c))
end
function suite.GetLocalPath_ReturnsName_OnParentPathSet()
local c = tree.add(tr, "Root/Child")
test.isequal("Child", tree.getlocalpath(c))
end
--
-- Tests for tree.remove()
--
function suite.Remove_RemovesNodes()
local n1 = tree.add(tr, "1")
local n2 = tree.add(tr, "2")
local n3 = tree.add(tr, "3")
tree.remove(n2)
local r = ""
for _, n in ipairs(tr.children) do r = r .. n.name end
test.isequal("13", r)
end
function suite.Remove_WorksInTraversal()
tree.add(tr, "Root/1")
tree.add(tr, "Root/2")
tree.add(tr, "Root/3")
local r = ""
tree.traverse(tr, {
onleaf = function(node)
r = r .. node.name
tree.remove(node)
end
})
test.isequal("123", r)
test.isequal(0, #tr.children[1])
end
--
-- Tests for tree.sort()
--
function suite.Sort_SortsAllLevels()
tree.add(tr, "B/3")
tree.add(tr, "B/1")
tree.add(tr, "A/2")
tree.add(tr, "A/1")
tree.add(tr, "B/2")
tree.sort(tr)
prepare()
test.capture [[
A
1
2
B
1
2
3
]]
end
--
-- If the root of the tree contains multiple items, it should not
-- be removed by trimroot()
--
function suite.trimroot_onItemsAtRoot()
tree.add(tr, "A/1")
tree.add(tr, "B/1")
tree.trimroot(tr)
prepare()
test.capture [[
A
1
B
1
]]
end
--
-- Should trim to first level with multiple items.
--
function suite.trimroot_onItemsInFirstNode()
tree.add(tr, "A/1")
tree.add(tr, "A/2")
tree.trimroot(tr)
prepare()
test.capture [[
1
2
]]
end
--
-- If the tree contains only a single node, don't trim it.
--
function suite.trimroot_onSingleNode()
tree.add(tr, "A")
tree.trimroot(tr)
prepare()
test.capture [[
A
]]
end
--
-- If the tree contains only a single node, don't trim it.
--
function suite.trimroot_onSingleLeafNode()
tree.add(tr, "A/1")
tree.trimroot(tr)
prepare()
test.capture [[
1
]]
end
--
-- A ".." folder containing a single subfolder should never appear
-- at the top of the source tree.
--
function suite.trimroot_removesDotDot_onTopLevelSiblings()
tree.add(tr, "../../tests/test_hello.c")
tree.add(tr, "../src/test.c")
tree.trimroot(tr)
prepare()
test.capture [[
tests
test_hello.c
src
test.c
]]
end
function suite.trimroot_removesDotDot_onTopLevel()
tree.add(tr, "../tests/test_hello.c")
tree.add(tr, "src/test.c")
tree.trimroot(tr)
prepare()
test.capture [[
tests
test_hello.c
src
test.c
]]
end
function suite.trimroot_removesDotDot_onMultipleNestings()
tree.add(tr, "../../../tests/test_hello.c")
tree.add(tr, "../src/test.c")
tree.trimroot(tr)
prepare()
test.capture [[
tests
test_hello.c
src
test.c
]]
end
--
-- When nodes are trimmed, the paths on the remaining nodes should
-- be updated to reflect the new hierarchy.
--
function suite.trimroot_updatesPaths_onNodesRemoved()
tree.add(tr, "A/1")
tree.add(tr, "A/2")
tree.trimroot(tr)
test.isequal("1", tr.children[1].path)
end
function suite.trimroot_updatesPaths_onDotDotRemoved()
tree.add(tr, "../../../tests/test_hello.c")
tree.add(tr, "../src/test.c")
tree.trimroot(tr)
test.isequal("tests", tr.children[1].path)
end
--
-- Nodes with the key "trim" set to false should be removed.
--
function suite.trimroot_respectsTrimFlag()
local n = tree.add(tr, "A")
tree.add(tr, "A/1")
n.trim = false
tree.trimroot(tr)
prepare()
test.capture [[
A
1
]]
end

View file

@ -0,0 +1,52 @@
--
-- tests/base/test_uuid.lua
-- Automated test suite for UUID generation.
-- Copyright (c) 2008-2012 Jason Perkins and the Premake project
--
local suite = test.declare("os_uuid")
--
-- Setup and teardown
--
local builtin_print, result
function suite.setup()
builtin_print = print
print = function(value)
result = value
end
end
function suite.teardown()
print = builtin_print
end
--
-- Make sure the return value looks like a UUID.
--
function suite.returnsValidUUID()
local g = os.uuid()
test.istrue(#g == 36)
for i=1,36 do
local ch = g:sub(i,i)
test.istrue(ch:find("[ABCDEF0123456789-]"))
end
test.isequal("-", g:sub(9,9))
test.isequal("-", g:sub(14,14))
test.isequal("-", g:sub(19,19))
test.isequal("-", g:sub(24,24))
end
--
-- Make sure the value returned is deterministic if a name is provided.
--
function suite.isDeterministic_onName()
test.isequal("885E8F4B-F43D-0EE7-FD55-99BD69B47448", os.uuid("MyValue"))
end

View file

@ -0,0 +1,130 @@
--
-- tests/base/test_validation.lua
-- Verify the project information sanity checking.
-- Copyright (c) 2013-20124 Jason Perkins and the Premake project
--
local suite = test.declare("premake_validation")
local p = premake
--
-- Setup
--
local function validate()
return pcall(function() p.container.validate(p.api.rootContainer()) end)
end
--
-- Validate should pass if the minimum requirements are met.
--
function suite.passes_onSane()
workspace("MyWorkspace")
configurations { "Debug", "Release" }
project "MyProject"
kind "ConsoleApp"
language "C++"
test.istrue(validate())
end
--
-- Fail if no configurations are present on the workspace.
--
function suite.fails_onNoWorkspaceConfigs()
workspace "MyWorkspace"
project "MyProject"
kind "ConsoleApp"
language "C++"
test.isfalse(validate())
end
--
-- Fail on duplicate project UUIDs.
--
function suite.fails_onDuplicateProjectIDs()
workspace "MyWorkspace"
configurations { "Debug", "Release" }
kind "ConsoleApp"
language "C++"
project "MyProject1"
uuid "D4110D7D-FB18-4A1C-A75B-CA432F4FE770"
project "MyProject2"
uuid "D4110D7D-FB18-4A1C-A75B-CA432F4FE770"
test.isfalse(validate())
end
--
-- Fail if no kind is set on the configuration.
--
function suite.fails_onNoConfigKind()
workspace "MyWorkspace"
configurations { "Debug", "Release" }
project "MyProject"
language "C++"
test.isfalse(validate())
end
--
-- Warn if a configuration value is set in the wrong scope.
--
function suite.warns_onWorkspaceStringField_inConfig()
workspace "MyWorkspace"
configurations { "Debug", "Release" }
filter "Debug"
startproject "MyProject"
project "MyProject"
kind "ConsoleApp"
language "C++"
validate()
test.stderr("'startproject' on config")
end
function suite.warns_onProjectStringField_inConfig()
workspace "MyWorkspace"
configurations { "Debug", "Release" }
project "MyProject"
kind "ConsoleApp"
language "C++"
filter "Debug"
location "MyProject"
validate()
test.stderr("'location' on config")
end
function suite.warns_onProjectListField_inConfig()
workspace "MyWorkspace"
configurations { "Debug", "Release" }
project "MyProject"
kind "ConsoleApp"
language "C++"
filter "Debug"
configurations "Deployment"
validate()
test.stderr("'configurations' on config")
end
--
-- If a rule is specified for inclusion, it must have been defined.
--
function suite.fails_onNoSuchRule()
workspace "MyWorkspace"
configurations { "Debug", "Release" }
project "MyProject"
rules { "NoSuchRule" }
test.isfalse(validate())
end

View file

@ -0,0 +1,187 @@
--
-- tests/base/test_versions.lua
-- Verify the version comparisons.
-- Copyright (c) 2015 Jason Perkins and the Premake project
--
local suite = test.declare("premake_versions")
local p = premake
--
-- If only major version is specified, anything after should pass.
--
function suite.pass_majorOnly_sameMajor()
test.istrue(p.checkVersion("1.0.0", "1"))
end
function suite.pass_majorOnly_laterMajor()
test.istrue(p.checkVersion("2.0.0", "1"))
end
function suite.pass_majorOnly_laterMinor()
test.istrue(p.checkVersion("1.1.0", "1"))
end
function suite.pass_majorOnly_laterPatch()
test.istrue(p.checkVersion("1.0.1", "1"))
end
--
-- prereleases should be fail against true release.
--
function suite.fail_majorOnly_alpha()
test.isfalse(p.checkVersion("1.0.0-alpha1", "1"))
end
function suite.fail_majorOnly_dev()
test.isfalse(p.checkVersion("1.0.0-dev", "1"))
end
--
-- ealier versions should be fail against major release.
--
function suite.fail_earlierMajor()
test.isfalse(p.checkVersion("0.9.0", "1"))
end
--
-- If major and minor are specified, anything after should pass
--
function suite.pass_majorMinor_sameMajorMinor()
test.istrue(p.checkVersion("1.1.0", "1.1"))
end
function suite.pass_majorMinor_sameMajorLaterMinor()
test.istrue(p.checkVersion("1.2.0", "1.1"))
end
function suite.pass_majorMinor_sameMajorLaterPath()
test.istrue(p.checkVersion("1.1.1", "1.1"))
end
function suite.pass_majorMinor_laterMajorSameMinor()
test.istrue(p.checkVersion("2.0.0", "1.1"))
end
function suite.pass_majorMinor_laterMajorEarlierMinor()
test.istrue(p.checkVersion("2.0.0", "1.1"))
end
function suite.pass_majorMinor_laterMajorLaterMinor()
test.istrue(p.checkVersion("2.2.0", "1.1"))
end
function suite.fail_majorMinor_sameMajorEarlierMinor()
test.isfalse(p.checkVersion("1.0.0", "1.1"))
end
function suite.fail_majorMinor_earlierMajor()
test.isfalse(p.checkVersion("0.9.0", "1.1"))
end
--
-- Alpha comes before beta comes before dev
--
function suite.pass_alphaBeforeBeta()
test.istrue(p.checkVersion("1.0.0-beta1", "1.0.0-alpha1"))
end
function suite.fail_alphaBeforeBeta()
test.isfalse(p.checkVersion("1.0.0-alpha1", "1.0.0-beta1"))
end
function suite.pass_betaBeforeDev()
test.istrue(p.checkVersion("1.0.0-dev", "1.0.0-beta1"))
end
function suite.fail_betaBeforeDev()
test.isfalse(p.checkVersion("1.0.0-beta1", "1.0.0-dev"))
end
--
-- Check ">=" operator
--
function suite.pass_ge_sameMajorMinorPatch()
test.istrue(p.checkVersion("1.1.0", ">=1.1"))
end
function suite.pass_ge_sameMajorMinorLaterPatch()
test.istrue(p.checkVersion("1.1.1", ">=1.1"))
end
function suite.pass_ge_laterMajorEarlierMinor()
test.istrue(p.checkVersion("2.0.1", ">=1.1"))
end
function suite.pass_ge_sameMajorLaterMinor()
test.istrue(p.checkVersion("1.2.1", ">=1.1"))
end
function suite.fail_ge_earlierMajor()
test.isfalse(p.checkVersion("0.1.1", ">=1.1"))
end
function suite.fail_ge_earlierMinor()
test.isfalse(p.checkVersion("1.0.1", ">=1.1"))
end
--
-- Check ">" operator
--
function suite.pass_gt_sameMajorMinorLaterPatch()
test.istrue(p.checkVersion("1.1.1", ">1.1"))
end
function suite.pass_gt_laterMajor()
test.istrue(p.checkVersion("2.0.1", ">1.1"))
end
function suite.pass_gt_laterMinor()
test.istrue(p.checkVersion("1.2.1", ">1.1"))
end
function suite.fail_gt_sameMajorMinorPatch()
test.isfalse(p.checkVersion("1.1.0", ">1.1"))
end
function suite.fail_gt_earlierMajor()
test.isfalse(p.checkVersion("0.1.1", ">1.1"))
end
function suite.fail_gt_earlierMinor()
test.isfalse(p.checkVersion("1.0.1", ">1.1"))
end
--
-- Check multiple conditions
--
function suite.pass_onMultipleConditions()
test.istrue(p.checkVersion("1.2.0", ">=1.0 <2.0"))
end
function suite.fail_onMultipleConditions()
test.isfalse(p.checkVersion("2.2.0", ">=1.0 <2.0"))
end
--
-- If there is no version information, fails.
--
function suite.fail_onNoVersion()
test.isfalse(p.checkVersion(nil, "1.0"))
end

View file

@ -0,0 +1,117 @@
--
-- tests/config/test_linkinfo.lua
-- Test the config object's link target accessor.
-- Copyright (c) 2012-2013 Jason Perkins and the Premake project
--
local p = premake
local suite = test.declare("config_linkinfo")
local config = p.config
--
-- Setup and teardown
--
local wks, prj
function suite.setup()
p.action.set("test")
wks, prj = test.createWorkspace()
kind "StaticLib"
system "Windows"
end
local function prepare()
local cfg = test.getconfig(prj, "Debug")
return config.getlinkinfo(cfg)
end
--
-- Directory should use targetdir() value if present.
--
function suite.directoryIsTargetDir_onTargetDir()
targetdir "../bin"
i = prepare()
test.isequal("../bin", path.getrelative(os.getcwd(), i.directory))
end
--
-- Shared library should use implibdir() if present.
--
function suite.directoryIsImpLibDir_onImpLibAndTargetDir()
kind "SharedLib"
targetdir "../bin"
implibdir "../lib"
i = prepare()
test.isequal("../lib", path.getrelative(os.getcwd(), i.directory))
end
--
-- Base name should use the project name by default.
--
function suite.basenameIsProjectName_onNoTargetName()
i = prepare()
test.isequal("MyProject", i.basename)
end
--
-- Base name should use targetname() if present.
--
function suite.basenameIsTargetName_onTargetName()
targetname "MyTarget"
i = prepare()
test.isequal("MyTarget", i.basename)
end
--
-- Shared library should use implibname() if present.
--
function suite.basenameIsImplibName_onTargetName()
kind "SharedLib"
targetname "MyTarget"
implibname "MyTargetImports"
i = prepare()
test.isequal("MyTargetImports", i.basename)
end
--
-- Test library name formatting.
--
function suite.nameFormatting_onWindows()
system "Windows"
i = prepare()
test.isequal("MyProject.lib", i.name)
end
function suite.nameFormatting_onLinux()
system "Linux"
i = prepare()
test.isequal("libMyProject.a", i.name)
end
--
-- The import library extension should not change if the a
-- custom target extension is set.
--
function suite.impLibExtensionUnmodified_OnCustomTargetExt()
system "windows"
kind "SharedLib"
targetextension ".mil"
i = prepare()
test.isequal("MyProject.lib", i.name)
end

View file

@ -0,0 +1,224 @@
--
-- tests/config/test_links.lua
-- Test the list of linked objects retrieval function.
-- Copyright (c) 2012-2013 Jason Perkins and the Premake project
--
local p = premake
local suite = test.declare("config_links")
local config = p.config
--
-- Setup and teardown
--
local wks, prj
function suite.setup()
p.action.set("test")
_TARGET_OS = "windows"
wks, prj = test.createWorkspace()
end
local function prepare(kind, part, linkage)
cfg = test.getconfig(prj, "Debug")
return config.getlinks(cfg, kind, part, linkage)
end
--
-- If no links are present, should return an empty table.
--
function suite.emptyResult_onNoLinks()
local r = prepare("all", "object")
test.isequal(0, #r)
end
--
-- System libraries which include path information are made project relative.
--
function suite.pathMadeRelative_onSystemLibWithPath()
location "build"
links { "../libs/z" }
local r = prepare("all", "fullpath")
test.isequal({ "../../libs/z" }, r)
end
--
-- Handle the case where the library extension has been explicitly
-- included in the link statement.
--
function suite.skipsExtension_onExplicitExtension()
system "windows"
links { "user32.lib" }
local r = prepare("all", "fullpath")
test.isequal({ "user32.lib" }, r)
end
--
-- Check handling of shell variables in library paths.
--
function suite.variableMaintained_onLeadingVariable()
system "windows"
location "build"
links { "$(LOCAL_DEV_PATH)/sdk/lib/DEVMAPI" }
local r = prepare("all", "fullpath")
test.isequal({ "$(LOCAL_DEV_PATH)/sdk/lib/DEVMAPI" }, r)
end
function suite.variableMaintained_onQuotedVariable()
system "windows"
location "build"
links { '"$(LOCAL_DEV_PATH)/sdk/lib/DEVMAPI.lib"' }
local r = prepare("all", "fullpath")
test.isequal({ '"$(LOCAL_DEV_PATH)/sdk/lib/DEVMAPI.lib"' }, r)
end
--
-- If fetching directories, the libdirs should be included in the result.
--
function suite.includesLibDirs_onDirectories()
libdirs { "../libs" }
local r = prepare("all", "directory")
test.isequal({ "../libs" }, r)
end
--
-- Managed C++ projects should ignore links to managed assemblies, which
-- are designated with an explicit ".dll" extension.
--
function suite.skipsAssemblies_onManagedCpp()
system "windows"
clr "On"
links { "user32", "System.dll" }
local r = prepare("all", "fullpath")
test.isequal({ "user32" }, r)
end
--
-- When explicitly requesting managed links, any unmanaged items in the
-- list should be ignored.
--
function suite.skipsUnmanagedLibs_onManagedLinkage()
system "windows"
clr "On"
links { "user32", "System.dll" }
local r = prepare("all", "fullpath", "managed")
test.isequal({ "System.dll" }, r)
end
--
-- Managed projects can link to other managed projects, and unmanaged
-- projects can link to unmanaged projects.
--
function suite.canLink_CppAndCpp()
links { "MyProject2" }
project "MyProject2"
kind "StaticLib"
language "C++"
local r = prepare("all", "fullpath")
test.isequal({ "bin/Debug/MyProject2.lib" }, r)
end
function suite.canLink_CsAndCs()
language "C#"
links { "MyProject2" }
project "MyProject2"
kind "SharedLib"
language "C#"
local r = prepare("all", "fullpath")
test.isequal({ "bin/Debug/MyProject2.dll" }, r)
end
function suite.canLink_ManagedCppAndManagedCpp()
clr "On"
links { "MyProject2" }
project "MyProject2"
kind "StaticLib"
language "C++"
clr "On"
local r = prepare("all", "fullpath")
test.isequal({ "bin/Debug/MyProject2.lib" }, r)
end
function suite.canLink_ManagedCppAndCs()
clr "On"
links { "MyProject2" }
project "MyProject2"
kind "SharedLib"
language "C#"
local r = prepare("all", "fullpath")
test.isequal({ "bin/Debug/MyProject2.dll" }, r)
end
--
-- Managed and unmanaged projects can not link to each other.
--
function suite.ignoreLink_CppAndCs()
links { "MyProject2" }
project "MyProject2"
kind "SharedLib"
language "C#"
local r = prepare("all", "fullpath")
test.isequal({}, r)
end
--
-- Mixed and unmanaged projects can link to each other.
--
function suite.canLink_MixedAndNativeCpp()
clr "On"
links { "MyProject2" }
project "MyProject2"
kind "SharedLib"
language "C++"
local r = prepare("all", "fullpath")
test.isequal({ "bin/Debug/MyProject2.lib" }, r)
end
function suite.canLink_NativeAndMixedCpp()
links { "MyProject2" }
project "MyProject2"
kind "SharedLib"
language "C++"
clr "On"
local r = prepare("all", "fullpath")
test.isequal({ "bin/Debug/MyProject2.lib" }, r)
end

View file

@ -0,0 +1,296 @@
--
-- tests/config/test_targetinfo.lua
-- Test the config object's build target accessor.
-- Copyright (c) 2011-2013 Jason Perkins and the Premake project
--
local p = premake
local suite = test.declare("config_targetinfo")
local config = p.config
--
-- Setup and teardown
--
local wks, prj
function suite.setup()
p.action.set("test")
wks, prj = test.createWorkspace()
system "macosx"
end
local function prepare()
local cfg = test.getconfig(prj, "Debug")
return config.gettargetinfo(cfg)
end
--
-- Directory uses targetdir() value if present.
--
function suite.directoryIsTargetDir_onTargetDir()
targetdir "../bin"
i = prepare()
test.isequal("../bin", path.getrelative(os.getcwd(), i.directory))
end
--
-- Base name should use the project name by default.
--
function suite.basenameIsProjectName_onNoTargetName()
i = prepare()
test.isequal("MyProject", i.basename)
end
--
-- Base name should use targetname() if present.
--
function suite.basenameIsTargetName_onTargetName()
targetname "MyTarget"
i = prepare()
test.isequal("MyTarget", i.basename)
end
--
-- Base name should use suffix if present.
--
function suite.basenameUsesSuffix_onTargetSuffix()
targetsuffix "-d"
i = prepare()
test.isequal("MyProject-d", i.basename)
end
--
-- Name should not have an extension for Posix executables.
--
function suite.nameHasNoExtension_onMacOSXConsoleApp()
system "MacOSX"
i = prepare()
test.isequal("MyProject", i.name)
end
function suite.nameHasNoExtension_onLinuxConsoleApp()
system "Linux"
i = prepare()
test.isequal("MyProject", i.name)
end
function suite.nameHasNoExtension_onBSDConsoleApp()
system "BSD"
i = prepare()
test.isequal("MyProject", i.name)
end
--
-- Name should use ".exe" for Windows executables.
--
function suite.nameUsesExe_onWindowsConsoleApp()
kind "ConsoleApp"
system "Windows"
i = prepare()
test.isequal("MyProject.exe", i.name)
end
function suite.nameUsesExe_onWindowsWindowedApp()
kind "WindowedApp"
system "Windows"
i = prepare()
test.isequal("MyProject.exe", i.name)
end
--
-- Name should use ".dll" for Windows shared libraries.
--
function suite.nameUsesDll_onWindowsSharedLib()
kind "SharedLib"
system "Windows"
i = prepare()
test.isequal("MyProject.dll", i.name)
end
--
-- Name should use ".lib" for Windows static libraries.
--
function suite.nameUsesLib_onWindowsStaticLib()
kind "StaticLib"
system "Windows"
i = prepare()
test.isequal("MyProject.lib", i.name)
end
--
-- Name should use "lib and ".dylib" for Mac shared libraries.
--
function suite.nameUsesLib_onMacSharedLib()
kind "SharedLib"
system "MacOSX"
i = prepare()
test.isequal("libMyProject.dylib", i.name)
end
--
-- Name should use "lib and ".a" for Mac static libraries.
--
function suite.nameUsesLib_onMacStaticLib()
kind "StaticLib"
system "MacOSX"
i = prepare()
test.isequal("libMyProject.a", i.name)
end
--
-- Name should use "lib" and ".so" for Linux shared libraries.
--
function suite.nameUsesLib_onLinuxSharedLib()
kind "SharedLib"
system "Linux"
i = prepare()
test.isequal("libMyProject.so", i.name)
end
--
-- Name should use "lib" and ".a" for Linux shared libraries.
--
function suite.nameUsesLib_onLinuxStaticLib()
kind "StaticLib"
system "Linux"
i = prepare()
test.isequal("libMyProject.a", i.name)
end
--
-- Name should use a prefix if set.
--
function suite.nameUsesPrefix_onTargetPrefix()
targetprefix "sys"
i = prepare()
test.isequal("sysMyProject", i.name)
end
--
-- Bundle name should be set and use ".app" for Mac windowed applications.
--
function suite.bundlenameUsesApp_onMacWindowedApp()
kind "WindowedApp"
system "MacOSX"
i = prepare()
test.isequal("MyProject.app", i.bundlename)
end
--
-- Bundle path should be set for Mac windowed applications.
--
function suite.bundlepathSet_onMacWindowedApp()
kind "WindowedApp"
system "MacOSX"
i = prepare()
test.isequal("bin/Debug/MyProject.app/Contents/MacOS", path.getrelative(os.getcwd(), i.bundlepath))
end
--
-- Bundle path should be set for macOS/iOS cocoa bundle.
--
function suite.bundlepathSet_onMacSharedLibOSXBundle()
kind "SharedLib"
sharedlibtype "OSXBundle"
system "macosx"
i = prepare()
test.isequal("bin/Debug/MyProject.bundle/Contents/MacOS", path.getrelative(os.getcwd(), i.bundlepath))
end
--
-- Bundle path should be set for macOS/iOS cocoa unit test bundle.
--
function suite.bundlepathSet_onMacSharedLibXCTest()
kind "SharedLib"
sharedlibtype "XCTest"
system "macosx"
i = prepare()
test.isequal("bin/Debug/MyProject.xctest/Contents/MacOS", path.getrelative(os.getcwd(), i.bundlepath))
end
--
-- Bundle path should be set for macOS/iOS framework.
--
function suite.bundlepathSet_onMacSharedLibOSXFramework()
kind "SharedLib"
sharedlibtype "OSXFramework"
system "macosx"
i = prepare()
test.isequal("bin/Debug/MyProject.framework/Versions/A", path.getrelative(os.getcwd(), i.bundlepath))
end
--
-- Target extension is used if set.
--
function suite.extensionSet_onTargetExtension()
targetextension ".self"
i = prepare()
test.isequal("MyProject.self", i.name)
end
--
-- .NET executables should always default to ".exe" extensions.
--
function suite.appUsesExe_onDotNet()
_TARGET_OS = "macosx"
language "C#"
i = prepare()
test.isequal("MyProject.exe", i.name)
end
--
-- .NET libraries should always default to ".dll" extensions.
--
function suite.appUsesExe_onDotNetSharedLib()
_TARGET_OS = "macosx"
language "C#"
kind "SharedLib"
i = prepare()
test.isequal("MyProject.dll", i.name)
end

View file

@ -0,0 +1 @@
return "ok"

View file

@ -0,0 +1 @@
premake.out("ok")

View file

@ -0,0 +1 @@
Hi there!

View file

@ -0,0 +1,142 @@
--
-- tests/oven/test_filtering.lua
-- Test the project object configuration accessor.
-- Copyright (c) 2011-2014 Jason Perkins and the Premake project
--
local p = premake
local suite = test.declare("oven_filtering")
--
-- Setup
--
local wks, prj, cfg
function suite.setup()
wks = test.createWorkspace()
end
local function prepare()
wks = test.getWorkspace(wks)
prj = test.getproject(wks, 1)
cfg = test.getconfig(prj, "Debug")
end
--
-- Test filtering by the selected action.
--
function suite.onAction()
p.action.set("vs2012")
filter { "action:vs2012" }
defines { "USE_VS2012" }
prepare()
test.isequal({ "USE_VS2012" }, prj.defines)
end
function suite.onActionMismatch()
p.action.set("vs2010")
filter { "action:vs2012" }
defines { "USE_VS2012" }
prepare()
test.isequal({}, prj.defines)
end
--
-- Test filtering on command line options.
--
function suite.onOptionNoValue()
_OPTIONS["release"] = ""
filter { "options:release" }
defines { "USE_RELEASE" }
prepare()
test.isequal({ "USE_RELEASE" }, prj.defines)
end
function suite.onOptionNoValueUnset()
filter { "options:release" }
defines { "USE_RELEASE" }
prepare()
test.isequal({ }, prj.defines)
end
function suite.onOptionWithValue()
_OPTIONS["renderer"] = "opengl"
filter { "options:renderer=opengl" }
defines { "USE_OPENGL" }
prepare()
test.isequal({ "USE_OPENGL" }, prj.defines)
end
function suite.onOptionWithValueMismatch()
_OPTIONS["renderer"] = "direct3d"
filter { "options:renderer=opengl" }
defines { "USE_OPENGL" }
prepare()
test.isequal({ }, prj.defines)
end
function suite.onOptionWithValueUnset()
filter { "options:renderer=opengl" }
defines { "USE_OPENGL" }
prepare()
test.isequal({ }, prj.defines)
end
--
-- Test filtering by the selected toolset.
--
function suite.onFilterToolset()
toolset "msc"
filter { "toolset:msc" }
defines { "USE_MSC" }
prepare()
test.isequal({ "USE_MSC" }, cfg.defines)
end
function suite.onFilterToolsetMismatch()
toolset "clang"
filter { "toolset:msc" }
defines { "USE_MSC" }
prepare()
test.isequal({}, cfg.defines)
end
function suite.onFilterToolsetNormalization()
toolset "v140"
filter { "toolset:msc-v140" }
defines { "USE_MSC" }
prepare()
test.isequal({ "USE_MSC" }, cfg.defines)
end
--
-- Test filtering on system.
--
function suite.onFilterLinuxIsPosix()
system "linux"
filter { "system:posix" }
defines { "POSIX" }
filter { "system:not posix" }
defines { "NOTPOSIX" }
prepare()
test.isequal({ "POSIX" }, cfg.defines)
end
function suite.onFilterWindowsIsNotPosix()
system "windows"
filter { "system:posix" }
defines { "POSIX" }
filter { "system:not posix" }
defines { "NOTPOSIX" }
prepare()
test.isequal({ "NOTPOSIX" }, cfg.defines)
end

View file

@ -0,0 +1,84 @@
---
-- tests/oven/test_objdirs.lua
-- Test the per-configuration object directory assignments.
-- Copyright (c) 2014-2015 Jason Perkins and the Premake project
---
local p = premake
local suite = test.declare("oven_objdirs")
local oven = p.oven
---
-- Setup
---
local wks, prj
function suite.setup()
wks = workspace("MyWorkspace")
configurations { "Debug", "Release" }
prj = project "MyProject"
end
local function prepare(buildcfg, platform)
cfg = test.getconfig(prj, buildcfg, platform)
end
function suite.singleProject_noPlatforms()
prepare("Debug")
test.isequal(path.getabsolute("obj/Debug"), cfg.objdir)
prepare("Release")
test.isequal(path.getabsolute("obj/Release"), cfg.objdir)
end
function suite.multipleProjects_noPlatforms()
project "MyProject2"
prepare("Debug")
test.createproject(wks)
test.isequal(path.getabsolute("obj/Debug/MyProject"), cfg.objdir)
end
function suite.singleProject_withPlatforms()
platforms { "x86", "x86_64" }
prepare("Debug", "x86")
test.isequal(path.getabsolute("obj/x86/Debug"), cfg.objdir)
end
function suite.singleProject_uniqueByTokens_noPlatforms()
objdir "obj/%{cfg.buildcfg}"
prepare("Debug")
test.isequal(path.getabsolute("obj/Debug"), cfg.objdir)
end
function suite.singleProject_uniqueByTokens_withPlatforms()
platforms { "x86", "x86_64" }
objdir "obj/%{cfg.buildcfg}_%{cfg.platform}"
prepare("Debug", "x86")
test.isequal(path.getabsolute("obj/Debug_x86"), cfg.objdir)
end
function suite.allowOverlap_onPrefixCode()
platforms { "x86", "x86_64" }
objdir "!obj/%{cfg.buildcfg}"
prepare("Debug", "x86")
test.isequal(path.getabsolute("obj/Debug"), cfg.objdir)
end
function suite.allowOverlap_onPrefixCode_withEnvironmentVariable()
platforms { "x86", "x86_64" }
objdir "!$(SolutionDir)/%{cfg.buildcfg}"
prepare("Debug", "x86")
test.isequal("$(SolutionDir)/Debug", cfg.objdir)
end

View file

@ -0,0 +1,629 @@
--[[
== Introduction ==
Note that this requires os.clock(), debug.sethook(),
and debug.getinfo() or your equivalent replacements to
be available if this is an embedded application.
Example usage:
profiler = newProfiler()
profiler:start()
< call some functions that take time >
profiler:stop()
local outfile = io.open( "profile.txt", "w+" )
profiler:report( outfile )
outfile:close()
== Optionally choosing profiling method ==
The rest of this comment can be ignored if you merely want a good profiler.
newProfiler(method, sampledelay):
If method is omitted or "time", will profile based on real performance.
optionally, frequency can be provided to control the number of opcodes
per profiling tick. By default this is 100000, which (on my system) provides
one tick approximately every 2ms and reduces system performance by about 10%.
This can be reduced to increase accuracy at the cost of performance, or
increased for the opposite effect.
If method is "call", will profile based on function calls. Frequency is
ignored.
"time" may bias profiling somewhat towards large areas with "simple opcodes",
as the profiling function (which introduces a certain amount of unavoidable
overhead) will be called more often. This can be minimized by using a larger
sample delay - the default should leave any error largely overshadowed by
statistical noise. With a delay of 1000 I was able to achieve inaccuray of
approximately 25%. Increasing the delay to 100000 left inaccuracy below my
testing error.
"call" may bias profiling heavily towards areas with many function calls.
Testing found a degenerate case giving a figure inaccurate by approximately
20,000%. (Yes, a multiple of 200.) This is, however, more directly comparable
to common profilers (such as gprof) and also gives accurate function call
counts, which cannot be retrieved from "time".
I strongly recommend "time" mode, and it is now the default.
== History ==
2008-09-16 - Time-based profiling and conversion to Lua 5.1
by Ben Wilhelm ( zorba-pepperfish@pavlovian.net ).
Added the ability to optionally choose profiling methods, along with a new
profiling method.
Converted to Lua 5, a few improvements, and
additional documentation by Tom Spilman ( tom@sickheadgames.com )
Additional corrections and tidying by original author
Daniel Silverstone ( dsilvers@pepperfish.net )
== Status ==
Daniel Silverstone is no longer using this code, and judging by how long it's
been waiting for Lua 5.1 support, I don't think Tom Spilman is either. I'm
perfectly willing to take on maintenance, so if you have problems or
questions, go ahead and email me :)
-- Ben Wilhelm ( zorba-pepperfish@pavlovian.net ) '
== Copyright ==
Lua profiler - Copyright Pepperfish 2002,2003,2004
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to
do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
--]]
--
-- All profiler related stuff is stored in the top level table '_profiler'
--
_profiler = {}
--
-- newProfiler() creates a new profiler object for managing
-- the profiler and storing state. Note that only one profiler
-- object can be executing at one time.
--
function newProfiler(variant, sampledelay)
if _profiler.running then
print("Profiler already running.")
return
end
variant = variant or "time"
if variant ~= "time" and variant ~= "call" then
print("Profiler method must be 'time' or 'call'.")
return
end
local newprof = {}
for k,v in pairs(_profiler) do
newprof[k] = v
end
newprof.variant = variant
newprof.sampledelay = sampledelay or 100000
return newprof
end
--
-- This function starts the profiler. It will do nothing
-- if this (or any other) profiler is already running.
--
function _profiler.start(self)
if _profiler.running then
return
end
-- Start the profiler. This begins by setting up internal profiler state
_profiler.running = self
self.rawstats = {}
self.callstack = {}
if self.variant == "time" then
self.lastclock = os.clock()
debug.sethook( _profiler_hook_wrapper_by_time, "", self.sampledelay )
elseif self.variant == "call" then
debug.sethook( _profiler_hook_wrapper_by_call, "cr" )
else
print("Profiler method must be 'time' or 'call'.")
sys.exit(1)
end
end
--
-- This function stops the profiler. It will do nothing
-- if a profiler is not running, and nothing if it isn't
-- the currently running profiler.
--
function _profiler.stop(self)
if _profiler.running ~= self then
return
end
-- Stop the profiler.
debug.sethook( nil )
_profiler.running = nil
end
--
-- Simple wrapper to handle the hook. You should not
-- be calling this directly. Duplicated to reduce overhead.
--
function _profiler_hook_wrapper_by_call(action)
if _profiler.running == nil then
debug.sethook( nil )
end
_profiler.running:_internal_profile_by_call(action)
end
function _profiler_hook_wrapper_by_time(action)
if _profiler.running == nil then
debug.sethook( nil )
end
_profiler.running:_internal_profile_by_time(action)
end
--
-- This is the main by-function-call function of the profiler and should not
-- be called except by the hook wrapper
--
function _profiler._internal_profile_by_call(self,action)
-- Since we can obtain the 'function' for the item we've had call us, we
-- can use that...
local caller_info = debug.getinfo( 3 )
if caller_info == nil then
print "No caller_info"
return
end
--SHG_LOG("[_profiler._internal_profile] "..(caller_info.name or "<nil>"))
-- Retrieve the most recent activation record...
local latest_ar = nil
local callstackLen = #self.callstack
if callstackLen > 0 then
latest_ar = self.callstack[callstackLen]
end
-- Are we allowed to profile this function?
local should_not_profile = 0
for k,v in pairs(self.prevented_functions) do
if k == caller_info.func then
should_not_profile = v
end
end
-- Also check the top activation record...
if latest_ar then
if latest_ar.should_not_profile == 2 then
should_not_profile = 2
end
end
-- Now then, are we in 'call' or 'return' ?
-- print("Profile:", caller_info.name, "SNP:", should_not_profile,
-- "Action:", action )
if action == "call" then
-- Making a call...
local this_ar = {}
this_ar.should_not_profile = should_not_profile
this_ar.parent_ar = latest_ar
this_ar.anon_child = 0
this_ar.name_child = 0
this_ar.children = {}
this_ar.children_time = {}
this_ar.clock_start = os.clock()
-- Last thing to do on a call is to insert this onto the ar stack...
table.insert( self.callstack, this_ar )
else
local this_ar = latest_ar
if this_ar == nil then
return -- No point in doing anything if no upper activation record
end
-- Right, calculate the time in this function...
this_ar.clock_end = os.clock()
this_ar.this_time = this_ar.clock_end - this_ar.clock_start
-- Now, if we have a parent, update its call info...
if this_ar.parent_ar then
this_ar.parent_ar.children[caller_info.func] =
(this_ar.parent_ar.children[caller_info.func] or 0) + 1
this_ar.parent_ar.children_time[caller_info.func] =
(this_ar.parent_ar.children_time[caller_info.func] or 0 ) +
this_ar.this_time
if caller_info.name == nil then
this_ar.parent_ar.anon_child =
this_ar.parent_ar.anon_child + this_ar.this_time
else
this_ar.parent_ar.name_child =
this_ar.parent_ar.name_child + this_ar.this_time
end
end
-- Now if we're meant to record information about ourselves, do so...
if this_ar.should_not_profile == 0 then
local inforec = self:_get_func_rec(caller_info.func,1)
inforec.count = inforec.count + 1
inforec.time = inforec.time + this_ar.this_time
inforec.anon_child_time = inforec.anon_child_time + this_ar.anon_child
inforec.name_child_time = inforec.name_child_time + this_ar.name_child
inforec.func_info = caller_info
for k,v in pairs(this_ar.children) do
inforec.children[k] = (inforec.children[k] or 0) + v
inforec.children_time[k] =
(inforec.children_time[k] or 0) + this_ar.children_time[k]
end
end
-- Last thing to do on return is to drop the last activation record...
local callstackLen = #self.callstack
table.remove( self.callstack, callstackLen )
end
end
--
-- This is the main by-time internal function of the profiler and should not
-- be called except by the hook wrapper
--
function _profiler._internal_profile_by_time(self,action)
-- we do this first so we add the minimum amount of extra time to this call
local timetaken = os.clock() - self.lastclock
local depth = 3
local at_top = true
local last_caller
local caller = debug.getinfo(depth)
while caller do
if not caller.func then caller.func = "(tail call)" end
if self.prevented_functions[caller.func] == nil then
local info = self:_get_func_rec(caller.func, 1, caller)
info.count = info.count + 1
info.time = info.time + timetaken
if last_caller then
-- we're not the head, so update the "children" times also
if last_caller.name then
info.name_child_time = info.name_child_time + timetaken
else
info.anon_child_time = info.anon_child_time + timetaken
end
info.children[last_caller.func] =
(info.children[last_caller.func] or 0) + 1
info.children_time[last_caller.func] =
(info.children_time[last_caller.func] or 0) + timetaken
end
end
depth = depth + 1
last_caller = caller
caller = debug.getinfo(depth)
end
self.lastclock = os.clock()
end
--
-- This returns a (possibly empty) function record for
-- the specified function. It is for internal profiler use.
--
function _profiler._get_func_rec(self,func,force,info)
-- Find the function ref for 'func' (if force and not present, create one)
local ret = self.rawstats[func]
if ret == nil and force ~= 1 then
return nil
end
if ret == nil then
-- Build a new function statistics table
ret = {}
ret.func = func
ret.count = 0
ret.time = 0
ret.anon_child_time = 0
ret.name_child_time = 0
ret.children = {}
ret.children_time = {}
ret.func_info = info
self.rawstats[func] = ret
end
return ret
end
--
-- This writes a profile report to the output file object. If
-- sort_by_total_time is nil or false the output is sorted by
-- the function time minus the time in it's children.
--
function _profiler.report( self, outfile, sort_by_total_time )
outfile:write
[[Lua Profile output created by profiler.lua. Copyright Pepperfish 2002+
]]
-- This is pretty awful.
local terms = {}
if self.variant == "time" then
terms.capitalized = "Sample"
terms.single = "sample"
terms.pastverb = "sampled"
elseif self.variant == "call" then
terms.capitalized = "Call"
terms.single = "call"
terms.pastverb = "called"
else
assert(false)
end
local total_time = 0
local ordering = {}
for func,record in pairs(self.rawstats) do
table.insert(ordering, func)
end
if sort_by_total_time then
table.sort( ordering,
function(a,b) return self.rawstats[a].time > self.rawstats[b].time end
)
else
table.sort( ordering,
function(a,b)
local arec = self.rawstats[a]
local brec = self.rawstats[b]
local atime = arec.time - (arec.anon_child_time + arec.name_child_time)
local btime = brec.time - (brec.anon_child_time + brec.name_child_time)
return atime > btime
end
)
end
local len = #ordering
for i=1,len do
local func = ordering[i]
local record = self.rawstats[func]
local thisfuncname = " " .. self:_pretty_name(func) .. " "
if string.len( thisfuncname ) < 42 then
local nameLen = math.ceil((42 - string.len(thisfuncname))/2)
thisfuncname =
string.rep( "-", nameLen) .. thisfuncname
thisfuncname =
thisfuncname .. string.rep( "-", 42 - string.len(thisfuncname) )
end
total_time = total_time + ( record.time - ( record.anon_child_time +
record.name_child_time ) )
outfile:write( string.rep( "-", 19 ) .. thisfuncname ..
string.rep( "-", 19 ) .. "\n" )
outfile:write( terms.capitalized.." count: " ..
string.format( "%4d", record.count ) .. "\n" )
outfile:write( "Time spend total: " ..
string.format( "%4.3f", record.time ) .. "s\n" )
outfile:write( "Time spent in children: " ..
string.format("%4.3f",record.anon_child_time+record.name_child_time) ..
"s\n" )
local timeinself =
record.time - (record.anon_child_time + record.name_child_time)
outfile:write( "Time spent in self: " ..
string.format("%4.3f", timeinself) .. "s\n" )
outfile:write( "Time spent per " .. terms.single .. ": " ..
string.format("%4.5f", record.time/record.count) ..
"s/" .. terms.single .. "\n" )
outfile:write( "Time spent in self per "..terms.single..": " ..
string.format( "%4.5f", timeinself/record.count ) .. "s/" ..
terms.single.."\n" )
-- Report on each child in the form
-- Child <funcname> called n times and took a.bs
local added_blank = 0
for k,v in pairs(record.children) do
if self.prevented_functions[k] == nil or
self.prevented_functions[k] == 0
then
if added_blank == 0 then
outfile:write( "\n" ) -- extra separation line
added_blank = 1
end
outfile:write( "Child " .. self:_pretty_name(k) ..
string.rep( " ", 41-string.len(self:_pretty_name(k)) ) .. " " ..
terms.pastverb.." " .. string.format("%6d", v) )
outfile:write( " times. Took " ..
string.format("%4.2f", record.children_time[k] ) .. "s\n" )
end
end
outfile:write( "\n" ) -- extra separation line
outfile:flush()
end
outfile:write( "\n\n" )
outfile:write( "Total time spent in profiled functions: " ..
string.format("%5.3g",total_time) .. "s\n" )
outfile:write( [[
END
]] )
outfile:flush()
end
--
-- This writes the profile to the output file object as
-- loadable Lua source.
--
function _profiler.lua_report(self,outfile)
-- Purpose: Write out the entire raw state in a cross-referenceable form.
local ordering = {}
local functonum = {}
for func,record in pairs(self.rawstats) do
table.insert(ordering, func)
local len = #ordering
functonum[func] = len
end
outfile:write(
"-- Profile generated by profiler.lua Copyright Pepperfish 2002+\n\n" )
outfile:write( "-- Function names\nfuncnames = {}\n" )
local len = #ordering
for i=1,len do
local thisfunc = ordering[i]
outfile:write( "funcnames[" .. i .. "] = " ..
string.format("%q", self:_pretty_name(thisfunc)) .. "\n" )
end
outfile:write( "\n" )
outfile:write( "-- Function times\nfunctimes = {}\n" )
local len = #ordering
for i=1,len do
local thisfunc = ordering[i]
local record = self.rawstats[thisfunc]
outfile:write( "functimes[" .. i .. "] = { " )
outfile:write( "tot=" .. record.time .. ", " )
outfile:write( "achild=" .. record.anon_child_time .. ", " )
outfile:write( "nchild=" .. record.name_child_time .. ", " )
outfile:write( "count=" .. record.count .. " }\n" )
end
outfile:write( "\n" )
outfile:write( "-- Child links\nchildren = {}\n" )
local len = #ordering
for i=1,len do
local thisfunc = ordering[i]
local record = self.rawstats[thisfunc]
outfile:write( "children[" .. i .. "] = { " )
for k,v in pairs(record.children) do
if functonum[k] then -- non-recorded functions will be ignored now
outfile:write( functonum[k] .. ", " )
end
end
outfile:write( "}\n" )
end
outfile:write( "\n" )
outfile:write( "-- Child call counts\nchildcounts = {}\n" )
local len = #ordering
for i=1,len do
local thisfunc = ordering[i]
local record = self.rawstats[thisfunc]
outfile:write( "children[" .. i .. "] = { " )
for k,v in record.children do
if functonum[k] then -- non-recorded functions will be ignored now
outfile:write( v .. ", " )
end
end
outfile:write( "}\n" )
end
outfile:write( "\n" )
outfile:write( "-- Child call time\nchildtimes = {}\n" )
local len = #ordering
for i=1,len do
local thisfunc = ordering[i]
local record = self.rawstats[thisfunc];
outfile:write( "children[" .. i .. "] = { " )
for k,v in pairs(record.children) do
if functonum[k] then -- non-recorded functions will be ignored now
outfile:write( record.children_time[k] .. ", " )
end
end
outfile:write( "}\n" )
end
outfile:write( "\n\n-- That is all.\n\n" )
outfile:flush()
end
-- Internal function to calculate a pretty name for the profile output
function _profiler._pretty_name(self,func)
-- Only the data collected during the actual
-- run seems to be correct.... why?
local info = self.rawstats[ func ].func_info
-- local info = debug.getinfo( func )
local name = ""
if info.what == "Lua" then
name = "L:"
end
if info.what == "C" then
name = "C:"
end
if info.what == "main" then
name = " :"
end
if info.name == nil then
name = name .. "<"..tostring(func) .. ">"
else
name = name .. info.name
end
if info.source then
name = name .. "@" .. info.source
else
if info.what == "C" then
name = name .. "@?"
else
name = name .. "@<string>"
end
end
name = name .. ":"
if info.what == "C" then
name = name .. "?"
else
name = name .. info.linedefined
end
return name
end
--
-- This allows you to specify functions which you do
-- not want profiled. Setting level to 1 keeps the
-- function from being profiled. Setting level to 2
-- keeps both the function and its children from
-- being profiled.
--
-- BUG: 2 will probably act exactly like 1 in "time" mode.
-- If anyone cares, let me (zorba) know and it can be fixed.
--
function _profiler.prevent(self, func, level)
self.prevented_functions[func] = (level or 1)
end
_profiler.prevented_functions = {
[_profiler.start] = 2,
[_profiler.stop] = 2,
[_profiler._internal_profile_by_time] = 2,
[_profiler._internal_profile_by_call] = 2,
[_profiler_hook_wrapper_by_time] = 2,
[_profiler_hook_wrapper_by_call] = 2,
[_profiler.prevent] = 2,
[_profiler._get_func_rec] = 2,
[_profiler.report] = 2,
[_profiler.lua_report] = 2,
[_profiler._pretty_name] = 2
}

View file

@ -0,0 +1,165 @@
--
-- tests/project/test_config_maps.lua
-- Test mapping from workspace to project configurations.
-- Copyright (c) 2012-2014 Jason Perkins and the Premake project
--
local suite = test.declare("project_config_maps")
--
-- Setup and teardown
--
local wks, prj, cfg
function suite.setup()
wks = workspace("MyWorkspace")
configurations { "Debug", "Release" }
end
local function prepare(buildcfg, platform)
prj = wks.projects[1]
cfg = test.getconfig(prj, buildcfg or "Debug", platform)
end
--
-- When no configuration is specified in the project, the workspace
-- settings should map directly to a configuration object.
--
function suite.workspaceConfig_onNoProjectConfigs()
project ("MyProject")
prepare()
test.isequal("Debug", cfg.buildcfg)
end
--
-- If a project configuration mapping exists, it should be taken into
-- account when fetching the configuration object.
--
function suite.appliesCfgMapping_onBuildCfgMap()
project ("MyProject")
configmap { ["Debug"] = "Development" }
prepare()
test.isequal("Development", cfg.buildcfg)
end
function suite.appliesCfgMapping_onPlatformMap()
platforms { "Shared", "Static" }
project ("MyProject")
configmap { ["Shared"] = "DLL" }
prepare("Debug", "Shared")
test.isequal("DLL", cfg.platform)
end
--
-- If a configuration mapping exists, can also use the mapped value
-- to fetch the configuration.
--
function suite.fetchesMappedCfg_onBuildCfgMap()
project ("MyProject")
configmap { ["Debug"] = "Development" }
prepare("Development")
test.isequal("Development", cfg.buildcfg)
end
function suite.fetchesMappedCfg_onPlatformMap()
platforms { "Shared", "Static" }
project ("MyProject")
configmap { ["Shared"] = "DLL" }
prepare("Debug", "DLL")
test.isequal("DLL", cfg.platform)
end
--
-- If the specified configuration has been removed from the project,
-- then nil should be returned.
--
function suite.returnsNil_onRemovedBuildCfg()
project ("MyProject")
removeconfigurations { "Debug" }
prepare()
test.isnil(cfg)
end
function suite.returnsNil_onRemovedPlatform()
platforms { "Shared", "Static" }
project ("MyProject")
removeplatforms { "Shared" }
prepare("Debug", "Shared")
test.isnil(cfg)
end
--
-- Check mapping from a buildcfg-platform tuple to a simple single
-- value platform configuration.
--
function suite.canMap_tupleToSingle()
platforms { "Win32", "Linux" }
project ("MyProject")
removeconfigurations "*"
removeplatforms "*"
configurations { "Debug Win32", "Release Win32", "Debug Linux", "Release Linux" }
configmap {
[{"Debug", "Win32"}] = "Debug Win32",
[{"Debug", "Linux"}] = "Debug Linux",
[{"Release", "Win32"}] = "Release Win32",
[{"Release", "Linux"}] = "Release Linux"
}
prepare("Debug", "Linux")
test.isequal("Debug Linux", cfg.buildcfg)
end
--
-- Check mapping from a buildcfg-platform tuple to new project
-- configuration tuple.
--
function suite.canMap_tupleToTuple()
platforms { "Win32", "Linux" }
project ("MyProject")
removeconfigurations "*"
removeplatforms "*"
configurations { "Development", "Production" }
platforms { "x86", "x86_64" }
configmap {
[{"Debug", "Win32"}] = { "Development", "x86" },
[{"Debug", "Linux"}] = { "Development", "x86_64" },
[{"Release", "Win32"}] = { "Production", "x86" },
[{"Release", "Linux"}] = { "Production", "x86_64" },
}
prepare("Debug", "Linux")
test.isequal({ "Development", "x86_64" }, { cfg.buildcfg, cfg.platform })
end
--
-- To allow some measure of global configuration, config maps that are contained
-- in configuration blocks are allowed to bubble up to the project level.
--
function suite.canBubbleUp_onConfiguration()
platforms { "XCUA", "XCUB" }
filter { "platforms:CCU" }
configmap { XCUA = "CCU", XCUB = "CCU" }
project "MyProject"
platforms { "CCU" }
prepare("Debug", "XCUA")
test.isequal({"Debug", "CCU"}, {cfg.buildcfg, cfg.platform})
end

View file

@ -0,0 +1,173 @@
--
-- tests/project/test_eachconfig.lua
-- Test the project object configuration iterator function.
-- Copyright (c) 2011-2015 Jason Perkins and the Premake project
--
local p = premake
local suite = test.declare("project_eachconfig")
--
-- Setup and teardown
--
local wks, prj
function suite.setup()
wks = workspace("MyWorkspace")
end
local function prepare(buildcfgs)
project("MyProject")
if buildcfgs then
configurations ( buildcfgs )
end
prj = test.getproject(wks, 1)
for cfg in p.project.eachconfig(prj) do
_p(2,'%s:%s', cfg.buildcfg or "", cfg.platform or "")
end
end
--
-- If no configurations have been defined, the iterator
-- should not return any values.
--
function suite.returnsNoValues_onNoConfigurationsAndNoPlatforms()
prepare()
test.isemptycapture()
end
--
-- If platforms have been defined, but no configurations, the
-- iterator should still not return any values.
--
function suite.returnsNoValues_onNoConfigurationsButPlatforms()
platforms { "x86", "x86_64" }
prepare()
test.isemptycapture()
end
--
-- Configurations should be iterated in the order in which they
-- appear in the script.
--
function suite.iteratesConfigsInOrder()
configurations { "Debug", "Profile", "Release", "Deploy" }
prepare()
test.capture [[
Debug:
Profile:
Release:
Deploy:
]]
end
--
-- If platforms are supplied, they should be paired with build
-- configurations, with the order of both maintained.
--
function suite.pairsConfigsAndPlatformsInOrder()
configurations { "Debug", "Release" }
platforms { "x86", "x86_64" }
prepare()
test.capture [[
Debug:x86
Debug:x86_64
Release:x86
Release:x86_64
]]
end
--
-- Test the mapping of a build configuration from workspace to project.
--
function suite.mapsBuildCfg_toBuildCfg()
configurations { "Debug", "Release" }
configmap { ["Debug"] = "ProjectDebug" }
prepare()
test.capture [[
ProjectDebug:
Release:
]]
end
--
-- Test mapping a platform from workspace to project.
--
function suite.mapsPlatform_toPlatform()
configurations { "Debug", "Release" }
platforms { "Win32" }
configmap { ["Win32"] = "x86_64" }
prepare()
test.capture [[
Debug:x86_64
Release:x86_64
]]
end
--
-- Test mapping a build configuration to a build config/platform pair.
-- This will cause a second platform to appear in the project, alongside
-- the one defined by the workspace.
--
function suite.mapsBuildCfg_toBuildCfgAndPlatform()
configurations { "Debug", "Release" }
platforms { "Win32" }
configmap { ["Debug"] = { "ProjectDebug", "x86_64" } }
prepare()
test.capture [[
ProjectDebug:x86_64
ProjectDebug:Win32
Release:x86_64
Release:Win32
]]
end
--
-- Any duplicate configurations created by the mapping should be removed.
--
function suite.removesDups_onConfigMapping()
configurations { "Debug", "Development", "Release" }
configmap { ["Development"] = "Debug" }
prepare()
test.capture [[
Debug:
Release:
]]
end
--
-- If there is overlap in the workspace and project configuration lists,
-- the ordering at the project level should be maintained to avoid
-- unnecessarily dirtying the project file.
--
function suite.maintainsProjectOrdering_onWorkspaceOverlap()
configurations { "Debug", "Release" }
prepare { "Debug", "Development", "Profile", "Release" }
test.capture [[
Debug:
Development:
Profile:
Release:
]]
end

View file

@ -0,0 +1,114 @@
--
-- tests/project/test_getconfig.lua
-- Test the project object configuration accessor.
-- Copyright (c) 2011-2014 Jason Perkins and the Premake project
--
local p = premake
local suite = test.declare("project_getconfig")
--
-- Setup and teardown
--
local wks, prj, cfg
function suite.setup()
wks = workspace("MyWorkspace")
configurations { "Debug", "Release" }
end
local function prepare(buildcfg, platform)
prj = wks.projects[1]
cfg = test.getconfig(prj, buildcfg or "Debug", platform)
end
--
-- If the target system is not specified, the current operating environment
-- should be used as the default.
--
function suite.usesCurrentOS_onNoSystemSpecified()
_TARGET_OS = "linux"
project ("MyProject")
filter { "system:linux" }
defines { "correct" }
prepare()
test.isequal("correct", cfg.defines[1])
end
--
-- If the current action specifies a target operating environment (i.e.
-- Visual Studio targets Windows), that should override the current
-- operating environment.
--
function suite.actionOverridesOS()
_TARGET_OS = "linux"
p.action.set("vs2005")
project ("MyProject")
filter { "system:windows" }
defines { "correct" }
prepare()
test.isequal("correct", cfg.defines[1])
end
--
-- If a target system is specified in a configuration, it should override
-- the current operating environment, as well as the tool's target OS.
--
function suite.usesCfgSystem()
_TARGET_OS = "linux"
p.action.set("vs2005")
project ("MyProject")
system "macosx"
filter { "system:macosx" }
defines { "correct" }
prepare()
test.isequal("correct", cfg.defines[1])
end
--
-- The current action should be taken into account.
--
function suite.appliesActionToFilters()
p.action.set("vs2005")
project ("MyProject")
filter { "action:vs2005" }
defines { "correct" }
prepare()
test.isequal("correct", cfg.defines[1])
end
--
-- If the platform matches an architecture identifier, and none was set,
-- the configuration's architecture should be set to match.
--
function suite.setsArchitecture_onMatchingPlatform()
platforms { "x86", "x86_64" }
project ("MyProject")
prepare("Debug", "x86")
test.isequal("x86", cfg.architecture)
end
--
-- If the platform matches an architecture, it should not modify any
-- currently set value.
--
function suite.doesNotOverride_onMatchingPlatform()
platforms { "x86", "x64" }
project ("MyProject")
architecture "x86_64"
prepare("Debug", "x86")
test.isequal("x86_64", cfg.architecture)
end

View file

@ -0,0 +1,57 @@
--
-- tests/project/test_location.lua
-- Test handling of the projects's location field.
-- Copyright (c) 2013 Jason Perkins and the Premake project
--
local suite = test.declare("project_location")
--
-- Setup and teardown
--
local wks, prj
function suite.setup()
wks = test.createWorkspace()
end
local function prepare()
prj = test.getproject(wks, 1)
end
--
-- If no explicit location is set, the location should be set to the
-- directory containing the script which defined the project.
--
function suite.usesScriptLocation_onNoLocation()
prepare()
test.isequal(os.getcwd(), prj.location)
end
--
-- If an explicit location has been set, use it.
--
function suite.usesLocation_onLocationSet()
location "build"
prepare()
test.isequal(path.join(os.getcwd(), "build"), prj.location)
end
--
-- If the workspace sets a location, and the project does not, it should
-- inherit the value from the workspace.
--
function suite.inheritsWorkspaceLocation_onNoProjectLocation()
workspace ()
location "build"
prepare()
test.isequal(path.join(os.getcwd(), "build"), prj.location)
end

View file

@ -0,0 +1,94 @@
--
-- tests/project/test_sources.lua
-- Automated test suite for the source tree, including tokens and wildcards.
-- Copyright (c) 2011-2013 Jason Perkins and the Premake project
--
local p = premake
local suite = test.declare("project_sources")
local project = p.project
--
-- Setup and teardown
--
local wks, prj
local cwd = os.getcwd()
local oldcwd
function suite.setup()
wks, prj = test.createWorkspace()
-- We change the directory to get nice relative paths
oldcwd = os.getcwd()
os.chdir(cwd)
-- Create a token to be used in search paths
p.api.register { name = "mytoken", kind = "string", scope = "config" }
mytoken "test"
end
function suite.teardown()
mytoken = nil
os.chdir(oldcwd)
end
local function run()
local cfg = test.getconfig(prj, "Debug")
local files = {}
for _, file in ipairs(cfg.files) do
table.insert(files, path.getrelative(cwd, file))
end
return files
end
--
-- Test single file
--
function suite.SingleFile()
files { "test_sources.lua" }
test.isequal({"test_sources.lua"}, run())
end
--
-- Test tokens
--
function suite.SingleFileWithToken()
files { "%{cfg.mytoken}_sources.lua" }
test.isequal({"test_sources.lua"}, run())
end
--
-- Test wildcards
--
function suite.FilesWithWildcard()
files { "test_*.lua" }
test.contains("test_sources.lua", run())
end
function suite.FilesWithRecursiveWildcard()
files { "../**_sources.lua" }
test.contains("test_sources.lua", run())
end
--
-- Test wildcards and tokens combined
--
function suite.FilesWithWildcardAndToken()
files { "%{cfg.mytoken}_*.lua" }
test.contains("test_sources.lua", run())
end
function suite.FilesWithRecursiveWildcardAndToken()
files { "../**/%{cfg.mytoken}_sources.lua" }
test.contains("test_sources.lua", run())
end

View file

@ -0,0 +1,151 @@
--
-- tests/project/test_vpaths.lua
-- Automated test suite for the project support functions.
-- Copyright (c) 2011-2013 Jason Perkins and the Premake project
--
local p = premake
local suite = test.declare("project_vpaths")
local project = p.project
--
-- Setup and teardown
--
local wks, prj
function suite.setup()
wks, prj = test.createWorkspace()
end
local function run()
local cfg = test.getconfig(prj, "Debug")
return project.getvpath(prj, cfg.files[1])
end
--
-- Test simple replacements
--
function suite.ReturnsOriginalPath_OnNoVpaths()
files { "hello.c" }
test.isequal(path.join(os.getcwd(), "hello.c"), run())
end
function suite.ReturnsOriginalPath_OnNoMatches()
files { "hello.c" }
vpaths { ["Headers"] = "**.h" }
test.isequal(path.join(os.getcwd(), "hello.c"), run())
end
function suite.CanStripPaths()
files { "src/myproject/hello.c" }
vpaths { [""] = "src" }
run()
test.isequal("hello.c", run())
end
function suite.CanTrimLeadingPaths()
files { "src/myproject/hello.c" }
vpaths { ["*"] = "src" }
test.isequal("myproject/hello.c", run())
end
function suite.PatternMayIncludeTrailingSlash()
files { "src/myproject/hello.c" }
vpaths { [""] = "src/myproject/" }
test.isequal("hello.c", run())
end
function suite.SimpleReplacementPatterns()
files { "src/myproject/hello.c" }
vpaths { ["sources"] = "src/myproject" }
test.isequal("sources/hello.c", run())
end
function suite.ExactFilenameMatch()
files { "src/hello.c" }
vpaths { ["sources"] = "src/hello.c" }
test.isequal("sources/hello.c", run())
end
--
-- Test wildcard patterns
--
function suite.MatchFilePattern_ToGroup_Flat()
files { "src/myproject/hello.h" }
vpaths { ["Headers"] = "**.h" }
test.isequal("Headers/hello.h", run())
end
function suite.MatchFilePattern_ToNone_Flat()
files { "src/myproject/hello.h" }
vpaths { [""] = "**.h" }
test.isequal("hello.h", run())
end
function suite.MatchFilePattern_ToNestedGroup_Flat()
files { "src/myproject/hello.h" }
vpaths { ["Source/Headers"] = "**.h" }
test.isequal("Source/Headers/hello.h", run())
end
function suite.MatchFilePattern_ToGroup_WithTrailingSlash()
files { "src/myproject/hello.h" }
vpaths { ["Headers/"] = "**.h" }
test.isequal("Headers/hello.h", run())
end
function suite.MatchFilePattern_ToGroup_Nested()
files { "src/myproject/hello.h" }
vpaths { ["Headers/*"] = "**.h" }
test.isequal("Headers/src/myproject/hello.h", run())
end
function suite.MatchFilePattern_ToGroup_Nested_OneStar()
files { "src/myproject/hello.h" }
vpaths { ["Headers/*"] = "**.h" }
test.isequal("Headers/src/myproject/hello.h", run())
end
function suite.MatchFilePatternWithPath_ToGroup_Nested()
files { "src/myproject/hello.h" }
vpaths { ["Headers/*"] = "src/**.h" }
test.isequal("Headers/myproject/hello.h", run())
end
function suite.matchBaseFileName_onWildcardExtension()
files { "hello.cpp" }
vpaths { ["Sources"] = "hello.*" }
test.isequal("Sources/hello.cpp", run())
end
--
-- Test with project locations
--
function suite.MatchPath_OnProjectLocationSet()
location "build"
files "src/hello.h"
vpaths { [""] = "src" }
test.isequal("hello.h", run())
end
function suite.MatchFilePattern_OnProjectLocationSet()
location "build"
files "src/hello.h"
vpaths { ["Headers"] = "**.h" }
test.isequal("Headers/hello.h", run())
end
function suite.MatchFilePatternWithPath_OnProjectLocationSet()
location "build"
files "src/hello.h"
vpaths { ["Headers"] = "src/**.h" }
test.isequal("Headers/hello.h", run())
end

View file

@ -0,0 +1,2 @@
#!/bin/sh
cd `dirname $0` && ../bin/debug/premake5 /file=../premake5.lua /scripts=.. $1 $2 $3 test

View file

@ -0,0 +1,4 @@
@echo off
pushd "%~dp0"
..\bin\debug\premake5.exe /scripts=.. /file=..\premake5.lua %* test
popd

View file

@ -0,0 +1,37 @@
--
-- tests/test_premake.lua
-- Automated test suite for the Premake support functions.
-- Copyright (c) 2008-2015 Jason Perkins and the Premake project
--
local suite = test.declare("premake")
local p = premake
--
-- Setup
--
local wks, prj
function suite.setup()
wks = test.createWorkspace()
location "MyLocation"
prj = p.workspace.getproject(wks, 1)
end
--
-- generate() tests
--
function suite.generate_OpensCorrectFile()
p.generate(prj, ".prj", function () end)
test.openedfile(path.join(os.getcwd(), "MyLocation/MyProject.prj"))
end
function suite.generate_ClosesFile()
p.generate(prj, ".prj", function () end)
test.closedfile(true)
end

View file

@ -0,0 +1,72 @@
---
-- tests/tests_stress.lua
--
-- Stress test for Premake. Creates a large (tunable, see local variables
-- at start of file) number of projects, files, and configurations. Then
-- generates them all while profiling the result.
--
-- Run it like normal, i.e. `premake5 --file=test_stress.lua gmake`. The
-- profile results will be placed at `build/profile.txt`.
--
-- Copyright (c) 2009-2015 Jason Perkins and the Premake project
---
--
-- Test parameters
--
local numProjects = 15
local numFiles = 100
local numBuildCfgs = 6
local numPlatforms = 6
local prjKind = "ConsoleApp"
local prjLanguage = "C++"
--
-- Generate the workspace and projects
--
workspace "MyWorkspace"
location "build"
for i = 1, numBuildCfgs do
configurations ( "BuildCfg" .. i )
end
for i = 1, numPlatforms do
platforms ( "Platform" .. i )
end
for i = 1, numProjects do
project ("Project" .. i)
location "build"
kind ( prjKind )
language ( prjLanguage )
for j = 1, numFiles do
files { "file" .. j .. ".cpp" }
end
end
--
-- Install profiling extensions
-- TODO: would be nice to build these into the core exe, and could be
-- triggered with a flag, i.e. `premake5 --profile gmake`
--
dofile("pepperfish_profiler.lua")
profiler = newProfiler()
profiler:start()
premake.override(premake.main, "postAction", function(base)
base()
profiler:stop()
local outfile = io.open("build/profile.txt", "w+" )
profiler:report(outfile)
outfile:close()
end)

View file

@ -0,0 +1,100 @@
--
-- tests/test_string.lua
-- Automated test suite for the new string functions.
-- Copyright (c) 2008 Jason Perkins and the Premake project
--
local suite = test.declare("string")
--
-- string.endswith() tests
--
function suite.endswith_ReturnsTrue_OnMatch()
test.istrue(string.endswith("Abcdef", "def"))
end
function suite.endswith_ReturnsFalse_OnMismatch()
test.isfalse(string.endswith("Abcedf", "efg"))
end
function suite.endswith_ReturnsFalse_OnLongerNeedle()
test.isfalse(string.endswith("Abc", "Abcdef"))
end
function suite.endswith_ReturnsFalse_OnNilHaystack()
test.isfalse(string.endswith(nil, "ghi"))
end
function suite.endswith_ReturnsFalse_OnNilNeedle()
test.isfalse(string.endswith("Abc", nil))
end
function suite.endswith_ReturnsTrue_OnExactMatch()
test.istrue(string.endswith("/", "/"))
end
--
-- string.explode() tests
--
function suite.explode_ReturnsParts_OnValidCall()
test.isequal({"aaa","bbb","ccc"}, string.explode("aaa/bbb/ccc", "/", true))
end
--
-- string.startswith() tests
--
function suite.startswith_OnMatch()
test.istrue(string.startswith("Abcdef", "Abc"))
end
function suite.startswith_OnMismatch()
test.isfalse(string.startswith("Abcdef", "ghi"))
end
function suite.startswith_OnLongerNeedle()
test.isfalse(string.startswith("Abc", "Abcdef"))
end
function suite.startswith_OnEmptyHaystack()
test.isfalse(string.startswith("", "Abc"))
end
function suite.startswith_OnEmptyNeedle()
test.istrue(string.startswith("Abcdef", ""))
end
--
-- string.escapepattern() tests
--
function suite.escapepattern_escapes()
test.isequal("boost_filesystem%-vc140%.1%.61%.0%.0", string.escapepattern("boost_filesystem-vc140.1.61.0.0"))
test.isequal("footage/down/temp/cars_%[100%]_upper/cars_%[100%]_upper%.exr", string.escapepattern("footage/down/temp/cars_[100]_upper/cars_[100]_upper.exr"))
end
function suite.escapepattern_doesntEscape()
local s = '<something foo="bar" />'
test.isequal(s, s:escapepattern())
s = 'lorem ipsum dolor sit amet'
test.isequal(s, s:escapepattern())
s = 'forward/slashes/foo/bar'
test.isequal(s, s:escapepattern())
s = '\\back\\slashes'
test.isequal(s, s:escapepattern())
s = 'new\nlines'
test.isequal(s, s:escapepattern())
end

View file

@ -0,0 +1,71 @@
--
-- tests/test_clang.lua
-- Automated test suite for the GCC toolset interface.
-- Copyright (c) 2009-2013 Jason Perkins and the Premake project
--
local p = premake
local suite = test.declare("tools_clang")
local clang = p.tools.clang
local project = p.project
--
-- Setup/teardown
--
local wks, prj, cfg
function suite.setup()
wks, prj = test.createWorkspace()
system "Linux"
end
local function prepare()
cfg = test.getconfig(prj, "Debug")
end
--
-- Check Mac OS X deployment target flags
--
function suite.cflags_macosx_systemversion()
system "MacOSX"
systemversion "10.9"
prepare()
test.contains({ "-mmacosx-version-min=10.9" }, clang.getcflags(cfg))
end
function suite.cxxflags_macosx_systemversion()
system "MacOSX"
systemversion "10.9"
prepare()
test.contains({ "-mmacosx-version-min=10.9" }, clang.getcxxflags(cfg))
end
function suite.cxxflags_macosx_systemversion_unspecified()
system "MacOSX"
prepare()
test.excludes({ "-mmacosx-version-min=10.9" }, clang.getcxxflags(cfg))
end
--
-- Check iOS deployment target flags
--
function suite.cflags_ios_systemversion()
system "iOS"
systemversion "12.1"
prepare()
test.contains({ "-miphoneos-version-min=12.1" }, clang.getcflags(cfg))
end
function suite.cxxflags_ios_systemversion()
system "iOS"
systemversion "5.0"
prepare()
test.contains({ "-miphoneos-version-min=5.0" }, clang.getcxxflags(cfg))
end

View file

@ -0,0 +1,57 @@
--
-- tests/tools/test_dotnet.lua
-- Automated test suite for the .NET toolset interface.
-- Copyright (c) 2012-2013 Jason Perkins and the Premake project
--
local p = premake
local suite = test.declare("tools_dotnet")
local dotnet = p.tools.dotnet
--
-- Setup/teardown
--
local wks, prj, cfg
function suite.setup()
wks, prj = test.createWorkspace()
end
local function prepare()
cfg = test.getconfig(prj, "Debug")
end
--
-- On Windows, use Microsoft's CSC compiler by default.
--
function suite.defaultCompiler_onWindows()
_TARGET_OS = "windows"
prepare()
test.isequal("csc", dotnet.gettoolname(cfg, "csc"))
end
--
-- Everywhere other than Windows, use Mono by default.
--
function suite.defaultCompiler_onMacOSX()
_TARGET_OS = "macosx"
prepare()
test.isequal("csc", dotnet.gettoolname(cfg, "csc"))
end
--
-- Check support for the `csversion` API
--
function suite.flags_csversion()
prepare()
csversion "7.2"
test.contains({ "/langversion:7.2" }, dotnet.getflags(cfg))
end

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,580 @@
--
-- tests/test_msc.lua
-- Automated test suite for the Microsoft C toolset interface.
-- Copyright (c) 2012-2013 Jason Perkins and the Premake project
--
local p = premake
local suite = test.declare("tools_msc")
local msc = p.tools.msc
--
-- Setup/teardown
--
local wks, prj, cfg
function suite.setup()
wks, prj = test.createWorkspace()
kind "SharedLib"
end
local function prepare()
cfg = test.getconfig(prj, "Debug")
end
--
-- Check the optimization flags.
--
function suite.cflags_onNoOptimize()
optimize "Off"
prepare()
test.contains("/Od", msc.getcflags(cfg))
end
function suite.cflags_onOptimize()
optimize "On"
prepare()
test.contains("/Ot", msc.getcflags(cfg))
end
function suite.cflags_onOptimizeSize()
optimize "Size"
prepare()
test.contains("/O1", msc.getcflags(cfg))
end
function suite.cflags_onOptimizeSpeed()
optimize "Speed"
prepare()
test.contains("/O2", msc.getcflags(cfg))
end
function suite.cflags_onOptimizeFull()
optimize "Full"
prepare()
test.contains("/Ox", msc.getcflags(cfg))
end
function suite.cflags_onOptimizeDebug()
optimize "Debug"
prepare()
test.contains("/Od", msc.getcflags(cfg))
end
function suite.cflags_onNoFramePointers()
flags "NoFramePointer"
prepare()
test.contains("/Oy", msc.getcflags(cfg))
end
function suite.cflags_onOmitFramePointer()
omitframepointer "On"
prepare()
test.contains("/Oy", msc.getcflags(cfg))
end
function suite.cflags_onNoOmitFramePointers()
omitframepointer "Off"
prepare()
test.excludes("/Oy", msc.getcflags(cfg))
end
function suite.cflags_onLinkTimeOptimizations()
flags "LinkTimeOptimization"
prepare()
test.contains("/GL", msc.getcflags(cfg))
end
function suite.ldflags_onLinkTimeOptimizations()
flags "LinkTimeOptimization"
prepare()
test.contains("/LTCG", msc.getldflags(cfg))
end
function suite.cflags_onStringPoolingOn()
stringpooling "On"
prepare()
test.contains("/GF", msc.getcflags(cfg))
end
function suite.cflags_onStringPoolingOff()
stringpooling "Off"
prepare()
test.contains("/GF-", msc.getcflags(cfg))
end
function suite.cflags_onStringPoolingNotSpecified()
prepare()
test.excludes("/GF", msc.getcflags(cfg))
test.excludes("/GF-", msc.getcflags(cfg))
end
function suite.cflags_onFloatingPointExceptionsOn()
floatingpointexceptions "On"
prepare()
test.contains("/fp:except", msc.getcflags(cfg))
end
function suite.cflags_onFloatingPointExceptionsOff()
floatingpointexceptions "Off"
prepare()
test.contains("/fp:except-", msc.getcflags(cfg))
end
function suite.cflags_onFloatingPointExceptionsNotSpecified()
prepare()
test.excludes("/fp:except", msc.getcflags(cfg))
test.excludes("/fp:except-", msc.getcflags(cfg))
end
function suite.cflags_onFunctionLevelLinkingOn()
functionlevellinking "On"
prepare()
test.contains("/Gy", msc.getcflags(cfg))
end
function suite.cflags_onFunctionLevelLinkingOff()
functionlevellinking "Off"
prepare()
test.contains("/Gy-", msc.getcflags(cfg))
end
function suite.cflags_onFunctionLevelLinkingNotSpecified()
prepare()
test.excludes("/Gy", msc.getcflags(cfg))
test.excludes("/Gy-", msc.getcflags(cfg))
end
function suite.cflags_onIntrinsicsOn()
intrinsics "On"
prepare()
test.contains("/Oi", msc.getcflags(cfg))
end
--
-- Check the translation of symbols.
--
function suite.cflags_onDefaultSymbols()
prepare()
test.excludes({ "/Z7" }, msc.getcflags(cfg))
end
function suite.cflags_onNoSymbols()
symbols "Off"
prepare()
test.excludes({ "/Z7" }, msc.getcflags(cfg))
end
function suite.cflags_onSymbols()
symbols "On"
prepare()
test.contains({ "/Z7" }, msc.getcflags(cfg))
end
--
-- Check the translation of unsignedchar.
--
function suite.sharedflags_onUnsignedCharOn()
unsignedchar "On"
prepare()
test.contains({ "/J" }, msc.getcflags(cfg))
test.contains({ "/J" }, msc.getcxxflags(cfg))
end
function suite.sharedflags_onUnsignedCharOff()
unsignedchar "Off"
prepare()
test.excludes({ "/J" }, msc.getcflags(cfg))
test.excludes({ "/J" }, msc.getcxxflags(cfg))
end
--
-- Check handling of debugging support.
--
function suite.ldflags_onSymbols()
symbols "On"
prepare()
test.contains("/DEBUG", msc.getldflags(cfg))
end
--
-- Check handling warnings and errors.
--
function suite.cflags_OnNoWarnings()
warnings "Off"
prepare()
test.contains("/W0", msc.getcflags(cfg))
end
function suite.cflags_OnHighWarnings()
warnings "High"
prepare()
test.contains("/W4", msc.getcflags(cfg))
end
function suite.cflags_OnExtraWarnings()
warnings "Extra"
prepare()
test.contains("/W4", msc.getcflags(cfg))
end
function suite.cflags_OnEverythingWarnings()
warnings "Everything"
prepare()
test.contains("/Wall", msc.getcflags(cfg))
end
function suite.cflags_OnFatalWarnings()
flags "FatalWarnings"
prepare()
test.contains("/WX", msc.getcflags(cfg))
end
function suite.cflags_onSpecificWarnings()
enablewarnings { "enable" }
disablewarnings { "disable" }
fatalwarnings { "fatal" }
prepare()
test.contains({ '/w1"enable"', '/wd"disable"', '/we"fatal"' }, msc.getcflags(cfg))
end
function suite.ldflags_OnFatalWarnings()
flags "FatalWarnings"
prepare()
test.contains("/WX", msc.getldflags(cfg))
end
--
-- Check handling of library search paths.
--
function suite.libdirs_onLibdirs()
libdirs { "../libs" }
prepare()
test.contains('/LIBPATH:"../libs"', msc.getLibraryDirectories(cfg))
end
--
-- Check handling of forced includes.
--
function suite.forcedIncludeFiles()
forceincludes { "include/sys.h" }
prepare()
test.contains('/FIinclude/sys.h', msc.getforceincludes(cfg))
end
--
-- Check handling of floating point modifiers.
--
function suite.cflags_onFloatingPointFast()
floatingpoint "Fast"
prepare()
test.contains("/fp:fast", msc.getcflags(cfg))
end
function suite.cflags_onFloatingPointStrict()
floatingpoint "Strict"
prepare()
test.contains("/fp:strict", msc.getcflags(cfg))
end
function suite.cflags_onSSE()
vectorextensions "SSE"
prepare()
test.contains("/arch:SSE", msc.getcflags(cfg))
end
function suite.cflags_onSSE2()
vectorextensions "SSE2"
prepare()
test.contains("/arch:SSE2", msc.getcflags(cfg))
end
function suite.cflags_onSSE4_2()
vectorextensions "SSE4.2"
prepare()
test.contains("/arch:SSE2", msc.getcflags(cfg))
end
function suite.cflags_onAVX()
vectorextensions "AVX"
prepare()
test.contains("/arch:AVX", msc.getcflags(cfg))
end
function suite.cflags_onAVX2()
vectorextensions "AVX2"
prepare()
test.contains("/arch:AVX2", msc.getcflags(cfg))
end
--
-- Check the defines and undefines.
--
function suite.defines()
defines "DEF"
prepare()
test.contains({ '/D"DEF"' }, msc.getdefines(cfg.defines, cfg))
end
function suite.undefines()
undefines "UNDEF"
prepare()
test.contains({ '/U"UNDEF"' }, msc.getundefines(cfg.undefines))
end
--
-- Check compilation options.
--
function suite.cflags_onNoMinimalRebuild()
flags "NoMinimalRebuild"
prepare()
test.contains("/Gm-", msc.getcflags(cfg))
end
function suite.cflags_onMultiProcessorCompile()
flags "MultiProcessorCompile"
prepare()
test.contains("/MP", msc.getcflags(cfg))
end
--
-- Check handling of C++ language features.
--
function suite.cxxflags_onExceptions()
exceptionhandling "on"
prepare()
test.contains("/EHsc", msc.getcxxflags(cfg))
end
function suite.cxxflags_onSEH()
exceptionhandling "SEH"
prepare()
test.contains("/EHa", msc.getcxxflags(cfg))
end
function suite.cxxflags_onNoExceptions()
exceptionhandling "Off"
prepare()
test.missing("/EHsc", msc.getcxxflags(cfg))
end
function suite.cxxflags_onNoRTTI()
rtti "Off"
prepare()
test.contains("/GR-", msc.getcxxflags(cfg))
end
--
-- Check handling of additional linker options.
--
function suite.ldflags_onOmitDefaultLibrary()
flags "OmitDefaultLibrary"
prepare()
test.contains("/NODEFAULTLIB", msc.getldflags(cfg))
end
function suite.ldflags_onNoIncrementalLink()
flags "NoIncrementalLink"
prepare()
test.contains("/INCREMENTAL:NO", msc.getldflags(cfg))
end
function suite.ldflags_onNoManifest()
flags "NoManifest"
prepare()
test.contains("/MANIFEST:NO", msc.getldflags(cfg))
end
function suite.ldflags_onDLL()
kind "SharedLib"
prepare()
test.contains("/DLL", msc.getldflags(cfg))
end
--
-- Check handling of CLR settings.
--
function suite.cflags_onClrOn()
clr "On"
prepare()
test.contains("/clr", msc.getcflags(cfg))
end
function suite.cflags_onClrUnsafe()
clr "Unsafe"
prepare()
test.contains("/clr", msc.getcflags(cfg))
end
function suite.cflags_onClrSafe()
clr "Safe"
prepare()
test.contains("/clr:safe", msc.getcflags(cfg))
end
function suite.cflags_onClrPure()
clr "Pure"
prepare()
test.contains("/clr:pure", msc.getcflags(cfg))
end
--
-- Check handling of character set switches
--
function suite.cflags_onCharSetDefault()
prepare()
test.contains('/D"_UNICODE"', msc.getdefines(cfg.defines, cfg))
end
function suite.cflags_onCharSetUnicode()
characterset "Unicode"
prepare()
test.contains('/D"_UNICODE"', msc.getdefines(cfg.defines, cfg))
end
function suite.cflags_onCharSetMBCS()
characterset "MBCS"
prepare()
test.contains('/D"_MBCS"', msc.getdefines(cfg.defines, cfg))
end
function suite.cflags_onCharSetASCII()
characterset "ASCII"
prepare()
test.excludes({'/D"_MBCS"', '/D"_UNICODE"'}, msc.getdefines(cfg.defines, cfg))
end
--
-- Check handling of system search paths.
--
function suite.includeDirs_onSysIncludeDirs()
sysincludedirs { "/usr/local/include" }
prepare()
test.contains("-I/usr/local/include", msc.getincludedirs(cfg, cfg.includedirs, cfg.sysincludedirs))
end
function suite.libDirs_onSysLibDirs()
syslibdirs { "/usr/local/lib" }
prepare()
test.contains('/LIBPATH:"/usr/local/lib"', msc.getLibraryDirectories(cfg))
end
--
-- Check handling of ignore default libraries
--
function suite.ignoreDefaultLibraries_WithExtensions()
ignoredefaultlibraries { "lib1.lib" }
prepare()
test.contains('/NODEFAULTLIB:lib1.lib', msc.getldflags(cfg))
end
function suite.ignoreDefaultLibraries_WithoutExtensions()
ignoredefaultlibraries { "lib1" }
prepare()
test.contains('/NODEFAULTLIB:lib1.lib', msc.getldflags(cfg))
end
--
-- Check handling of shared C/C++ flags.
--
function suite.mixedToolFlags_onCFlags()
flags { "FatalCompileWarnings" }
prepare()
test.isequal({ "/WX", "/MD" }, msc.getcflags(cfg))
end
function suite.mixedToolFlags_onCxxFlags()
flags { "FatalCompileWarnings" }
prepare()
test.isequal({ "/WX", "/MD", "/EHsc" }, msc.getcxxflags(cfg))
end
--
-- Check handling of Run-Time Library flags.
--
function suite.cflags_onStaticRuntime()
staticruntime "On"
prepare()
test.isequal({ "/MT" }, msc.getcflags(cfg))
end
function suite.cflags_onDynamicRuntime()
staticruntime "Off"
prepare()
test.isequal({ "/MD" }, msc.getcflags(cfg))
end
function suite.cflags_onStaticRuntimeAndDebug()
staticruntime "On"
runtime "Debug"
prepare()
test.isequal({ "/MTd" }, msc.getcflags(cfg))
end
function suite.cflags_onDynamicRuntimeAndDebug()
staticruntime "Off"
runtime "Debug"
prepare()
test.isequal({ "/MDd" }, msc.getcflags(cfg))
end
function suite.cflags_onStaticRuntimeAndSymbols()
staticruntime "On"
symbols "On"
prepare()
test.isequal({ "/MTd", "/Z7" }, msc.getcflags(cfg))
end
function suite.cflags_onDynamicRuntimeAndSymbols()
staticruntime "Off"
symbols "On"
prepare()
test.isequal({ "/MDd", "/Z7" }, msc.getcflags(cfg))
end
function suite.cflags_onDynamicRuntimeAndReleaseAndSymbols()
staticruntime "Off"
runtime "Release"
symbols "On"
prepare()
test.isequal({ "/MD", "/Z7" }, msc.getcflags(cfg))
end

View file

@ -0,0 +1,182 @@
--
-- tests/test_snc.lua
-- Automated test suite for the SNC toolset interface.
-- Copyright (c) 2012-2013 Jason Perkins and the Premake project
--
local p = premake
local suite = test.declare("tools_snc")
local snc = p.tools.snc
--
-- Setup/teardown
--
local wks, prj, cfg
function suite.setup()
wks, prj = test.createWorkspace()
system "PS3"
end
local function prepare()
cfg = test.getconfig(prj, "Debug")
end
--
-- Check the selection of tools based on the target system.
--
function suite.tools_onDefaults()
prepare()
test.isnil(snc.gettoolname(cfg, "cc"))
test.isnil(snc.gettoolname(cfg, "cxx"))
test.isnil(snc.gettoolname(cfg, "ar"))
end
function suite.tools_onPS3()
system "PS3"
prepare()
test.isnil(snc.gettoolname(cfg, "cc"))
test.isnil(snc.gettoolname(cfg, "cxx"))
test.isnil(snc.gettoolname(cfg, "ar"))
end
--
-- By default, the -MMD -MP are used to generate dependencies.
--
function suite.cppflags_defaultWithMMD()
prepare()
test.isequal({ "-MMD", "-MP" }, snc.getcppflags(cfg))
end
--
-- Check the translation of CFLAGS.
--
function suite.cflags_onFatalWarnings()
flags { "FatalWarnings" }
prepare()
test.isequal({ "-Xquit=2" }, snc.getcflags(cfg))
end
--
-- Check the optimization flags.
--
function suite.cflags_onNoOptimize()
optimize "Off"
prepare()
test.isequal({ "-O0" }, snc.getcflags(cfg))
end
function suite.cflags_onOptimize()
optimize "On"
prepare()
test.isequal({ "-O1" }, snc.getcflags(cfg))
end
function suite.cflags_onOptimizeSize()
optimize "Size"
prepare()
test.isequal({ "-Os" }, snc.getcflags(cfg))
end
function suite.cflags_onOptimizeSpeed()
optimize "Speed"
prepare()
test.isequal({ "-O2" }, snc.getcflags(cfg))
end
function suite.cflags_onOptimizeFull()
optimize "Full"
prepare()
test.isequal({ "-O3" }, snc.getcflags(cfg))
end
function suite.cflags_onOptimizeDebug()
optimize "Debug"
prepare()
test.isequal({ "-Od" }, snc.getcflags(cfg))
end
--
-- Turn on exceptions and RTTI by default, to match the other Premake supported toolsets.
--
function suite.cxxflags_onDefault()
prepare()
test.isequal({ "-Xc+=exceptions", "-Xc+=rtti" }, snc.getcxxflags(cfg))
end
--
-- Check the translation of LDFLAGS.
--
function suite.cflags_onDefaults()
prepare()
test.isequal({ "-s" }, snc.getldflags(cfg))
end
--
-- Check the formatting of linked libraries.
--
function suite.links_onSystemLibs()
links { "fs_stub", "net_stub" }
prepare()
test.isequal({ "-lfs_stub", "-lnet_stub" }, snc.getlinks(cfg))
end
--
-- When linking to a static sibling library, the relative path to the library
-- should be used instead of the "-l" flag. This prevents linking against a
-- shared library of the same name, should one be present.
--
function suite.links_onStaticSiblingLibrary()
links { "MyProject2" }
test.createproject(wks)
system "Linux"
kind "StaticLib"
location "MyProject2"
targetdir "lib"
prepare()
test.isequal({ "lib/libMyProject2.a" }, snc.getlinks(cfg))
end
--
-- When linking object files, leave off the "-l".
--
function suite.links_onObjectFile()
links { "generated.o" }
prepare()
test.isequal({ "generated.o" }, snc.getlinks(cfg))
end
--
-- Check handling of forced includes.
--
function suite.forcedIncludeFiles()
forceincludes { "stdafx.h", "include/sys.h" }
prepare()
test.isequal({'-include stdafx.h', '-include include/sys.h'}, snc.getforceincludes(cfg))
end

View file

@ -0,0 +1,85 @@
--
-- tests/workspace/test_eachconfig.lua
-- Automated test suite for the workspace-level configuration iterator.
-- Copyright (c) 2012-2015 Jason Perkins and the Premake project
--
local suite = test.declare("workspace_eachconfig")
local p = premake
--
-- Setup and teardown
--
local wks
function suite.setup()
wks = workspace("MyWorkspace")
end
local function prepare()
p.w("-")
for cfg in p.workspace.eachconfig(wks) do
p.w("%s:%s", cfg.buildcfg or "", cfg.platform or "")
end
p.w("-")
end
--
-- All configurations listed at the workspace level should be enumerated.
--
function suite.listsBuildConfigurations_onWorkspaceLevel()
configurations { "Debug", "Release" }
project("MyProject")
prepare()
test.capture [[
-
Debug:
Release:
-
]]
end
--
-- Iteration order should be build configurations, then platforms.
--
function suite.listsInOrder_onBuildConfigsAndPlatforms()
configurations { "Debug", "Release" }
platforms { "x86", "x86_64" }
project("MyProject")
prepare()
test.capture [[
-
Debug:x86
Debug:x86_64
Release:x86
Release:x86_64
-
]]
end
--
-- Configurations listed at the project level should *not* be included
-- in the workspace-level lists.
--
function suite.excludesProjectLevelConfigs()
configurations { "Debug", "Release" }
project ("MyProject")
configurations { "PrjDebug", "PrjRelease" }
platforms { "x86", "x86_64" }
prepare()
test.capture [[
-
Debug:
Release:
-
]]
end

View file

@ -0,0 +1,44 @@
--
-- tests/workspace/test_location.lua
-- Test handling of the workspace's location field.
-- Copyright (c) 2013-2015 Jason Perkins and the Premake project
--
local suite = test.declare("workspace_location")
--
-- Setup and teardown
--
local wks
function suite.setup()
wks = workspace("MyWorkspace")
end
local function prepare()
wks = test.getWorkspace(wks)
end
--
-- If no explicit location is set, the location should be set to the
-- directory containing the script which defined the workspace.
--
function suite.usesScriptLocation_onNoLocation()
prepare()
test.isequal(os.getcwd(), wks.location)
end
--
-- If an explicit location has been set, use it.
--
function suite.usesLocation_onLocationSet()
location "build"
prepare()
test.isequal(path.join(os.getcwd(), "build"), wks.location)
end

View file

@ -0,0 +1,86 @@
--
-- tests/workspace/test_objdirs.lua
-- Test the workspace unique objects directory building.
-- Copyright (c) 2012-2015 Jason Perkins and the Premake project
--
local p = premake
local suite = test.declare("workspace_objdir")
--
-- Setup and teardown
--
local wks
function suite.setup()
p.action.set("test")
wks = workspace("MyWorkspace")
system "macosx"
end
local function result()
local platforms = wks.platforms or {}
local prj = project("MyProject")
local cfg = test.getconfig(prj, "Debug", platforms[1])
return p.project.getrelative(cfg.project, cfg.objdir)
end
--
-- Objects directory should "obj" by default.
--
function suite.directoryIsObj_onNoValueSet()
configurations { "Debug" }
test.isequal("obj", result())
end
--
-- If a conflict occurs between platforms, the platform names should
-- be used to make unique.
--
function suite.directoryIncludesPlatform_onPlatformConflict()
configurations { "Debug" }
platforms { "x86", "x86_64" }
test.isequal("obj/x86", result())
end
--
-- If a conflict occurs between build configurations, the build
-- configuration names should be used to make unique.
--
function suite.directoryIncludesBuildCfg_onBuildCfgConflict()
configurations { "Debug", "Release" }
test.isequal("obj/Debug", result())
end
--
-- If a conflict occurs between both build configurations and platforms,
-- both should be used to make unique.
--
function suite.directoryIncludesBuildCfg_onPlatformAndBuildCfgConflict()
configurations { "Debug", "Release" }
platforms { "x86", "x86_64" }
test.isequal("obj/x86/Debug", result())
end
--
-- If a conflict occurs between projects, the project name should be
-- used to make unique.
--
function suite.directoryIncludesBuildCfg_onProjectConflict()
configurations { "Debug", "Release" }
project "MyProject2"
test.isequal("obj/Debug/MyProject", result())
end