local SUITE = require 'TestSuite' 'cdata'

-- Only relevant in LUAJIT.
if type(jit) ~= 'table' then  return SUITE  end

SUITE:setEnvironment{
    format  = require 'pretty',
    analyze_byte_string = require 'analyze_byte_string',
}

--------------------------------------------------------------------------------
-- Test stuff.

local ffi = require('ffi')
ffi.cdef[[
    typedef struct foo { int a, b; } foo_t;

    void free(void *ptr);
    void *malloc(size_t size);
    int poll(struct pollfd *fds, unsigned long nfds, int timeout);
]]

-- TODO: Add more advanced understanding of cdata.


local function format_test (t)
    SUITE:addTest(t.expect, function ()
        assert_equal(t.expect, format(t.input, t.options))
    end)
end

--------------------------------------------------------------------------------
-- Understanding binary data

SUITE:addTest('Understand ascii', function ()
    local str   =  'hello world'
    local info  =  analyze_byte_string(str)
    assert_equal('ascii', info.most_likely)
end)

SUITE:addTest('Understand utf8', function ()
    local str = 'Æh? Hvø Tæler Då Om?'
    local info  =  analyze_byte_string(str)
    assert_equal('utf8', info.most_likely)
end)

SUITE:addTest('Understand binary', function ()
    local str = '\190\098\140\097\255'
    local info  =  analyze_byte_string(str)
    print(format(info))
    assert_equal('binary', info.most_likely)
end)

SUITE:addTest('More binary', function ()
    local str = '\098\140\097\140\100'
    local info  =  analyze_byte_string(str)
    assert_equal('binary', info.most_likely)
end)

SUITE:addTest('Classify an actual binary as binary', function ()
    local f = io.open('/usr/bin/ln', 'r')
    local str = f:read '*all'
    f:close()
    local info  =  analyze_byte_string(str)
    assert_equal('binary', info.most_likely)
end)

--------------------------------------------------------------------------------

format_test {
    input  = ffi.C.poll,
    expect = 'cdata<.+>: 0x%x+',
}

do
    local list = ffi.new('char [17]')
    for i = 0, 16 do  list[i] = i end
    format_test {
        input  = list,
        expect = 'cdata<.+>: 0x%x+',
    }
end

do
    local list = ffi.new('int [17]')
    for i = 0, 16 do  list[i] = i end
    format_test {
        input  = list,
        expect = 'cdata<.+>: 0x%x+',
    }
end

do
    local list = ffi.new('char [10]')
    for i = 0, 10-1 do  list[i] = i + 65 end
    format_test {
        input  = list,
        expect = 'cdata<.+>: 0x%x+',
    }
end

do
    local mat = ffi.new('char [3][3]')
    for x = 0, 2 do for y = 0, 2 do mat[x][y] = x * 16 + y end end
    format_test {
        input  = mat,
        expect = 'cdata<.+>: 0x%x+',
    }
end

do
    local p = ffi.gc(ffi.C.malloc(1), ffi.C.free)
    format_test {
        input  = p,
        expect = 'cdata<.+>: 0x%x+',
    }
end

SUITE:addTest('a very small amount of math ruins everything', function ()
    local p = ffi.new('char[1]')
          p[0] = 27
    local actual_result  =  format(p + 0, {})
    assert_equal('Derp', actual_result)
end)

do
    local p = ffi.new('foo_t[1]')
          p[0].a = 27
          p[0].b = 27
    format_test {
        input  = p + 0,
        expect = 'cdata<.+>: 0x%x+',
    }
end

--------------------------------------------------------------------------------

return SUITE