123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257 | # This file contains auto-generated tests from the examples in api/*.yaml
test "Bool.parse"
assert Bool.parse("yes") == yes
assert Bool.parse("no") == no
assert Bool.parse("???") == none
assert Bool.parse("yesJUNK") == none
remainder : Text
assert Bool.parse("yesJUNK", &remainder) == yes
assert remainder == "JUNK"
test "Byte.get_bit"
assert not Byte(6).get_bit(1)
assert Byte(6).get_bit(2)
assert Byte(6).get_bit(3)
assert not Byte(6).get_bit(4)
test "Byte.hex"
assert Byte(18).hex(prefix=yes) == "0x12"
test "Byte.is_between"
assert Byte(7).is_between(1, 10)
assert Byte(7).is_between(10, 1)
assert not Byte(7).is_between(100, 200)
assert Byte(7).is_between(1, 7)
test "Byte.parse"
assert Byte.parse("5") == Byte(5)
assert Byte.parse("asdf") == none
assert Byte.parse("123xyz") == none
remainder : Text
assert Byte.parse("123xyz", remainder=&remainder) == Byte(123)
assert remainder == "xyz"
test "Byte.to"
iter := Byte(2).to(4)
assert iter() == Byte(2)
assert iter() == Byte(3)
assert iter() == Byte(4)
assert iter() == none
assert [x for x in Byte(2).to(5)] == [Byte(2), Byte(3), Byte(4), Byte(5)]
assert [x for x in Byte(5).to(2)] == [Byte(5), Byte(4), Byte(3), Byte(2)]
assert [x for x in Byte(2).to(5, step=2)] == [Byte(2), Byte(4)]
test "CString.as_text"
assert CString("Hello").as_text() == "Hello"
assert Text(CString("Hello"))! == "Hello"
test "CString.bytes"
assert CString("Hi").bytes() == [72, 105]
test "CString.join"
assert CString(",").join([CString("a"), CString("b")]) == CString("a,b")
test "Float64.abs"
assert Float64(-3.5).abs() == 3.5
test "Float64.acos"
assert Float64(0.0).acos().near(1.5707963267948966)
test "Float64.acosh"
assert Float64(1.0).acosh() == 0
test "Float64.asin"
assert Float64(0.5).asin().near(0.5235987755982989)
test "Float64.asinh"
assert Float64(0.0).asinh() == 0
test "Float64.atan"
assert Float64(1.0).atan().near(0.7853981633974483)
test "Float64.atan2"
assert Float64.atan2(1, 1).near(0.7853981633974483)
test "Float64.atanh"
assert Float64(0.5).atanh().near(0.5493061443340549)
test "Float64.cbrt"
assert Float64(27.0).cbrt() == 3
test "Float64.ceil"
assert Float64(3.2).ceil() == 4
test "Float64.clamped"
assert Float64(2.5).clamped(5.5, 10.5) == 5.5
test "Float64.copysign"
assert Float64(3.0).copysign(-1) == -3
test "Float64.cos"
assert Float64(0.0).cos() == 1
test "Float64.cosh"
assert Float64(0.0).cosh() == 1
test "Float64.erf"
assert Float64(0.0).erf() == 0
test "Float64.erfc"
assert Float64(0.0).erfc() == 1
test "Float64.exp"
assert Float64(1.0).exp().near(2.718281828459045)
test "Float64.exp2"
assert Float64(3.0).exp2() == 8
test "Float64.expm1"
assert Float64(1.0).expm1().near(1.7182818284590453)
test "Float64.fdim"
assert Float64(5.0).fdim(3) == 2
test "Float64.floor"
assert Float64(3.7).floor() == 3
test "Float64.hypot"
assert Float64.hypot(3, 4) == 5
test "Float64.is_between"
assert Float64(7.5).is_between(1, 10)
assert Float64(7.5).is_between(10, 1)
assert not Float64(7.5).is_between(100, 200)
assert Float64(7.5).is_between(1, 7.5)
test "Float64.isfinite"
assert Float64(1.0).isfinite()
assert not Float64.INF.isfinite()
test "Float64.isinf"
assert Float64.INF.isinf()
assert not Float64(1.0).isinf()
test "Float64.j0"
assert Float64(0.0).j0() == 1
test "Float64.j1"
assert Float64(0.0).j1() == 0
test "Float64.log"
assert Float64.E.log() == 1
test "Float64.log10"
assert Float64(100.0).log10() == 2
test "Float64.log1p"
assert Float64(1.0).log1p().near(0.6931471805599453)
test "Float64.log2"
assert Float64(8.0).log2() == 3
test "Float64.logb"
assert Float64(8.0).logb() == 3
test "Float64.mix"
assert Float64(0.5).mix(10, 20) == 15
assert Float64(0.25).mix(10, 20) == 12.5
test "Float64.near"
assert Float64(1.0).near(1.000000001)
assert Float64(100.0).near(110, ratio=0.1)
assert Float64(5.0).near(5.1, min_epsilon=0.1)
test "Float64.nextafter"
assert Float64(1.0).nextafter(1.1) == 1.0000000000000002
test "Float64.parse"
assert Float64.parse("3.14") == 3.14
assert Float64.parse("1e3") == 1000
assert Float64.parse("1.5junk") == none
remainder : Text
assert Float64.parse("1.5junk", &remainder) == 1.5
assert remainder == "junk"
test "Float64.percent"
assert Float64(0.5).percent() == "50%"
assert (Float64(1.) / Float64(3.)).percent(2) == "34%"
assert (Float64(1.) / Float64(3.)).percent(precision=0.0001) == "33.3333%"
assert (Float64(1.) / Float64(3.)).percent(precision=10.) == "30%"
test "Float64.rint"
assert Float64(3.5).rint() == 4
assert Float64(2.5).rint() == 2
test "Float64.round"
assert Float64(2.3).round() == 2
assert Float64(2.7).round() == 3
test "Float64.significand"
assert Float64(1234.567).significand() == 1.2056318359375
test "Float64.sin"
assert Float64(0.0).sin() == 0
test "Float64.sinh"
assert Float64(0.0).sinh() == 0
test "Float64.sqrt"
assert Float64(16.0).sqrt() == 4
test "Float64.tan"
assert Float64(0.0).tan() == 0
test "Float64.tanh"
assert Float64(0.0).tanh() == 0
test "Float64.tgamma"
assert Float64(1.0).tgamma() == 1
test "Float64.trunc"
assert Float64(3.7).trunc() == 3
assert Float64(-3.7).trunc() == -3
test "Float64.with_precision"
assert Float64(0.1234567).with_precision(0.01) == 0.12
assert Float64(123456.).with_precision(100) == 123500
assert Float64(1234567.).with_precision(5) == 1234565
test "Float64.y0"
assert Float64(1.0).y0().near(0.08825696421567698)
test "Float64.y1"
assert Float64(1.0).y1().near(-0.7812128213002887)
test "Int.abs"
assert (-10).abs() == 10
test "Int.choose"
assert 4.choose(2) == 6
test "Int.clamped"
assert 2.clamped(5, 10) == 5
test "Int.factorial"
assert 10.factorial() == 3628800
test "Int.get_bit"
assert not 6.get_bit(1)
assert 6.get_bit(2)
assert 6.get_bit(3)
assert not 6.get_bit(4)
test "Int.hex"
assert 255.hex(digits=4, uppercase=yes, prefix=yes) == "0x00FF"
test "Int.is_between"
assert 7.is_between(1, 10)
assert 7.is_between(10, 1)
assert not 7.is_between(100, 200)
assert 7.is_between(1, 7)
test "Int.is_prime"
assert 7.is_prime()
assert not 6.is_prime()
test "Int.next_prime"
assert 11.next_prime() == 13
test "Int.octal"
assert 64.octal(digits=4, prefix=yes) == "0o0100"
test "Int.onward"
nums : &[Int] = &[]
for i in 5.onward()
nums.insert(i)
break if i == 10
assert nums[] == [5, 6, 7, 8, 9, 10]
test "Int.parse"
assert Int.parse("123") == 123
assert Int.parse("0xFF") == 255
assert Int.parse("123xyz") == none
remainder : Text
assert Int.parse("123xyz", remainder=&remainder) == 123
assert remainder == "xyz"
# Can't parse:
assert Int.parse("asdf") == none
# Outside valid range:
assert Int8.parse("9999999") == none
# Explicitly specifying base:
assert Int.parse("10", base=16) == 16
test "Int.sqrt"
assert 16.sqrt() == 4
assert 17.sqrt() == 4
test "Int.to"
iter := 2.to(5)
assert iter() == 2
assert iter() == 3
assert iter() == 4
assert iter() == 5
assert iter() == none
assert [x for x in 2.to(5)] == [2, 3, 4, 5]
assert [x for x in 5.to(2)] == [5, 4, 3, 2]
assert [x for x in 2.to(5, step=2)] == [2, 4]
test "List.binary_search"
# Find an item:
assert [10, 20, 30, 40].binary_search(func(x:Int) x == 30) == 3
# No such item:
assert [10, 20, 30, 40].binary_search(func(x:Int) x == 25) == none
# Find an insertion point (where an item would go to preserve sort order):
assert [10, 20, 30, 40].binary_search(func(x:Int) x >= 25) == 3
test "List.by"
assert [1, 2, 3, 4, 5, 6].by(2) == [1, 3, 5]
test "List.clear"
list := &[10, 20]
list.clear()
assert list[] == []
test "List.counts"
assert [10, 20, 30, 30, 30].counts() == {10:1, 20:1, 30:3}
test "List.find"
assert [10, 20, 30, 40, 50].find(20) == 2
assert [10, 20, 30, 40, 50].find(9999) == none
test "List.from"
assert [10, 20, 30, 40, 50].from(3) == [30, 40, 50]
test "List.has"
assert [10, 20, 30].has(20)
test "List.heap_pop"
my_heap := &[30, 10, 20]
my_heap.heapify()
assert my_heap.heap_pop() == 10
test "List.heap_push"
my_heap : &[Int]
my_heap.heap_push(10)
assert my_heap.heap_pop() == 10
test "List.heapify"
my_heap := &[30, 10, 20]
my_heap.heapify()
test "List.insert"
list := &[10, 20]
list.insert(30)
assert list == [10, 20, 30]
list.insert(999, at=2)
assert list == [10, 999, 20, 30]
test "List.insert_all"
list := &[10, 20]
list.insert_all([30, 40])
assert list == [10, 20, 30, 40]
list.insert_all([99, 100], at=2)
assert list == [10, 99, 100, 20, 30, 40]
test "List.pairs"
assert ["$a$b" for a, b in [1, 2, 3].pairs()] == ["12", "13", "23"]
test "List.pop"
list := &[10, 20, 30, 40]
assert list.pop() == 40
assert list[] == [10, 20, 30]
assert list.pop(index=2) == 20
assert list[] == [10, 30]
test "List.random"
nums := [10, 20, 30]
pick := nums.random()!
assert nums.has(pick)
empty : [Int]
assert empty.random() == none
test "List.remove_at"
list := &[10, 20, 30, 40, 50]
list.remove_at(2)
assert list == [10, 30, 40, 50]
list.remove_at(2, count=2)
assert list == [10, 50]
test "List.remove_item"
list := &[10, 20, 10, 20, 30]
list.remove_item(10)
assert list == [20, 20, 30]
list.remove_item(20, max_count=1)
assert list == [20, 30]
test "List.reversed"
assert [10, 20, 30].reversed() == [30, 20, 10]
test "List.sample"
_ := [10, 20, 30].sample(2, weights=[90%, 5%, 5%]) # E.g. [10, 10]
test "List.shuffle"
nums := &[10, 20, 30, 40]
nums.shuffle()
# E.g. [20, 40, 10, 30]
test "List.shuffled"
nums := [10, 20, 30, 40]
_ := nums.shuffled()
# E.g. [20, 40, 10, 30]
test "List.slice"
assert [10, 20, 30, 40, 50].slice(2, 4) == [20, 30, 40]
assert [10, 20, 30, 40, 50].slice(-3, -2) == [30, 40]
test "List.sort"
list := &[40, 10, -30, 20]
list.sort()
assert list == [-30, 10, 20, 40]
list.sort(func(a,b:Int) a.abs() <> b.abs())
assert list == [10, 20, -30, 40]
test "List.sorted"
assert [40, 10, -30, 20].sorted() == [-30, 10, 20, 40]
assert [40, 10, -30, 20].sorted(
func(a,b:Int) a.abs() <> b.abs()
) == [10, 20, -30, 40]
test "List.swap"
list := &[10, 20, 30]
list.swap(1, 3)
assert list == [30, 20, 10]
list.swap(2, -1)
assert list == [30, 10, 20]
test "List.to"
assert [10, 20, 30, 40, 50].to(3) == [10, 20, 30]
assert [10, 20, 30, 40, 50].to(-2) == [10, 20, 30, 40]
test "List.unique"
assert [10, 20, 10, 10, 30].unique() == {10, 20, 30}
test "List.where"
assert ["BC", "ABC", "CD"].where(func(t:Text) t.starts_with("A")) == 2
assert ["BC", "ABC", "CD"].where(func(t:Text) t.starts_with("X")) == none
test "Num.PI"
assert Num.PI.sin() == 0
assert Num.PI.digits(10) == "3.1415926535…"
test "Num.TAU"
assert Num.TAU == 2 * Num.PI
test "Num.abs"
assert (-3.5).abs() == 3.5
test "Num.acos"
assert (1.).acos()! == 0
assert (2.).acos() == none
test "Num.asin"
assert (0.).asin()! == 0
assert (2.).asin() == none
test "Num.atan"
assert (0.).atan() == 0
assert (1.).atan() == Num.PI / 4
test "Num.atan2"
assert (1.).atan2(1)! == Num.PI / 4
assert (0.).atan2(0) == none
test "Num.ceil"
assert (4.2).ceil() == 5
assert (-4.2).ceil() == -4
test "Num.clamped"
assert (1.5).clamped(0, 1) == 1
assert (0.5).clamped(0, 1) == 0.5
test "Num.cos"
assert (0.).cos() == 1
assert Num.PI.cos() == -1
test "Num.cosh"
assert (0.).cosh() == 1
test "Num.digits"
assert (1/3).digits(10) == "0.3333333333…"
assert Num.PI.digits(10) == "3.1415926535…"
assert (2/3).digits(10, ellipsis="") == "0.6666666666"
assert (0.25).digits(10) == "0.25"
test "Num.exp"
assert (0.).exp() == 1
test "Num.floor"
assert (4.8).floor() == 4
assert (-4.2).floor() == -5
test "Num.gcd"
assert (12.).gcd(18)! == 6
assert (1./2.).gcd(1./3.)! == 1./6.
test "Num.inverse"
assert (4.).inverse()! == 0.25
assert (0.).inverse() == none
test "Num.is_between"
assert (0.5).is_between(0, 1)
assert not (1.5).is_between(0, 1)
test "Num.is_exact"
assert (0.25).is_exact(10)
assert not (1./3.).is_exact(10)
test "Num.is_integer"
assert (4.).is_integer()
assert not (4.5).is_integer()
test "Num.is_rational"
assert (1./3.).is_rational()
assert not (2.).sqrt()!.is_rational()
test "Num.lcm"
assert (4.).lcm(6)! == 12
test "Num.log"
assert (1.).log()! == 0
assert (0.).log() == none
test "Num.log10"
assert (100.).log10()! == 2
test "Num.log2"
assert (8.).log2()! == 3
assert (1./4.).log2()! == -2
test "Num.max"
assert (0.3).max(0.5) == 0.5
test "Num.min"
assert (0.3).min(0.5) == 0.3
test "Num.mix"
assert (0.25).mix(10, 20) == 12.5
assert (1./3.).mix(0, 1) == 1./3.
test "Num.parse"
assert Num.parse("0.1")! == 0.1
assert Num.parse("22/7")! == 22./7.
assert Num.parse("nope") == none
test "Num.percent"
assert (0.5).percent() == "50%"
assert (1./3.).percent() == "33%"
assert (1./3.).percent(0.01%) == "33.33%"
test "Num.round"
assert (4.6).round() == 5
assert (2.5).round() == 2
assert (3.14159).round(0.01) == 3.14
assert (0.13).round(0.05) == 0.15
assert (0.5).round(1/3) == 2/3
assert (1234567.).round(1000) == 1235000
test "Num.sin"
assert (0.).sin() == 0
assert Num.PI.sin() == 0
test "Num.sinh"
assert (0.).sinh() == 0
test "Num.sqrt"
assert (16.).sqrt()! == 4
assert (2.).sqrt()! * (2.).sqrt()! == 2
assert (-1.).sqrt() == none
test "Num.symbolic"
assert (1./3.).symbolic() == "1/3"
assert (2.).sqrt()!.symbolic() == "sqrt(2)"
assert Num.PI.symbolic() == "pi"
test "Num.tan"
assert (0.).tan()! == 0
test "Num.tanh"
assert (0.).tanh() == 0
test "Num.tex"
assert (1./3.).tex() == "\\frac{1}{3}"
assert (2.).sqrt()!.tex() == "\\sqrt{2}"
test "Num.trunc"
assert (4.8).trunc() == 4
assert (-4.8).trunc() == -4
test "Path.accessed"
if no
assert (./file.txt).accessed() == Int64(1704221100)
assert (./not-a-file).accessed() == none
test "Path.append"
if no
(./log.txt).append("extra line\n")!
test "Path.append_bytes"
if no
(./log.txt).append_bytes([104, 105])!
test "Path.base_name"
if no
assert (./path/to/file.txt).base_name() == "file.txt"
test "Path.by_line"
if no
# Safely handle file not being readable:
if lines := (./file.txt).by_line()
for line in lines
say(line.upper())
else
say("Couldn't read file!")
# Assume the file is readable and error if that's not the case:
for line in (/dev/stdin).by_line()!
say(line.upper())
test "Path.byte_writer"
if no
write := (./file.txt).byte_writer()
write("Hello\n".utf8())!
write("world\n".utf8(), close=yes)!
test "Path.bytes"
if no
assert (/foo/bar).bytes() == [47, 102, 111, 111, 47, 98, 97, 114]
test "Path.can_execute"
if no
assert (/bin/sh).can_execute()
assert not (/usr/include/stdlib.h).can_execute()
assert not (/non/existant/file).can_execute()
test "Path.can_read"
if no
assert (/usr/include/stdlib.h).can_read()
assert not (/etc/shadow).can_read()
assert not (/non/existant/file).can_read()
test "Path.can_write"
if no
assert (/tmp).can_write()
assert not (/etc/passwd).can_write()
assert not (/non/existant/file).can_write()
test "Path.changed"
if no
assert (./file.txt).changed() == Int64(1704221100)
assert (./not-a-file).changed() == none
test "Path.child"
if no
assert (./directory).child("file.txt") == (./directory/file.txt)
test "Path.children"
if no
assert (./directory).children(include_hidden=yes)!.sorted() == [(./directory/.git), (./directory/foo.txt)]
# A directory that can't be read gives `none`, not an empty list:
assert (./not-a-directory).children() == none
test "Path.components"
if no
assert (./foo/baz.txt).components() == [".", "foo", "baz.txt"]
assert (/absolute/path/).components() == ["/", "absolute", "path"]
test "Path.concatenated_with"
if no
assert (/foo/bar).concatenated_with((./baz)) == (/foo/bar/baz)
assert ((/foo/bar) ++ (./baz/../qux)) == (/foo/bar/qux)
test "Path.copy_to"
if no
(./file.txt).copy_to(/tmp/copy.txt)!
test "Path.create_directory"
if no
(./new_directory).create_directory()!
test "Path.current_dir"
if no
assert Path.current_dir() == (/home/user/tomo)
test "Path.each_child"
if no
# Safely handle the directory not being readable:
if children := (/dir).each_child()
for child in children
say("Child: $child")
else
say("Couldn't read the directory!")
# Assume the directory is readable and error if that's not the case:
for child in (/dir).each_child()!
say("Child: $child")
test "Path.exists"
if no
assert (/).exists()
test "Path.expand_home"
if no
# Assume current user is 'user'
assert (~/foo).expand_home() == (/home/user/foo)
# No change
assert (/foo).expand_home() == (/foo)
test "Path.extension"
if no
assert (./file.tar.gz).extension() == "tar.gz"
assert (./file.tar.gz).extension(full=no) == "gz"
# No "." in the name means no extension:
assert (/foo).extension() == none
assert (./.git).extension() == none
assert (./foo.).extension() == none
test "Path.files"
if no
assert (./directory).files(include_hidden=yes)!.sorted() == [(./directory/file1.txt), (./directory/file2.txt)]
test "Path.glob"
if no
# A directory containing: foo.txt, baz.txt, qux.jpg, .hidden, sub/deep.txt
assert (./dir).glob("*.txt")! == [(./dir/baz.txt), (./dir/foo.txt)]
assert (./dir).glob(".*")! == [(./dir/.hidden)]
assert (./dir).glob("sub/*.txt")! == [(./dir/sub/deep.txt)]
# "**" is zero or more components:
assert (./dir).glob("**/*.txt")! == [(./dir/baz.txt), (./dir/foo.txt), (./dir/sub/deep.txt)]
# A pattern matching nothing is an empty list:
assert (./dir).glob("*.xxx")! == []
# A directory that can't be read is none:
assert (./not-a-directory).glob("*") == none
test "Path.group"
if no
assert (/bin).group() == "root"
assert (/non/existent/file).group() == none
test "Path.has_extension"
if no
assert (/foo.txt).has_extension("txt")
assert (/foo.txt).has_extension(".txt")
assert (/foo.tar.gz).has_extension("gz")
assert not (/foo.tar.gz).has_extension("zip")
# Asking for an empty extension is the same question as `.extension()`
# being `none`, for any name that is valid UTF-8:
assert (/foo).has_extension("")
assert (/).has_extension("")
test "Path.is_directory"
if no
assert (./directory/).is_directory()
assert not (./file.txt).is_directory()
test "Path.is_file"
if no
assert (./file.txt).is_file()
assert not (./directory/).is_file()
test "Path.is_pipe"
if no
assert (./my-fifo).is_pipe()
assert not (./file.txt).is_pipe()
test "Path.is_socket"
if no
assert (./socket).is_socket()
test "Path.is_symlink"
if no
assert (./link).is_symlink()
test "Path.lines"
if no
lines := (./file.txt).lines()!
test "Path.matches_glob"
if no
# A bare pattern asks about the file's name, whatever form the path is in:
assert (./file.txt).matches_glob("*.txt")
assert (/tmp/dir/file.txt).matches_glob("*.txt")
assert not (./file.txt).matches_glob("*.jpg")
# More components match a longer suffix:
assert (./src/file.c).matches_glob("src/*.[ch]")
assert (./src/file.c).matches_glob("./src/*.[ch]")
# A leading "/" anchors the pattern to the whole path:
assert (/tmp/dir/file.txt).matches_glob("/tmp/dir/*.txt")
assert not (/other/dir/file.txt).matches_glob("/tmp/dir/*.txt")
# "**" is zero or more components:
assert (./a/b/c/file.txt).matches_glob("**/*.txt")
assert (./file.txt).matches_glob("**/*.txt")
# "*" does not match a leading "." or cross a "/":
assert not (./dir/.hidden).matches_glob("*")
assert (./dir/.hidden).matches_glob(".*")
test "Path.modified"
if no
assert (./file.txt).modified() == Int64(1704221100)
assert (./not-a-file).modified() == none
test "Path.move"
if no
(./file.txt).move(/tmp/renamed.txt)!
test "Path.owner"
if no
assert (/bin).owner() == "root"
assert (/non/existent/file).owner() == none
test "Path.parent"
if no
assert (./path/to/file.txt).parent() == (./path/to)
test "Path.read"
if no
assert (./hello.txt).read() == "Hello"
assert (./nosuchfile.xxx).read() == none
test "Path.read_bytes"
if no
assert (./hello.txt).read_bytes()! == [72, 101, 108, 108, 111]
assert (./nosuchfile.xxx).read_bytes() == none
test "Path.relative_to"
if no
# A path relative to itself is the current directory:
assert (/tmp).relative_to((/tmp)) == (.)
assert "$((./path/to/file.txt).relative_to((./path)))" == "to/file.txt"
assert "$((/tmp/foo).relative_to((/tmp)))" == "foo"
assert (/a/b/c).relative_to((/a/x)) == (../b/c)
test "Path.remove"
if no
(./file.txt).remove()!
test "Path.resolved"
if no
# Assume the current directory is /home/user
assert (~/foo).resolved() == (/home/user/foo)
assert (./foo).resolved() == (/home/user/foo)
assert (./path/to/file.txt).resolved(relative_to=(/foo)) == (/foo/path/to/file.txt)
test "Path.set_owner"
if no
(./file.txt).set_owner(owner="root", group="wheel")!
test "Path.sibling"
if no
assert (/foo/baz).sibling("doop") == (/foo/doop)
assert (/).sibling("doop") == none
test "Path.subdirectories"
if no
assert (./directory).subdirectories()!.sorted() == [(./directory/subdir1), (./directory/subdir2)]
assert (./directory).subdirectories(include_hidden=yes)!.sorted() == [(./directory/.git), (./directory/subdir1), (./directory/subdir2)]
test "Path.unique_directory"
if no
created := (/tmp/my-dir.XXXXXX).unique_directory()!
assert created.is_directory()
created.remove()!
test "Path.walk"
if no
for p in (/tmp).walk()!
say("File or dir: $p")
# The path itself is always included:
assert [p for p in (./file.txt).walk()!] == [(./file.txt)]
# A path that isn't there has nothing to walk:
assert (./not-a-path).walk() == none
test "Path.with_extension"
if no
assert (./file.tar.gz).with_extension("zip") == (./file.zip)
assert (./file.tar.gz).with_extension(".zip") == (./file.zip)
assert (./file.tar.gz).with_extension("") == (./file)
assert (./file.tar.gz).with_extension("zip", replace=no) == (./file.tar.gz.zip)
assert (./file).with_extension("txt") == (./file.txt)
test "Path.write"
if no
(./file.txt).write("Hello, world!")!
test "Path.write_bytes"
if no
(./file.txt).write_bytes([104, 105])!
test "Path.write_unique"
if no
# The created path has the XXXXXX replaced by random characters,
# e.g. (./file-27QHtq.txt):
created := (./file-XXXXXX.txt).write_unique("Hello, world!")!
assert created.read()! == "Hello, world!"
created.remove()!
test "Path.write_unique_bytes"
if no
# The created path has the XXXXXX replaced by random characters,
# e.g. (./file-27QHtq.txt):
created := (./file-XXXXXX.txt).write_unique_bytes([1, 2, 3])!
assert created.read_bytes()! == [1, 2, 3]
created.remove()!
test "Path.writer"
if no
write := (./file.txt).writer()
write("Hello\n")!
write("world\n", close=yes)!
test "Table.clear"
t := &{"A":1}
t.clear()
assert t[] == {}
test "Table.difference"
t1 := {"A": 1, "B": 2, "C": 3}
t2 := {"B": 2, "C":30, "D": 40}
assert t1.difference(t2) == {"A": 1, "D": 40}
test "Table.entries"
t := {"A": 1, "B": 2}
assert ["$k=$v" for k, v in t.entries()] == ["A=1", "B=2"]
test "Table.get"
t := {"A": 1, "B": 2}
assert t.get("A") == 1
assert t.get("????") == none
assert t.get("A")! == 1
assert t.get("????") or 0 == 0
test "Table.get_or_set"
t := &{"A": @[1, 2, 3]; default=@[]}
t.get_or_set("A").insert(4)
t.get_or_set("B").insert(99)
assert t["A"][] == [1, 2, 3, 4]
assert t["B"][] == [99]
assert t.get_or_set("C", @[0, 0, 0])[] == [0, 0, 0]
test "Table.has"
assert {"A": 1, "B": 2}.has("A")
assert not {"A": 1, "B": 2}.has("xxx")
test "Table.intersection"
t1 := {"A": 1, "B": 2, "C": 3}
t2 := {"B": 2, "C":30, "D": 40}
assert t1.intersection(t2) == {"B": 2}
test "Table.remove"
t := &{"A": 1, "B": 2}
t.remove("A")
assert t == {"B": 2}
test "Table.set"
t := &{"A": 1, "B": 2}
t.set("C", 3)
assert t == {"A": 1, "B": 2, "C": 3}
test "Table.with"
t := {"A": 1, "B": 2}
assert t.with({"B": 20, "C": 30}) == {"A": 1, "B": 20, "C": 30}
test "Table.with_fallback"
t := {"A": 1; fallback={"B": 2}}
t2 := t.with_fallback({"B": 3})
assert t2["B"] == 3
t3 := t.with_fallback(none)
assert t3["B"] == none
test "Table.without"
t := {"A": 1, "B": 2, "C": 3}
assert t.without({"B": 2, "C": 30, "D": 40}) == {"A": 1, "C": 3}
test "Text.as_c_string"
assert "Hello".as_c_string() == CString("Hello")
test "Text.at"
assert "Amélie".at(3) == "é"
assert "Amélie".at(-1) == "e"
assert "Amélie".at(99) == none
test "Text.by_line"
text := "
line one
line two
"
lines := [line for line in text.by_line()]
assert lines == ["line one", "line two"]
test "Text.by_split"
text := "one,two,three"
chunks := [chunk for chunk in text.by_split(",")]
assert chunks == ["one", "two", "three"]
test "Text.by_split_any"
text := "one,two,;,three"
chunks := [chunk for chunk in text.by_split_any(",;")]
assert chunks == ["one", "two", "three"]
test "Text.caseless_equals"
assert "A".caseless_equals("a")
# Turkish lowercase "I" is "ı" (dotless I), not "i"
assert not "I".caseless_equals("i", language="tr_TR")
test "Text.codepoint_names"
assert "Amélie".codepoint_names() == [
"LATIN CAPITAL LETTER A",
"LATIN SMALL LETTER M",
"LATIN SMALL LETTER E WITH ACUTE",
"LATIN SMALL LETTER L",
"LATIN SMALL LETTER I",
"LATIN SMALL LETTER E",
]
test "Text.distance"
assert "hello".distance("hello") == 0
texts := &["goodbye", "hello", "hallo"]
texts.sort(func(a,b:Text) a.distance("hello") <> b.distance("hello"))
assert texts == ["hello", "hallo", "goodbye"]
assert "kitten".distance("sitting") == 3
assert "flaw".distance("lawn") == 2
# A transposition costs one edit, even when the texts differ in length:
assert "ab".distance("ba") == 1
assert "xab".distance("ba") == 2
test "Text.ends_with"
assert "hello world".ends_with("world")
remainder : Text
assert "hello world".ends_with("world", &remainder)
assert remainder == "hello "
test "Text.find"
assert "one two".find("one") == 1
assert "one two".find("two") == 5
assert "one two".find("three") == none
assert "one two".find("o", start=2) == 7
test "Text.from"
assert "hello".from(2) == "ello"
assert "hello".from(-2) == "lo"
test "Text.from_c_string"
assert Text.from_c_string(CString("Hello")) == "Hello"
test "Text.from_codepoint_names"
text := Text.from_codepoint_names([
"LATIN CAPITAL LETTER A WITH RING ABOVE",
"LATIN SMALL LETTER K",
"LATIN SMALL LETTER E",
])
assert text == "Åke"
test "Text.from_utf16"
assert Text.from_utf16([197, 107, 101]) == "Åke"
assert Text.from_utf16([12371, 12435, 12395, 12385, 12399, 19990, 30028]) == "こんにちは世界"
test "Text.from_utf32"
assert Text.from_utf32([197, 107, 101]) == "Åke"
test "Text.from_utf8"
assert Text.from_utf8([195, 133, 107, 101]) == "Åke"
test "Text.has"
assert "hello world".has("wo")
assert not "hello world".has("xxx")
test "Text.join"
assert ", ".join(["one", "two", "three"]) == "one, two, three"
test "Text.left_pad"
assert "x".left_pad(5) == " x"
assert "x".left_pad(5, "ABC") == "ABCAx"
test "Text.lines"
assert "one\ntwo\nthree".lines() == ["one", "two", "three"]
assert "one\ntwo\nthree\n".lines() == ["one", "two", "three"]
assert "one\ntwo\nthree\n\n".lines() == ["one", "two", "three", ""]
assert "one\r\ntwo\r\nthree\r\n".lines() == ["one", "two", "three"]
assert "".lines() == []
test "Text.lower"
assert "AMÉLIE".lower() == "amélie"
assert "I".lower(language="tr_TR") == "ı"
test "Text.matches_glob"
assert "hello world".matches_glob("h* *d")
test "Text.middle_pad"
assert "x".middle_pad(6) == " x "
assert "x".middle_pad(10, "ABC") == "ABCAxABCAB"
test "Text.nearest"
commands := ["build", "run", "test"]
assert "bulid".nearest(commands) == "build"
assert "frobnicate".nearest(commands) == none
assert "x".nearest([]) == none
test "Text.quoted"
assert "one\ntwo".quoted() == "\"one\\ntwo\""
test "Text.repeat"
assert "Abc".repeat(3) == "AbcAbcAbc"
test "Text.replace"
assert "Hello world".replace("world", "there") == "Hello there"
test "Text.reversed"
assert "Abc".reversed() == "cbA"
test "Text.right_pad"
assert "x".right_pad(5) == "x "
assert "x".right_pad(5, "ABC") == "xABCA"
test "Text.slice"
assert "hello".slice(2, 3) == "el"
assert "hello".slice(to=-2) == "hell"
assert "hello".slice(from=2) == "ello"
test "Text.split"
assert "one,two,,three".split(",") == ["one", "two", "", "three"]
assert "abc".split() == ["a", "b", "c"]
test "Text.split_any"
assert "one, two,,three".split_any(", ") == ["one", "two", "three"]
test "Text.starts_with"
assert "hello world".starts_with("hello")
remainder : Text
assert "hello world".starts_with("hello", &remainder)
assert remainder == " world"
test "Text.title"
assert "amélie".title() == "Amélie"
# In Turkish, uppercase "i" is "İ"
assert "i".title(language="tr_TR") == "İ"
test "Text.to"
assert "goodbye".to(3) == "goo"
assert "goodbye".to(-2) == "goodby"
test "Text.translate"
text := "A <tag> & an ampersand".translate({
"&": "&",
"<": "<",
">": ">",
'"': """,
"'": "'",
})
assert text == "A <tag> & an ampersand"
test "Text.trim"
assert " x y z \n".trim() == "x y z"
assert "one,".trim(",") == "one"
assert " xyz ".trim(right=no) == "xyz "
test "Text.upper"
assert "amélie".upper() == "AMÉLIE"
# In Turkish, uppercase "i" is "İ"
assert "i".upper(language="tr_TR") == "İ"
test "Text.utf16"
assert "Åke".utf16() == [197, 107, 101]
assert "こんにちは世界".utf16() == [12371, 12435, 12395, 12385, 12399, 19990, 30028]
test "Text.utf32"
assert "Amélie".utf32() == [65, 109, 233, 108, 105, 101]
test "Text.utf8"
assert "Amélie".utf8() == [65, 109, 195, 169, 108, 105, 101]
test "Text.width"
assert "Amélie".width() == 6
assert "🤠".width() == 2
test "Text.without_prefix"
assert "foo:baz".without_prefix("foo:") == "baz"
assert "qux".without_prefix("foo:") == "qux"
test "Text.without_suffix"
assert "baz.foo".without_suffix(".foo") == "baz"
assert "qux".without_suffix(".foo") == "qux"
test "ask"
if no
assert ask("What's your name? ") == "Arthur Dent"
test "at_cleanup"
if no
at_cleanup(func()
_ := (/tmp/file.txt).remove(ignore_missing=yes)
)
test "breakpoint"
total := 0
for i in 10
total += i
breakpoint() # `tomo run --debug` stops here, with `total` and `i` in scope
test "exit"
if no
exit("Goodbye forever!", Int32(1))
test "fail"
if no
fail("Oh no!")
test "getenv"
if no
assert getenv("TERM") == "xterm-256color"
assert getenv("not_a_variable") == none
test "print"
if no
print("Hello ", newline=no)
print("world!")
test "say"
if no
say("Hello ", newline=no)
say("world!")
test "setenv"
if no
setenv("FOOBAR", "xyz")
test "sleep"
if no
sleep(1.5)
|