diff options
Diffstat (limited to 'test')
| -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(...) | 
