File: test.rb

package info (click to toggle)
bindfs 1.13.10-1
  • links: PTS
  • area: main
  • in suites: buster
  • size: 1,804 kB
  • sloc: sh: 4,206; ansic: 3,213; ruby: 1,089; makefile: 37
file content (121 lines) | stat: -rwxr-xr-x 3,234 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
#!/usr/bin/env ruby
HELP = <<EOS
Runs the bindfs test suite in all vagrant boxes in parallel.

Usage: test.rb [--nohalt] [vm1 [...]]
Options:
  -h      --help            Print this and exit.
  --nohalt                  Don't halt VMs when done.

If VM names are given, only those are tested.

Bugs:
  - Spurious "Connection to 127.0.0.1 closed." messages can appear, and the
    terminal may need a `reset` after this command finishes.
EOS

require 'fileutils'

Dir.chdir(File.dirname(__FILE__))

halt_vms = true
specifically_selected_vms = []
ARGV.each do |arg|
  if arg == '-h' || arg == '--help'
    puts HELP
    exit
  elsif arg == '--nohalt'
    halt_vms = false
  elsif !arg.start_with?('-')
    specifically_selected_vms << arg
  else
    raise "Unknown option: #{arg}"
  end
end

dirs = Dir.glob('*/Vagrantfile').map { |path| File.dirname(path) }
unless specifically_selected_vms.empty?
  dirs = dirs.select { |dir| ARGV.include?(dir) }
end

def with_retries(n, options = {}, &block)
  options = {
    sleep: 0,
    sleep_jitter: 0,
  }.merge options
  loop do
    begin
      return block.call
    rescue
      raise $! if n <= 0
      puts "Retrying #{n} more times after catching: #{$!}"
    end
    sleep(options[:sleep] + (Random.rand - 0.5) * options[:sleep_jitter])
    n -= 1
  end
end

puts "Running #{dirs.size} VMs in parallel: #{dirs.join(' ')}"
puts "You can follow the progress of each VM by tailing vagrant/*/test.log"
puts "Note: if your terminal goes wonky after this command, type 'reset'"
mutex = Thread::Mutex.new  # protects `$stdout` and `errors`
errors = []
threads = dirs.map do |dir|
  Thread.new do
    begin
      File.open(dir + "/test.log", "wb") do |logfile|
        run_and_log = -> (command) do
          logfile.puts ""
          logfile.puts "##### #{command} #####"
          logfile.flush
          pid = Process.spawn(command, chdir: dir, out: logfile, err: :out)
          Process.waitpid(pid)
          $?.success?
        end
        # parallel `vagrant up` commands can be flaky with VirtualBox due to lock contention,
        # so give it a few retries.
        with_retries(3, sleep: 1.0, sleep_jitter: 0.5) do
          unless run_and_log.call "vagrant up"
            raise "vagrant up failed"
          end
        end
        unless run_and_log.call "vagrant rsync"
          raise "vagrant rsync failed"
        end
        unless run_and_log.call "vagrant ssh -c 'cd /bindfs && sudo rm -Rf tests/tmp_test_bindfs && ./configure && make clean && make && make check && sudo make check'"
          mutex.synchronize do
            errors << "VM #{dir} tests failed."
          end
        end
        if halt_vms
          unless run_and_log.call "vagrant halt"
            raise "vagrant halt failed"
          end
        end
      end
    rescue
      mutex.synchronize do
        errors << "VM #{dir} error: #{$!}"
      end
    ensure
      mutex.synchronize do
        puts "Finished VM: #{dir}"
      end
    end
  end
end

threads.each(&:join)

if errors.empty?
  puts "OK"
else
  unless errors.empty?
    puts
    puts "Errors:"
    errors.each { |err| puts "  #{err}" }
    puts
    puts "See test.log in a failed VM's directory for more information"
    puts
  end
end