File: test_coordinator.rb

package info (click to toggle)
ruby-sshkit 1.9.0-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 604 kB
  • ctags: 619
  • sloc: ruby: 3,045; makefile: 2
file content (131 lines) | stat: -rw-r--r-- 4,041 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
require 'time'
require 'helper'

module SSHKit

  class TestCoordinator < UnitTest
    def setup
      super
      @output = String.new
      SSHKit.config.output_verbosity = :debug
      SSHKit.config.output = SSHKit::Formatter::SimpleText.new(@output)
      SSHKit.config.backend = SSHKit::Backend::Printer
    end

    def echo_time
      lambda do |_host|
        execute "echo #{Time.now.to_f}"
      end
    end

    def test_the_connection_manager_handles_empty_argument
      Coordinator.new([]).each do
        raise "This should not be executed"
      end
    end

    def test_connection_manager_handles_a_single_argument
      h = Host.new('1.example.com')
      Host.expects(:new).with('1.example.com').once().returns(h)
      Coordinator.new '1.example.com'
    end

    def test_connection_manager_resolves_hosts
      h = Host.new('n.example.com')
      Host.expects(:new).times(3).returns(h)
      Coordinator.new %w{1.example.com 2.example.com 3.example.com}
    end

    def test_the_connection_manager_yields_the_host_to_each_connection_instance
      Coordinator.new(%w{1.example.com}).each do |host|
        execute "echo #{host.hostname}"
      end
      assert_equal "Command: echo 1.example.com\n", actual_output_commands.last
    end

    def test_the_connection_manaager_runs_things_in_parallel_by_default
      Coordinator.new(%w{1.example.com 2.example.com}).each(&echo_time)
      assert_equal 2, actual_execution_times.length
      assert_within_10_ms(actual_execution_times)
    end

    def test_the_connection_manager_can_run_things_in_sequence
      Coordinator.new(%w{1.example.com 2.example.com}).each in: :sequence, &echo_time
      assert_equal 2, actual_execution_times.length
      assert_at_least_1_sec_apart(actual_execution_times.first, actual_execution_times.last)
    end

    class MyRunner < SSHKit::Runner::Parallel
      def execute
        threads = hosts.map do |host|
          Thread.new(host) do |h|
            b = backend(h, &block)
            b.run
            b.warn "custom runner out"
          end
        end
        threads.each(&:join)
      end
    end

    def test_the_connection_manager_can_run_things_in_custom_runner
      begin
        $original_runner = SSHKit.config.default_runner
        SSHKit.config.default_runner = MyRunner

        Coordinator.new(%w{1.example.com 2.example.com}).each(&echo_time)
        assert_equal 2, actual_execution_times.length
        assert_within_10_ms(actual_execution_times)
        assert_match(/custom runner out/, @output)
      ensure
        SSHKit.config.default_runner = $original_runner
      end
    end

    def test_the_connection_manager_can_run_things_in_sequence_with_wait
      start = Time.now
      Coordinator.new(%w{1.example.com 2.example.com}).each in: :sequence, wait: 10, &echo_time
      stop = Time.now
      assert_operator(stop - start, :>=, 10.0)
    end

    def test_the_connection_manager_can_run_things_in_groups
      Coordinator.new(
        %w{
          1.example.com
          2.example.com
          3.example.com
          4.example.com
          5.example.com
          6.example.com
        }
      ).each in: :groups, &echo_time
      assert_equal 6, actual_execution_times.length
      assert_within_10_ms(actual_execution_times[0..1])
      assert_within_10_ms(actual_execution_times[2..3])
      assert_within_10_ms(actual_execution_times[4..5])
      assert_at_least_1_sec_apart(actual_execution_times[1], actual_execution_times[2])
      assert_at_least_1_sec_apart(actual_execution_times[3], actual_execution_times[4])
    end

    private

    def assert_at_least_1_sec_apart(first_time, last_time)
      assert_operator(last_time - first_time, :>, 1.0)
    end

    def assert_within_10_ms(array)
      assert_in_delta(*array, 0.01) # 10 msec
    end

    def actual_execution_times
      actual_output_commands.map { |line| line.split(' ').last.to_f }
    end

    def actual_output_commands
      @output.lines.select { |line| line.start_with?('Command:') }
    end

  end

end