From a68aa47e5f835cceafb523e6634c19cbf7ed5249 Mon Sep 17 00:00:00 2001 From: Jason Perkins Date: Thu, 5 Apr 2012 20:02:53 -0400 Subject: [PATCH] Added new array API value type, and started support for new key-value handling --- src/base/api.lua | 66 ++++++++++++++++++++++++++++++----- tests/api/test_array_kind.lua | 44 +++++++++++++++++++++++ tests/api/test_callback.lua | 57 ++++++++++++++++++++++++++++-- tests/api/test_register.lua | 23 ++++-------- tests/premake4.lua | 1 + 5 files changed, 164 insertions(+), 27 deletions(-) create mode 100644 tests/api/test_array_kind.lua diff --git a/src/base/api.lua b/src/base/api.lua index cc8ae393..f3e9ba7e 100644 --- a/src/base/api.lua +++ b/src/base/api.lua @@ -20,9 +20,9 @@ -- for usage examples. -- - function api.register(description) + function api.register(field) -- verify the name - local name = description.name + local name = field.name if not name then error("missing name", 2) end @@ -32,12 +32,17 @@ end -- make sure there is a handler available for this kind of value - if not api["set" .. description.kind] then - error("invalid kind", 2) + local kind = field.kind + if kind:startswith("key-") then + kind = kind:sub(5) + end + + if not api["set" .. kind] then + error("invalid kind '" .. kind .. "'", 2) end _G[name] = function(value) - return api.callback(description, value) + return api.callback(field, value) end end @@ -60,9 +65,51 @@ 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) + -- A keyed value is a table containing key-value pairs, where the + -- type of the value is defined by the field. + if field.kind:startswith("key-") then + target[field.name] = target[field.name] or {} + api.setkeyvalue(target[field.name], field, value) + + -- Otherwise, it is a "simple" value defined by the field + else + local setter = api["set" .. field.kind] + setter(target, field.name, field, value) + end + end + + +-- +-- Update a keyed value. Iterate over the keys in the new value, and use +-- the corresponding values to update the target object. +-- + + function api.setkeyvalue(target, field, values) + if type(values) ~= "table" then + error("value must be a table of key-value pairs", 4) + end + + local kind = field.kind:sub(5) + local setter = api["set" .. kind] + for key, value in pairs(values) do + setter(target, key, field, value) + end + end + + +-- +-- Set a new array value. Arrays are lists of values stored by "value", +-- in that new values overwrite old ones, rather than merging like lists. +-- + + function api.setarray(target, name, field, value) + -- put simple values in an array + if type(value) ~= "table" then + value = { value } + end + + -- store it, overwriting any existing value + target[field.name] = value end @@ -70,7 +117,8 @@ -- Set a new string value on an API field. -- - function api.setstring(target, field, value) + function api.setstring(target, name, field, value) + error("setstring is not yet implemented") end diff --git a/tests/api/test_array_kind.lua b/tests/api/test_array_kind.lua new file mode 100644 index 00000000..005b5996 --- /dev/null +++ b/tests/api/test_array_kind.lua @@ -0,0 +1,44 @@ +-- +-- tests/api/test_array_kind.lua +-- Tests the array API value type. +-- Copyright (c) 2012 Jason Perkins and the Premake project +-- + + T.api_array_kind = {} + local suite = T.api_array_kind + local api = premake.api + + +-- +-- Setup and teardown +-- + + function suite.setup() + api.register { name = "testapi", kind = "array", scope = "project" } + test.createsolution() + 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 + diff --git a/tests/api/test_callback.lua b/tests/api/test_callback.lua index eb16bdb5..d830853c 100644 --- a/tests/api/test_callback.lua +++ b/tests/api/test_callback.lua @@ -14,9 +14,10 @@ -- function suite.setup() - api.settest = function(target, field, value) + api.settest = function(target, name, field, value) test_args = { ["target"] = target, + ["name"] = name, ["field"] = field, ["value"] = value } @@ -25,7 +26,7 @@ function suite.teardown() - _G["testapi"] = nil + testapi = nil test_args = nil api.settest = nil end @@ -46,6 +47,18 @@ end +-- +-- Verify that the target field name is getting passed to the setter. +-- + + function suite.setterGetsFieldName() + api.register { name = "testapi", kind = "test", scope = "project" } + solution "MySolution" + testapi "test" + test.isequal("testapi", test_args.name) + end + + -- -- Verify that the field description is passed along to the setter. -- @@ -137,3 +150,43 @@ testapi "test" test.istrue(cfg == test_args.target) end + + +-- +-- On key-value APIs, the keyed object value should be the target. +-- + + function suite.keyObjectTarget_onKeyValue() + api.register { name = "testapi", kind = "key-test", scope = "project" } + local sln = solution "MySolution" + testapi { key = "test" } + test.istrue(sln.testapi == test_args.target) + end + + + +-- +-- On key-value APIs, the field name should be the key value from the supplied table. +-- + + function suite.keyObjectName_onKeyValue() + api.register { name = "testapi", kind = "key-test", scope = "project" } + local sln = solution "MySolution" + testapi { key = "test" } + test.isequal("key", test_args.name) + end + + +-- +-- Raise an error is a simple value is passed to a key-value API. +-- + + function suite.keyValueRaisesError_onSimpleValue() + api.register { name = "testapi", kind = "key-test", scope = "project" } + local sln = solution "MySolution" + ok, err = pcall(function () + testapi "test" + end) + test.isfalse(ok) + end + diff --git a/tests/api/test_register.lua b/tests/api/test_register.lua index f63dff85..2c6c578a 100644 --- a/tests/api/test_register.lua +++ b/tests/api/test_register.lua @@ -13,18 +13,8 @@ -- 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 + testapi = nil end @@ -87,11 +77,12 @@ -- --- Verify that the central API callback is invoked by the registered function. +-- Verify that key-value forms are accepted. -- - function suite.callbackInvoked_onApiCall() - api.register { name = "testapi", kind = "testkind", scope = "project" } - testapi "testvalue" - test.isnotnil(callback_args) + function suite.succeeds_onKeyValueForm() + ok, err = pcall(function () + api.register { name = "testapi", kind = "key-string", scope = "project" } + end) + test.istrue(ok) end diff --git a/tests/premake4.lua b/tests/premake4.lua index f4b8cbaa..e3cfe11f 100644 --- a/tests/premake4.lua +++ b/tests/premake4.lua @@ -76,6 +76,7 @@ dofile("config/test_targetinfo.lua") -- API tests + dofile("api/test_array_kind.lua") dofile("api/test_callback.lua") dofile("api/test_register.lua")