text: # Copyright 2020 Northern.tech AS
  #
  #    Licensed under the Apache License, Version 2.0 (the "License");
  #    you may not use this file except in compliance with the License.
  #    You may obtain a copy of the License at
  #
  #        https://www.apache.org/licenses/LICENSE-2.0
  #
  #    Unless required by applicable law or agreed to in writing, software
  #    distributed under the License is distributed on an "AS IS" BASIS,
  #    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  #    See the License for the specific language governing permissions and
  #    limitations under the License.
  
  import os
  import sys
  import shutil
  import re
  from unittest.mock import patch
  
  import pytest
  
  from release_tool import main
  from release_tool import docker_compose_files_list
  
  THIS_DIR = os.path.dirname(os.path.abspath(__file__))
  RELEASE_TOOL = os.path.join(THIS_DIR, "release_tool.py")
  INTEGRATION_DIR = os.path.normpath(os.path.join(THIS_DIR, ".."))
  
  
  @pytest.fixture(scope="function", autouse=True)
  def master_yml_files(request):
      """Edit all yml files setting them to 'master'/'mender-master' versions
  
      So that the tests can be run from any branch or with any
      local changes in the yml files. The files are restored after
      the test run.
      """
  
      docker_files = docker_compose_files_list(INTEGRATION_DIR, "docker")
      for filename in docker_files:
          shutil.copyfile(filename, filename + ".bkp")
      for filename in docker_compose_files_list(INTEGRATION_DIR, "git"):
          if filename not in docker_files:
              shutil.copyfile(filename, filename + ".bkp")
  
      for filename in docker_files:
          with open(filename) as fd:
              full_content = "".join(fd.readlines())
          with open(filename, "w") as fd:
              fd.write(
                  re.sub(
                      r"image:\s+(mendersoftware|.*mender\.io)/((?!mender\-client\-.+|mender-artifact|mender-cli).+):.*",
                      r"image: \g<1>/\g<2>:mender-master",
                      full_content,
                  )
              )
          with open(filename) as fd:
              full_content = "".join(fd.readlines())
          with open(filename, "w") as fd:
              fd.write(
                  re.sub(
                      r"image:\s+(mendersoftware|.*mender\.io)/(mender\-client\-.+|mender-artifact|mender-cli):.*",
                      r"image: \g<1>/\g<2>:master",
                      full_content,
                  )
              )
  
      for filename in docker_compose_files_list(INTEGRATION_DIR, "git"):
          if filename not in docker_files:
              with open(filename) as fd:
                  full_content = "".join(fd.readlines())
              with open(filename, "w") as fd:
                  fd.write(
                      re.sub(
                          r"image:\s+(mendersoftware|.*mender\.io)/(.+):.*",
                          r"image: \g<1>/\g<2>:master",
                          full_content,
                      )
                  )
  
      def restore():
          docker_files = docker_compose_files_list(INTEGRATION_DIR, "docker")
          for filename in docker_files:
              os.rename(filename + ".bkp", filename)
          for filename in docker_compose_files_list(INTEGRATION_DIR, "git"):
              if filename not in docker_files:
                  os.rename(filename + ".bkp", filename)
  
      request.addfinalizer(restore)
  
  
  def run_main_assert_result(capsys, args, expect=None):
      testargs = [RELEASE_TOOL] + args
      with patch.object(sys, "argv", testargs):
          main()
  
      captured = capsys.readouterr().out.strip()
      if expect is not None:
          assert captured == expect
      return captured
  
  
  def test_version_of(capsys):
      # On a clean checkout, both will be master
      run_main_assert_result(capsys, ["--version-of", "deviceauth"], "master")
      run_main_assert_result(
          capsys,
          ["--version-of", "deviceauth", "--version-type", "docker"],
          "mender-master",
      )
      run_main_assert_result(
          capsys, ["--version-of", "deviceauth", "--version-type", "git"], "master"
      )
  
      # For an independent component, it should still accept docker/git type of the query
      run_main_assert_result(capsys, ["--version-of", "mender"], "master")
      run_main_assert_result(
          capsys, ["--version-of", "mender", "--version-type", "docker"], "master"
      )
      run_main_assert_result(
          capsys, ["--version-of", "mender", "--version-type", "git"], "master"
      )
      run_main_assert_result(capsys, ["--version-of", "mender-client-qemu"], "master")
      run_main_assert_result(
          capsys,
          ["--version-of", "mender-client-qemu", "--version-type", "docker"],
          "master",
      )
      run_main_assert_result(
          capsys,
          ["--version-of", "mender-client-qemu", "--version-type", "git"],
          "master",
      )
  
      # Manually modifying the Git version:
      filename = os.path.join(INTEGRATION_DIR, "git-versions.yml")
      with open(filename, "w") as fd:
          fd.write(
              """services:
      mender-deviceauth:
          image: mendersoftware/deviceauth:1.2.3-git
  """
          )
      run_main_assert_result(capsys, ["--version-of", "deviceauth"], "1.2.3-git")
      run_main_assert_result(
          capsys,
          ["--version-of", "deviceauth", "--version-type", "docker"],
          "mender-master",
      )
      run_main_assert_result(
          capsys, ["--version-of", "deviceauth", "--version-type", "git"], "1.2.3-git"
      )
  
      # Manually modifying the Docker version:
      filename = os.path.join(INTEGRATION_DIR, "docker-compose.yml")
      with open(filename, "w") as fd:
          fd.write(
              """services:
      mender-deviceauth:
          image: mendersoftware/deviceauth:4.5.6-docker
  """
          )
      run_main_assert_result(capsys, ["--version-of", "deviceauth"], "1.2.3-git")
      run_main_assert_result(
          capsys,
          ["--version-of", "deviceauth", "--version-type", "docker"],
          "4.5.6-docker",
      )
      run_main_assert_result(
          capsys, ["--version-of", "deviceauth", "--version-type", "git"], "1.2.3-git"
      )
  
  
  def test_version_of_with_in_integration_version(capsys):
      # In remote master, shall be master
      run_main_assert_result(
          capsys,
          ["--version-of", "inventory", "--in-integration-version", "master"],
          "master",
      )
      run_main_assert_result(
          capsys,
          [
              "--version-of",
              "inventory",
              "--version-type",
              "docker",
              "--in-integration-version",
              "master",
          ],
          "mender-master",
      )
      run_main_assert_result(
          capsys,
          [
              "--version-of",
              "inventory",
              "--version-type",
              "git",
              "--in-integration-version",
              "master",
          ],
          "master",
      )
  
      # For old releases, --version-type shall be ignored
      run_main_assert_result(
          capsys,
          ["--version-of", "inventory", "--in-integration-version", "2.3.0"],
          "1.7.0",
      )
      run_main_assert_result(
          capsys,
          [
              "--version-of",
              "inventory",
              "--version-type",
              "git",
              "--in-integration-version",
              "2.3.0",
          ],
          "1.7.0",
      )
      run_main_assert_result(
          capsys,
          [
              "--version-of",
              "inventory",
              "--version-type",
              "docker",
              "--in-integration-version",
              "2.3.0",
          ],
          "1.7.0",
      )
  
  
  def test_set_version_of(capsys):
      # Using --set-version-of modifies both versions, regardless of using the repo name
      run_main_assert_result(
          capsys, ["--set-version-of", "deviceauth", "--version", "1.2.3-test"]
      )
      run_main_assert_result(capsys, ["--version-of", "deviceauth"], "1.2.3-test")
      run_main_assert_result(
          capsys, ["--version-of", "deviceauth", "--version-type", "docker"], "1.2.3-test"
      )
      run_main_assert_result(
          capsys, ["--version-of", "deviceauth", "--version-type", "git"], "1.2.3-test"
      )
  
      # or the container name. However, setting from the container name sets all repos (os + ent)
      run_main_assert_result(
          capsys, ["--set-version-of", "mender-deployments", "--version", "4.5.6-test"]
      )
      run_main_assert_result(capsys, ["--version-of", "mender-deployments"], "4.5.6-test")
      run_main_assert_result(
          capsys,
          ["--version-of", "mender-deployments", "--version-type", "docker"],
          "4.5.6-test",
      )
      run_main_assert_result(
          capsys,
          ["--version-of", "mender-deployments", "--version-type", "git"],
          "4.5.6-test",
      )
      # NOTE: skip check for OS flavor for branches without it (namely staging)
      list_repos = run_main_assert_result(capsys, ["--list", "git"], None)
      if "deployments" in list_repos.split("\n"):
          run_main_assert_result(capsys, ["--version-of", "deployments"], "4.5.6-test")
          run_main_assert_result(
              capsys,
              ["--version-of", "deployments", "--version-type", "docker"],
              "4.5.6-test",
          )
          run_main_assert_result(
              capsys,
              ["--version-of", "deployments", "--version-type", "git"],
              "4.5.6-test",
          )
      run_main_assert_result(
          capsys, ["--version-of", "deployments-enterprise"], "4.5.6-test"
      )
      run_main_assert_result(
          capsys,
          ["--version-of", "deployments-enterprise", "--version-type", "docker"],
          "4.5.6-test",
      )
      run_main_assert_result(
          capsys,
          ["--version-of", "deployments-enterprise", "--version-type", "git"],
          "4.5.6-test",
      )
  
  
  def test_integration_versions_including(capsys):
      captured = run_main_assert_result(
          capsys,
          ["--integration-versions-including", "inventory", "--version", "master"],
          None,
      )
      # The output shall be <remote>/master
      assert captured.endswith("/master")
  
      captured = run_main_assert_result(
          capsys,
          ["--integration-versions-including", "inventory", "--version", "1.6.x"],
          None,
      )
      # Three versions: <remote>/2.2.x, <remote>/2.1.x, <remote>/2.0.x
      versions = captured.split("\n")
      assert len(versions) == 3
      assert versions[0].endswith("/2.2.x")
      assert versions[1].endswith("/2.1.x")
      assert versions[2].endswith("/2.0.x")
  
  
  def test_docker_compose_files_list():
      list_git = docker_compose_files_list(INTEGRATION_DIR, version="git")
      list_git_filenames = [os.path.basename(file) for file in list_git]
      assert "docker-compose.client.demo.yml" in list_git_filenames
      assert "docker-compose.no-ssl.yml" in list_git_filenames
      assert "docker-compose.testing.enterprise.yml" in list_git_filenames
      assert "other-components.yml" in list_git_filenames
      assert "docker-compose.storage.minio.yml" in list_git_filenames
      assert "docker-compose.client.rofs.yml" in list_git_filenames
      assert "docker-compose.client-dev.yml" in list_git_filenames
      assert "docker-compose.mt.client.yml" in list_git_filenames
      assert "docker-compose.demo.yml" in list_git_filenames
      assert "docker-compose.client.yml" in list_git_filenames
      assert "docker-compose.docker-client.yml" in list_git_filenames
  
      assert "git-versions.yml" in list_git_filenames
      assert "git-versions-enterprise.yml" in list_git_filenames
      assert "docker-compose.yml" not in list_git_filenames
      assert "docker-compose.enterprise.yml" not in list_git_filenames
  
      list_docker = docker_compose_files_list(INTEGRATION_DIR, version="docker")
      list_docker_filenames = [os.path.basename(file) for file in list_docker]
      assert "docker-compose.client.demo.yml" in list_docker_filenames
      assert "docker-compose.no-ssl.yml" in list_docker_filenames
      assert "docker-compose.testing.enterprise.yml" in list_docker_filenames
      assert "other-components.yml" in list_docker_filenames
      assert "docker-compose.storage.minio.yml" in list_docker_filenames
      assert "docker-compose.client.rofs.yml" in list_docker_filenames
      assert "docker-compose.client-dev.yml" in list_docker_filenames
      assert "docker-compose.mt.client.yml" in list_docker_filenames
      assert "docker-compose.demo.yml" in list_docker_filenames
      assert "docker-compose.client.yml" in list_docker_filenames
      assert "docker-compose.docker-client.yml" in list_docker_filenames
  
      assert "git-versions.yml" not in list_docker_filenames
      assert "git-versions-enterprise.yml" not in list_docker_filenames
      assert "docker-compose.yml" in list_docker_filenames
      assert "docker-compose.enterprise.yml" in list_docker_filenames
  