From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from [87.239.111.99] (localhost [127.0.0.1]) by dev.tarantool.org (Postfix) with ESMTP id 23AC09E72A2; Tue, 6 Feb 2024 16:15:17 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 23AC09E72A2 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1707225317; bh=7sB2d75H4tKdumezrDCrVxsoFP8vmHeRoQQryxhPgKo=; h=Date:To:References:In-Reply-To:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=MyaV3l5OsW1xcjrUHpKcruWlbfSbPmVrTe23TJunxA/MHJmppMva9QcVftmv88jnv RP1lRIU0OXCWWrXgiMS5N9riUB2JF6olDRcNGareAjTg9gsZMeUKqFS6IU238Y3s66 Foa/RRW28zZf1j9fDJv+asOJjAVSaA/Pn4huw7mw= Received: from smtp61.i.mail.ru (smtp61.i.mail.ru [95.163.41.99]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id 6482A9E72A2 for ; Tue, 6 Feb 2024 16:15:15 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 6482A9E72A2 Received: by smtp61.i.mail.ru with esmtpa (envelope-from ) id 1rXLI9-00000001frs-2oUO; Tue, 06 Feb 2024 16:15:14 +0300 Date: Tue, 6 Feb 2024 16:11:16 +0300 To: Maxim Kokryashkin Message-ID: References: <4d80dfc5a12d8e7d0ca668432543a9241dd58017.1706520765.git.skaplun@tarantool.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: X-Mailru-Src: smtp X-4EC0790: 10 X-7564579A: 78E4E2B564C1792B X-77F55803: 4F1203BC0FB41BD94C460F083DF69F515295F69A3DCCED9A65A8B27103DC31E2182A05F538085040ED37EBD8A610C5069487ABAC94A94B5438CF772954710EDA67F967DB3C6FC7F51E13962C942EC85E X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE70B8ADF238913687CB287FD4696A6DC2FA8DF7F3B2552694A4E2F5AFA99E116B42401471946AA11AFEE3A9D0FB4FE0F999A02CFBD12041B858F08D7030A58E5AD1A62830130A00468AEEEE3FBA3A834EE7353EFBB5533756645B9F6836320F6B4C6D484BA046F9342F5397BE681C1206ED12A29A4FBD989CB389733CBF5DBD5E913377AFFFEAFD269176DF2183F8FC7C091DAD9F922AA71188941B15DA834481FCF19DD082D7633A0EF3E4896CB9E6436389733CBF5DBD5E9D5E8D9A59859A8B64854413538E1713FCC7F00164DA146DA6F5DAA56C3B73B237318B6A418E8EAB86D1867E19FE14079C09775C1D3CA48CFED8438A78DFE0A9E1DD303D21008E298D5E8D9A59859A8B6B372FE9A2E580EFC725E5C173C3A84C30584FF81F342DA0735872C767BF85DA2F004C90652538430E4A6367B16DE6309 X-C1DE0DAB: 0D63561A33F958A53FD24AFAE3D2F1A25002B1117B3ED696E74DA26856BF1C3AE20DC3F561CE4150823CB91A9FED034534781492E4B8EEAD01200A96CB7104FFBDAD6C7F3747799A X-C8649E89: 1C3962B70DF3F0ADE00A9FD3E00BEEDF3FED46C3ACD6F73ED3581295AF09D3DF87807E0823442EA2ED31085941D9CD0AF7F820E7B07EA4CF9B78496714E2E5770E812A615D506091EE7E1627DEEDB594B822B712B8FED8FD90F5B3B6BD0F620E807D692F32DC70321D6E5BE22464D60F9D93215B6EAE6236B651385ADC3F44F15F4332CA8FE04980913E6812662D5F2A5EAB5682573093F7837F15F2B5E4A70B33F2C28C22F508233FCF178C6DD14203 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2biojh/iSjD2txnMVSuraFNIE6A== X-DA7885C5: A947DA2CCA541843F255D290C0D534F9BCC62A061AD54F5D8D7A91745444A1DCEA29D72220D503765B1A4C17EAA7BC4BEF2421ABFA55128DAF83EF9164C44C7E X-Mailru-Sender: 689FA8AB762F7393590D8C940224AE33D2AC4E9DFDD575D79748C2D2F6B4D439F1C9A00E55DD5402E49D44BB4BD9522A059A1ED8796F048DB274557F927329BE89D5A3BC2B10C37545BD1C3CC395C826B4A721A3011E896F X-Mras: Ok Subject: Re: [Tarantool-patches] [PATCH v2 luajit 09/26] test: enable in LuaJIT-tests X-BeenThere: tarantool-patches@dev.tarantool.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Sergey Kaplun via Tarantool-patches Reply-To: Sergey Kaplun Cc: tarantool-patches@dev.tarantool.org Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" Hi, Maxim! Thanks for the review! Fixed your comments and force-pushed the branch. On 31.01.24, Maxim Kokryashkin wrote: > Hi, Sergey! > Thanks for the patch! > Please consider my comments below. > > On Mon, Jan 29, 2024 at 01:45:09PM +0300, Sergey Kaplun wrote: > > This patch changes `dofile()` (which uses an unreliable relative file > > path and mutates `_G` with global functions to be defined) to the > > corresponding require and renames the C library in the `require()` call. > > It adds groups with the names of subtests and enables the test in > > . It renames structure and enum typedefs to avoid conflicts with > > cdef in other tests. The GC threshold is increased since all tests run > > in a single process, so the number of GC objects is greater. > > > > Part of tarantool/tarantool#9398 > > --- The new commit message is the following: | test: enable in LuaJIT-tests | | This patch changes `dofile()` (which uses an unreliable relative file | path and mutates `_G` with global functions to be defined) to the | corresponding require and renames the C library in the `require()` call. | It adds groups with the names of subtests and enables the test in | . It renames structure and enum typedefs to avoid conflicts with | cdef in other tests. The GC threshold is increased since all tests run | in a single process, so the number of GC objects is greater. Also, the | one test case is splitted into several. | | Part of tarantool/tarantool#9398 > > test/LuaJIT-tests/lib/ffi/ffi_convert.lua | 35 +++++++++++------------ > > test/LuaJIT-tests/lib/ffi/index | 1 + > > 2 files changed, 18 insertions(+), 18 deletions(-) > > > > diff --git a/test/LuaJIT-tests/lib/ffi/ffi_convert.lua b/test/LuaJIT-tests/lib/ffi/ffi_convert.lua > > index bd3fb1f9..284f2b53 100644 > > --- a/test/LuaJIT-tests/lib/ffi/ffi_convert.lua > > +++ b/test/LuaJIT-tests/lib/ffi/ffi_convert.lua > > @@ -1,8 +1,7 @@ > > local ffi = require("ffi") > > > > -local ctest = require("ctest") > > - > > -dofile("../common/ffi_util.inc") > > +local ctest = require("libctest") > > +local fails = require("common.fails") > > > > local tonumber = tonumber > > > > @@ -32,15 +31,15 @@ typedef struct arrinc_t { > > int a[]; > > } arrinc_t; > > > > -typedef enum uenum_t { > > +typedef enum uenum_convert_t { > > UE0, UE71 = 71, UE72 > > -} uenum_t; > > +} uenum_convert_t; > `convert` acts as a namespace here, and those are usually used as a > prefix. Here and below. Renamed. See the iterative patch below. =================================================================== diff --git a/test/LuaJIT-tests/lib/ffi/ffi_convert.lua b/test/LuaJIT-tests/lib/ffi/ffi_convert.lua index 284f2b53..3d1b0064 100644 --- a/test/LuaJIT-tests/lib/ffi/ffi_convert.lua +++ b/test/LuaJIT-tests/lib/ffi/ffi_convert.lua @@ -31,15 +31,15 @@ typedef struct arrinc_t { int a[]; } arrinc_t; -typedef enum uenum_convert_t { +typedef enum convert_uenum_t { UE0, UE71 = 71, UE72 -} uenum_convert_t; +} convert_uenum_t; typedef enum ienum_convert_t { IE0, IEM12 = -12, IEM11 } ienum_convert_t; -typedef struct foo_convert_t { +typedef struct convert_foo_t { bool b; int8_t i8; uint8_t u8; @@ -78,9 +78,9 @@ typedef struct foo_convert_t { int si_guard; nest_t sn; uni_t ui; - uenum_convert_t ue; + convert_uenum_t ue; ienum_convert_t ie; -} foo_convert_t; +} convert_foo_t; char *strcpy(char *dest, const char *src); typedef struct FILE FILE; @@ -89,10 +89,10 @@ int _fileno(FILE *stream); ]] do --- misc - local foo_convert_t = ffi.typeof("foo_convert_t") - local sz = ffi.sizeof(foo_convert_t) - local x = foo_convert_t() - local y = foo_convert_t() + local convert_foo_t = ffi.typeof("convert_foo_t") + local sz = ffi.sizeof(convert_foo_t) + local x = convert_foo_t() + local y = convert_foo_t() ffi.fill(x, sz, 0xff) ffi.fill(y, sz, 0xee) =================================================================== > > > > -typedef enum ienum_t { > > +typedef enum ienum_convert_t { > > > > -do > > - local foo_t = ffi.typeof("foo_t") > > - local sz = ffi.sizeof(foo_t) > > - local x = foo_t() > > - local y = foo_t() > > +do --- misc > Is there any chance to split it up? Splitted. See the iterative patch below. Branch is force-pushed. =================================================================== diff --git a/test/LuaJIT-tests/lib/ffi/ffi_convert.lua b/test/LuaJIT-tests/lib/ffi/ffi_convert.lua index 3d1b0064..2d530f90 100644 --- a/test/LuaJIT-tests/lib/ffi/ffi_convert.lua +++ b/test/LuaJIT-tests/lib/ffi/ffi_convert.lua @@ -88,21 +88,23 @@ int fileno(FILE *stream); int _fileno(FILE *stream); ]] -do --- misc - local convert_foo_t = ffi.typeof("convert_foo_t") - local sz = ffi.sizeof(convert_foo_t) - local x = convert_foo_t() - local y = convert_foo_t() - ffi.fill(x, sz, 0xff) - ffi.fill(y, sz, 0xee) - - -- unknown member +local convert_foo_t = ffi.typeof("convert_foo_t") +local sz = ffi.sizeof(convert_foo_t) +local x = convert_foo_t() +local y = convert_foo_t() +ffi.fill(x, sz, 0xff) +ffi.fill(y, sz, 0xee) + +do --- unknown member fails(function(x) local a = x.bad end, x) fails(function(x) x.bad = 1 end, x) - -- too many initializers +end + +do --- too many initializers, double fails(function(x) x.d = ffi.new("double", 1,2) end, x) +end - -- conversions to bool +do --- conversions to bool x.b = false assert(x.b == false) x.b = true @@ -122,8 +124,9 @@ do --- misc assert(x.b == true) x.b = ffi.new("int32_t", 0) assert(x.b == false) +end - -- conversions from bool +do --- conversions from bool x.i32 = true assert(x.i32 == 1) x.i32 = false @@ -136,13 +139,16 @@ do --- misc assert(x.d == 1) x.d = ffi.new("bool", false) assert(x.d == 0) - -- assignment of bool to other types is not allowed +end + +do --- assignment of bool to other types is not allowed fails(function(x) x.cd = true end, x) fails(function(x) x.v4si = true end, x) fails(function(x) x.ai = true end, x) fails(function(x) x.s = true end, x) +end - -- int to int conversions +do --- int to int conversions x.i8 = 99 assert(x.i8 == 99) x.i8 = -99 @@ -298,8 +304,9 @@ do --- misc assert(tonumber(x.u64) == 0xffeeddcc) x.u64 = ffi.new("int64_t", -0x7feeddcc*2^32) assert(tonumber(x.u64) == 2^64-0x7feeddcc*2^32) +end - -- FP to int conversions, test for truncation +do --- FP to int conversions, test for truncation x.i32 = 1.9 assert(x.i32 == 1) x.i32 = 2.9 @@ -320,8 +327,9 @@ do --- misc assert(x.u32 == 1) x.u64 = 1.9 assert(tonumber(x.u64) == 1) +end - -- int to FP conversions (most tested above) +do --- int to FP conversions (most tested above) x.f = ffi.new("int32_t", -17) assert(x.f == -17) x.d = ffi.new("int32_t", -17) @@ -334,16 +342,20 @@ do --- misc x.d = ffi.new("union { uint32_t u32[2]; uint64_t u64; }", {{ 0x77777777, 0x77777777}}).u64 assert(x.d == 0x77777777*2^32 + 0x77777800) +end - -- complex initialization +do --- complex initialization x.cd = ffi.new("complex", 9.125, -78.5) assert(x.cd.re == 9.125 and x.cd.im == -78.5) x.cd = ffi.new("complex", {9.125, -78.5}) assert(x.cd.re == 9.125 and x.cd.im == -78.5) - -- too many initializers +end + +do --- too many initializers, complex fails(function(x) x.cd = ffi.new("complex", 1,2,3) end, x) +end - -- conversions between FP and complex +do --- conversions between FP and complex x.cf = -17.25 assert(x.cf.re == -17.25 and x.cf.im == 0) x.cf = ffi.new("complex float", -57.5) -- missing initializer @@ -371,25 +383,30 @@ do --- misc assert(x.d == 9.125) x.d = ffi.new("complex double", 9.125, -78.5) assert(x.d == 9.125) +end - -- conversions between int and complex +do --- conversions between int and complex x.cd = ffi.new("int32_t", -138) assert(x.cd.re == -138 and x.cd.im == 0) x.i32 = ffi.new("complex", 9.125, -78.5) assert(x.i32 == 9) +end - -- vector initialization +do --- vector initialization x.v4si = ffi.new("int __attribute__((mode(__V4SI__)))", 1, 2, 3, 4) assert(x.v4si[0] == 1 and x.v4si[1] == 2 and x.v4si[2] == 3 and x.v4si[3] == 4) x.v2df = ffi.new("double __attribute__((mode(__V2DF__)))", {3.5, -6.75}) assert(x.v2df[0] == 3.5 and x.v2df[1] == -6.75) - -- too many initializers +end + +do --- too many initializers, vector fails(function(x) x.v4si = ffi.new("int __attribute__((mode(__V4SI__)))", 1,2,3,4,5) end, x) +end - -- conversions to vectors +do --- conversions to vectors x.v4si = -17 assert(x.v4si[0] == -17 and x.v4si[1] == -17 and x.v4si[2] == -17 and x.v4si[3] == -17) @@ -400,14 +417,16 @@ do --- misc assert(x.v2df[0] == 12.5 and x.v2df[1] == 12.5) x.v2df = ffi.new("complex", 9.125, -78.5) assert(x.v2df[0] == 9.125 and x.v2df[1] == 9.125) +end - -- assignment of same-sized but differently-typed vectors +do --- assignment of same-sized but differently-typed vectors x.v16qi = 99 x.v4si = 0x33333333 x.v16qi = x.v4si assert(x.v16qi[0] == 0x33 and x.v16qi[15] == 0x33) +end - -- string converted to enum +do --- string converted to enum -- x.ue = -1 -- this is undefined on some architectures -- assert(x.ue == 0xffffffff) x.ue = "UE0" @@ -420,58 +439,74 @@ do --- misc assert(x.ie == 0) x.ie = "IEM11" assert(x.ie == -11) +end +do --- self assignment is ok x.pi = x.pi - -- assignment to pointer with higher qualifiers is ok +end + +do --- assignment to pointer with higher qualifiers is ok x.pci = x.pi x.pvi = x.pi - -- assignment to pointer with lower qualifiers is not ok +end + +do --- assignment to pointer with lower qualifiers is not ok fails(function(x) x.pi = x.pci end, x) fails(function(x) x.pi = x.pvi end, x) fails(function(x) x.pci = x.pvi end, x) fails(function(x) x.pvi = x.pci end, x) - -- assignment of pointers with incompatible child types is not ok +end + +do --- assignment of pointers with incompatible child types is not ok fails(function(x) x.ppi = x.ai end, x) fails(function(x) x.ppi = x.pi end, x) fails(function(x) x.ppv = x.ppi end, x) - -- qualifiers of child types must match, higher qualifiers not ok +end + +do --- qualifiers of child types must match, higher qualifiers not ok fails(function(x) x.ppci = x.ppi end, x) fails(function(x) x.ppi = x.ppci end, x) +end - -- pointer/int conversions are not allowed by default +do --- pointer/int conversions are not allowed by default fails(function(x) x.pi = 1 end, x) fails(function(x) x.i32 = x.pi end, x) assert(tonumber(x.pi) == nil) assert(tonumber(x.ai) == nil) assert(tonumber(x.si) == nil) +end - -- but pointer/int casts are allowed +do --- pointer/int casts are allowed x.pi = ffi.cast("int *", ffi.new("int32_t", 0x12345678)) x.i32 = ffi.cast("int32_t", x.pi) assert(x.i32 == 0x12345678) x.pi = ffi.cast("int *", 1234560.3) x.i32 = ffi.cast("int32_t", x.pi) assert(x.i32 == 1234560) - -- bad cast from non-TValue double to pointer +end + +do --- bad cast from non-TValue double to pointer fails(function(x) ffi.cast("int *", ffi.new("double", 1.5)) end, x) +end - -- nil sets a pointer to NULL +do --- nil sets a pointer to NULL x.pi = nil assert(tonumber(ffi.cast("uintptr_t", x.pi)) == 0) +end - -- userdata and lightuserdata are treated as void * - do - local u = newproxy() - local uaddr = _G.tonumber(string.match(tostring(u), "(0x.*)")) - x.pi = u - assert(tonumber(ffi.cast("uintptr_t", x.pi)) == uaddr) - x.pi = ctest.lightud(12345678) - assert(tonumber(ffi.cast("uintptr_t", x.pi)) == 12345678) - end - -- io.* file converts to file handle (as a void *) +do --- userdata and lightuserdata are treated as void * + local u = newproxy() + local uaddr = _G.tonumber(string.match(tostring(u), "(0x.*)")) + x.pi = u + assert(tonumber(ffi.cast("uintptr_t", x.pi)) == uaddr) + x.pi = ctest.lightud(12345678) + assert(tonumber(ffi.cast("uintptr_t", x.pi)) == 12345678) +end + +do --- io.* file converts to file handle (as a void *) if ffi.abi("win") then assert(ffi.C._fileno(io.stdout) == 1) assert(ffi.C._fileno(io.stderr) == 2) @@ -485,44 +520,47 @@ do --- misc for i=1,100 do x = ffi.C.fileno(io.stderr) end assert(x == 2) end +end - -- truncation/extension of __ptr32 - if ffi.abi("64bit") then - x.pi = ffi.cast("int *", 15*2^32+0x12345678) - assert(tonumber(ffi.cast("uintptr_t", x.pi)) == 15*2^32+0x12345678) - x.p32i = x.pi - assert(tonumber(ffi.cast("uintptr_t", x.p32i)) == 0x12345678) - x.pi = ffi.cast("int *", 0x1234*2^32+0x56780000) - x.pi = x.p32i - assert(tonumber(ffi.cast("uintptr_t", x.pi)) == 0x12345678) - end +do --- truncation/extension of __ptr32 +abi64 + x.pi = ffi.cast("int *", 15*2^32+0x12345678) + assert(tonumber(ffi.cast("uintptr_t", x.pi)) == 15*2^32+0x12345678) + x.p32i = x.pi + assert(tonumber(ffi.cast("uintptr_t", x.p32i)) == 0x12345678) + x.pi = ffi.cast("int *", 0x1234*2^32+0x56780000) + x.pi = x.p32i + assert(tonumber(ffi.cast("uintptr_t", x.pi)) == 0x12345678) +end - -- reference initialization - do - x.ai[0] = 712 - local ri = ffi.new("int &", x.ai) - assert(tonumber(ri) == 712) - local ra = ffi.new("int (&)[10]", ffi.cast("int (*)[10]", x.ai)) - assert(ra[0] == 712) - end +do --- reference initialization + x.ai[0] = 712 + local ri = ffi.new("int &", x.ai) + assert(tonumber(ri) == 712) + local ra = ffi.new("int (&)[10]", ffi.cast("int (*)[10]", x.ai)) + assert(ra[0] == 712) +end - -- ffi.sizeof follows references +do --- ffi.sizeof follows references assert(ffi.sizeof(x.ai) == 4*10) -- ffi.offsetof follows references assert(ffi.offsetof(x.s, "v") == 0) assert(ffi.offsetof(x.s, "w") == 4) +end - -- ffi.fill writes the right amount +do --- ffi.fill writes the right amount ffi.fill(x.ai2, ffi.sizeof(x.ai2), 0x72) ffi.fill(x.ai, ffi.sizeof(x.ai), 0x13) assert(x.ai[0] == 0x13131313) assert(x.ai[9] == 0x13131313) assert(x.ai2[0] == 0x72727272) assert(x.ai2[9] == 0x72727272) +end - -- array cannot be assigned a pointer +do --- array cannot be assigned a pointer fails(function(x) x.ai = x.pi end, x) - -- but pointer can be assigned the address of an array +end + +do --- pointer can be assigned the address of an array x.pi = x.ai2 assert(x.pi[0] == 0x72727272) assert(x.pi[9] == 0x72727272) @@ -535,21 +573,28 @@ do --- misc -- reflected via pointer, too assert(x.pi[0] == 0x72727272) assert(x.pi[9] == 0x72727272) - -- mismatched type or size in array copy +end + +do --- mismatched type or size in array copy fails(function(x) x.ai = x.ac end, x) fails(function(x) x.ai = ffi.new("int[20]") end, x) fails(function(x) x.ai = ffi.new("arrinc_t").a end, x) fails(function(x) ffi.new("arrinc_t").a = x.ai end, x) +end +do --- assignment follows references ffi.fill(x.s2, ffi.sizeof(x.s2), 0x59) x.s.v = 0x12345678 x.s.w = 0x789abcde assert(x.s.v == 0x12345678) assert(x.s.w == 0x789abcde) +end - -- struct cannot be assigned a pointer +do --- struct cannot be assigned a pointer fails(function(x) x.s = x.ps end, x) - -- but pointer can be assigned the address of a struct +end + +do --- pointer can be assigned the address of a struct x.ps = x.s assert(x.ps.v == 0x12345678) assert(x.ps.w == 0x789abcde) @@ -562,12 +607,14 @@ do --- misc -- reflected via pointer, too assert(x.ps.v == 0x59595959) assert(x.ps.w == 0x59595959) +end - -- structs must be identical, structural equivalence is not enough +do --- structs must be identical, structural equivalence is not enough fails(function(x) x.ps = x.sx end, x) fails(function(x) x.s = x.sx end, x) +end - -- string copy to arrays +do --- string copy to arrays x.ac_guard = 99 ffi.fill(x.ac, 10, 0x37) x.ac = "ABCD" @@ -584,26 +631,31 @@ do --- misc x.ac = "ABCDEFGHIJKLM" assert(x.ac[8] == 65+8) assert(x.ac[9] == 65+9) - do -- copy to a[?] - local vx = ffi.new("struct { char ac[?]; }", 20) - ffi.fill(vx.ac, 20, 0x37) - vx.ac = "ABCDEFGHI" - assert(vx.ac[8] == 65+8) - assert(vx.ac[9] == 0) - end - do -- copy to a[0] - local vx = ffi.new("union { char ac[0]; char c[20]; }") - ffi.fill(vx.ac, 20, 0x37) - vx.ac = "ABCDEFGHI" - assert(vx.ac[8] == 65+8) - assert(vx.ac[9] == 0) - end - -- mismatched type or size in string copy +end + +do --- copy to a[?] + local vx = ffi.new("struct { char ac[?]; }", 20) + ffi.fill(vx.ac, 20, 0x37) + vx.ac = "ABCDEFGHI" + assert(vx.ac[8] == 65+8) + assert(vx.ac[9] == 0) +end + +do --- copy to a[0] + local vx = ffi.new("union { char ac[0]; char c[20]; }") + ffi.fill(vx.ac, 20, 0x37) + vx.ac = "ABCDEFGHI" + assert(vx.ac[8] == 65+8) + assert(vx.ac[9] == 0) +end + +do --- mismatched type or size in string copy fails(function(x) x.i32 = "ABCD" end, x) fails(function(x) x.ai = "ABCD" end, x) assert(x.ac_guard == 99) -- Check guard +end - -- array initialization +do --- array initialization x.ai = ffi.new("int[10]") -- zero fill for i=0,9 do assert(x.ai[i] == 0) end x.ai = ffi.new("int[10]", -67) -- replicate first element @@ -616,25 +668,28 @@ do --- misc for i=0,9 do assert(x.ai[i] == i+1) end x.ai = ffi.new("int[10]", {1,2,3,4,5,6,7,8,9,10}) for i=0,9 do assert(x.ai[i] == i+1) end - -- VLA initialization - do - local v = ffi.new("int[?]", 4) - for i=0,3 do assert(v[i] == 0) end - local v = ffi.new("int[?]", 4, 833) - for i=0,3 do assert(v[i] == 833) end - local v = ffi.new("int[?]", 4, 12, -9) - assert(v[0] == 12 and v[1] == -9 and v[2] == 0 and v[3] == 0) - local v = ffi.new("int[?]", 4, 1,2,3,4) - assert(v[0] == 1 and v[1] == 2 and v[2] == 3 and v[3] == 4) - end - -- too many initializers +end + +do --- VLA initialization + local v = ffi.new("int[?]", 4) + for i=0,3 do assert(v[i] == 0) end + local v = ffi.new("int[?]", 4, 833) + for i=0,3 do assert(v[i] == 833) end + local v = ffi.new("int[?]", 4, 12, -9) + assert(v[0] == 12 and v[1] == -9 and v[2] == 0 and v[3] == 0) + local v = ffi.new("int[?]", 4, 1,2,3,4) + assert(v[0] == 1 and v[1] == 2 and v[2] == 3 and v[3] == 4) +end + +do --- too many initializers, array fails(function(x) x.ai = {1,2,3,4,5,6,7,8,9,10,11} end, x) for i=0,9 do assert(x.ai[i] == i+1) end -- but it's partially executed fails(function(x) local v = ffi.new("int[?]", 4, 1,2,3,4,5) end, x) +end - -- struct initialization +do --- struct initialization x.sn = ffi.new("nest_t") -- zero fill assert(x.sn.e.e2 == 0) x.sn = ffi.new("nest_t", 1,2) -- remainder filled with zero @@ -649,27 +704,32 @@ do --- misc assert(x.sn.a == 1 and x.sn.b == 2 and x.sn.c == 3 and x.sn.d == 4) assert(x.sn.e.e1 == 5 and x.sn.e.e2 == 6) assert(x.sn.f[0] == 7 and x.sn.f[1] == 8) - -- VLS initialization - do - local v = ffi.new("struct { int x; int a[?]; }", 4) - assert(v.x == 0) - for i=0,3 do assert(v.a[i] == 0) end - local v = ffi.new("struct { int x; int a[?]; }", 4, 9, {833}) - assert(v.x == 9) - -- NYI: fill up VLA in VLS. currently seen as indefinite length - -- for i=0,3 do assert(v.a[i] == 833) end - assert(v.a[0] == 833 and v.a[1] == 0 and v.a[2] == 0 and v.a[3] == 0) - end - -- no multi-value init beyond first level +end + +do --- VLS initialization + local v = ffi.new("struct { int x; int a[?]; }", 4) + assert(v.x == 0) + for i=0,3 do assert(v.a[i] == 0) end + local v = ffi.new("struct { int x; int a[?]; }", 4, 9, {833}) + assert(v.x == 9) + -- NYI: fill up VLA in VLS. currently seen as indefinite length + -- for i=0,3 do assert(v.a[i] == 833) end + assert(v.a[0] == 833 and v.a[1] == 0 and v.a[2] == 0 and v.a[3] == 0) +end + +do --- no multi-value init beyond first level fails(function(x) x.sn = ffi.new("nest_t", 1,2,3,4,5,6,7,8) end, x) - -- too many initializers +end + +do --- too many initializers, nested structure fails(function(x) x.sn = ffi.new("nest_t", 1,2,3,4,{5,6},{7,8}, 9) end, x) +end - -- union initialization +do --- union initialization x.ui = ffi.new("uni_t") -- zero fill assert(x.ui.a == 0 and x.ui.b == 0 and x.ui.c == 0) x.ui = ffi.new("uni_t", 255) -- initialize first field, remainder is zero @@ -678,15 +738,18 @@ do --- misc else assert(x.ui.a == -1 and x.ui.b == -256 and x.ui.c == -16777216) end - -- too many initializers +end + +do --- too many initializers, union fails(function(x) x.sn = ffi.new("uni_t", 1,2) end, x) fails(function() ffi.new("union { struct { int x; }; int y; }", 1,2) end) +end - -- table converted to array +do --- table converted to array ffi.fill(x.ai, ffi.sizeof(x.ai), 0x13) x.ai_guard = 99 x.ai = {} -- zero fill @@ -700,8 +763,9 @@ do --- misc assert(x.ai[1] == -27) for i=2,9 do assert(x.ai[i] == 0) end assert(x.ai_guard == 99) -- Check guard +end - -- table converted to struct +do --- table converted to struct ffi.fill(x.si, ffi.sizeof(x.si), 0x74) x.si_guard = 97 -- convert from array part @@ -723,8 +787,9 @@ do --- misc x.si = {b = 12, 5, 6, 7} -- hash part ignored if array part exists assert(x.si.a == 5 and x.si.b == 6 and x.si.c == 7) assert(x.si_guard == 97) -- Check guard +end - -- table converted to struct with transparent/nested structs and arrays +do --- table converted to struct with transparent/nested structs and arrays ffi.fill(x.sn, ffi.sizeof(x.sn), 0x74) x.sn = {} -- zero fill assert(x.sn.e.e2 == 0) @@ -736,8 +801,9 @@ do --- misc assert(x.sn.a == 0 and x.sn.b == 0 and x.sn.c == 10 and x.sn.d == 0) assert(x.sn.e.e1 == 11 and x.sn.e.e2 == 12) assert(x.sn.f[0] == 13 and x.sn.f[1] == 14) +end - -- table converted to union +do --- table converted to union ffi.fill(x.ui, ffi.sizeof(x.ui), 0x58) x.ui = {} -- zero fill assert(x.ui.a == 0 and x.ui.b == 0 and x.ui.c == 0) @@ -753,18 +819,18 @@ do --- misc else assert(x.ui.a == -1 and x.ui.b == -1 and x.ui.c == -65536) end +end - -- copy constructor - do - x.s.v = 1; x.s.w = 2 - local s = ffi.new("bar_t", x.s) - assert(s.v == 1 and s.w == 2) - for i=0,9 do x.ai[i] = i end - local a = ffi.new("int[10]", x.ai) - for i=0,9 do assert(a[i] == i) end - end +do --- copy constructor + x.s.v = 1; x.s.w = 2 + local s = ffi.new("bar_t", x.s) + assert(s.v == 1 and s.w == 2) + for i=0,9 do x.ai[i] = i end + local a = ffi.new("int[10]", x.ai) + for i=0,9 do assert(a[i] == i) end +end - -- assignment to function pointer +do --- assignment to function pointer x.ppf = ffi.C.strcpy end =================================================================== > > + local foo_convert_t = ffi.typeof("foo_convert_t") > > + local sz = ffi.sizeof(foo_convert_t) > > + local x = foo_convert_t() > > + local y = foo_convert_t() > > ffi.fill(x, sz, 0xff) > > ffi.fill(y, sz, 0xee) > > > > @@ -769,7 +768,7 @@ do > > x.ppf = ffi.C.strcpy > > end > > > > -do > > +do --- GC cdata __index > > collectgarbage() > > local oc = collectgarbage("count") > > local cd = ffi.new"struct { struct { int a; } x;}" > > @@ -780,7 +779,7 @@ do > > for i=1,2 do > > f(cd) > > local nc = collectgarbage("count") > > - assert(nc < oc + 200, "GC step missing for cdata __index") > Are you sure it is the lower bound threshold? For big platforms, yes. But more importantly, this is a relative threshold, so it is unreliable from platform memory usage. > > + assert(nc < oc * 3, "GC step missing for cdata __index") > > -- > > 2.43.0 > > -- Best regards, Sergey Kaplun