632 lines
16 KiB
Lua
632 lines
16 KiB
Lua
local lunit, RUN = lunit do
|
|
RUN = lunit and function()end or function ()
|
|
local res = lunit.run()
|
|
if res.errors + res.failed > 0 then
|
|
os.exit(-1)
|
|
end
|
|
return os.exit(0)
|
|
end
|
|
lunit = require "lunit"
|
|
end
|
|
|
|
local TEST_CASE = assert(lunit.TEST_CASE)
|
|
local skip = lunit.skip or function() end
|
|
|
|
local curl = require "lcurl"
|
|
local utils = require "utils"
|
|
|
|
local weak_ptr, gc_collect, dump_mime_ = utils.import('weak_ptr', 'gc_collect', 'dump_mime')
|
|
|
|
local GET_URL = 'http://127.0.0.1:7090/get'
|
|
|
|
local null = curl.null
|
|
|
|
local function is_freed(c)
|
|
return not not string.find(tostring(c), '%(freed%)')
|
|
end
|
|
|
|
local _ENV = TEST_CASE'mime lifetime' if not curl.OPT_MIMEPOST then
|
|
function test() skip("MIMI API supports since cURL 7.56.0") end
|
|
else
|
|
|
|
local easy, mime
|
|
|
|
function setup()
|
|
easy = curl.easy()
|
|
end
|
|
|
|
function teardown()
|
|
if easy then easy:close() end
|
|
if mime then mime:free() end
|
|
easy, mime = nil
|
|
end
|
|
|
|
function test_preserve_mime_part_reference()
|
|
-- mime part stores references to all parts
|
|
|
|
local mime, part = easy:mime() do
|
|
part = weak_ptr(mime:addpart())
|
|
end
|
|
gc_collect()
|
|
|
|
assert_not_nil(part.value)
|
|
|
|
mime = nil
|
|
gc_collect()
|
|
|
|
assert_nil(part.value)
|
|
|
|
easy:close()
|
|
end
|
|
|
|
function test_free_mime_subparts()
|
|
-- when free root free all nodes
|
|
|
|
-- mime
|
|
-- +- part3
|
|
-- +- alt
|
|
-- +- part1
|
|
-- +- part2
|
|
|
|
local mime, a, p1, p2, p3 = easy:mime() do
|
|
|
|
local alt = easy:mime()
|
|
|
|
local part1 = alt:addpart()
|
|
|
|
local part2 = alt:addpart()
|
|
|
|
local part3 = mime:addpart()
|
|
part3:subparts(alt, "multipart/alternative")
|
|
|
|
a = weak_ptr(alt)
|
|
p1 = weak_ptr(part1)
|
|
p2 = weak_ptr(part2)
|
|
p3 = weak_ptr(part3)
|
|
end
|
|
|
|
gc_collect()
|
|
|
|
assert_not_nil(a.value)
|
|
assert_not_nil(p1.value)
|
|
assert_not_nil(p2.value)
|
|
assert_not_nil(p3.value)
|
|
|
|
-- reamove reference to root node
|
|
mime = nil
|
|
gc_collect(4)
|
|
|
|
assert_nil(a.value)
|
|
assert_nil(p1.value)
|
|
assert_nil(p2.value)
|
|
assert_nil(p3.value)
|
|
|
|
easy:close()
|
|
end
|
|
|
|
function test_preserve_mime_subparts()
|
|
-- if we have references to subnode but we free root
|
|
-- then all references have to become to invalid
|
|
|
|
-- mime
|
|
-- +- part3
|
|
-- +- alt
|
|
-- +- part1
|
|
-- +- part2
|
|
|
|
local easy = curl.easy()
|
|
|
|
local mime, a, p1, p2, p3 = easy:mime() do
|
|
|
|
local alt = easy:mime()
|
|
|
|
local part1 = alt:addpart()
|
|
|
|
local part2 = alt:addpart()
|
|
|
|
local part3 = mime:addpart()
|
|
part3:subparts(alt, "multipart/alternative")
|
|
|
|
a = weak_ptr(alt)
|
|
p1 = weak_ptr(part1)
|
|
p2 = weak_ptr(part2)
|
|
p3 = weak_ptr(part3)
|
|
end
|
|
|
|
gc_collect()
|
|
|
|
assert_not_nil(a.value)
|
|
assert_not_nil(p1.value)
|
|
assert_not_nil(p2.value)
|
|
assert_not_nil(p3.value)
|
|
|
|
-- save reference to subnode
|
|
local subnode = a.value
|
|
|
|
mime = nil
|
|
|
|
-- in this case call `free` to root node.
|
|
-- there no way to get reference to this node from child
|
|
-- so there no way to use it.
|
|
gc_collect()
|
|
|
|
-- libcurl still close all childs
|
|
-- so all reference are invalid
|
|
|
|
assert_not_nil(a.value)
|
|
assert_not_nil(is_freed(a.value))
|
|
assert_nil(p1.value)
|
|
assert_nil(p2.value)
|
|
assert_nil(p3.value)
|
|
|
|
easy:close()
|
|
end
|
|
|
|
function test_preserve_mime_by_easy()
|
|
|
|
local mime do
|
|
mime = weak_ptr(easy:mime())
|
|
easy:setopt_mimepost(mime.value)
|
|
end
|
|
|
|
gc_collect()
|
|
|
|
assert_not_nil(mime.value)
|
|
|
|
easy:unsetopt_mimepost()
|
|
|
|
gc_collect()
|
|
|
|
assert_nil(mime.value)
|
|
end
|
|
|
|
function test_mime_does_not_ref_to_easy()
|
|
-- exists of mime object does not prevent easy from GC
|
|
|
|
local mime = easy:mime()
|
|
local peasy = weak_ptr(easy)
|
|
easy = nil
|
|
|
|
gc_collect()
|
|
|
|
assert_nil(peasy.value)
|
|
end
|
|
|
|
function test_mimepost_does_not_ref_to_easy()
|
|
-- exists of mime object does not prevent easy from GC
|
|
|
|
-- create mime and set it as mimepost option
|
|
local mime = easy:mime()
|
|
easy:setopt_mimepost(mime)
|
|
|
|
local peasy = weak_ptr(easy)
|
|
easy = nil
|
|
|
|
gc_collect()
|
|
|
|
assert_nil(peasy.value)
|
|
end
|
|
|
|
function test_cleanup_on_easy_reset()
|
|
|
|
local mime do
|
|
mime = weak_ptr(easy:mime())
|
|
easy:setopt_mimepost(mime.value)
|
|
end
|
|
|
|
gc_collect()
|
|
|
|
assert_not_nil(mime.value)
|
|
|
|
easy:reset()
|
|
|
|
gc_collect(10)
|
|
|
|
assert_nil(mime.value)
|
|
|
|
easy:setopt{url = GET_URL, writefunction = function() end}
|
|
easy:perform()
|
|
end
|
|
|
|
end
|
|
|
|
local _ENV = TEST_CASE'mime basic' if not curl.OPT_MIMEPOST then
|
|
function test() skip("MIMI API supports since cURL 7.56.0") end
|
|
else
|
|
|
|
local easy, mime
|
|
|
|
local function dump_mime(mime)
|
|
return dump_mime_(easy, mime, GET_URL)
|
|
end
|
|
|
|
function setup()
|
|
easy = curl.easy()
|
|
mime = easy:mime()
|
|
end
|
|
|
|
function teardown()
|
|
if easy then easy:close() end
|
|
if mime then mime:free() end
|
|
easy, mime = nil
|
|
end
|
|
|
|
function test_data()
|
|
mime:addpart():data('hello')
|
|
local info = assert_string(dump_mime(mime))
|
|
assert_match('\r\n\r\nhello', info)
|
|
end
|
|
|
|
function test_data_type()
|
|
mime:addpart():data('hello', 'test/html')
|
|
local info = assert_string(dump_mime(mime))
|
|
assert_match('\r\n\r\nhello', info)
|
|
assert_match('Content%-Type:%s+test/html', info)
|
|
end
|
|
|
|
function test_data_type_name()
|
|
mime:addpart():data('hello', 'test/html', 'test')
|
|
local info = assert_string(dump_mime(mime))
|
|
assert_match('\r\n\r\nhello', info)
|
|
assert_match('Content%-Type:%s+test/html', info)
|
|
assert_match('Content%-Disposition:.-%sname="test"', info)
|
|
end
|
|
|
|
function test_data_name()
|
|
mime:addpart():data('hello', nil, 'test')
|
|
local info = assert_string(dump_mime(mime))
|
|
assert_match('\r\n\r\nhello', info)
|
|
assert_match('Content%-Disposition:.-%sname="test"', info)
|
|
end
|
|
|
|
function test_data_filename()
|
|
mime:addpart():data('hello', nil, nil, 'test.html')
|
|
local info = assert_string(dump_mime(mime))
|
|
assert_match('\r\n\r\nhello', info)
|
|
assert_match('Content%-Disposition:.-%sfilename="test%.html"', info)
|
|
end
|
|
|
|
function test_data_should_not_unset_on_nil()
|
|
local part = mime:addpart():data('hello', 'test/html', 'test', {
|
|
'X-Custom-Header: hello'
|
|
})
|
|
local info = assert_string(dump_mime(mime))
|
|
assert_match('\r\n\r\nhello', info)
|
|
assert_match('Content%-Type:%s+test/html', info)
|
|
assert_match('Content%-Disposition:.-name="test"', info)
|
|
assert_match('X%-Custom%-Header:%s*hello', info)
|
|
|
|
part:data('world', nil, 'test2')
|
|
info = assert_string(dump_mime(mime))
|
|
assert_match('\r\n\r\nworld', info)
|
|
assert_match('Content%-Type:%s+test/html', info)
|
|
assert_match('Content%-Disposition:.-name="test2"', info)
|
|
assert_match('X%-Custom%-Header:%s*hello', info)
|
|
|
|
part:data('!!!!!', 'text/xml', nil)
|
|
info = assert_string(dump_mime(mime))
|
|
assert_match('\r\n\r\n!!!!!', info)
|
|
assert_match('Content%-Type:%s+text/xml', info)
|
|
assert_match('Content%-Disposition:.-name="test2"', info)
|
|
assert_match('X%-Custom%-Header:%s*hello', info)
|
|
|
|
part:data('!!!!!!!', 'text/xml', nil, nil)
|
|
info = assert_string(dump_mime(mime))
|
|
assert_match('\r\n\r\n!!!!!', info)
|
|
assert_match('Content%-Type:%s+text/xml', info)
|
|
assert_match('Content%-Disposition:.-name="test2"', info)
|
|
assert_match('X%-Custom%-Header:%s*hello', info)
|
|
end
|
|
|
|
function test_data_headers()
|
|
mime:addpart():data('hello', {
|
|
'X-Custom-Header: hello'
|
|
})
|
|
local info = assert_string(dump_mime(mime))
|
|
assert_match('\r\n\r\nhello', info)
|
|
assert_match('X%-Custom%-Header:%s*hello', info)
|
|
end
|
|
|
|
function test_unset_name()
|
|
mime:addpart():data('hello', 'test/html', 'test'):name(false)
|
|
|
|
local info = assert_string(dump_mime(mime))
|
|
assert_match('\r\n\r\nhello', info)
|
|
assert_match('Content%-Type:%s+test/html', info)
|
|
assert_not_match('Content%-Disposition:.-name="test"', info)
|
|
end
|
|
|
|
function test_unset_name_by_null()
|
|
mime:addpart():data('hello', 'test/html', 'test'):name(null)
|
|
|
|
local info = assert_string(dump_mime(mime))
|
|
assert_match('\r\n\r\nhello', info)
|
|
assert_match('Content%-Type:%s+test/html', info)
|
|
assert_not_match('Content%-Disposition:.-name="test"', info)
|
|
end
|
|
|
|
function test_unset_type()
|
|
mime:addpart():data('hello', 'test/html'):type(false)
|
|
|
|
local info = assert_string(dump_mime(mime))
|
|
assert_match('\r\n\r\nhello', info)
|
|
assert_not_match('Content%-Type:%s+test/html', info)
|
|
end
|
|
|
|
function test_unset_type_by_null()
|
|
mime:addpart():data('hello', 'test/html'):type(null)
|
|
|
|
local info = assert_string(dump_mime(mime))
|
|
assert_match('\r\n\r\nhello', info)
|
|
assert_not_match('Content%-Type:%s+test/html', info)
|
|
end
|
|
|
|
function test_unset_headers()
|
|
mime:addpart():data('hello', 'test/html',{
|
|
'X-Custom-Header: hello'
|
|
}):headers(false)
|
|
|
|
local info = assert_string(dump_mime(mime))
|
|
assert_match('\r\n\r\nhello', info)
|
|
assert_not_match('X%-Custom%-Header:%s*hello', info)
|
|
end
|
|
|
|
function test_unset_headers_by_null()
|
|
mime:addpart():data('hello', 'test/html',{
|
|
'X-Custom-Header: hello'
|
|
}):headers(null)
|
|
|
|
local info = assert_string(dump_mime(mime))
|
|
assert_match('\r\n\r\nhello', info)
|
|
assert_not_match('X%-Custom%-Header:%s*hello', info)
|
|
end
|
|
|
|
function test_unset_headers_by_empty_array()
|
|
mime:addpart():data('hello', 'test/html',{
|
|
'X-Custom-Header: hello'
|
|
}):headers({})
|
|
|
|
local info = assert_string(dump_mime(mime))
|
|
assert_match('\r\n\r\nhello', info)
|
|
assert_not_match('X%-Custom%-Header:%s*hello', info)
|
|
end
|
|
|
|
function test_unset_data()
|
|
mime:addpart():data('hello', 'test/html', 'test'):data(false)
|
|
|
|
local info = assert_string(dump_mime(mime))
|
|
assert_not_match('\r\n\r\nhello', info)
|
|
assert_match('Content%-Type:%s+test/html', info)
|
|
assert_match('Content%-Disposition:.-name="test"', info)
|
|
end
|
|
|
|
function test_unset_data_by_null()
|
|
mime:addpart():data('hello', 'test/html', 'test'):data(null)
|
|
|
|
local info = assert_string(dump_mime(mime))
|
|
assert_not_match('\r\n\r\nhello', info)
|
|
assert_match('Content%-Type:%s+test/html', info)
|
|
assert_match('Content%-Disposition:.-name="test"', info)
|
|
end
|
|
|
|
function test_unset_data_type_1()
|
|
local part = mime:addpart():data('hello', 'test/html', 'test', {
|
|
'X-Custom-Header: hello'
|
|
}):data('hello', false)
|
|
|
|
local info = assert_string(dump_mime(mime))
|
|
assert_match('\r\n\r\nhello', info)
|
|
assert_not_match('Content%-Type:%s+test/html', info)
|
|
assert_match('Content%-Disposition:.-name="test"', info)
|
|
assert_match('X%-Custom%-Header:%s*hello', info)
|
|
end
|
|
|
|
function test_unset_data_type_1_by_null()
|
|
local part = mime:addpart():data('hello', 'test/html', 'test', {
|
|
'X-Custom-Header: hello'
|
|
}):data('hello', null)
|
|
|
|
local info = assert_string(dump_mime(mime))
|
|
assert_match('\r\n\r\nhello', info)
|
|
assert_not_match('Content%-Type:%s+test/html', info)
|
|
assert_match('Content%-Disposition:.-name="test"', info)
|
|
assert_match('X%-Custom%-Header:%s*hello', info)
|
|
end
|
|
|
|
function test_unset_data_type_2()
|
|
local part = mime:addpart():data('hello', 'test/html', 'test', {
|
|
'X-Custom-Header: hello'
|
|
}):data('hello', false, nil, nil)
|
|
|
|
local info = assert_string(dump_mime(mime))
|
|
assert_match('\r\n\r\nhello', info)
|
|
assert_not_match('Content%-Type:%s+test/html', info)
|
|
assert_match('Content%-Disposition:.-name="test"', info)
|
|
assert_match('X%-Custom%-Header:%s*hello', info)
|
|
end
|
|
|
|
function test_unset_data_name_1()
|
|
local part = mime:addpart():data('hello', 'test/html', 'test', {
|
|
'X-Custom-Header: hello'
|
|
}):data('hello', nil, false)
|
|
|
|
local info = assert_string(dump_mime(mime))
|
|
assert_match('\r\n\r\nhello', info)
|
|
assert_match('Content%-Type:%s+test/html', info)
|
|
assert_not_match('Content%-Disposition:.-name="test"', info)
|
|
assert_match('X%-Custom%-Header:%s*hello', info)
|
|
end
|
|
|
|
function test_unset_data_name_1_by_null()
|
|
local part = mime:addpart():data('hello', 'test/html', 'test', {
|
|
'X-Custom-Header: hello'
|
|
}):data('hello', nil, null)
|
|
|
|
local info = assert_string(dump_mime(mime))
|
|
assert_match('\r\n\r\nhello', info)
|
|
assert_match('Content%-Type:%s+test/html', info)
|
|
assert_not_match('Content%-Disposition:.-name="test"', info)
|
|
assert_match('X%-Custom%-Header:%s*hello', info)
|
|
end
|
|
|
|
function test_unset_data_name_2()
|
|
local part = mime:addpart():data('hello', 'test/html', 'test', {
|
|
'X-Custom-Header: hello'
|
|
}):data('hello', nil, false, nil)
|
|
|
|
local info = assert_string(dump_mime(mime))
|
|
assert_match('\r\n\r\nhello', info)
|
|
assert_match('Content%-Type:%s+test/html', info)
|
|
assert_not_match('Content%-Disposition:.-name="test"', info)
|
|
assert_match('X%-Custom%-Header:%s*hello', info)
|
|
end
|
|
|
|
function test_unset_data_header()
|
|
local part = mime:addpart():data('hello', 'test/html', 'test', {
|
|
'X-Custom-Header: hello'
|
|
}):data('hello', nil, nil, nil, false)
|
|
|
|
local info = assert_string(dump_mime(mime))
|
|
assert_match('\r\n\r\nhello', info)
|
|
assert_match('Content%-Type:%s+test/html', info)
|
|
assert_match('Content%-Disposition:.-name="test"', info)
|
|
assert_not_match('X%-Custom%-Header:%s*hello', info)
|
|
end
|
|
|
|
function test_unset_data_header_by_null()
|
|
local part = mime:addpart():data('hello', 'test/html', 'test', {
|
|
'X-Custom-Header: hello'
|
|
}):data('hello', nil, nil, nil, null)
|
|
|
|
local info = assert_string(dump_mime(mime))
|
|
assert_match('\r\n\r\nhello', info)
|
|
assert_match('Content%-Type:%s+test/html', info)
|
|
assert_match('Content%-Disposition:.-name="test"', info)
|
|
assert_not_match('X%-Custom%-Header:%s*hello', info)
|
|
end
|
|
|
|
function test_unset_data_filename_1()
|
|
local part = mime:addpart():data('hello', 'test/html', 'test', 'test.html', {
|
|
'X-Custom-Header: hello'
|
|
}):data('hello', nil, nil, false)
|
|
|
|
local info = assert_string(dump_mime(mime))
|
|
assert_match('\r\n\r\nhello', info)
|
|
assert_match('Content%-Type:%s+test/html', info)
|
|
assert_match('Content%-Disposition:.-%sname="test"', info)
|
|
assert_not_match('Content%-Disposition:.-%sfilename="test%.html"', info)
|
|
assert_match('X%-Custom%-Header:%s*hello', info)
|
|
end
|
|
|
|
function test_unset_data_filename_1_by_null()
|
|
local part = mime:addpart():data('hello', 'test/html', 'test', 'test.html', {
|
|
'X-Custom-Header: hello'
|
|
}):data('hello', nil, nil, null)
|
|
|
|
local info = assert_string(dump_mime(mime))
|
|
assert_match('\r\n\r\nhello', info)
|
|
assert_match('Content%-Type:%s+test/html', info)
|
|
assert_match('Content%-Disposition:.-%sname="test"', info)
|
|
assert_not_match('Content%-Disposition:.-%sfilename="test%.html"', info)
|
|
assert_match('X%-Custom%-Header:%s*hello', info)
|
|
end
|
|
|
|
function test_fail_pass_nil_as_first_arg()
|
|
local part = mime:addpart()
|
|
assert_error(function() part:data() end)
|
|
assert_error(function() part:data(nil) end)
|
|
|
|
assert_error(function() part:name() end)
|
|
assert_error(function() part:name(nil) end)
|
|
|
|
assert_error(function() part:type() end)
|
|
assert_error(function() part:type(nil) end)
|
|
|
|
assert_error(function() part:headers() end)
|
|
assert_error(function() part:headers(nil) end)
|
|
end
|
|
|
|
end
|
|
|
|
local _ENV = TEST_CASE'mime addpart' if not curl.OPT_MIMEPOST then
|
|
function test() skip("MIMI API supports since cURL 7.56.0") end
|
|
else
|
|
|
|
local easy, mime
|
|
|
|
local function dump_mime(mime)
|
|
return dump_mime_(easy, mime, GET_URL)
|
|
end
|
|
|
|
function setup()
|
|
easy = curl.easy()
|
|
mime = easy:mime()
|
|
end
|
|
|
|
function teardown()
|
|
if easy then easy:close() end
|
|
if mime then mime:free() end
|
|
easy, mime = nil
|
|
end
|
|
|
|
function test_empty_table()
|
|
assert(mime:addpart{})
|
|
end
|
|
|
|
function test_pass_args()
|
|
assert(mime:addpart{
|
|
data = 'hello';
|
|
encoder = 'base64';
|
|
name = 'test';
|
|
filename = 'test.html';
|
|
type = 'test/html';
|
|
headers = {
|
|
'X-Custom-Header: hello';
|
|
}
|
|
})
|
|
|
|
local info = assert_string(dump_mime(mime))
|
|
assert_match('\r\n\r\naGVsbG8=', info)
|
|
assert_match('Content%-Type:%s+test/html', info)
|
|
assert_match('Content%-Disposition:.-%sname="test"', info)
|
|
assert_not_match('Content%-Disposition:.-%sname="test%.html"', info)
|
|
assert_match('X%-Custom%-Header:%s*hello', info)
|
|
assert_match('Content%-Transfer%-Encoding:%s*base64', info)
|
|
end
|
|
|
|
local function easy_dump_mime(easy, mime, url)
|
|
assert(mime:addpart{
|
|
data = 'hello';
|
|
encoder = 'base64';
|
|
name = 'test';
|
|
filename = 'test.html';
|
|
type = 'test/html';
|
|
headers = {
|
|
'X-Custom-Header: hello';
|
|
}
|
|
})
|
|
|
|
easy:setopt{
|
|
mimepost = mime;
|
|
}
|
|
|
|
assert(easy:setopt{
|
|
url = GET_URL;
|
|
customrequest = "GET";
|
|
|
|
writefunction = function()end;
|
|
})
|
|
|
|
if not ok then return nil, err end
|
|
|
|
ok, err = easy:perform()
|
|
|
|
if not ok then return nil, err end
|
|
|
|
return table.concat(buffer)
|
|
end
|
|
|
|
end
|
|
|
|
RUN()
|