Lua-cURLv3/test/test_mime.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()