mirror of
https://github.com/janet-lang/janet
synced 2025-11-01 08:03:02 +00:00
Merge branch 'master' into compile-opt
This commit is contained in:
@@ -39,7 +39,7 @@
|
||||
(defmacro assert
|
||||
[x &opt e]
|
||||
(def xx (gensym))
|
||||
(default e ~',x)
|
||||
(default e (string/format "%j" x))
|
||||
~(do
|
||||
(def ,xx ,x)
|
||||
(,assert-no-tail ,xx ,e)
|
||||
|
||||
@@ -896,11 +896,18 @@
|
||||
(struct/with-proto {:a [1 2 3]} :c 22 :b [1 2 3 4] :d "test" :e "test2"))
|
||||
(table/setproto table-to-freeze @{:a @[1 2 3]})
|
||||
|
||||
(assert (deep= {:a [1 2 3] :b [1 2 3 4] :c 22 :d "test" :e "test2"}
|
||||
(freeze table-to-freeze)))
|
||||
(assert (deep= struct-to-thaw (freeze table-to-freeze)))
|
||||
(assert (deep= table-to-freeze-with-inline-proto (thaw table-to-freeze)))
|
||||
(assert (deep= table-to-freeze-with-inline-proto (thaw struct-to-thaw)))
|
||||
|
||||
# Check that freezing mutable keys is deterministic
|
||||
# for issue #1535
|
||||
(def hashes @{})
|
||||
(repeat 200
|
||||
(def x (freeze {@"" 1 @"" 2 @"" 3 @"" 4 @"" 5}))
|
||||
(put hashes (hash x) true))
|
||||
(assert (= 1 (length hashes)) "freeze mutable keys is deterministic")
|
||||
|
||||
# Make sure Carriage Returns don't end up in doc strings
|
||||
# e528b86
|
||||
(assert (not (string/find "\r"
|
||||
@@ -1006,4 +1013,18 @@
|
||||
(assert-error "assertf error 3" (assertf false "%s message" "mystery"))
|
||||
(assert-error "assertf error 4" (assertf nil "%s %s" "alice" "bob"))
|
||||
|
||||
# issue #1535
|
||||
(loop [i :range [1 1000]]
|
||||
(assert (deep-not= @{:key1 "value1" @"key" "value2"}
|
||||
@{:key1 "value1" @"key" "value2"}) "deep= mutable keys"))
|
||||
(assert (deep-not= {"abc" 123} {@"abc" 123}) "deep= mutable keys vs immutable key")
|
||||
(assert (deep-not= {@"" 1 @"" 2 @"" 3} {@"" 1 @"" 2 @"" 3}) "deep= duplicate mutable keys")
|
||||
(assert (deep-not= {@"" @"" @"" @"" @"" 3} {@"" @"" @"" @"" @"" 3}) "deep= duplicate mutable keys 2")
|
||||
(assert (deep-not= {@[] @"" @[] @"" @[] 3} {@[] @"" @[] @"" @[] 3}) "deep= duplicate mutable keys 3")
|
||||
(assert (deep-not= {@{} @"" @{} @"" @{} 3} {@{} @"" @{} @"" @{} 3}) "deep= duplicate mutable keys 4")
|
||||
(assert (deep-not= @{:key1 "value1" @"key2" @"value2"}
|
||||
@{:key1 "value1" @"key2" "value2"}) "deep= mutable keys")
|
||||
(assert (deep-not= @{:key1 "value1" [@"key2"] @"value2"}
|
||||
@{:key1 "value1" [@"key2"] @"value2"}) "deep= mutable keys")
|
||||
|
||||
(end-suite)
|
||||
|
||||
@@ -174,6 +174,7 @@
|
||||
(assert (deep= (range 0 17 4) @[0 4 8 12 16]) "(range 0 17 4)")
|
||||
(assert (deep= (range 16 0 -4) @[16 12 8 4]) "(range 16 0 -4)")
|
||||
(assert (deep= (range 17 0 -4) @[17 13 9 5 1]) "(range 17 0 -4)")
|
||||
(assert-error "large range" (range 0xFFFFFFFFFF))
|
||||
|
||||
(assert (= (length (range 10)) 10) "(range 10)")
|
||||
(assert (= (length (range -10)) 0) "(range -10)")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2023 Calvin Rose & contributors
|
||||
# Copyright (c) 2025 Calvin Rose & contributors
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to
|
||||
@@ -199,7 +199,7 @@
|
||||
(assert s "made server 1")
|
||||
|
||||
(defn test-echo [msg]
|
||||
(with [conn (net/connect test-host test-port)]
|
||||
(with [conn (assert (net/connect test-host test-port))]
|
||||
(net/write conn msg)
|
||||
(def res (net/read conn 1024))
|
||||
(assert (= (string res) msg) (string "echo " msg))))
|
||||
@@ -213,6 +213,7 @@
|
||||
|
||||
# Test on both server and client
|
||||
# 504411e
|
||||
(var iterations 0)
|
||||
(defn names-handler
|
||||
[stream]
|
||||
(defer (:close stream)
|
||||
@@ -220,21 +221,26 @@
|
||||
(ev/read stream 1)
|
||||
(def [host port] (net/localname stream))
|
||||
(assert (= host test-host) "localname host server")
|
||||
(assert (= port (scan-number test-port)) "localname port server")))
|
||||
(assert (= port (scan-number test-port)) "localname port server")
|
||||
(++ iterations)
|
||||
(ev/write stream " ")))
|
||||
|
||||
# Test localname and peername
|
||||
# 077bf5eba
|
||||
(repeat 10
|
||||
(with [s (net/server test-host test-port names-handler)]
|
||||
(repeat 10
|
||||
(with [conn (net/connect test-host test-port)]
|
||||
(with [conn (assert (net/connect test-host test-port))]
|
||||
(def [host port] (net/peername conn))
|
||||
(assert (= host test-host) "peername host client ")
|
||||
(assert (= port (scan-number test-port)) "peername port client")
|
||||
# let server close
|
||||
(ev/write conn " "))))
|
||||
(++ iterations)
|
||||
(ev/write conn " ")
|
||||
(ev/read conn 1))))
|
||||
(gccollect))
|
||||
|
||||
(assert (= iterations 200) "localname and peername not enough checks")
|
||||
|
||||
# Create pipe
|
||||
# 12f09ad2d
|
||||
(var pipe-counter 0)
|
||||
@@ -410,6 +416,10 @@
|
||||
(ev/call handler connection)
|
||||
(break))))
|
||||
|
||||
# Make sure we can't bind again with no-reuse
|
||||
(assert-error "no-reuse"
|
||||
(net/listen test-host test-port :stream true))
|
||||
|
||||
# Read from socket
|
||||
|
||||
(defn expect-read
|
||||
@@ -418,11 +428,17 @@
|
||||
(assert (= result text) (string/format "expected %v, got %v" text result)))
|
||||
|
||||
# Now do our telnet chat
|
||||
(def bob (net/connect test-host test-port))
|
||||
(def bob (assert (net/connect test-host test-port :stream)))
|
||||
(expect-read bob "Whats your name?\n")
|
||||
(net/write bob "bob")
|
||||
(if (= :mingw (os/which))
|
||||
(net/write bob "bob")
|
||||
(do
|
||||
(def fbob (ev/to-file bob))
|
||||
(file/write fbob "bob")
|
||||
(file/flush fbob)
|
||||
(:close fbob)))
|
||||
(expect-read bob "Welcome bob\n")
|
||||
(def alice (net/connect test-host test-port))
|
||||
(def alice (assert (net/connect test-host test-port)))
|
||||
(expect-read alice "Whats your name?\n")
|
||||
(net/write alice "alice")
|
||||
(expect-read alice "Welcome alice\n")
|
||||
@@ -436,7 +452,7 @@
|
||||
(expect-read bob "[alice]:hi\n")
|
||||
|
||||
# Ted joins the chat server
|
||||
(def ted (net/connect test-host test-port))
|
||||
(def ted (assert (net/connect test-host test-port)))
|
||||
(expect-read ted "Whats your name?\n")
|
||||
(net/write ted "ted")
|
||||
(expect-read ted "Welcome ted\n")
|
||||
@@ -465,4 +481,49 @@
|
||||
# Close chat server
|
||||
(:close chat-server)
|
||||
|
||||
# Issue #1531
|
||||
(defn sleep-print [x] (ev/sleep 0) (print x))
|
||||
(protect (with-dyns [*out* sleep-print] (prin :foo)))
|
||||
(defn level-trigger-handling [conn &] (:close conn))
|
||||
(def s (assert (net/server test-host test-port level-trigger-handling)))
|
||||
(def c (assert (net/connect test-host test-port)))
|
||||
(:close s)
|
||||
|
||||
# Issue #1531 no. 2
|
||||
(def c (ev/chan 0))
|
||||
(ev/spawn (while (def x (ev/take c))))
|
||||
(defn print-to-chan [x] (ev/give c x))
|
||||
(assert-error "coerce await inside janet_call to error"
|
||||
(with-dyns [*out* print-to-chan]
|
||||
(pp :foo)))
|
||||
(ev/chan-close c)
|
||||
|
||||
# soreuseport on unix domain sockets
|
||||
(compwhen (or (= :macos (os/which)) (= :linux (os/which)))
|
||||
(assert-no-error "unix-domain socket reuseaddr"
|
||||
(let [s (net/listen :unix "./unix-domain-socket" :stream)]
|
||||
(:close s))))
|
||||
|
||||
# net/accept-loop level triggering
|
||||
(gccollect)
|
||||
(def maxconn 50)
|
||||
(var connect-count 0)
|
||||
(defn level-trigger-handling
|
||||
[conn &]
|
||||
(with [conn conn]
|
||||
(ev/write conn (ev/read conn 4096))
|
||||
(++ connect-count)))
|
||||
(def s (assert (net/server test-host test-port level-trigger-handling)))
|
||||
(def cons @[])
|
||||
(repeat maxconn (array/push cons (assert (net/connect test-host test-port))))
|
||||
(assert (= maxconn (length cons)))
|
||||
(defn do-connect [i]
|
||||
(with [c (get cons i)]
|
||||
(ev/write c "abc123")
|
||||
(ev/read c 4096)))
|
||||
(for i 0 maxconn (ev/spawn (do-connect i)))
|
||||
(ev/sleep 0.1)
|
||||
(assert (= maxconn connect-count))
|
||||
(:close s)
|
||||
|
||||
(end-suite)
|
||||
|
||||
@@ -207,7 +207,7 @@ neldb\0\0\0\xD8\x05printG\x01\0\xDE\xDE\xDE'\x03\0marshal_tes/\x02
|
||||
(assert (= 2 (length tclone)) "table/weak-values marsh 2")
|
||||
(gccollect)
|
||||
(assert (= 1 (length t)) "table/weak-value marsh 3")
|
||||
(assert (deep= t tclone) "table/weak-values marsh 4")
|
||||
(assert (deep= (freeze t) (freeze tclone)) "table/weak-values marsh 4")
|
||||
|
||||
# tables with prototypes
|
||||
(def t (table/weak-values 1))
|
||||
@@ -219,7 +219,7 @@ neldb\0\0\0\xD8\x05printG\x01\0\xDE\xDE\xDE'\x03\0marshal_tes/\x02
|
||||
(assert (= 2 (length tclone)) "marsh weak tables with prototypes 2")
|
||||
(gccollect)
|
||||
(assert (= 1 (length t)) "marsh weak tables with prototypes 3")
|
||||
(assert (deep= t tclone) "marsh weak tables with prototypes 4")
|
||||
(assert (deep= (freeze t) (freeze tclone)) "marsh weak tables with prototypes 4")
|
||||
(assert (deep= (getproto t) (getproto tclone)) "marsh weak tables with prototypes 5")
|
||||
|
||||
(end-suite)
|
||||
|
||||
@@ -57,6 +57,8 @@
|
||||
(for i (+ index 1) (+ index indent 1)
|
||||
(case (get text i)
|
||||
nil (break)
|
||||
(chr "\r") (if-not (= (chr "\n") (get text (inc i)))
|
||||
(set rewrite false))
|
||||
(chr "\n") (break)
|
||||
(chr " ") nil
|
||||
(set rewrite false))))
|
||||
@@ -64,12 +66,17 @@
|
||||
# Only re-indent if no dedented characters.
|
||||
(def str
|
||||
(if rewrite
|
||||
(peg/replace-all ~(* "\n" (between 0 ,indent " ")) "\n" text)
|
||||
(peg/replace-all ~(* '(* (? "\r") "\n") (between 0 ,indent " "))
|
||||
(fn [mtch eol] eol) text)
|
||||
text))
|
||||
|
||||
(def first-nl (= (chr "\n") (first str)))
|
||||
(def last-nl (= (chr "\n") (last str)))
|
||||
(string/slice str (if first-nl 1 0) (if last-nl -2)))
|
||||
(def first-eol (cond
|
||||
(string/has-prefix? "\r\n" str) :crlf
|
||||
(string/has-prefix? "\n" str) :lf))
|
||||
(def last-eol (cond
|
||||
(string/has-suffix? "\r\n" str) :crlf
|
||||
(string/has-suffix? "\n" str) :lf))
|
||||
(string/slice str (case first-eol :crlf 2 :lf 1 0) (case last-eol :crlf -3 :lf -2)))
|
||||
|
||||
(defn reindent-reference
|
||||
"Same as reindent but use parser functionality. Useful for
|
||||
@@ -89,8 +96,10 @@
|
||||
(let [a (reindent text indent)
|
||||
b (reindent-reference text indent)]
|
||||
(assert (= a b)
|
||||
(string "indent " indent-counter " (indent=" indent ")"))))
|
||||
(string/format "reindent: %q, parse: %q (indent-test #%d with indent of %d)" a b indent-counter indent)
|
||||
)))
|
||||
|
||||
# Unix EOLs
|
||||
(check-indent "" 0)
|
||||
(check-indent "\n" 0)
|
||||
(check-indent "\n" 1)
|
||||
@@ -106,6 +115,17 @@
|
||||
(check-indent "\n Hello, world!\n " 4)
|
||||
(check-indent "\n Hello, world!\n dedented text\n " 4)
|
||||
(check-indent "\n Hello, world!\n indented text\n " 4)
|
||||
# Windows EOLs
|
||||
(check-indent "\r\n" 0)
|
||||
(check-indent "\r\n" 1)
|
||||
(check-indent "\r\n\r\n" 0)
|
||||
(check-indent "\r\n\r\n" 1)
|
||||
(check-indent "\r\nHello, world!" 0)
|
||||
(check-indent "\r\nHello, world!" 1)
|
||||
(check-indent "\r\n Hello, world!\r\n " 4)
|
||||
(check-indent "\r\n Hello, world!\r\n " 4)
|
||||
(check-indent "\r\n Hello, world!\r\n dedented text\r\n " 4)
|
||||
(check-indent "\r\n Hello, world!\r\n indented text\r\n " 4)
|
||||
|
||||
# Symbols with @ character
|
||||
# d68eae9
|
||||
@@ -188,5 +208,14 @@
|
||||
(parser/consume p `")`)
|
||||
(assert (= (parser/produce p) ["hello"]))
|
||||
|
||||
# Hex floats
|
||||
(assert (= math/pi +0x1.921fb54442d18p+0001))
|
||||
(assert (= math/int-max +0x1.ffff_ffff_ffff_ffp+0052))
|
||||
(assert (= math/int-min -0x1.ffff_ffff_ffff_ffp+0052))
|
||||
(assert (= 1 0x1P0))
|
||||
(assert (= 2 0x1P1))
|
||||
(assert (= -2 -0x1p1))
|
||||
(assert (= -0.5 -0x1p-1))
|
||||
|
||||
(end-suite)
|
||||
|
||||
|
||||
@@ -713,6 +713,41 @@
|
||||
"abcdef"
|
||||
@[])
|
||||
|
||||
(test "til: basic matching"
|
||||
~(til "d" "abc")
|
||||
"abcdef"
|
||||
@[])
|
||||
|
||||
(test "til: second pattern can't see past the first occurrence of first pattern"
|
||||
~(til "d" (* "abc" -1))
|
||||
"abcdef"
|
||||
@[])
|
||||
|
||||
(test "til: fails if first pattern fails"
|
||||
~(til "x" "abc")
|
||||
"abcdef"
|
||||
nil)
|
||||
|
||||
(test "til: fails if second pattern fails"
|
||||
~(til "abc" "x")
|
||||
"abcdef"
|
||||
nil)
|
||||
|
||||
(test "til: discards captures from initial pattern"
|
||||
~(til '"d" '"abc")
|
||||
"abcdef"
|
||||
@["abc"])
|
||||
|
||||
(test "til: positions inside second match are still relative to the entire input"
|
||||
~(* "one\ntw" (til 0 (* ($) (line) (column))))
|
||||
"one\ntwo\nthree\n"
|
||||
@[6 2 3])
|
||||
|
||||
(test "til: advances to the end of the first pattern's first occurrence"
|
||||
~(* (til "d" "ab") "e")
|
||||
"abcdef"
|
||||
@[])
|
||||
|
||||
(test "split: basic functionality"
|
||||
~(split "," '1)
|
||||
"a,b,c"
|
||||
@@ -772,5 +807,33 @@
|
||||
"5:apple6:banana6:cherry"
|
||||
@["apple" "banana" "cherry"])
|
||||
|
||||
# Issue #1539 - make sure split with "" doesn't infinite loop/oom
|
||||
(test "issue 1539"
|
||||
~(split "" (capture (to -1)))
|
||||
"hello there friends"
|
||||
nil)
|
||||
|
||||
(test "issue 1539 pt. 2"
|
||||
~(split "," (capture 0))
|
||||
"abc123,,,,"
|
||||
@["" "" "" "" ""])
|
||||
|
||||
# Issue #1549 - allow buffers as peg literals
|
||||
(test "issue 1549"
|
||||
''@"abc123"
|
||||
"abc123"
|
||||
@["abc123"])
|
||||
|
||||
# Issue 1554 - 0-width match termination behavior
|
||||
(test "issue 1554 case 1" '(any (> '1)) "abc" @[])
|
||||
(test "issue 1554 case 2" '(any (? (> '1))) "abc" @[])
|
||||
(test "issue 1554 case 3" '(any (> (? '1))) "abc" @[])
|
||||
(test "issue 1554 case 4" '(* "a" (> '1)) "abc" @["b"])
|
||||
(test "issue 1554 case 5" '(* "a" (? (> '1))) "abc" @["b"])
|
||||
(test "issue 1554 case 6" '(* "a" (> (? '1))) "abc" @["b"])
|
||||
(test "issue 1554 case 7" '(between 0 2 (> '1)) "abc" @["a" "a"])
|
||||
(test "issue 1554 case 8" '(between 2 3 (? (> '1))) "abc" @["a" "a" "a"])
|
||||
(test "issue 1554 case 9" '(between 0 0 (> (? '1))) "abc" @[])
|
||||
|
||||
(end-suite)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user