<commit_before>#!/usr/bin/env ../test_wrapper.sh lib

require_relative 'lib_test_base'

class DockerGitCloneRunnerTests < LibTestBase

  def setup
    super
    @bash = BashStub.new
    @cid_filename = 'stub.cid'
    set_disk_class_name     'DiskStub'
    set_git_class_name      'GitSpy'
    set_one_self_class_name 'OneSelfDummy'
    @id = '12345ABCDE'
    kata = make_kata(@id)
    @lion = kata.start_avatar(['lion'])
  end

  # - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  test 'when docker is not installed constructor raises' do
    stub_docker_not_installed
    assert_raises(RuntimeError) { make_docker_runner }
  end

  # - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  test 'bash commands run inside initialize() use sudo' do
    stub_docker_installed
    make_docker_runner
    assert @bash.spied[0].start_with?(sudoi('docker info')), 'docker info'
    assert @bash.spied[1].start_with?(sudoi('docker images')), 'docker images'
  end

  # - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  test 'when docker is installed, image_names determines runnability' do
    stub_docker_installed
    docker = make_docker_runner
    expected_image_names =
    [
      "cyberdojo/python-3.3.5_pytest",
      "cyberdojo/rust-1.0.0_test"
    ]
    c_assert = languages['C-assert']
    python_py_test = languages['Python-py.test']

    assert_equal expected_image_names, docker.image_names, 'image names'
    refute docker.runnable?(c_assert), 'c_assert'
    assert docker.runnable?(python_py_test), 'python_py_test'
  end
    
  # - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  test 'started(avatar) is a not a no-op' do
    stub_docker_installed
    docker = make_docker_runner
    assert_equal 2, @bash.spied.size, 'before'
    docker.started(@lion)
    assert_equal 3, @bash.spied.size, 'after'    
    bash_cmd = @bash.spied[2]
    assert bash_cmd.include?('git clone --bare lion'), 'creates bare repo'
    assert bash_cmd.include?('sudo -u cyber-dojo scp -r lion.git'), 'copies it to git server'
    assert bash_cmd.include?('git-daemon-export-ok'), 'sets git-daemon-export-ok'
    assert bash_cmd.include?('git remote add master'), 'sets up git remote master 1'
    assert bash_cmd.include?('sudo -u cyber-dojo git push --set-upstream master master'), 'sets up git remote master 1'    
  end

  # - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  test 'pre_test(avatar) is a not a no-op' do
    stub_docker_installed
    docker = make_docker_runner
    assert_equal 2, @bash.spied.size, 'before'
    docker.pre_test(@lion)
    assert_equal 3, @bash.spied.size, 'after'
    bash_cmd = @bash.spied[2]
    assert bash_cmd.include?('sudo -u cyber-dojo git commit'), 'git commit'
    assert bash_cmd.include?('sudo -u cyber-dojo git push'), 'git push'
  end
    
  # - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  include IdSplitter

  test 'exact docker run command to refactor against' do
    stub_docker_installed
    docker = make_docker_runner
    stub_docker_run(completes)
    cmd = 'cyber-dojo.sh'
    docker.run(@lion.sandbox, cmd, max_seconds=5)

    clone_and_timeout_cmd =
      "git clone git://#{docker.git_server_ip}/#{outer(@id)}/#{inner(@id)}/lion.git /tmp/lion 2>&1 > /dev/null;" +
      "cd /tmp/lion/sandbox && timeout --signal=#{kill} 5s #{cmd} 2>&1"

    expected =
      "timeout --signal=#{kill} 10s" +
        ' docker run' +
          ' --user=www-data' +
          " --cidfile=#{quoted(@cid_filename)}" +
          ' --net=host' +
          " #{@lion.kata.language.image_name}" +
          " /bin/bash -c #{quoted(clone_and_timeout_cmd)} 2>&1"

    actual = @bash.spied[3]
    assert_equal expected, actual
  end

  # - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  test 'docker run <-> bash interaction when cyber-dojo.sh completes in time' do
    stub_docker_installed
    docker = make_docker_runner
    begin
      stub_docker_run(completes)
      cmd = 'cyber-dojo.sh'
      output = docker.run(@lion.sandbox, cmd, max_seconds=5)      
      assert_equal 'blah',output, 'output'      
      assert_spied(max_seconds, cmd, pid)
    rescue Exception => e  
      p e.message
      @bash.dump
      assert false
    end
  end    
  
  # - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  test 'docker run <-> bash interaction when cyber-dojo.sh times out' do
    stub_docker_installed
    docker = make_docker_runner
    begin
      stub_docker_run(times_out)
      cmd = 'cyber-dojo.sh'
      output = docker.run(@lion.sandbox, cmd, max_seconds=5)      
      assert output.start_with?("Unable to complete the tests in #{max_seconds} seconds."), 'Unable'      
      assert_spied(max_seconds, cmd, pid)
    rescue Exception => e
      p e.message
      @bash.dump    
      assert false
    end
  end
  
  # - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  
  def assert_spied(max_seconds, cmd, pid)
    run_cmd = @bash.spied[3]
    expected = "timeout --signal=#{kill} #{max_seconds+5}s"
    assert run_cmd.start_with?(expected), 'timeout(outer)'
    expected = 'git clone'
    assert run_cmd.include?(expected), 'git clone'
    expected = "timeout --signal=#{kill} #{max_seconds}s cyber-dojo.sh"
    assert run_cmd.include?(expected), 'timeout(inner)'    
    
    assert run_cmd.include?('docker run'), 'docker run'
    assert run_cmd.include?('--user=www-data'), 'user inside docker container is www-data'
    assert run_cmd.include?("--cidfile="), 'explicit cidfile'
    refute run_cmd.include?('--rm'), 'rm is *not* specified'
    refute run_cmd.include?('-v "/var/www/cyber-dojo/languages'), 'volume mount languages/'
    refute run_cmd.include?('-v "/var/www/cyber-dojo/katas'), 'volume mount katas/'
    assert_equal "docker stop #{pid}", @bash.spied[5], 'docker stop'
    assert_equal "docker rm #{pid}",   @bash.spied[6], 'docker rm'
  end
  
  # - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  
  def make_docker_runner
    DockerGitCloneRunner.new(@bash,@cid_filename)
  end

  # - - - - - - - - - - - - - - - - - - - - - - - - - - - -
