Start of API system overhaul, in support of configuration mapping
This commit is contained in:
parent
38ae459803
commit
22266a995d
@ -4,6 +4,82 @@
|
||||
-- Copyright (c) 2002-2012 Jason Perkins and the Premake project
|
||||
--
|
||||
|
||||
premake.api = {}
|
||||
local api = premake.api
|
||||
|
||||
|
||||
--
|
||||
-- A place to store the current active objects in each project scope.
|
||||
--
|
||||
|
||||
api.scope = {}
|
||||
|
||||
|
||||
--
|
||||
-- Register a new API function. See the built-in API definitions below
|
||||
-- for usage examples.
|
||||
--
|
||||
|
||||
function api.register(description)
|
||||
-- verify the name
|
||||
local name = description.name
|
||||
if not name then
|
||||
error("missing name", 2)
|
||||
end
|
||||
|
||||
if _G[name] then
|
||||
error("name in use", 2)
|
||||
end
|
||||
|
||||
-- make sure there is a handler available for this kind of value
|
||||
if not api["set" .. description.kind] then
|
||||
error("invalid kind", 2)
|
||||
end
|
||||
|
||||
_G[name] = function(value)
|
||||
return api.callback(description, value)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Callback for all API functions; everything comes here first, and then
|
||||
-- parceled out to the individual set...() functions.
|
||||
--
|
||||
|
||||
function api.callback(field, value)
|
||||
-- find the right target object for this field
|
||||
local target
|
||||
if field.scope == "project" then
|
||||
target = api.scope.project or api.scope.solution
|
||||
else
|
||||
target = api.scope.configuration
|
||||
end
|
||||
|
||||
if not target then
|
||||
error("no " .. field.scope .. " in scope", 3)
|
||||
end
|
||||
|
||||
-- find and call the setter for this field's value kind
|
||||
local setter = api["set" .. field.kind]
|
||||
setter(target, field, value)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Set a new string value on an API field.
|
||||
--
|
||||
|
||||
function api.setstring(target, field, value)
|
||||
end
|
||||
|
||||
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Everything below this point is a candidate for deprecation
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
--
|
||||
-- Here I define all of the getter/setter functions as metadata. The actual
|
||||
-- functions are built programmatically below.
|
||||
@ -808,6 +884,10 @@
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- this is the new place for storing scoped objects
|
||||
api.scope.configuration = cfg
|
||||
|
||||
return cfg
|
||||
end
|
||||
|
||||
@ -915,6 +995,9 @@
|
||||
-- add an empty, global configuration to the project
|
||||
configuration { }
|
||||
|
||||
-- this is the new place for storing scoped objects
|
||||
api.scope.project = premake.CurrentContainer
|
||||
|
||||
return premake.CurrentContainer
|
||||
end
|
||||
|
||||
@ -936,6 +1019,9 @@
|
||||
-- add an empty, global configuration
|
||||
configuration { }
|
||||
|
||||
-- this is the new place for storing scoped objects
|
||||
api.scope.solution = premake.CurrentContainer
|
||||
|
||||
return premake.CurrentContainer
|
||||
end
|
||||
|
||||
|
@ -157,6 +157,21 @@
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Looks for an object within an array. Returns its index if found,
|
||||
-- or nil if the object could not be found.
|
||||
--
|
||||
|
||||
function table.indexof(tbl, obj)
|
||||
local count = #tbl
|
||||
for i = 1, count do
|
||||
if tbl[i] == obj then
|
||||
return i
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Translates the values contained in array, using the specified
|
||||
-- translation table, and returns the results in a new array.
|
||||
|
139
tests/api/test_callback.lua
Normal file
139
tests/api/test_callback.lua
Normal file
@ -0,0 +1,139 @@
|
||||
--
|
||||
-- tests/api/test_callback.lua
|
||||
-- Tests the main API value-setting callback.
|
||||
-- Copyright (c) 2012 Jason Perkins and the Premake project
|
||||
--
|
||||
|
||||
T.api_callback = {}
|
||||
local suite = T.api_callback
|
||||
local api = premake.api
|
||||
|
||||
|
||||
--
|
||||
-- Setup and teardown
|
||||
--
|
||||
|
||||
function suite.setup()
|
||||
api.settest = function(target, field, value)
|
||||
test_args = {
|
||||
["target"] = target,
|
||||
["field"] = field,
|
||||
["value"] = value
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function suite.teardown()
|
||||
_G["testapi"] = nil
|
||||
test_args = nil
|
||||
api.settest = nil
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Verify that the callback hands off control to setter for
|
||||
-- the field's value kind.
|
||||
--
|
||||
|
||||
function suite.callsSetter_onFieldKind()
|
||||
api.register { name = "testapi", kind = "test", scope = "project" }
|
||||
solution "MySolution"
|
||||
testapi "test"
|
||||
test.isnotnil(test_args)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Verify that the field description is passed along to the setter.
|
||||
--
|
||||
|
||||
function suite.setterGetsFieldDescription()
|
||||
api.register { name = "testapi", kind = "test", scope = "project" }
|
||||
solution "MySolution"
|
||||
testapi "test"
|
||||
test.isequal("testapi", test_args.field.name)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Verify that the value is passed along to the setter.
|
||||
--
|
||||
|
||||
function suite.setterGetsFieldDescription()
|
||||
api.register { name = "testapi", kind = "test", scope = "project" }
|
||||
solution "MySolution"
|
||||
testapi "test"
|
||||
test.isequal("test", test_args.value)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- If the field scope is "project", and there is no active solution
|
||||
-- or project, an error should be raised.
|
||||
--
|
||||
|
||||
function suite.errorRaised_onProjectScopeWithNoProject()
|
||||
api.register { name = "testapi", kind = "test", scope = "project" }
|
||||
ok, err = pcall(function ()
|
||||
testapi "test"
|
||||
end)
|
||||
test.isfalse(ok)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- If the field scope is "configuration" and there is no active configuration,
|
||||
-- an error should be raised.
|
||||
--
|
||||
|
||||
function suite.errorRaised_onConfigScopeWithNoConfig()
|
||||
api.register { name = "testapi", kind = "test", scope = "configuration" }
|
||||
ok, err = pcall(function ()
|
||||
testapi "test"
|
||||
end)
|
||||
test.isfalse(ok)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- If the field scope is "project" and there is an active solution, but not an
|
||||
-- active project, the solution should be the target.
|
||||
--
|
||||
|
||||
function suite.solutionTarget_onProjectScopeWithActiveSolution()
|
||||
api.register { name = "testapi", kind = "test", scope = "project" }
|
||||
local sln = solution "MySolution"
|
||||
testapi "test"
|
||||
test.istrue(sln == test_args.target)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- If the field scope is "project" and there is an active project, it should
|
||||
-- be the target.
|
||||
--
|
||||
|
||||
function suite.projectTarget_onProjectScopeWithActiveProject()
|
||||
api.register { name = "testapi", kind = "test", scope = "project" }
|
||||
local sln = solution "MySolution"
|
||||
local prj = project "MyProject"
|
||||
testapi "test"
|
||||
test.istrue(prj == test_args.target)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- If the field scope is "configuration" and there is an active configuration,
|
||||
-- it should be the target.
|
||||
--
|
||||
|
||||
function suite.configTarget_onConfigScopeWithActiveConfig()
|
||||
api.register { name = "testapi", kind = "test", scope = "configuration" }
|
||||
local sln = solution "MySolution"
|
||||
local cfg = configuration {}
|
||||
testapi "test"
|
||||
test.istrue(cfg == test_args.target)
|
||||
end
|
97
tests/api/test_register.lua
Normal file
97
tests/api/test_register.lua
Normal file
@ -0,0 +1,97 @@
|
||||
--
|
||||
-- tests/api/test_register.lua
|
||||
-- Tests the new API registration function.
|
||||
-- Copyright (c) 2012 Jason Perkins and the Premake project
|
||||
--
|
||||
|
||||
T.api_register = {}
|
||||
local suite = T.api_register
|
||||
local api = premake.api
|
||||
|
||||
|
||||
--
|
||||
-- Setup and teardown
|
||||
--
|
||||
|
||||
local callback_args
|
||||
|
||||
function suite.setup()
|
||||
suite.callback = api.callback
|
||||
api.callback = function(...) callback_args = arg end
|
||||
end
|
||||
|
||||
|
||||
function suite.teardown()
|
||||
_G["testapi"] = nil
|
||||
api.callback = suite.callback
|
||||
callback_args = nil
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Verify that the function exists.
|
||||
--
|
||||
|
||||
function suite.registerFunctionExists()
|
||||
test.isequal("function", type(premake.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 the central API callback is invoked by the registered function.
|
||||
--
|
||||
|
||||
function suite.callbackInvoked_onApiCall()
|
||||
api.register { name = "testapi", kind = "testkind", scope = "project" }
|
||||
testapi "testvalue"
|
||||
test.isnotnil(callback_args)
|
||||
end
|
@ -8,6 +8,8 @@
|
||||
T.table = { }
|
||||
local suite = T.table
|
||||
|
||||
local t
|
||||
|
||||
|
||||
--
|
||||
-- table.contains() tests
|
||||
@ -44,6 +46,16 @@
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- table.indexof() tests
|
||||
--
|
||||
|
||||
function suite.indexof_returnsIndexOfValueFound()
|
||||
local idx = table.indexof({ "a", "b", "c" }, "b")
|
||||
test.isequal(2, idx)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- table.isempty() tests
|
||||
--
|
||||
|
@ -75,6 +75,10 @@
|
||||
dofile("config/test_objdir.lua")
|
||||
dofile("config/test_targetinfo.lua")
|
||||
|
||||
-- API tests
|
||||
dofile("api/test_callback.lua")
|
||||
dofile("api/test_register.lua")
|
||||
|
||||
-- Baking tests
|
||||
dofile("base/test_baking.lua")
|
||||
|
||||
|
@ -197,13 +197,18 @@
|
||||
-- Test execution function
|
||||
--
|
||||
local _OS_host = _OS
|
||||
|
||||
-- TODO: move this out to the test suite's premake4.lua so
|
||||
-- this file can be reused for other projects
|
||||
local function test_setup(suite, fn)
|
||||
-- clear out some important globals
|
||||
_ACTION = "test"
|
||||
_ARGS = { }
|
||||
_OPTIONS = { }
|
||||
_OS = _OS_host
|
||||
|
||||
premake.solution.list = { }
|
||||
premake.api.scope = { }
|
||||
|
||||
io.indent = nil
|
||||
io.eol = "\n"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user