src.elv.sh@v0.21.0-dev.0.20240515223629-06979efb9a2a/pkg/eval/builtin_fn_flow_test.elvts (about)

     1  ////////////////
     2  # run-parallel #
     3  ////////////////
     4  
     5  ~> run-parallel { put lorem } { put ipsum } | order
     6  ▶ ipsum
     7  ▶ lorem
     8  ~> run-parallel { } { fail foo }
     9  Exception: foo
    10    [tty]:1:20-28: run-parallel { } { fail foo }
    11    [tty]:1:1-29: run-parallel { } { fail foo }
    12  
    13  ////////
    14  # each #
    15  ////////
    16  
    17  ~> put 1 233 | each $put~
    18  ▶ 1
    19  ▶ 233
    20  ~> echo "1\n233" | each $put~
    21  ▶ 1
    22  ▶ 233
    23  ~> echo "1\r\n233" | each $put~
    24  ▶ 1
    25  ▶ 233
    26  ~> each $put~ [1 233]
    27  ▶ 1
    28  ▶ 233
    29  ~> range 10 | each {|x| if (== $x 4) { break }; put $x }
    30  ▶ (num 0)
    31  ▶ (num 1)
    32  ▶ (num 2)
    33  ▶ (num 3)
    34  ~> range 10 | each {|x| if (== $x 4) { continue }; put $x }
    35  ▶ (num 0)
    36  ▶ (num 1)
    37  ▶ (num 2)
    38  ▶ (num 3)
    39  ▶ (num 5)
    40  ▶ (num 6)
    41  ▶ (num 7)
    42  ▶ (num 8)
    43  ▶ (num 9)
    44  ~> range 10 | each {|x| if (== $x 4) { fail haha }; put $x }
    45  ▶ (num 0)
    46  ▶ (num 1)
    47  ▶ (num 2)
    48  ▶ (num 3)
    49  Exception: haha
    50    [tty]:1:37-46: range 10 | each {|x| if (== $x 4) { fail haha }; put $x }
    51    [tty]:1:12-57: range 10 | each {|x| if (== $x 4) { fail haha }; put $x }
    52  
    53  // TODO: Test that "each" does not close the stdin.
    54  
    55  /////////
    56  # peach #
    57  /////////
    58  
    59  ~> range 5 | peach {|x| * 2 $x } | order
    60  ▶ (num 0)
    61  ▶ (num 2)
    62  ▶ (num 4)
    63  ▶ (num 6)
    64  ▶ (num 8)
    65  // continue
    66  ~> range 5 | peach {|x| if (== $x 2) { continue }; * 2 $x } | order
    67  ▶ (num 0)
    68  ▶ (num 2)
    69  ▶ (num 6)
    70  ▶ (num 8)
    71  
    72  ## processing order is non-deterministic ##
    73  // Test that inputs are not necessarily processed in order.
    74  // 
    75  // Most of the time this effect can be observed without the need of any jitter,
    76  // but if the system only has one CPU core to execute goroutines (which can
    77  // happen even when GOMAXPROCS > 1), the scheduling of goroutines can become
    78  // deterministic. The random jitter fixes that by forcing goroutines to yield
    79  // the thread and allow other goroutines to execute.
    80  ~> var @in = (range 100)
    81     while $true {
    82       var @out = (all $in | peach {|x| sleep (* (rand) 0.01); put $x })
    83       if (not-eq $in $out) {
    84         put $true
    85         break
    86       }
    87     }
    88  ▶ $true
    89  
    90  ## exception propagation ##
    91  ~> peach {|x| fail $x } [a]
    92  Exception: a
    93    [tty]:1:12-19: peach {|x| fail $x } [a]
    94    [tty]:1:1-24: peach {|x| fail $x } [a]
    95  
    96  ## break ##
    97  // It is technically possible for break to only take effect after the whole
    98  // sequence has been consumed, but that doesn't seem to ever happen in practice.
    99  ~> range 1 101 |
   100       peach {|x| if (== 50 $x) { break } else { put $x } } |
   101       < (+ (all)) (+ (range 1 101))
   102  ▶ $true
   103  
   104  ## parallelism ##
   105  
   106  //test-time-scale-in-global
   107  
   108  // Test the parallelism of peach by observing its run time relative to the run
   109  // time of the function. Since the exact run time is subject to scheduling
   110  // differences, benchmark it multiple times and use the fastest run time.
   111  
   112  // Unlimited workers: when scheduling allows, no two function runs are serial,
   113  // so the best run time should be between t and 2t, regardless of input size.
   114  ~> var t = (* 0.005 $test-time-scale)
   115     var best-run = (benchmark &min-runs=5 &min-time=0 {
   116         range 6 | peach {|_| sleep $t }
   117     } &on-end={|metrics| put $metrics[min] })
   118     < $t $best-run (* 2 $t)
   119  ▶ $true
   120  // 2 workers: when scheduling allows, at least two function runs are parallel.
   121  // On the other hand, No more than two functions are parallel. Best run time
   122  // should be between (ceil(n/2) * t) and n*t, where n is the input size.
   123  ~> var t = (* 0.005 $test-time-scale)
   124     var best-run = (benchmark &min-runs=5 &min-time=0 {
   125         range 6 | peach &num-workers=2 {|_| sleep $t }
   126     } &on-end={|metrics| put $metrics[min] })
   127     < (* 3 $t) $best-run (* 6 $t)
   128  ▶ $true
   129  
   130  ## invalid &num-workers ##
   131  ~> peach &num-workers=0 {|x| * 2 $x }
   132  Exception: bad value: peach &num-workers must be exact positive integer or +inf, but is 0
   133    [tty]:1:1-34: peach &num-workers=0 {|x| * 2 $x }
   134  ~> peach &num-workers=-2 {|x| * 2 $x }
   135  Exception: bad value: peach &num-workers must be exact positive integer or +inf, but is -2
   136    [tty]:1:1-35: peach &num-workers=-2 {|x| * 2 $x }
   137  
   138  ////////
   139  # fail #
   140  ////////
   141  
   142  ~> fail haha
   143  Exception: haha
   144    [tty]:1:1-9: fail haha
   145  ~> fn f { fail haha }
   146     fail ?(f)
   147  Exception: haha
   148    [tty]:1:8-17: fn f { fail haha }
   149    [tty]:2:8-8: fail ?(f)
   150  ~> fail []
   151  Exception: []
   152    [tty]:1:1-7: fail []
   153  ~> put ?(fail 1)[reason][type]
   154  ▶ fail
   155  ~> put ?(fail 1)[reason][content]
   156  ▶ 1
   157  
   158  //////////
   159  # return #
   160  //////////
   161  
   162  ~> return
   163  Exception: return
   164    [tty]:1:1-6: return
   165  
   166  // Use of return inside fn is tested alongside fn in builtin_special_test.elvts.
   167  
   168  /////////
   169  # defer #
   170  /////////
   171  
   172  ~> { defer { put a }; put b }
   173  ▶ b
   174  ▶ a
   175  ~> { defer { put a }; fail bad }
   176  ▶ a
   177  Exception: bad
   178    [tty]:1:20-28: { defer { put a }; fail bad }
   179    [tty]:1:1-29: { defer { put a }; fail bad }
   180  ~> defer { }
   181  Exception: defer must be called from within a closure
   182    [tty]:1:1-9: defer { }
   183  ~> { defer { fail foo } }
   184  Exception: foo
   185    [tty]:1:11-19: { defer { fail foo } }
   186    [tty]:1:1-22: { defer { fail foo } }
   187  ~> { defer {|x| } }
   188  Exception: arity mismatch: arguments must be 1 value, but is 0 values
   189    [tty]:1:3-15: { defer {|x| } }
   190    [tty]:1:1-16: { defer {|x| } }