<commit_msg>DockerRunner related test refactoring<commit_after>#!/usr/bin/env ../test_wrapper.sh lib

require_relative 'lib_test_base'

class DockerGitCloneRunnerTests < LibTestBase

  def setup
    super
    @bash = BashStub.new
    @cid_filename = 'stub.cid'
    set_disk_class_name     'DiskStub'
    set_git_class_name      'GitSpy'
    set_one_self_class_name 'OneSelfDummy'
    @id = '<KEY>'
    kata = make_kata(@id)
    @lion = kata.start_avatar(['lion'])
  end

  # - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  test 'when docker is not installed constructor raises' do
    stub_docker_not_installed
    assert_raises(RuntimeError) { make_docker_runner }
  end

  # - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  test 'bash commands run inside initialize() use sudo' do
    stub_docker_installed
    make_docker_runner
    assert @bash.spied[0].start_with?(sudoi('docker info')), 'docker info'
    assert @bash.spied[1].start_with?(sudoi('docker images')), 'docker images'
  end

  # - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  test 'when docker is installed, image_names determines runnability' do
    stub_docker_installed
    docker = make_docker_runner
    expected_image_names =
    [
      "cyberdojo/python-3.3.5_pytest",
      "cyberdojo/rust-1.0.0_test"
    ]
    c_assert = languages['C-assert']
    python_py_test = languages['Python-py.test']

    assert_equal expected_image_names, docker.image_names, 'image names'
    refute docker.runnable?(c_assert), 'c_assert'
    assert docker.runnable?(python_py_test), 'python_py_test'
  end
    
  # - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  test 'started(avatar) clones avatar repo and pushes it to git server' do
    stub_docker_installed
    docker = make_docker_runner
    assert_equal 2, @bash.spied.size, 'before'
    docker.started(@lion)
    assert_equal 3, @bash.spied.size, 'after'    
    bash_cmd = @bash.spied[2]
    assert bash_cmd.include?('git clone --bare lion'), 'creates bare repo'
    assert bash_cmd.include?('sudo -u cyber-dojo scp -r lion.git'), 'copies it to git server'
    assert bash_cmd.include?('git-daemon-export-ok'), 'sets git-daemon-export-ok'
    assert bash_cmd.include?('git remote add master'), 'sets up git remote master 1'
    assert bash_cmd.include?('sudo -u cyber-dojo git push --set-upstream master master'), 'sets up git remote master 1'    
  end

  # - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  test 'pre_test(avatar) commits and pushes to git server' do
    stub_docker_installed
    docker = make_docker_runner
    assert_equal 2, @bash.spied.size, 'before'
    docker.pre_test(@lion)
    assert_equal 3, @bash.spied.size, 'after'
    bash_cmd = @bash.spied[2]
    assert bash_cmd.include?('sudo -u cyber-dojo git commit'), 'git commit'
    assert bash_cmd.include?('sudo -u cyber-dojo git push'), 'git push'
  end
    
  # - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  test 'docker run does not timeout' do
    stub_docker_installed
    make_docker_runner
    stub_docker_run(completes)
    cmd = 'cyber-dojo.sh'
    output = @runner.run(@lion.sandbox, cmd, max_seconds=5)
    assert_equal 'blah',output, 'output'
    assert_spied(max_seconds, cmd, pid)
  end

  # - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  test 'docker run times out' do
    stub_docker_installed
    make_docker_runner
    stub_docker_run(times_out)
    cmd = 'cyber-dojo.sh'
    output = @runner.run(@lion.sandbox, cmd, max_seconds=5)
    assert output.start_with?("Unable to complete the tests in #{max_seconds} seconds."), 'Unable'
    assert_spied(max_seconds, cmd, pid)
  end
  
  # - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  include IdSplitter

  def exact_docker_run_cmd
    repo = "git://#{@runner.git_server_ip}/#{outer(@id)}/#{inner(@id)}/lion.git"
    clone_and_timeout_cmd =
      "git clone #{repo} /tmp/lion 2>&1 > /dev/null;" +
      "cd /tmp/lion/sandbox && timeout --signal=#{kill} 5s cyber-dojo.sh 2>&1"

    "timeout --signal=#{kill} 10s" +
      ' docker run' +
        ' --user=www-data' +
        " --cidfile=#{quoted(@cid_filename)}" +
        ' --net=host' +
        " #{@lion.kata.language.image_name}" +
        " /bin/bash -c #{quoted(clone_and_timeout_cmd)} 2>&1"
  end

  # - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  
  def assert_spied(max_seconds, cmd, pid)
    spied = @bash.spied
    assert_equal "rm -f #{@cid_filename}", spied[2], 'remove cidfile'
    assert_equal exact_docker_run_cmd,     spied[3], 'main docker run command'
    assert_equal "cat #{@cid_filename}",   spied[4], 'get pid from cidfile'
    assert_equal "docker stop #{pid}",     spied[5], 'docker stop'
    assert_equal "docker rm #{pid}",       spied[6], 'docker rm'
  end
  
  # - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  
  def make_docker_runner
    @runner = DockerGitCloneRunner.new(@bash,@cid_filename)
  end

  # - - - - - - - - - - - - - - - - - - - - - - - - - - - -

{'fraction_non_alphanumeric': 0.1667117482643585, 'fraction_numerical': 0.006311423676855108, 'mean_word_length': 2.112233445566779, 'pattern_counts': {'":': 0, '<': 8, '<?xml version=': 0, '>': 16, 'https://': 0, 'lorem ipsum': 0, 'www.': 6, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 88, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2876561', 'n_tokens_mistral': 4294, 'n_tokens_neox': 4053, 'n_words': 772}