diff options
author | Justin M. Keyes <justinkz@gmail.com> | 2017-01-04 11:54:11 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-01-04 11:54:11 +0100 |
commit | af828f22575c8591a176bd9d85ee07f87ba8b911 (patch) | |
tree | c4692cf380b69e8d3b6065d1f8d2855b6e4a50dd | |
parent | c56411ed87fe560149b68e67f63916f829affd1b (diff) | |
parent | 937b6fac8fecb701895b2c4151a864861aaf03f4 (diff) | |
download | rneovim-af828f22575c8591a176bd9d85ee07f87ba8b911.tar.gz rneovim-af828f22575c8591a176bd9d85ee07f87ba8b911.tar.bz2 rneovim-af828f22575c8591a176bd9d85ee07f87ba8b911.zip |
Merge #5864 from ZyX-I/fix-5857
unittest: Allow multiple indirect includes
-rw-r--r-- | test/functional/helpers.lua | 41 | ||||
-rw-r--r-- | test/helpers.lua | 40 | ||||
-rw-r--r-- | test/unit/formatc.lua | 8 | ||||
-rw-r--r-- | test/unit/helpers.lua | 15 | ||||
-rw-r--r-- | test/unit/preprocess.lua | 155 |
5 files changed, 153 insertions, 106 deletions
diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua index f3332cff4f..d67f225ed1 100644 --- a/test/functional/helpers.lua +++ b/test/functional/helpers.lua @@ -21,6 +21,9 @@ local nvim_argv = {nvim_prog, '-u', 'NONE', '-i', 'NONE', '-N', local mpack = require('mpack') +local tmpname = global_helpers.tmpname +local uname = global_helpers.uname + -- Formulate a path to the directory containing nvim. We use this to -- help run test executables. It helps to keep the tests working, even -- when the build is not in the default location. @@ -334,44 +337,6 @@ local function write_file(name, text, dont_dedent) file:close() end --- Tries to get platform name from $SYSTEM_NAME, uname; fallback is "Windows". -local uname = (function() - local platform = nil - return (function() - if platform then - return platform - end - - platform = os.getenv("SYSTEM_NAME") - if platform then - return platform - end - - local status, f = pcall(io.popen, "uname -s") - if status then - platform = f:read("*l") - else - platform = 'Windows' - end - return platform - end) -end)() - -local function tmpname() - local fname = os.tmpname() - if uname() == 'Windows' and fname:sub(1, 2) == '\\s' then - -- In Windows tmpname() returns a filename starting with - -- special sequence \s, prepend $TEMP path - local tmpdir = os.getenv('TEMP') - return tmpdir..fname - elseif fname:match('^/tmp') and uname() == 'Darwin' then - -- In OS X /tmp links to /private/tmp - return '/private'..fname - else - return fname - end -end - local function source(code) local fname = tmpname() write_file(fname, code) diff --git a/test/helpers.lua b/test/helpers.lua index 4c50c7644f..0bc62da5d7 100644 --- a/test/helpers.lua +++ b/test/helpers.lua @@ -52,9 +52,49 @@ local function check_logs() assert(0 == runtime_errors) end +-- Tries to get platform name from $SYSTEM_NAME, uname; fallback is "Windows". +local uname = (function() + local platform = nil + return (function() + if platform then + return platform + end + + platform = os.getenv("SYSTEM_NAME") + if platform then + return platform + end + + local status, f = pcall(io.popen, "uname -s") + if status then + platform = f:read("*l") + else + platform = 'Windows' + end + return platform + end) +end)() + +local function tmpname() + local fname = os.tmpname() + if uname() == 'Windows' and fname:sub(1, 2) == '\\s' then + -- In Windows tmpname() returns a filename starting with + -- special sequence \s, prepend $TEMP path + local tmpdir = os.getenv('TEMP') + return tmpdir..fname + elseif fname:match('^/tmp') and uname() == 'Darwin' then + -- In OS X /tmp links to /private/tmp + return '/private'..fname + else + return fname + end +end + return { eq = eq, neq = neq, ok = ok, check_logs = check_logs, + uname = uname, + tmpname = tmpname, } diff --git a/test/unit/formatc.lua b/test/unit/formatc.lua index 00637e0b8d..e288081960 100644 --- a/test/unit/formatc.lua +++ b/test/unit/formatc.lua @@ -219,13 +219,7 @@ local function standalone(...) -- luacheck: ignore Preprocess.add_to_include_path('./../../build/include') Preprocess.add_to_include_path('./../../.deps/usr/include') - local input = Preprocess.preprocess_stream(arg[1]) - local raw = input:read('*all') - input:close() - - if raw == nil then - print("ERROR: Preprocess.preprocess_stream():read() returned empty") - end + local raw = Preprocess.preprocess('', arg[1]) local formatted if #arg == 2 and arg[2] == 'no' then diff --git a/test/unit/helpers.lua b/test/unit/helpers.lua index 3564f76442..a485a875ab 100644 --- a/test/unit/helpers.lua +++ b/test/unit/helpers.lua @@ -45,6 +45,8 @@ local function filter_complex_blocks(body) return table.concat(result, "\n") end +local previous_defines = '' + -- use this helper to import C files, you can pass multiple paths at once, -- this helper will return the C namespace of the nvim library. local function cimport(...) @@ -66,17 +68,8 @@ local function cimport(...) return libnvim end - local body = nil - for _ = 1, 10 do - local stream = Preprocess.preprocess_stream(unpack(paths)) - body = stream:read("*a") - stream:close() - if body ~= nil then break end - end - - if body == nil then - print("ERROR: helpers.lua: Preprocess.preprocess_stream():read() returned empty") - end + local body + body, previous_defines = Preprocess.preprocess(previous_defines, unpack(paths)) -- format it (so that the lines are "unique" statements), also filter out -- Objective-C blocks diff --git a/test/unit/preprocess.lua b/test/unit/preprocess.lua index 10ba997758..8c2a5c73e5 100644 --- a/test/unit/preprocess.lua +++ b/test/unit/preprocess.lua @@ -7,22 +7,22 @@ local ccs = {} local env_cc = os.getenv("CC") if env_cc then - table.insert(ccs, {path = "/usr/bin/env " .. tostring(env_cc), type = "gcc"}) + table.insert(ccs, {path = {"/usr/bin/env", env_cc}, type = "gcc"}) end if ffi.os == "Windows" then - table.insert(ccs, {path = "cl", type = "msvc"}) + table.insert(ccs, {path = {"cl"}, type = "msvc"}) end -table.insert(ccs, {path = "/usr/bin/env cc", type = "gcc"}) -table.insert(ccs, {path = "/usr/bin/env gcc", type = "gcc"}) -table.insert(ccs, {path = "/usr/bin/env gcc-4.9", type = "gcc"}) -table.insert(ccs, {path = "/usr/bin/env gcc-4.8", type = "gcc"}) -table.insert(ccs, {path = "/usr/bin/env gcc-4.7", type = "gcc"}) -table.insert(ccs, {path = "/usr/bin/env clang", type = "clang"}) -table.insert(ccs, {path = "/usr/bin/env icc", type = "gcc"}) +table.insert(ccs, {path = {"/usr/bin/env", "cc"}, type = "gcc"}) +table.insert(ccs, {path = {"/usr/bin/env", "gcc"}, type = "gcc"}) +table.insert(ccs, {path = {"/usr/bin/env", "gcc-4.9"}, type = "gcc"}) +table.insert(ccs, {path = {"/usr/bin/env", "gcc-4.8"}, type = "gcc"}) +table.insert(ccs, {path = {"/usr/bin/env", "gcc-4.7"}, type = "gcc"}) +table.insert(ccs, {path = {"/usr/bin/env", "clang"}, type = "clang"}) +table.insert(ccs, {path = {"/usr/bin/env", "icc"}, type = "gcc"}) -local quote_me = '[^%w%+%-%=%@%_%/]' -- complement (needn't quote) +local quote_me = '[^.%w%+%-%@%_%/]' -- complement (needn't quote) local function shell_quote(str) if string.find(str, quote_me) or str == '' then return "'" .. string.gsub(str, "'", [['"'"']]) .. "'" @@ -61,12 +61,12 @@ end -- will produce a string that represents a meta C header file that includes -- all the passed in headers. I.e.: -- --- headerize({"stdio.h", "math.h", true} +-- headerize({"stdio.h", "math.h"}, true) -- produces: -- #include <stdio.h> -- #include <math.h> -- --- headerize({"vim.h", "memory.h", false} +-- headerize({"vim.h", "memory.h"}, false) -- produces: -- #include "vim.h" -- #include "memory.h" @@ -79,8 +79,7 @@ local function headerize(headers, global) end local formatted = {} - for i = 1, #headers do - local hdr = headers[i] + for _, hdr in ipairs(headers) do formatted[#formatted + 1] = "#include " .. tostring(pre) .. tostring(hdr) .. @@ -91,49 +90,77 @@ local function headerize(headers, global) end local Gcc = { + preprocessor_extra_flags = {}, + get_defines_extra_flags = {'-std=c99', '-dM', '-E'}, + get_declarations_extra_flags = {'-std=c99', '-P', '-E'}, +} + +function Gcc:define(name, args, val) + local define = '-D' .. name + if args ~= nil then + define = define .. '(' .. table.concat(args, ',') .. ')' + end + if val ~= nil then + define = define .. '=' .. val + end + self.preprocessor_extra_flags[#self.preprocessor_extra_flags + 1] = define +end + +function Gcc:undefine(name) + self.preprocessor_extra_flags[#self.preprocessor_extra_flags + 1] = ( + '-U' .. name) +end + +function Gcc:init_defines() -- preprocessor flags that will hopefully make the compiler produce C -- declarations that the LuaJIT ffi understands. - preprocessor_extra_flags = { - '-D "aligned(ARGS)="', - '-D "__attribute__(ARGS)="', - '-D "__asm(ARGS)="', - '-D "__asm__(ARGS)="', - '-D "__inline__="', - '-D "EXTERN=extern"', - '-D "INIT(...)="', - '-D_GNU_SOURCE', - '-DINCLUDE_GENERATED_DECLARATIONS', - - -- Needed for FreeBSD - '-D "_Thread_local="', - - -- Needed for macOS Sierra - '-D "_Nullable="', - '-D "_Nonnull="', - '-U__BLOCKS__', - } -} + self:define('aligned', {'ARGS'}, '') + self:define('__attribute__', {'ARGS'}, '') + self:define('__asm', {'ARGS'}, '') + self:define('__asm__', {'ARGS'}, '') + self:define('__inline__', nil, '') + self:define('EXTERN', nil, 'extern') + self:define('INIT', {'...'}, '') + self:define('_GNU_SOURCE') + self:define('INCLUDE_GENERATED_DECLARATIONS') + -- Needed for FreeBSD + self:define('_Thread_local', nil, '') + -- Needed for macOS Sierra + self:define('_Nullable', nil, '') + self:define('_Nonnull', nil, '') + self:undefine('__BLOCKS__') +end function Gcc:new(obj) obj = obj or {} setmetatable(obj, self) self.__index = self + self:init_defines() return obj end function Gcc:add_to_include_path(...) - local paths = {...} - for i = 1, #paths do - local path = paths[i] - local directive = '-I ' .. '"' .. path .. '"' + for i = 1, select('#', ...) do + local path = select(i, ...) local ef = self.preprocessor_extra_flags - ef[#ef + 1] = directive + ef[#ef + 1] = '-I' .. path + end +end + +local function argss_to_cmd(...) + local cmd = '' + for i = 1, select('#', ...) do + for _, arg in ipairs(select(i, ...)) do + cmd = cmd .. ' ' .. shell_quote(arg) + end end + return cmd end -- returns a list of the headers files upon which this file relies function Gcc:dependencies(hdr) - local out = io.popen(tostring(self.path) .. " -M " .. tostring(hdr) .. " 2>&1") + local cmd = argss_to_cmd(self.path, {'-M', hdr}) .. ' 2>&1' + local out = io.popen(cmd) local deps = out:read("*a") out:close() if deps then @@ -143,23 +170,51 @@ function Gcc:dependencies(hdr) end end +local function repeated_call(...) + local cmd = argss_to_cmd(...) + for _ = 1, 10 do + local stream = io.popen(cmd) + local ret = stream:read('*a') + stream:close() + if ret then + return ret + end + end + print('ERROR: preprocess.lua: Failed to execute ' .. cmd .. ': nil return after 10 attempts') + return nil +end + -- returns a stream representing a preprocessed form of the passed-in headers. -- Don't forget to close the stream by calling the close() method on it. -function Gcc:preprocess_stream(...) +function Gcc:preprocess(previous_defines, ...) -- create pseudo-header local pseudoheader = headerize({...}, false) - local defines = table.concat(self.preprocessor_extra_flags, ' ') - local cmd = ("echo $hdr | " .. - tostring(self.path) .. - " " .. - tostring(defines) .. - " -std=c99 -P -E -"):gsub('$hdr', shell_quote(pseudoheader)) + local pseudoheader_fname = 'tmp_pseudoheader.h' + local pseudoheader_file = io.open(pseudoheader_fname, 'w') + pseudoheader_file:write(previous_defines) + pseudoheader_file:write("\n") + pseudoheader_file:write(pseudoheader) + pseudoheader_file:flush() + pseudoheader_file:close() + + local defines = repeated_call(self.path, self.preprocessor_extra_flags, + self.get_defines_extra_flags, + {pseudoheader_fname}) + -- lfs = require("lfs") -- print("CWD: #{lfs.currentdir!}") -- print("CMD: #{cmd}") -- io.stderr\write("CWD: #{lfs.currentdir!}\n") -- io.stderr\write("CMD: #{cmd}\n") - return io.popen(cmd) + + local declarations = repeated_call(self.path, self.preprocessor_extra_flags, + self.get_declarations_extra_flags, + {pseudoheader_fname}) + + os.remove(pseudoheader_fname) + + assert(declarations and defines) + return declarations, defines end local Clang = Gcc:new() @@ -197,8 +252,8 @@ return { includes = function(hdr) return cc:dependencies(hdr) end, - preprocess_stream = function(...) - return cc:preprocess_stream(...) + preprocess = function(...) + return cc:preprocess(...) end, add_to_include_path = function(...) return cc:add_to_include_path(...) |