# file      : bx/testscript
# license   : MIT; see accompanying LICENSE file

test.options += --no-default-options

: script
:
{{
  test.arguments += test.bx

  : variables
  :
  {{
    : special
    :
    {{
      : success
      :
      {
        cat <<EOI >=test.bx
          echo $*
          echo $0 $1 $2 $3 $4 $5 $6 $7 $8 $9 ($*[10])
          echo $~
          EOI

        $* a b c d e f g h i j >>~%EOO%
          test.bx a b c d e f g h i j
          test.bx a b c d e f g h i j
          %.+[/\\]success[/\\]%
          EOO
      }

      : failure
      :
      {{
        : multi-digit
        :
        {
          cat <<EOI >=test.bx
            echo $10
            EOI

          $* 2>>EOE != 0
            test.bx:1:8: error: multi-digit special variable name
              info: use '($*[NN])' to access elements beyond 9
            EOE
        }

        : assign-special
        :
        {
          cat <<EOI >=test.bx
            0 = foo
            EOI

          $* 2>>EOE != 0
            test.bx:1:1: error: attempt to set '0' special variable
            EOE
        }
      }}
    }}

    : global
    :
    {
      cat <<EOI >=test.bx
        echo "$shell.work" # Strip trailing slash.
        EOI

      $* >"$~"
    }

    : assignment
    :
    {
      cat <<EOI >=test.bx
        foo = bar
        bar = $foo
        bar += baz
        bar += fox
        echo $bar
        EOI

      $* >'bar baz fox'
    }
  }}

  : no-default-cleanups
  :
  {
    cat <<EOI >=test.bx
      touch foo
      echo "" >=bar
      EOI

    $* &foo &bar

    test -f foo && test -f bar
  }

  : exit
  :
  {{
    : success
    :
    {{
      : code
      :
      {
        cat <<EOI >=test.bx
          echo 1
          exit 0
          echo 2
          EOI

        $* >'1'
      }

      : no-code
      :
      {
        cat <<EOI >=test.bx
          echo 1
          exit
          echo 2
          EOI

        $* >'1'
      }

      : diag
      :
      {
        cat <<EOI >=test.bx
          echo 1
          exit 0 'diagnostics'
          echo 2
          EOI

        $* >'1' 2>>EOE != 0
          test.bx:2:1: error: exit: diagnostics is specified for 0 exit code
          EOE
      }

      : cleanups
      :
      {
        cat <<EOI >=test.bx
          touch foo &foo
          exit
          EOI

        $*
      }
    }}

    : failure
    :
    {{
      : code
      :
      {
        cat <<EOI >=test.bx
          echo 1
          exit 5
          echo 2
          EOI

        $* >'1' == 5
      }

      : no-code
      :
      {
        cat <<EOI >=test.bx
          echo 1
          exit 'diagnostics'
          echo 2
          EOI

        $* >'1' 2>>EOE == 1
          test.bx:2:1: error: diagnostics
          EOE
      }

      : diag
      :
      {
        cat <<EOI >=test.bx
          echo 1
          exit 5 'diagnostics'
          echo 2
          EOI

        $* >'1' 2>>EOE == 5
          test.bx:2:1: error: diagnostics
          EOE
      }

      : if-cond
      :
      {
        cat <<EOI >=test.bx
          echo 1
          if exit 5
            echo 2
          echo 3
          EOI

        $* >'1' == 5
      }

      : if-block
      :
      {
        cat <<EOI >=test.bx
          echo 1
          if true
          {
            echo 2
            exit 5
            echo 3
          }
          echo 4
          EOI

        $* >>EOO == 5
          1
          2
          EOO
      }

      : elif-cond
      :
      {
        cat <<EOI >=test.bx
          echo 1
          if false
            echo 2
          elif exit 5
            echo 3
          echo 4
          EOI

        $* >'1' == 5
      }

      : elif-block
      :
      {
        cat <<EOI >=test.bx
          echo 1
          if false
            echo 2
          elif true
          {
            echo 3
            exit 5
            echo 4
          }
          echo 5
          EOI

        $* >>EOO == 5
          1
          3
          EOO
      }

      : else-block
      :
      {
        cat <<EOI >=test.bx
          echo 1
          if false
            echo 2
          else
          {
            echo 3
            exit 5
            echo 4
          }
          echo 5
          EOI

        $* >>EOO == 5
          1
          3
          EOO
      }

      : for-args
      :
      {
        cat <<EOI >=test.bx
          echo 1
          for i: 2 3
          {
            echo $i
            exit 5
          }
          echo 4
          EOI

        $* >>EOO == 5
          1
          2
          EOO
      }

      : for-stream
      :
      {
        cat <<EOI >=test.bx
          echo 1
          echo 2 3 | for i
          {
            echo $i
            exit 5
          }
          echo 4
          EOI

        $* >>EOO == 5
          1
          2
          EOO
      }

      : while-cond
      :
      {
        cat <<EOI >=test.bx
          echo 1
          while exit 5
            echo 2
          echo 3
          EOI

        $* >'1' == 5
      }

      : while-block
      :
      {
        cat <<EOI >=test.bx
          echo 1
          while true
          {
            echo 2
            exit 5
            echo 3
          }
          echo 4
          EOI

        $* >>EOO == 5
          1
          2
          EOO
      }

      : cleanups
      :
      {
        cat <<EOI >=test.bx
          touch foo &foo
          exit 5
          EOI

        $* == 5
      }
    }}

    : error
    :
    {{
      : big-code
      :
      : While at it, check that the cleanups are not performed on a script
      : execution error to help with troubleshooting.
      :
      {
        cat <<EOI >=test.bx &foo
          touch foo &foo
          exit 555
          EOI

        $* 2>>EOE == 1
          test.bx:2:1: error: exit: exit code must be an unsigned integer less than 256
          EOE
      }

      : unexpected-arg
      :
      {
        cat <<EOI >=test.bx
          exit 5 'diagnostics' junk
          EOI

        $* 2>>EOE == 1
          test.bx:1:1: error: exit: unexpected argument 'junk'
          EOE
      }
    }}
  }}

  : if
  :
  {{
    : success
    :
    {
      cat <<EOI >=test.bx
        echo 1

        if true
        {
          echo 2
          echo 3
        }

        if false
        {
          echo 4
          echo 5
        }

        if true
          echo 6
        if false
          echo 7

        if false
        {
          echo 8
          echo 9
        }
        elif true
        {
          echo 10
          echo 11
        }

        if false
          echo 12
        elif true
          echo 13

        if false
        {
          echo 14
          echo 15
        }
        elif false
        {
          echo 16
          echo 17
        }
        else
        {
          echo 18
          echo 19
        }

        if false
          echo 20
        elif false
          echo 21
        else
          echo 22

        if true
        {
          if true
          {
            echo 23
          }
        }
        else
          if true
            echo 24

        ifn [null]
          echo 25
        else
          echo 26

        ifn foo
          echo 27
        elifn $foo
          echo 28

        ifn! [null]
          echo 29
        else
          echo 30

        ifn! foo
          echo 31
        elifn! $foo
          echo 32

        ife ()
          echo 33
        else
          echo 34

        ife foo
          echo 35
        elife $foo
          echo 36

        ife! ()
          echo 37
        else
          echo 38

        ife! foo
          echo 39
        elife! $foo
          echo 40

        echo 41
        EOI

      $* >>EOO
        1
        2
        3
        6
        10
        11
        13
        18
        19
        22
        23
        25
        28
        30
        31
        33
        36
        38
        39
        41
        EOO
    }

    : failure
    :
    {{
      : unexpected-lcbrace
      :
      {
        cat <<EOI >=test.bx
          if true
          {
            {
          EOI

        $* 2>>EOE != 0
          test.bx:3:3: error: expected command instead of '{'
          EOE
      }

      : unexpected-else
      :
      {
        cat <<EOI >=test.bx
          if true
          {
            else
            {
          EOI

        $* 2>>EOE != 0
          test.bx:3:3: error: 'else' without preceding 'if'
          EOE
      }

      : elif-after-else
      :
      {
        cat <<EOI >=test.bx
          if true
            echo ''
          else
            echo ''
          elif true
            echo ''
          EOI

        $* 2>>EOE != 0
          test.bx:5:1: error: 'elif' after 'else'
          EOE
      }
    }}
  }}

  : for-args
  :
  {{
    : success
    :
    {
      cat <<EOI >=test.bx
        echo 1
        for i: 2 3
        {
          for j: 4 5
            echo $i $j

          for j: 6 7 8 9
          {
            if ($j == 6)
              continue

            echo $i $j

            if ($j == 7)
              break
          }
        }
        echo 10 $i $j
        EOI

      $* >>EOO
        1
        2 4
        2 5
        2 7
        3 4
        3 5
        3 7
        10 3 7
        EOO
    }

    : failure
    :
    {{
      : unexpected-lcbrace
      :
      {
        cat <<EOI >=test.bx
          for i: 2 3
          {
            {
          EOI

        $* 2>>EOE != 0
          test.bx:3:3: error: expected command instead of '{'
          EOE
      }

      : unexpected-else
      :
      {
        cat <<EOI >=test.bx
          for i: 2 3
          {
            else
            {
          EOI

        $* 2>>EOE != 0
          test.bx:3:3: error: 'else' without preceding 'if'
          EOE
      }
    }}
  }}

  : for-stream
  :
  {{
    : success
    :
    {
      cat <<EOI >=test.bx
        echo 1
        for i <<< "2 3"
        {
          echo 4 5 | for j
            echo $i $j

          echo 6 7 8 9 | for j
          {
            if ($j == 6)
              continue

            echo $i $j

            if ($j == 7)
              break
          }
        }
        echo 10 $i $j
        EOI

      $* >>EOO
        1
        2 4
        2 5
        2 7
        3 4
        3 5
        3 7
        10 3 7
        EOO
    }

    : failure
    :
    {{
      : unexpected-lcbrace
      :
      {
        cat <<EOI >=test.bx
          echo 4 5 | for i
          {
            {
          EOI

        $* 2>>EOE != 0
          test.bx:3:3: error: expected command instead of '{'
          EOE
      }

      : unexpected-else
      :
      {
        cat <<EOI >=test.bx
          echo 4 5 | for i
          {
            elif
            {
          EOI

        $* 2>>EOE != 0
          test.bx:3:3: error: 'elif' without preceding 'if'
          EOE
      }
    }}
  }}

  : while
  :
  {{
    : success
    :
    {
      cat <<EOI >=test.bx
        echo 1
        i = [uint64] 2
        while ($i != 4)
        {
          j = [uint64] 4

          while ($j != 6)
          {
            echo $i $j
            j += 1
          }

          while ($j != 10)
          {
            if ($j == 6)
            {
              j += 1
              continue
            }

            echo $i $j

            if ($j == 7)
              break

            j += 1
          }

          i += 1
        }
        echo 10 $i $j
        EOI

      $* >>EOO
        1
        2 4
        2 5
        2 7
        3 4
        3 5
        3 7
        10 4 7
        EOO
    }

    : failure
    :
    {{
      : unexpected-lcbrace
      :
      {
        cat <<EOI >=test.bx
          while true
          {
            {
          EOI

        $* 2>>EOE != 0
          test.bx:3:3: error: expected command instead of '{'
          EOE
      }

      : unexpected-else
      :
      {
        cat <<EOI >=test.bx
          while true
          {
            elif
            {
          EOI

        $* 2>>EOE != 0
          test.bx:3:3: error: 'elif' without preceding 'if'
          EOE
      }
    }}
  }}

  : path-search
  :
  : Test that the current working directory is implied by the
  : $filesystem.path_search() function whenever required.
  :
  {
    mkdir foo
    touch foo/bar.txt

    cat <<EOI >=test.bx
      echo $path_search($~/**.txt)
      echo $path_search(**.txt, $~)
      echo $path_search(*.txt)
      echo $path_search(**.txt)
      echo $path_search(foo/*.txt)
      echo $path_search(*.txt, foo)
      EOI

    $* >>/"EOO"
      $~/foo/bar.txt
      foo/bar.txt

      foo/bar.txt
      foo/bar.txt
      bar.txt
      EOO
  }
}}

: task
:
{{
  : named
  :
  {
    $* foo bar 2>'error: task running not yet implemented' != 0
  }

  : default
  :
  {
    $* 2>'error: task running not yet implemented' != 0
  }

  : default-args
  :
  {
    $* -- foo 2>'error: task running not yet implemented' != 0
  }
}}
