<commit_before>require 'spec_helper'
require 'gitlab/docker_image_memory_measurer'

describe Gitlab::DockerImageMemoryMeasurer do
  let(:image_reference) { 'mocked_image_reference' }
  let(:measurer) { described_class.new(image_reference, debug_output_dir) }
  let(:delete_debug_output_dir) { FileUtils.remove_dir(debug_output_dir, true) }
  let(:create_debug_output_dir) { FileUtils.mkdir_p(debug_output_dir) unless debug_output_dir.nil? }

  before(:each) do
    create_debug_output_dir
  end

  after(:each) do
    delete_debug_output_dir
  end

  describe '.new' do
    context 'debug_output_dir is specified' do
      let(:debug_output_dir) { 'tmp/measure_log_folder' }

      it 'set debug output file names' do
        expect(measurer.container_log_file).to eq('tmp/measure_log_folder/container_setup.log')
        expect(measurer.pid_command_map_file).to eq('tmp/measure_log_folder/pid_command_map.txt')
        expect(measurer.smem_result_file).to eq('tmp/measure_log_folder/smem_result.txt')
      end
    end

    context 'debug_output_dir is not specified' do
      let(:debug_output_dir) { nil }

      it 'set debug output file names' do
        expect(measurer.container_log_file).to be_nil
        expect(measurer.pid_command_map_file).to be_nil
        expect(measurer.smem_result_file).to be_nil
      end
    end
  end

  describe '.check_url' do
    let(:debug_output_dir) { nil }

    it 'pass through the return value' do
      result = measurer.check_url do
        'value'
      end

      expect(result).to eq('value')
    end

    context 'when yield raise StandardError' do
      let(:raise_exception_in_yield) do
        measurer.check_url do
          raise StandardError
        end
      end

      it 'return false' do
        expect(raise_exception_in_yield).to be false
      end
    end
  end

  describe '.check_url_alive' do
    let(:debug_output_dir) { nil }
    let(:url) { 'url' }

    it 'return true when HTTP return code 200' do
      expect(HTTP).to receive(:get).with(url)
      allow(HTTP).to receive_message_chain(:get, :code).and_return(200)

      expect(measurer.check_url_alive(url)).to be true
    end

    it 'return false when HTTP return code 502' do
      expect(HTTP).to receive(:get).with(url)
      allow(HTTP).to receive_message_chain(:get, :code).and_return(502)

      expect(measurer.check_url_alive(url)).to be false
    end

    it 'return false when HTTP throw StandardError' do
      expect(HTTP).to receive(:get).with(url).and_raise(StandardError)

      expect(measurer.check_url_alive(url)).to be false
    end
  end

  describe '.status_ok?' do
    let(:debug_output_dir) { nil }

    context 'given non hash value' do
      let(:hash) { nil }

      it 'return false' do
        expect(measurer.status_ok?(hash)).to be false
      end
    end

    context 'given empty hash' do
      let(:hash) { {} }

      it 'return false' do
        expect(measurer.status_ok?(hash)).to be false
      end
    end

    context 'given valid hash with all status ok' do
      let(:hash) { { 'db_check' => { 'status' => 'ok' }, 'redis_check' => { 'status' => 'ok' } } }

      it 'return true' do
        expect(measurer.status_ok?(hash)).to be true
      end
    end

    context 'given valid hash with one status not ok' do
      let(:hash) { { 'db_check' => { 'status' => 'failed' }, 'redis_check' => { 'status' => 'ok' } } }

      it 'return false' do
        expect(measurer.status_ok?(hash)).to be false
      end
    end
  end

  describe '.check_gitlab_ready' do
    let(:debug_output_dir) { nil }
    let(:url) { 'url' }
    let(:http_return) { 'http_return' }
    let(:response) { 'response' }
    let(:status_ok_return) { 'status_ok_return' }

    it 'return whatever status_ok? result' do
      expect(HTTP).to receive(:get).with(url).and_return(http_return)
      allow(JSON).to receive(:parse).with(http_return).and_return(response)
      expect(measurer).to receive(:status_ok?).with(response).and_return(status_ok_return)

      expect(measurer.check_gitlab_ready(url)).to eq(status_ok_return)
    end

    it 'return false when HTTP throw StandardError' do
      expect(HTTP).to receive(:get).with(url).and_raise(StandardError)

      expect(measurer.check_gitlab_ready(url)).to be false
    end

    it 'return false when JSON throw StandardError' do
      expect(HTTP).to receive(:get).with(url).and_return(http_return)
      allow(JSON).to receive(:parse).with(http_return).and_raise(StandardError)

      expect(measurer.check_gitlab_ready(url)).to be false
    end
  end

  describe '.container_exec_command' do
    let(:debug_output_dir) { 'tmp/measure' }
    let(:container) { double }
    let(:command) { 'ls' }
    let(:log_file) { 'tmp/measure/log_file.txt' }

    context 'command succeed' do
      it 'return the stdout result' do
        expect(container).to receive(:exec).with(command).and_return([%w[success message], [], 0])
        command_ret = measurer.container_exec_command(container, command, log_file)
        expect(command_ret).to eq('successmessage')
      end
    end

    context 'command fail' do
      it 'should raise error' do
        expect(container).to receive(:exec).with(command).and_return([[], %w[error message], 1])
        expect { measurer.container_exec_command(container, command, log_file) }.to raise_error(SystemExit, 'errormessage')
      end
    end
  end

  describe '.stdout_to_hash_array' do
    let(:debug_output_dir) { nil }

    context 'use customised separator' do
      let(:stdout) do
        <<-STDOUTSTRING
           PID<Pid_Command_Separator>COMMAND
           1<Pid_Command_Separator>/bin/bash /assets/wrapper
           23<Pid_Command_Separator>runsv sshd
           24<Pid_Command_Separator>svlogd -tt /var/log/gitlab/sshd
        STDOUTSTRING
      end
      let(:separator) { /<Pid_Command_Separator>/ }
      let(:expected_ret) do
        [
          { 'PID' => '1', 'COMMAND' => '/bin/bash /assets/wrapper' },
          { 'PID' => '23', 'COMMAND' => 'runsv sshd' },
          { 'PID' => '24', 'COMMAND' => 'svlogd -tt /var/log/gitlab/sshd' }
        ]
      end

      it 'return hash array' do
        expect(measurer.stdout_to_hash_array(stdout, separator)).to eq(expected_ret)
      end
    end<commit_msg>Update metrics measurement spec test<commit_after>require 'spec_helper'
