Merge tests into a larger file (part 1 of ∞) (#9318)
* merge actiontable tests * merge arithm tests * merge array tests * merge assign tests * merge bind tests * merge casestmt tests * merge closure tests * merge cnt seq tests * merge collections tests * merge concept issues tests * merge concept tests * fix failing tests * smaller outputs Use `doAssert` where possible. * fix wrong output * split `tcomputedgoto` * revert merging concepts * fix failing test
This commit is contained in:
parent
d2b04a8bc7
commit
7f18d7cbc1
103 changed files with 3736 additions and 3368 deletions
|
|
@ -1,275 +1,375 @@
|
|||
discard """
|
||||
cmd: "nim c --threads:on $file"
|
||||
output: '''true'''
|
||||
file: "ttables.nim"
|
||||
output: '''
|
||||
done
|
||||
And we get here
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
'''
|
||||
"""
|
||||
import hashes, sequtils, tables
|
||||
|
||||
import hashes, tables, sharedtables
|
||||
|
||||
const
|
||||
data = {
|
||||
"34": 123456, "12": 789,
|
||||
"90": 343, "0": 34404,
|
||||
"1": 344004, "2": 344774,
|
||||
"3": 342244, "4": 3412344,
|
||||
"5": 341232144, "6": 34214544,
|
||||
"7": 3434544, "8": 344544,
|
||||
"9": 34435644, "---00": 346677844,
|
||||
"10": 34484, "11": 34474, "19": 34464,
|
||||
"20": 34454, "30": 34141244, "40": 344114,
|
||||
"50": 344490, "60": 344491, "70": 344492,
|
||||
"80": 344497}
|
||||
block tableadds:
|
||||
proc main =
|
||||
var tab = newTable[string, string]()
|
||||
for i in 0..1000:
|
||||
tab.add "key", "value " & $i
|
||||
|
||||
sorteddata = {
|
||||
"---00": 346677844,
|
||||
"0": 34404,
|
||||
"1": 344004,
|
||||
"10": 34484,
|
||||
"11": 34474,
|
||||
"12": 789,
|
||||
"19": 34464,
|
||||
"2": 344774, "20": 34454,
|
||||
"3": 342244, "30": 34141244,
|
||||
"34": 123456,
|
||||
"4": 3412344, "40": 344114,
|
||||
"5": 341232144, "50": 344490,
|
||||
"6": 34214544, "60": 344491,
|
||||
"7": 3434544, "70": 344492,
|
||||
"8": 344544, "80": 344497,
|
||||
"9": 34435644,
|
||||
"90": 343}
|
||||
main()
|
||||
echo "done"
|
||||
|
||||
block tableTest1:
|
||||
var t = initTable[tuple[x, y: int], string]()
|
||||
t[(0,0)] = "00"
|
||||
t[(1,0)] = "10"
|
||||
t[(0,1)] = "01"
|
||||
t[(1,1)] = "11"
|
||||
for x in 0..1:
|
||||
for y in 0..1:
|
||||
assert t[(x,y)] == $x & $y
|
||||
assert($t ==
|
||||
"{(x: 0, y: 1): \"01\", (x: 0, y: 0): \"00\", (x: 1, y: 0): \"10\", (x: 1, y: 1): \"11\"}")
|
||||
|
||||
block tableTest2:
|
||||
var t = initTable[string, float]()
|
||||
t["test"] = 1.2345
|
||||
t["111"] = 1.000043
|
||||
t["123"] = 1.23
|
||||
t.del("111")
|
||||
block tcounttable:
|
||||
# bug #2625
|
||||
const s_len = 32
|
||||
var substr_counts: CountTable[string] = initCountTable[string]()
|
||||
var my_string = "Hello, this is sadly broken for strings over 64 characters. Note that it *does* appear to work for short strings."
|
||||
for i in 0..(my_string.len - s_len):
|
||||
let s = my_string[i..i+s_len-1]
|
||||
substr_counts[s] = 1
|
||||
# substr_counts[s] = substr_counts[s] + 1 # Also breaks, + 2 as well, etc.
|
||||
# substr_counts.inc(s) # This works
|
||||
#echo "Iteration ", i
|
||||
|
||||
t["012"] = 67.9
|
||||
t["123"] = 1.5 # test overwriting
|
||||
echo "And we get here"
|
||||
|
||||
assert t["123"] == 1.5
|
||||
try:
|
||||
echo t["111"] # deleted
|
||||
except KeyError:
|
||||
discard
|
||||
assert(not hasKey(t, "111"))
|
||||
|
||||
assert "123" in t
|
||||
assert("111" notin t)
|
||||
block thashes:
|
||||
# Test with int
|
||||
block:
|
||||
var t = initTable[int,int]()
|
||||
t[0] = 42
|
||||
t[1] = t[0] + 1
|
||||
assert(t[0] == 42)
|
||||
assert(t[1] == 43)
|
||||
let t2 = {1: 1, 2: 2}.toTable
|
||||
assert(t2[2] == 2)
|
||||
|
||||
for key, val in items(data): t[key] = val.toFloat
|
||||
for key, val in items(data): assert t[key] == val.toFloat
|
||||
# Test with char
|
||||
block:
|
||||
var t = initTable[char,int]()
|
||||
t['0'] = 42
|
||||
t['1'] = t['0'] + 1
|
||||
assert(t['0'] == 42)
|
||||
assert(t['1'] == 43)
|
||||
let t2 = {'1': 1, '2': 2}.toTable
|
||||
assert(t2['2'] == 2)
|
||||
|
||||
assert(not t.hasKeyOrPut("456", 4.0)) # test absent key
|
||||
assert t.hasKeyOrPut("012", 3.0) # test present key
|
||||
var x = t.mgetOrPut("111", 1.5) # test absent key
|
||||
x = x * 2
|
||||
assert x == 3.0
|
||||
x = t.mgetOrPut("test", 1.5) # test present key
|
||||
x = x * 2
|
||||
assert x == 2 * 1.2345
|
||||
# Test with enum
|
||||
block:
|
||||
type
|
||||
E = enum eA, eB, eC
|
||||
var t = initTable[E,int]()
|
||||
t[eA] = 42
|
||||
t[eB] = t[eA] + 1
|
||||
assert(t[eA] == 42)
|
||||
assert(t[eB] == 43)
|
||||
let t2 = {eA: 1, eB: 2}.toTable
|
||||
assert(t2[eB] == 2)
|
||||
|
||||
block orderedTableTest1:
|
||||
var t = initOrderedTable[string, int](2)
|
||||
for key, val in items(data): t[key] = val
|
||||
for key, val in items(data): assert t[key] == val
|
||||
var i = 0
|
||||
# `pairs` needs to yield in insertion order:
|
||||
for key, val in pairs(t):
|
||||
assert key == data[i][0]
|
||||
assert val == data[i][1]
|
||||
inc(i)
|
||||
# Test with range
|
||||
block:
|
||||
type
|
||||
R = range[1..10]
|
||||
var t = initTable[R,int]() # causes warning, why?
|
||||
t[1] = 42 # causes warning, why?
|
||||
t[2] = t[1] + 1
|
||||
assert(t[1] == 42)
|
||||
assert(t[2] == 43)
|
||||
let t2 = {1.R: 1, 2.R: 2}.toTable
|
||||
assert(t2[2.R] == 2)
|
||||
|
||||
for key, val in mpairs(t): val = 99
|
||||
for val in mvalues(t): assert val == 99
|
||||
# Test which combines the generics for tuples + ordinals
|
||||
block:
|
||||
type
|
||||
E = enum eA, eB, eC
|
||||
var t = initTable[(string, E, int, char), int]()
|
||||
t[("a", eA, 0, '0')] = 42
|
||||
t[("b", eB, 1, '1')] = t[("a", eA, 0, '0')] + 1
|
||||
assert(t[("a", eA, 0, '0')] == 42)
|
||||
assert(t[("b", eB, 1, '1')] == 43)
|
||||
let t2 = {("a", eA, 0, '0'): 1, ("b", eB, 1, '1'): 2}.toTable
|
||||
assert(t2[("b", eB, 1, '1')] == 2)
|
||||
|
||||
block orderedTableTest2:
|
||||
var
|
||||
s = initOrderedTable[string, int]()
|
||||
t = initOrderedTable[string, int]()
|
||||
assert s == t
|
||||
for key, val in items(data): t[key] = val
|
||||
assert s != t
|
||||
for key, val in items(sorteddata): s[key] = val
|
||||
assert s != t
|
||||
t.clear()
|
||||
assert s != t
|
||||
for key, val in items(sorteddata): t[key] = val
|
||||
assert s == t
|
||||
# Test to check if overloading is possible
|
||||
# Unfortunately, this does not seem to work for int
|
||||
# The same test with a custom hash(s: string) does
|
||||
# work though.
|
||||
block:
|
||||
proc hash(x: int): Hash {.inline.} =
|
||||
echo "overloaded hash"
|
||||
result = x
|
||||
var t = initTable[int, int]()
|
||||
t[0] = 0
|
||||
|
||||
block countTableTest1:
|
||||
var s = data.toTable
|
||||
var t = initCountTable[string]()
|
||||
# Check hashability of all integer types (issue #5429)
|
||||
block:
|
||||
let intTables = (
|
||||
newTable[int, string](),
|
||||
newTable[int8, string](),
|
||||
newTable[int16, string](),
|
||||
newTable[int32, string](),
|
||||
newTable[int64, string](),
|
||||
newTable[uint, string](),
|
||||
newTable[uint8, string](),
|
||||
newTable[uint16, string](),
|
||||
newTable[uint32, string](),
|
||||
newTable[uint64, string](),
|
||||
)
|
||||
|
||||
for k in s.keys: t.inc(k)
|
||||
for k in t.keys: assert t[k] == 1
|
||||
t.inc("90", 3)
|
||||
t.inc("12", 2)
|
||||
t.inc("34", 1)
|
||||
assert t.largest()[0] == "90"
|
||||
echo "true"
|
||||
|
||||
t.sort()
|
||||
var i = 0
|
||||
for k, v in t.pairs:
|
||||
case i
|
||||
of 0: assert k == "90" and v == 4
|
||||
of 1: assert k == "12" and v == 3
|
||||
of 2: assert k == "34" and v == 2
|
||||
else: break
|
||||
inc i
|
||||
|
||||
block countTableTest2:
|
||||
var
|
||||
s = initCountTable[int]()
|
||||
t = initCountTable[int]()
|
||||
assert s == t
|
||||
s.inc(1)
|
||||
assert s != t
|
||||
t.inc(2)
|
||||
assert s != t
|
||||
t.inc(1)
|
||||
assert s != t
|
||||
s.inc(2)
|
||||
assert s == t
|
||||
s.inc(1)
|
||||
assert s != t
|
||||
t.inc(1)
|
||||
assert s == t
|
||||
block tindexby:
|
||||
doAssert indexBy(newSeq[int](), proc(x: int):int = x) == initTable[int, int](), "empty int table"
|
||||
|
||||
block mpairsTableTest1:
|
||||
var t = initTable[string, int]()
|
||||
t["a"] = 1
|
||||
t["b"] = 2
|
||||
t["c"] = 3
|
||||
t["d"] = 4
|
||||
for k, v in t.mpairs:
|
||||
if k == "a" or k == "c":
|
||||
v = 9
|
||||
var tbl1 = initTable[int, int]()
|
||||
tbl1.add(1,1)
|
||||
tbl1.add(2,2)
|
||||
doAssert indexBy(@[1,2], proc(x: int):int = x) == tbl1, "int table"
|
||||
|
||||
for k, v in t.pairs:
|
||||
if k == "a" or k == "c":
|
||||
assert v == 9
|
||||
else:
|
||||
assert v != 1 and v != 3
|
||||
type
|
||||
TElem = object
|
||||
foo: int
|
||||
bar: string
|
||||
|
||||
block SyntaxTest:
|
||||
var x = toTable[int, string]({:})
|
||||
let
|
||||
elem1 = TElem(foo: 1, bar: "bar")
|
||||
elem2 = TElem(foo: 2, bar: "baz")
|
||||
|
||||
block zeroHashKeysTest:
|
||||
proc doZeroHashValueTest[T, K, V](t: T, nullHashKey: K, value: V) =
|
||||
let initialLen = t.len
|
||||
var testTable = t
|
||||
testTable[nullHashKey] = value
|
||||
assert testTable[nullHashKey] == value
|
||||
assert testTable.len == initialLen + 1
|
||||
testTable.del(nullHashKey)
|
||||
assert testTable.len == initialLen
|
||||
var tbl2 = initTable[string, TElem]()
|
||||
tbl2.add("bar", elem1)
|
||||
tbl2.add("baz", elem2)
|
||||
doAssert indexBy(@[elem1,elem2], proc(x: TElem): string = x.bar) == tbl2, "element table"
|
||||
|
||||
|
||||
# with empty table
|
||||
doZeroHashValueTest(toTable[int,int]({:}), 0, 42)
|
||||
doZeroHashValueTest(toTable[string,int]({:}), "", 23)
|
||||
doZeroHashValueTest(toOrderedTable[int,int]({:}), 0, 42)
|
||||
doZeroHashValueTest(toOrderedTable[string,int]({:}), "", 23)
|
||||
block tableconstr:
|
||||
# Test if the new table constructor syntax works:
|
||||
|
||||
# with non-empty table
|
||||
doZeroHashValueTest(toTable[int,int]({1:2}), 0, 42)
|
||||
doZeroHashValueTest(toTable[string,string]({"foo": "bar"}), "", "zero")
|
||||
doZeroHashValueTest(toOrderedTable[int,int]({3:4}), 0, 42)
|
||||
doZeroHashValueTest(toOrderedTable[string,string]({"egg": "sausage"}),
|
||||
"", "spam")
|
||||
|
||||
block clearTableTest:
|
||||
var t = data.toTable
|
||||
assert t.len() != 0
|
||||
t.clear()
|
||||
assert t.len() == 0
|
||||
|
||||
block clearOrderedTableTest:
|
||||
var t = data.toOrderedTable
|
||||
assert t.len() != 0
|
||||
t.clear()
|
||||
assert t.len() == 0
|
||||
|
||||
block clearCountTableTest:
|
||||
var t = initCountTable[string]()
|
||||
t.inc("90", 3)
|
||||
t.inc("12", 2)
|
||||
t.inc("34", 1)
|
||||
assert t.len() != 0
|
||||
t.clear()
|
||||
assert t.len() == 0
|
||||
|
||||
block withKeyTest:
|
||||
var t: SharedTable[int, int]
|
||||
t.init()
|
||||
t.withKey(1) do (k: int, v: var int, pairExists: var bool):
|
||||
assert(v == 0)
|
||||
pairExists = true
|
||||
v = 42
|
||||
assert(t.mget(1) == 42)
|
||||
t.withKey(1) do (k: int, v: var int, pairExists: var bool):
|
||||
assert(v == 42)
|
||||
pairExists = false
|
||||
try:
|
||||
discard t.mget(1)
|
||||
assert(false, "KeyError expected")
|
||||
except KeyError:
|
||||
discard
|
||||
t.withKey(2) do (k: int, v: var int, pairExists: var bool):
|
||||
pairExists = false
|
||||
try:
|
||||
discard t.mget(2)
|
||||
assert(false, "KeyError expected")
|
||||
except KeyError:
|
||||
template ignoreExpr(e) =
|
||||
discard
|
||||
|
||||
block takeTest:
|
||||
var t = initTable[string, int]()
|
||||
t["key"] = 123
|
||||
# test first class '..' syntactical citizen:
|
||||
ignoreExpr x <> 2..4
|
||||
# test table constructor:
|
||||
ignoreExpr({:})
|
||||
ignoreExpr({2: 3, "key": "value"})
|
||||
|
||||
var val = 0
|
||||
assert(t.take("key", val))
|
||||
assert(val == 123)
|
||||
# NEW:
|
||||
assert 56 in 50..100
|
||||
|
||||
val = -1
|
||||
assert(not t.take("key", val))
|
||||
assert(val == -1)
|
||||
|
||||
assert(not t.take("otherkey", val))
|
||||
assert(val == -1)
|
||||
|
||||
proc orderedTableSortTest() =
|
||||
var t = initOrderedTable[string, int](2)
|
||||
for key, val in items(data): t[key] = val
|
||||
for key, val in items(data): assert t[key] == val
|
||||
t.sort(proc (x, y: tuple[key: string, val: int]): int = cmp(x.key, y.key))
|
||||
var i = 0
|
||||
# `pairs` needs to yield in sorted order:
|
||||
for key, val in pairs(t):
|
||||
doAssert key == sorteddata[i][0]
|
||||
doAssert val == sorteddata[i][1]
|
||||
inc(i)
|
||||
|
||||
# check that lookup still works:
|
||||
for key, val in pairs(t):
|
||||
doAssert val == t[key]
|
||||
# check that insert still works:
|
||||
t["newKeyHere"] = 80
|
||||
assert 56 in ..60
|
||||
|
||||
|
||||
orderedTableSortTest()
|
||||
echo "true"
|
||||
block ttables2:
|
||||
proc TestHashIntInt() =
|
||||
var tab = initTable[int,int]()
|
||||
for i in 1..1_000_000:
|
||||
tab[i] = i
|
||||
for i in 1..1_000_000:
|
||||
var x = tab[i]
|
||||
if x != i : echo "not found ", i
|
||||
|
||||
proc run1() = # occupied Memory stays constant, but
|
||||
for i in 1 .. 50: # aborts at run: 44 on win32 with 3.2GB with out of memory
|
||||
TestHashIntInt()
|
||||
|
||||
# bug #2107
|
||||
|
||||
var delTab = initTable[int,int](4)
|
||||
|
||||
for i in 1..4:
|
||||
delTab[i] = i
|
||||
delTab.del(i)
|
||||
delTab[5] = 5
|
||||
|
||||
|
||||
run1()
|
||||
echo "true"
|
||||
|
||||
|
||||
block tablesref:
|
||||
const
|
||||
data = {
|
||||
"34": 123456, "12": 789,
|
||||
"90": 343, "0": 34404,
|
||||
"1": 344004, "2": 344774,
|
||||
"3": 342244, "4": 3412344,
|
||||
"5": 341232144, "6": 34214544,
|
||||
"7": 3434544, "8": 344544,
|
||||
"9": 34435644, "---00": 346677844,
|
||||
"10": 34484, "11": 34474, "19": 34464,
|
||||
"20": 34454, "30": 34141244, "40": 344114,
|
||||
"50": 344490, "60": 344491, "70": 344492,
|
||||
"80": 344497}
|
||||
|
||||
sorteddata = {
|
||||
"---00": 346677844,
|
||||
"0": 34404,
|
||||
"1": 344004,
|
||||
"10": 34484,
|
||||
"11": 34474,
|
||||
"12": 789,
|
||||
"19": 34464,
|
||||
"2": 344774, "20": 34454,
|
||||
"3": 342244, "30": 34141244,
|
||||
"34": 123456,
|
||||
"4": 3412344, "40": 344114,
|
||||
"5": 341232144, "50": 344490,
|
||||
"6": 34214544, "60": 344491,
|
||||
"7": 3434544, "70": 344492,
|
||||
"8": 344544, "80": 344497,
|
||||
"9": 34435644,
|
||||
"90": 343}
|
||||
|
||||
block tableTest1:
|
||||
var t = newTable[tuple[x, y: int], string]()
|
||||
t[(0,0)] = "00"
|
||||
t[(1,0)] = "10"
|
||||
t[(0,1)] = "01"
|
||||
t[(1,1)] = "11"
|
||||
for x in 0..1:
|
||||
for y in 0..1:
|
||||
assert t[(x,y)] == $x & $y
|
||||
assert($t ==
|
||||
"{(x: 0, y: 1): \"01\", (x: 0, y: 0): \"00\", (x: 1, y: 0): \"10\", (x: 1, y: 1): \"11\"}")
|
||||
|
||||
block tableTest2:
|
||||
var t = newTable[string, float]()
|
||||
t["test"] = 1.2345
|
||||
t["111"] = 1.000043
|
||||
t["123"] = 1.23
|
||||
t.del("111")
|
||||
|
||||
t["012"] = 67.9
|
||||
t["123"] = 1.5 # test overwriting
|
||||
|
||||
assert t["123"] == 1.5
|
||||
try:
|
||||
echo t["111"] # deleted
|
||||
except KeyError:
|
||||
discard
|
||||
assert(not hasKey(t, "111"))
|
||||
assert "111" notin t
|
||||
|
||||
for key, val in items(data): t[key] = val.toFloat
|
||||
for key, val in items(data): assert t[key] == val.toFloat
|
||||
|
||||
|
||||
block orderedTableTest1:
|
||||
var t = newOrderedTable[string, int](2)
|
||||
for key, val in items(data): t[key] = val
|
||||
for key, val in items(data): assert t[key] == val
|
||||
var i = 0
|
||||
# `pairs` needs to yield in insertion order:
|
||||
for key, val in pairs(t):
|
||||
assert key == data[i][0]
|
||||
assert val == data[i][1]
|
||||
inc(i)
|
||||
|
||||
for key, val in mpairs(t): val = 99
|
||||
for val in mvalues(t): assert val == 99
|
||||
|
||||
block countTableTest1:
|
||||
var s = data.toTable
|
||||
var t = newCountTable[string]()
|
||||
for k in s.keys: t.inc(k)
|
||||
for k in t.keys: assert t[k] == 1
|
||||
t.inc("90", 3)
|
||||
t.inc("12", 2)
|
||||
t.inc("34", 1)
|
||||
assert t.largest()[0] == "90"
|
||||
|
||||
t.sort()
|
||||
var i = 0
|
||||
for k, v in t.pairs:
|
||||
case i
|
||||
of 0: assert k == "90" and v == 4
|
||||
of 1: assert k == "12" and v == 3
|
||||
of 2: assert k == "34" and v == 2
|
||||
else: break
|
||||
inc i
|
||||
|
||||
block SyntaxTest:
|
||||
var x = newTable[int, string]({:})
|
||||
discard x
|
||||
|
||||
block nilTest:
|
||||
var i, j: TableRef[int, int] = nil
|
||||
assert i == j
|
||||
j = newTable[int, int]()
|
||||
assert i != j
|
||||
assert j != i
|
||||
i = newTable[int, int]()
|
||||
assert i == j
|
||||
|
||||
proc orderedTableSortTest() =
|
||||
var t = newOrderedTable[string, int](2)
|
||||
for key, val in items(data): t[key] = val
|
||||
for key, val in items(data): assert t[key] == val
|
||||
t.sort(proc (x, y: tuple[key: string, val: int]): int = cmp(x.key, y.key))
|
||||
var i = 0
|
||||
# `pairs` needs to yield in sorted order:
|
||||
for key, val in pairs(t):
|
||||
doAssert key == sorteddata[i][0]
|
||||
doAssert val == sorteddata[i][1]
|
||||
inc(i)
|
||||
|
||||
# check that lookup still works:
|
||||
for key, val in pairs(t):
|
||||
doAssert val == t[key]
|
||||
# check that insert still works:
|
||||
t["newKeyHere"] = 80
|
||||
|
||||
block anonZipTest:
|
||||
let keys = @['a','b','c']
|
||||
let values = @[1, 2, 3]
|
||||
doAssert "{'a': 1, 'b': 2, 'c': 3}" == $ toTable zip(keys, values)
|
||||
|
||||
block clearTableTest:
|
||||
var t = newTable[string, float]()
|
||||
t["test"] = 1.2345
|
||||
t["111"] = 1.000043
|
||||
t["123"] = 1.23
|
||||
assert t.len() != 0
|
||||
t.clear()
|
||||
assert t.len() == 0
|
||||
|
||||
block clearOrderedTableTest:
|
||||
var t = newOrderedTable[string, int](2)
|
||||
for key, val in items(data): t[key] = val
|
||||
assert t.len() != 0
|
||||
t.clear()
|
||||
assert t.len() == 0
|
||||
|
||||
block clearCountTableTest:
|
||||
var t = newCountTable[string]()
|
||||
t.inc("90", 3)
|
||||
t.inc("12", 2)
|
||||
t.inc("34", 1)
|
||||
assert t.len() != 0
|
||||
t.clear()
|
||||
assert t.len() == 0
|
||||
|
||||
orderedTableSortTest()
|
||||
echo "true"
|
||||
|
||||
|
||||
block tablesref2:
|
||||
proc TestHashIntInt() =
|
||||
var tab = newTable[int,int]()
|
||||
for i in 1..1_000_000:
|
||||
tab[i] = i
|
||||
for i in 1..1_000_000:
|
||||
var x = tab[i]
|
||||
if x != i : echo "not found ", i
|
||||
|
||||
proc run1() = # occupied Memory stays constant, but
|
||||
for i in 1 .. 50: # aborts at run: 44 on win32 with 3.2GB with out of memory
|
||||
TestHashIntInt()
|
||||
|
||||
run1()
|
||||
echo "true"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue