# file      : tests/ci.testscript
# license   : MIT; see accompanying LICENSE file

.include common.testscript project.testscript

# bdep-ci requirements for the minimum supported git version are higher then
# the default 2.1.0 (see bdep/ci.cxx for details).
#
+if! ($git_version_major >  2 || \
      $git_version_major == 2 && $git_version_minor >= 11)
  exit
end

server = $config.bdep.tests.ci.server

+if ("$server" == '')
  exit
end

# Create the remote repository.
#
+mkdir --no-cleanup prj.git
+git -C prj.git -c init.defaultBranch=master init --bare --quiet &prj.git/***

# Adjust the local repository and push it to the remote one.
#
+sed -i -e 's/^(version:) .*$/\1 1.0.1/' prj/manifest

+cat <<EOI >+prj/build/root.build
  config [bool] config.prj.network ?= false
  config [bool] config.prj.cache ?= false
  EOI

+cat <<EOI >+prj/manifest
  network-build-config: config.prj.network=true
  EOI

g = [cmdline] git -C prj 2>! >&2

+$g config user.name 'Test Script'
+$g config user.email 'testscript@example.com'
+$g remote add origin $~/prj.git
+$g add '*'
+$g commit -m 'Create' --no-verify
+$g push --set-upstream origin master

# Repository the CI-ed packages come from.
#
repository='http://example.com/prj.git'

test.arguments += --yes --repository "$repository" --server "$server" \
                  --simulate 'success'

config_cxx = [cmdline] cc config.cxx=$quote($recall($cxx.path) $cxx.config.mode, true)

new  += --vcs git,branch=master 2>!
init += $config_cxx -d prj 2>! &prj/**/bootstrap/***

windows = ($cxx.target.class == 'windows')

# Normally we disable the progress indication that complicates stderr output
# validation. We also disable the progress indication test on Windows, as
# curl's progress is not always properly terminated there, messing up with
# the subsequent output.
#
: single-pkg
:
{
  : single-cfg
  :
  {
    $clone_root_prj;
    $init -C @cfg &prj-cfg/***;

    $* --no-progress 2>>~%EOE%
      %CI request is queued.*%
      %reference: .+%
      EOE
  }

  : progress
  :
  if! $windows
  {
    $clone_root_prj;
    $init -C @cfg &prj-cfg/***;

    $* 2>>~"%EOE%"
      submitting to $server
      %.*
      %CI request is queued.*%
      %reference: .+%
      EOE
  }

  : no-cfg
  :
  {
    $new prj &prj/***;

    $* 2>>~%EOE% != 0
      %error: no default configuration in project .+%
      %  info: use .+%
      EOE
  }

  : multi-cfg
  :
  {
    $clone_root_prj;
    $init -C @cfg1 &prj-cfg1/***;
    $init -C @cfg2 &prj-cfg2/***;

    $* --all 2>>EOE != 0
      error: package prj is initialized in multiple specified configurations
        info: @cfg1
        info: @cfg2
      EOE
  }

  : no-commits
  :
  {
    $new prj &prj/***;
    $init -C @cfg &prj-cfg/***;

    $* 2>>~%EOE% != 0
      error: no commits in project repository
      %  info: run .+%
      EOE
  }

  : invalid-repo
  :
  {
    test.arguments += --repository "$repository#frag"

    $clone_root_prj;
    $init -C @cfg &prj-cfg/***;

    $* 2>>"EOE" != 0
      error: remote git repository URL '$repository#frag' already has fragment
      EOE
  }

  : overrides
  :
  {
    +$clone_root_prj
    +$init -C @cfg &prj-cfg/***

    test.options += --no-progress

    : common-build-constraints
    :
    : Here we only test that bdep-ci does not fail for valid overrides. It
    : seems to be impossible to verify the submitted overrides manifest.
    :
    {
      $clone_prj;

      cat <<EOI >=overrides.manifest;
        : 1
        builds: all
        EOI

      $* --overrides-file overrides.manifest \
         --build-email 'foo@example.com' \
         --override 'build-error-email: error@example.com' \
         --override 'builds: &gcc' \
         --override 'build-include: linux*' \
         --override 'build-exclude: *' 2>>~%EOE%
        %CI request is queued.*%
        %reference: .+%
        EOE
    }

    : package-build-constraints
    :
    {
      $clone_prj;

      $* --builds 'default/&gcc' \
         --override 'default-build-include: linux*' \
         --override 'default-build-exclude: *' 2>>~%EOE%
        %CI request is queued.*%
        %reference: .+%
        EOE
    }

    : build-configs
    :
    {
      $clone_prj;

      $* --override 'mytest-build-config: config.prj.network=true config.prj.cache=true' \
         --override 'default-build-config: config.prj.network=true' 2>>~%EOE%
        %CI request is queued.*%
        %reference: .+%
        EOE
    }

    : build-configs-constraints
    :
    {
      $clone_prj;

      $* --override 'mytest-build-config: config.prj.network=true config.prj.cache=true' \
         --build-config 'mytest/linux*-gcc*' \
         --override 'default-build-config: config.prj.network=true' \
         --build-config 'default/macos*-gcc*' 2>>~%EOE%
        %CI request is queued.*%
        %reference: .+%
        EOE
    }

    : build-configs-package-config
    :
    {
      $clone_prj;

      $* --override 'mytest-build-config: config.prj.network=true config.prj.cache=true' \
         --package-config 'mytest' 2>>~%EOE%
        %CI request is queued.*%
        %reference: .+%
        EOE
    }

    : common-package-build-constraints
    :
    {
      $clone_prj;

      cat <<EOI >=overrides.manifest;
        : 1
        builds: all
        EOI

      $* --builds 'network/&gcc' --overrides-file overrides.manifest 2>>~%EOE% != 0
        error: invalid file referenced by --overrides-file option: 'builds' override specified together with 'network-builds' override
          info: override: builds: all
        EOE
    }

    : invalid-option
    :
    {
      +$clone_prj

      : overrides-file
      :
      {
        +$clone_prj

        : reading
        :
        {
          $clone_prj;

          $* --overrides-file overrides.manifest 2>>~%EOE% != 0
            %error: invalid value 'overrides.manifest' for option '--overrides-file': unable to read: .+%
            EOE
        }

        : parsing
        :
        {
          $clone_prj;

          cat <<EOI >=overrides.manifest;
            builds: all
            EOI

          $* --overrides-file overrides.manifest 2>>EOE != 0
            error: invalid value 'overrides.manifest' for option '--overrides-file': unable to parse: 1:1: error: format version pair expected
            EOE
        }
      }

      : override
      :
      {
        $clone_prj;

        $* --override 'all' 2>>EOE != 0
          error: invalid value 'all' for option '--override': missing ':'
          EOE
      }

      : override-pair
      :
      : Each override option is valid by its own, but the resulting overrides
      : manifest is invalid.
      :
      {
        $clone_prj;

        $* --override 'builds: all' --override 'builds: default : &gcc' 2>>EOE != 0
          error: invalid --override option value: invalid package builds: unexpected underlying class set
            info: override: builds: default : &gcc
          EOE
      }

      : overrides
      :
      : This is a fake option (see ci.cli for details).
      :
      {
        $clone_prj;

        $* --overrides 'all' 2>>EOE != 0
          error: unknown option '--overrides'
          EOE
      }

      : target-and-package-configs
      :
      {
        $clone_prj;

        $* --override 'builds: gcc' --override 'network-builds: linux' 2>>EOE != 0
          error: invalid --override option value: 'network-builds' override specified together with 'builds' override
            info: override: network-builds: linux
          EOE
      }
    }
  }

  : target-config
  :
  {
    +$clone_root_prj
    +$init -C @cfg &prj-cfg/***

    test.options += --no-progress

    : valid
    :
    {
      $clone_prj;

      $* --target-config 'linux**/x86_64**' --target-config 'freebsd**' 2>>~%EOE%
        %CI request is queued.*%
        %reference: .+%
        EOE
    }

    : empty-config
    :
    {
      $clone_prj;

      $* --target-config '/x86_64**' 2>>EOE != 0
        error: invalid --target-config option value: empty build configuration name pattern
          info: override: build-include: /x86_64**
        EOE
    }

    : empty-target
    :
    {
      $clone_prj;

      $* --target-config 'linux**/' 2>>EOE != 0
        error: invalid --target-config option value: empty build target pattern
          info: override: build-include: linux**/
        EOE
    }

    : overrides
    :
    {
      $clone_prj;

      $* --target-config 'linux_debian_8-gcc_4.9' --builds '&gcc' 2>>EOE != 0
        error: invalid --builds option value: 'builds' override specified together with --target-config
          info: override: builds: &gcc
        EOE
    }

    : interactive
    :
    {
      $clone_prj;

      $* --target-config 'linux**' --interactive 'linux_debian_8-gcc_4.9' 2>>EOE != 0
        error: --target-config specified together with --interactive|-i
        EOE
    }

    : package-config
    :
    {
      $clone_prj;

      $* --target-config 'linux**' --package-config 'default' 2>>EOE != 0
        error: --target-config specified together with --package-config
        EOE
    }
  }

  : build-config
  :
  {
    +$clone_root_prj
    +$init -C @cfg &prj-cfg/***

    test.options += --no-progress

    : multiple
    :
    {
      $clone_prj;

      $* --build-config 'default/linux**/x86_64**' --build-config 'default/freebsd**' 2>>~%EOE%
        %CI request is queued.*%
        %reference: .+%
        EOE
    }

    : invalid-package-config
    :
    {
      $clone_prj;

      $* --build-config 'default/linux**/x86_64**' --package-config 'cache' 2>>EOE != 0
        error: invalid --package-config option value: package prj has no build configuration 'cache'
        EOE
    }

    : with-package-config-option
    :
    {
      $clone_prj;

      $* --build-config 'default/linux**/x86_64**' --package-config 'network' 2>>~%EOE%
        %CI request is queued.*%
        %reference: .+%
        EOE
    }

    : invalid-package-config-option
    :
    {
      $clone_prj;

      $* --build-config 'default/linux**/x86_64**' --package-config 'default' 2>>EOE != 0
        error: package configuration default is specified using both --package-config and --build-config
        EOE
    }

    : no-target-config
    :
    {
      $clone_prj;

      $* --build-config 'default' 2>>EOE != 0
        error: invalid --build-config option value: no target configuration in 'default'
        EOE
    }

    : empty-package-config
    :
    {
      $clone_prj;

      $* --build-config '/linux**/x86_64**' 2>>EOE != 0
        error: invalid --build-config option value: no package configuration in '/linux**/x86_64**'
        EOE
    }

    : empty-target-config
    :
    {
      $clone_prj;

      $* --build-config 'default//x86_64**' 2>>EOE != 0
        error: invalid --build-config option value: empty build configuration name pattern
          info: override: default-build-include: /x86_64**
        EOE
    }

    : empty-target
    :
    {
      $clone_prj;

      $* --build-config 'default/linux**/' 2>>EOE != 0
        error: invalid --build-config option value: empty build target pattern
          info: override: default-build-include: linux**/
        EOE
    }

    : overrides
    :
    {
      $clone_prj;

      $* --build-config 'default/linux_debian_8-gcc_4.9' --builds '&gcc' 2>>EOE != 0
        error: invalid --builds option value: 'builds' override specified together with --build-config
          info: override: builds: &gcc
        EOE
    }

    : interactive
    :
    {
      $clone_prj;

      $* --build-config 'default/linux**' --interactive 'linux_debian_8-gcc_4.9' 2>>EOE != 0
        error: --build-config specified together with --interactive|-i
        EOE
    }

    : package-config
    :
    {
      $clone_prj;

      $* --build-config 'linux**' --target-config 'linux_debian_8-gcc_4.9' 2>>EOE != 0
        error: --target-config specified together with --build-config
        EOE
    }
  }

  : package-config
  :
  {
    +$clone_root_prj
    +$init -C @cfg &prj-cfg/***

    test.options += --no-progress

    : valid
    :
    {
      $clone_prj;

      $* --package-config 'network' 2>>~%EOE%
        %CI request is queued.*%
        %reference: .+%
        EOE
    }

    : interactive
    :
    {
      $clone_prj;

      $* --package-config 'default' --interactive 'linux_debian_8-gcc_4.9' 2>>EOE != 0
        error: --package-config specified together with --interactive|-i
        EOE
    }
  }

  : interactive
  :
  {
    +$clone_root_prj
    +$init -C @cfg &prj-cfg/***

    test.options += --no-progress

    : target-config
    :
    {
      $clone_prj;

      $* --interactive 'linux_debian_8-gcc_4.9:warning' 2>>~%EOE%
        %CI request is queued.*%
        %reference: .+%
        EOE
    }

    : package-target-config
    :
    {
      $clone_prj;

      $* --interactive 'network/linux_debian_8-gcc_4.9:warning' 2>>~%EOE%
        %CI request is queued.*%
        %reference: .+%
        EOE
    }

    : package-target-config-target
    :
    {
      $clone_prj;

      $* --interactive 'network/linux_debian_8-gcc_4.9/aarch64**:warning' 2>>~%EOE%
        %CI request is queued.*%
        %reference: .+%
        EOE
    }

    : def-breakpoint
    :
    {
      $clone_prj;

      $* --interactive 'linux_debian_8-gcc_4.9' 2>>~%EOE%
        %CI request is queued.*%
        %reference: .+%
        EOE
    }

    : config-empty
    :
    {
      $clone_prj;

      $* --interactive '/warning' 2>>EOE != 0
        error: invalid --interactive|-i option value '/warning': package configuration name is empty
        EOE
    }

    : overrides
    :
    {
      $clone_prj;

      $* --interactive 'linux_debian_8-gcc_4.9' --builds '&gcc' 2>>EOE != 0
        error: invalid --builds option value: 'builds' override specified together with --interactive|-i
          info: override: builds: &gcc
        EOE
    }
  }

  : non-standard-version
  :
  : Test submitting a package with the non-standard version from a
  : non-bdep-initialized project, using the forwarded build2 configuration.
  :
  {
    cp --no-cleanup -pr ../../prj ./ &prj/***;
    rm -r prj/.bdep/;

    sed -i -e 's/^(version:) .*$/\1 12345/' prj/manifest;

    sed -i \
        -e 's/^(project =.*)$/\1\nversion = 12345/' \
        -e 's/^using version$//' \
        prj/build/bootstrap.build;

    $g branch non-standard-version;
    $g checkout non-standard-version;
    $g -c core.safecrlf=false commit -a -m 'Change version';
    $g push --set-upstream origin non-standard-version;

    $build 'configure:' prj/@prj-cfg/,forward &prj/build/bootstrap/*** 2>!;

    $* --no-progress --forward 2>>~%EOE%
      %CI request is queued.*%
      %reference: .+%
      EOE
  }
}

: multi-pkg
:
{
  # Create the remote repository.
  #
  +mkdir --no-cleanup prj.git
  +git -C prj.git -c init.defaultBranch=master init --bare --quiet &prj.git/***

  # Create the local repository and push it to the remote one.
  #
  +$new -t empty prj &prj/***
  +$new --package -t lib libprj -d prj
  +$new --package -t exe prj    -d prj
  +sed -i -e 's/^(version:) .*$/\1 1.0.1/' prj/libprj/manifest
  +sed -i -e 's/^(version:) .*$/\1 1.0.1/' prj/prj/manifest

  +$g config user.name 'Test Script'
  +$g config user.email 'testscript@example.com'
  +$g remote add origin $~/prj.git
  +$g add '*'
  +$g commit -m 'Create'
  +$g push --set-upstream origin master

  test.options += --no-progress

  : both
  :
  {
    $clone_prj;
    $init -C @cfg &prj-cfg/***;

    $* 2>>~%EOE%
      %CI request is queued.*%
      %reference: .+%
      EOE
  }

  : diff-configs
  :
  {
    $clone_prj;
    $init -C @cfg1 -d prj/libprj &prj-cfg1/***;

    # While at it, test that we fail for uninitialized package.
    #
    $* -d prj/prj 2>>EOE != 0;
      error: package prj is not initialized in any configuration
      EOE

    $init -C @cfg2 --config-type host -d prj/prj &prj-cfg2/***;

    $* 2>>~%EOE%
      %CI request is queued.*%
      %reference: .+%
      EOE
  }

  : single
  :
  {
    $clone_prj;
    $init -C @cfg &prj-cfg/***;

    # CI the single libprj package rather than the whole prj project.
    #
    test.arguments = $regex.apply($test.arguments, '^(prj)$', '\1/libprj');

    $* 2>>~%EOE%
      %CI request is queued.*%
      %reference: .+%
      EOE
  }

  : interactive
  :
  {
    $clone_prj;
    $init -C @cfg &prj-cfg/***;

    $* --interactive 'linux_debian_8-gcc_4.9' 2>>EOE != 0
      error: multiple packages specified with --interactive|-i
      EOE
  }

  : prompt
  :
  {
    $clone_prj;
    $init -C @cfg &prj-cfg/***;

    # Suppress the --yes option.
    #
    test.arguments = $regex.apply($test.arguments, '^(--yes)$', '');

    $* <'y' 2>>~"%EOE%"
      submitting:
        to:      $server
      %  in:      $repository#master@.{40}%

        package: libprj
        version: 1.0.1

        package: prj
        version: 1.0.1
      %continue\\?.+ CI request is queued.*%
      %reference: .+%
      EOE
  }
}