require 'gitlab/docker_image_memory_measurer'

describe Gitlab::DockerImageMemoryMeasurer do
  let(:image_reference) { 'mocked_image_reference' }
  let(:measurer) { described_class.new(image_reference, debug_output_dir) }
  let(:delete_debug_output_dir) { FileUtils.remove_dir(debug_output_dir, true) }
  let(:create_debug_output_dir) { FileUtils.mkdir_p(debug_output_dir) unless debug_output_dir.nil? }

  before(:each) do
    create_debug_output_dir
  end

  after(:each) do
    delete_debug_output_dir
  end

  describe '.new' do
    context 'debug_output_dir is specified' do
      let(:debug_output_dir) { 'tmp/measure_log_folder' }

      it 'set debug output file names' do
        expect(measurer.container_log_file).to eq('tmp/measure_log_folder/container_setup.log')
        expect(measurer.pid_command_map_file).to eq('tmp/measure_log_folder/pid_command_map.txt')
        expect(measurer.smem_result_file).to eq('tmp/measure_log_folder/smem_result.txt')
      end
    end

    context 'debug_output_dir is not specified' do
      let(:debug_output_dir) { nil }

      it 'set debug output file names' do
        expect(measurer.container_log_file).to be_nil
        expect(measurer.pid_command_map_file).to be_nil
        expect(measurer.smem_result_file).to be_nil
      end
    end
  end

  describe '.check_url' do
    let(:debug_output_dir) { nil }

    it 'pass through the return value' do
      result = measurer.check_url do
        'value'
      end

      expect(result).to eq('value')
    end

    context 'when yield raise StandardError' do
      let(:raise_exception_in_yield) do
        measurer.check_url do
          raise StandardError
        end
      end

      it 'return false' do
        expect(raise_exception_in_yield).to be false
      end
    end
  end

  describe '.check_url_alive' do
    let(:debug_output_dir) { nil }
    let(:url) { 'url' }

    it 'return true when HTTP return code 200' do
      expect(HTTP).to receive(:get).with(url)
      allow(HTTP).to receive_message_chain(:get, :code).and_return(200)

      expect(measurer.check_url_alive(url)).to be true
    end

    it 'return false when HTTP return code 502' do
      expect(HTTP).to receive(:get).with(url)
      allow(HTTP).to receive_message_chain(:get, :code).and_return(502)

      expect(measurer.check_url_alive(url)).to be false
    end

    it 'return false when HTTP throw StandardError' do
      expect(HTTP).to receive(:get).with(url).and_raise(StandardError)

      expect(measurer.check_url_alive(url)).to be false
    end
  end

  describe '.status_ok?' do
    let(:debug_output_dir) { nil }

    context 'given non hash value' do
      let(:hash) { nil }

      it 'return false' do
        expect(measurer.status_ok?(hash)).to be false
      end
    end

    context 'given empty hash' do
      let(:hash) { {} }

      it 'return false' do
        expect(measurer.status_ok?(hash)).to be false
      end
    end

    context 'given valid hash with all status ok' do
      let(:hash) { { 'db_check' => { 'status' => 'ok' }, 'redis_check' => { 'status' => 'ok' } } }

      it 'return true' do
        expect(measurer.status_ok?(hash)).to be true
      end
    end

    context 'given valid hash with one status not ok' do
      let(:hash) { { 'db_check' => { 'status' => 'failed' }, 'redis_check' => { 'status' => 'ok' } } }

      it 'return false' do
        expect(measurer.status_ok?(hash)).to be false
      end
    end
  end

  describe '.check_gitlab_ready' do
    let(:debug_output_dir) { nil }
    let(:url) { 'url' }
    let(:http_return) { 'http_return' }
    let(:response) { 'response' }
    let(:status_ok_return) { 'status_ok_return' }

    it 'return whatever status_ok? result' do
      expect(HTTP).to receive(:get).with(url).and_return(http_return)
      allow(JSON).to receive(:parse).with(http_return).and_return(response)
      expect(measurer).to receive(:status_ok?).with(response).and_return(status_ok_return)

      expect(measurer.check_gitlab_ready(url)).to eq(status_ok_return)
    end

    it 'return false when HTTP throw StandardError' do
      expect(HTTP).to receive(:get).with(url).and_raise(StandardError)

      expect(measurer.check_gitlab_ready(url)).to be false
    end

    it 'return false when JSON throw StandardError' do
      expect(HTTP).to receive(:get).with(url).and_return(http_return)
      allow(JSON).to receive(:parse).with(http_return).and_raise(StandardError)

      expect(measurer.check_gitlab_ready(url)).to be false
    end
  end

  describe '.container_exec_command' do
    let(:debug_output_dir) { 'tmp/measure' }
    let(:container) { double }
    let(:command) { 'ls' }
    let(:log_file) { 'tmp/measure/log_file.txt' }

    context 'command succeed' do
      it 'return the stdout result' do
        expect(container).to receive(:exec).with(command, wait: 120).and_return([%w[success message], [], 0])
        command_ret = measurer.container_exec_command(container, command, log_file, 120)
        expect(command_ret).to eq('successmessage')
      end
    end

    context 'command fail' do
      it 'should raise error' do
        expect(container).to receive(:exec).with(command, wait: 120).and_return([[], %w[error message], 1])
        expect { measurer.container_exec_command(container, command, log_file, 120) }.to raise_error(SystemExit, 'errormessage')
      end
    end
  end

  describe '.stdout_to_hash_array' do
    let(:debug_output_dir) { nil }

    context 'use customised separator' do
      let(:stdout) do
        <<-STDOUTSTRING
           PID<Pid_Command_Separator>COMMAND
           1<Pid_Command_Separator>/bin/bash /assets/wrapper
           23<Pid_Command_Separator>runsv sshd
           24<Pid_Command_Separator>svlogd -tt /var/log/gitlab/sshd
        STDOUTSTRING
      end
      let(:separator) { /<Pid_Command_Separator>/ }
      let(:expected_ret) do
        [
          { 'PID' => '1', 'COMMAND' => '/bin/bash /assets/wrapper' },
          { 'PID' => '23', 'COMMAND' => 'runsv sshd' },
          { 'PID' => '24', 'COMMAND' => 'svlogd -tt /var/log/gitlab/sshd' }
        ]
      end

      it 'return hash array' do
        expect(measurer.stdout_to_hash_array(stdout, separator)).to eq(expected_ret)
      end
    end
{'fraction_non_alphanumeric': 0.11685107060415506, 'fraction_numerical': 0.0047759293162461195, 'mean_word_length': 3.101860920666014, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '818764', 'n_tokens_mistral': 4211, 'n_tokens_neox': 4026, 'n_words': 883}