aboutsummaryrefslogtreecommitdiff
path: root/test/unit/eval/tv_clear_spec.lua
blob: ca37301b32163da2534636557970ac5ec0c2e90d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
local helpers = require('test.unit.helpers')(after_each)
local itp = helpers.gen_itp(it)
local eval_helpers = require('test.unit.eval.helpers')

local alloc_log_new = helpers.alloc_log_new
local cimport = helpers.cimport
local ffi = helpers.ffi
local eq = helpers.eq

local a = eval_helpers.alloc_logging_helpers
local type_key = eval_helpers.type_key
local list_type = eval_helpers.list_type
local list_items = eval_helpers.list_items
local dict_items = eval_helpers.dict_items
local lua2typvalt = eval_helpers.lua2typvalt

local lib = cimport('./src/nvim/eval/typval.h', './src/nvim/eval.h')

local alloc_log = alloc_log_new()

before_each(function()
  alloc_log:before_each()
end)

after_each(function()
  alloc_log:after_each()
end)

describe('tv_clear()', function()
  itp('successfully frees all lists in [&l [1], *l, *l]', function()
    local l_inner = {1}
    local list = {l_inner, l_inner, l_inner}
    local list_tv = ffi.gc(lua2typvalt(list), nil)
    local list_p = list_tv.vval.v_list
    local lis = list_items(list_p)
    local list_inner_p = lis[1].li_tv.vval.v_list
    local lis_inner = list_items(list_inner_p)
    alloc_log:check({
      a.list(list_p),
      a.list(list_inner_p),
      a.li(lis_inner[1]),
      a.li(lis[1]),
      a.li(lis[2]),
      a.li(lis[3]),
    })
    eq(3, list_inner_p.lv_refcount)
    lib.tv_clear(list_tv)
    alloc_log:check({
      a.freed(lis_inner[1]),
      a.freed(list_inner_p),
      a.freed(lis[1]),
      a.freed(lis[2]),
      a.freed(lis[3]),
      a.freed(list_p),
    })
  end)
  itp('successfully frees all lists in [&l [], *l, *l]', function()
    local l_inner = {[type_key]=list_type}
    local list = {l_inner, l_inner, l_inner}
    local list_tv = ffi.gc(lua2typvalt(list), nil)
    local list_p = list_tv.vval.v_list
    local lis = list_items(list_p)
    local list_inner_p = lis[1].li_tv.vval.v_list
    alloc_log:check({
      a.list(list_p),
      a.list(list_inner_p),
      a.li(lis[1]),
      a.li(lis[2]),
      a.li(lis[3]),
    })
    eq(3, list_inner_p.lv_refcount)
    lib.tv_clear(list_tv)
    alloc_log:check({
      a.freed(list_inner_p),
      a.freed(lis[1]),
      a.freed(lis[2]),
      a.freed(lis[3]),
      a.freed(list_p),
    })
  end)
  itp('successfully frees all dictionaries in [&d {}, *d]', function()
    local d_inner = {}
    local list = {d_inner, d_inner}
    local list_tv = ffi.gc(lua2typvalt(list), nil)
    local list_p = list_tv.vval.v_list
    local lis = list_items(list_p)
    local dict_inner_p = lis[1].li_tv.vval.v_dict
    alloc_log:check({
      a.list(list_p),
      a.dict(dict_inner_p),
      a.li(lis[1]),
      a.li(lis[2]),
    })
    eq(2, dict_inner_p.dv_refcount)
    lib.tv_clear(list_tv)
    alloc_log:check({
      a.freed(dict_inner_p),
      a.freed(lis[1]),
      a.freed(lis[2]),
      a.freed(list_p),
    })
  end)
  itp('successfully frees all dictionaries in [&d {a: 1}, *d]', function()
    local d_inner = {a=1}
    local list = {d_inner, d_inner}
    local list_tv = ffi.gc(lua2typvalt(list), nil)
    local list_p = list_tv.vval.v_list
    local lis = list_items(list_p)
    local dict_inner_p = lis[1].li_tv.vval.v_dict
    local dis = dict_items(dict_inner_p)
    alloc_log:check({
      a.list(list_p),
      a.dict(dict_inner_p),
      a.di(dis.a, 1),
      a.li(lis[1]),
      a.li(lis[2]),
    })
    eq(2, dict_inner_p.dv_refcount)
    lib.tv_clear(list_tv)
    alloc_log:check({
      a.freed(dis.a),
      a.freed(dict_inner_p),
      a.freed(lis[1]),
      a.freed(lis[2]),
      a.freed(list_p),
    })
  end)
end)