# file      : tests/test/script/runner/expr.test
# copyright : Copyright (c) 2014-2017 Code Synthesis Ltd
# license   : MIT; see accompanying LICENSE file

.include ../common.test

: short-circuit
:
: Test expression result calculation and short-circuiting. We verify the
: correctness of the above for all possible expressions of a length up to 3
: operands. While some of tests may look redundant the full expression tree is
: easier to maintain than the one with gaps (also much less chances that we
: have missed something useful). Each pipe-operand has a label which is printed
: to stdout when the pipe is executed. Pipes stdouts are pass-redirected, so we
: just check that build2 output matches expectations.
:
: Note that expression evaluation goes left-to-right with AND and OR having the
: same precedence.
:
{
  true  = '$* >| -o'
  false = '$* -s 1 >| -o'

  bf = $b 2>/~'%.+/driver(\.exe)? exit status 1 != 0%'

  : true
  :
  {
    : TERM
    :
    $c <"$true 1" && $b >>EOO
    1
    EOO

    : OR
    :
    {
      : true
      :
      {
        : TERM
        :
        $c <"$true 1 || $true 2" && $b >>EOO
        1
        EOO

        : OR
        :
        {
          : true
          :
          {
            $c <"$true 1 || $true 2 || $true 3" && $b >>EOO
            1
            EOO
          }

          : false
          :
          {
            $c <"$true 1 || $true 2 || $false 3" && $b >>EOO
            1
            EOO
          }
        }

        : AND
        :
        {
          : true
          :
          {
            $c <"$true 1 || $true 2 && $true 3" && $b >>EOO
            1
            3
            EOO
          }

          : false
          :
          {
            $c <"$true 1 || $true 2 && $false 3" && $bf >>EOO != 0
            1
            3
            EOO
          }
        }
      }

      : false
      :
      {
        : TERM
        :
        $c <"$true 1 || $false 2" && $b >>EOO
        1
        EOO

        : OR
        :
        {
          : true
          :
          {
            $c <"$true 1 || $false 2 || $true 3" && $b >>EOO
            1
            EOO
          }

          : false
          :
          {
            $c <"$true 1 || $false 2 || $false 3" && $b >>EOO
            1
            EOO
          }
        }

        : AND
        :
        {
          : true
          :
          {
            $c <"$true 1 || $false 2 && $true 3" && $b >>EOO
            1
            3
            EOO
          }

          : false
          :
          {
            $c <"$true 1 || $false 2 && $false 3" && $bf >>EOO != 0
            1
            3
            EOO
          }
        }
      }
    }

    : AND
    :
    {
      : true
      :
      {
        : TERM
        :
        $c <"$true 1 && $true 2" && $b >>EOO
        1
        2
        EOO

        : OR
        :
        {
          : true
          :
          {
            $c <"$true 1 && $true 2 || $true 3" && $b >>EOO
            1
            2
            EOO
          }

          : false
          :
          {
            $c <"$true 1 && $true 2 || $false 3" && $b >>EOO
            1
            2
            EOO
          }
        }

        : AND
        :
        {
          : true
          :
          {
            $c <"$true 1 && $true 2 && $true 3" && $b >>EOO
            1
            2
            3
            EOO
          }

          : false
          :
          {
            $c <"$true 1 && $true 2 && $false 3" && $bf >>EOO != 0
            1
            2
            3
            EOO
          }
        }
      }

      : false
      :
      {
        : TERM
        :
        $c <"$true 1 && $false 2" && $bf >>EOO != 0
        1
        2
        EOO

        : OR
        :
        {
          : true
          :
          {
            $c <"$true 1 && $false 2 || $true 3" && $b >>EOO
            1
            2
            3
            EOO
          }

          : false
          :
          {
            $c <"$true 1 && $false 2 || $false 3" && $bf >>EOO != 0
            1
            2
            3
            EOO
          }
        }

        : AND
        :
        {
          : true
          :
          {
            $c <"$true 1 && $false 2 && $true 3" && $bf >>EOO != 0
            1
            2
            EOO
          }

          : false
          :
          {
            $c <"$true 1 && $false 2 && $false 3" && $bf >>EOO != 0
            1
            2
            EOO
          }
        }
      }
    }
  }

  : false
  :
  {
    : TERM
    :
    $c <"$false 1" && $bf >>EOO != 0
    1
    EOO

    : OR
    :
    {
      : true
      :
      {
        : TERM
        :
        $c <"$false 1 || $true 2" && $b >>EOO
        1
        2
        EOO

        : OR
        :
        {
          : true
          :
          {
            $c <"$false 1 || $true 2 || $true 3" && $b >>EOO
            1
            2
            EOO
          }

          : false
          :
          {
            $c <"$false 1 || $true 2 || $false 3" && $b >>EOO
            1
            2
            EOO
          }
        }

        : AND
        :
        {
          : true
          :
          {
            $c <"$false 1 || $true 2 && $true 3" && $b >>EOO
            1
            2
            3
            EOO
          }

          : false
          :
          {
            $c <"$false 1 || $true 2 && $false 3" && $bf >>EOO != 0
            1
            2
            3
            EOO
          }
        }
      }

      : false
      :
      {
        : TERM
        :
        $c <"$false 1 || $false 2" && $bf >>EOO != 0
        1
        2
        EOO

        : OR
        :
        {
          : true
          :
          {
            $c <"$false 1 || $false 2 || $true 3" && $b >>EOO
            1
            2
            3
            EOO
          }

          : false
          :
          {
            $c <"$false 1 || $false 2 || $false 3" && $bf >>EOO != 0
            1
            2
            3
            EOO
          }
        }

        : AND
        :
        {
          : true
          :
          {
            $c <"$false 1 || $false 2 && $true 3" && $bf >>EOO != 0
            1
            2
            EOO
          }

          : false
          :
          {
            $c <"$false 1 || $false 2 && $false 3" && $bf >>EOO != 0
            1
            2
            EOO
          }
        }
       }
    }

    : AND
    :
    {
      : true
      :
      {
        : TERM
        :
        $c <"$false 1 && $true 2" && $bf >>EOO != 0
        1
        EOO

        : OR
        :
        {
          : true
          :
          {
            $c <"$false 1 && $true 2 || $true 3" && $b >>EOO
            1
            3
            EOO
          }

          : false
          :
          {
            $c <"$false 1 && $true 2 || $false 3" && $bf >>EOO != 0
            1
            3
            EOO
          }
        }

        : AND
        :
        {
          : true
          :
          {
            $c <"$false 1 && $true 2 && $true 3" && $bf >>EOO != 0
            1
            EOO
          }

          : false
          :
          {
            $c <"$false 1 && $true 2 && $false 3" && $bf >>EOO != 0
            1
            EOO
          }
        }
      }

      : false
      :
      {
        : TERM
        :
        $c <"$false 1 && $false 2" && $bf >>EOO != 0
        1
        EOO

        : OR
        :
        {
          : true
          :
          {
            $c <"$false 1 && $false 2 || $true 3" && $b >>EOO
            1
            3
            EOO
          }

          : false
          :
          {
            $c <"$false 1 && $false 2 || $false 3" && $bf >>EOO != 0
            1
            3
            EOO
          }
        }

        : AND
        :
        {
          : true
          :
          {
            $c <"$false 1 && $false 2 && $true 3" && $bf >>EOO != 0
            1
            EOO
          }

          : false
          :
          {
            $c <"$false 1 && $false 2 && $false 3" && $bf >>EOO != 0
            1
            EOO
          }
        }
      }
    }
  }
}

: diagnostics
:
: Check that the diagnostics is printed for only the last faulty pipe.
:
{
  true  = '$*'
  false = '$* -s 1 2>'X' -e' # Compares stderr to value that never matches.

  : trailing
  :
  $c <"$false 1 != 0 || $true && $false 2 != 0" && $b 2>>~/EOE/ != 0
  /.{7}
  -X
  +2
  EOE

  : non-trailing
  :
  $c <"$false 1 != 0 || $true && $false 2 != 0 && $true" && $b 2>>~/EOE/ != 0
  /.{7}
  -X
  +2
  EOE
}