diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/README.md | 12 | ||||
| -rw-r--r-- | tests/order.rb | 15 | ||||
| -rw-r--r-- | tests/white-box/couchdb.rb | 109 | ||||
| -rw-r--r-- | tests/white-box/dummy.rb | 71 | ||||
| -rw-r--r-- | tests/white-box/network.rb | 60 | ||||
| -rw-r--r-- | tests/white-box/openvpn.rb | 16 | ||||
| -rw-r--r-- | tests/white-box/webapp.rb | 63 | 
7 files changed, 346 insertions, 0 deletions
diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 00000000..debbf700 --- /dev/null +++ b/tests/README.md @@ -0,0 +1,12 @@ +This directory contains to kinds of tests: + +White Box Tests +================================ + +These tests are run on the server as superuser. They are for troubleshooting any problems with the internal setup of the server. + +Black Box Tests +================================ + +These test are run the user's local machine. They are for troubleshooting any external problems with the service exposed by the server. + diff --git a/tests/order.rb b/tests/order.rb new file mode 100644 index 00000000..ffa6ae4e --- /dev/null +++ b/tests/order.rb @@ -0,0 +1,15 @@ +class LeapCli::Config::Node +  # +  # returns a list of node names that should be tested before this node. +  # make sure to not return ourselves (please no dependency loops!). +  # +  def test_dependencies +    dependents = LeapCli::Config::ObjectList.new +    unless services.include?('couchdb') +      if services.include?('webapp') || services.include?('mx') || services.include?('soledad') +        dependents.merge! nodes_like_me[:services => 'couchdb'] +      end +    end +    dependents.keys.delete_if {|name| self.name == name} +  end +end
\ No newline at end of file diff --git a/tests/white-box/couchdb.rb b/tests/white-box/couchdb.rb new file mode 100644 index 00000000..9d5da94f --- /dev/null +++ b/tests/white-box/couchdb.rb @@ -0,0 +1,109 @@ +raise SkipTest unless $node["services"].include?("couchdb") + +require 'json' + +class CouchDB < LeapTest +  depends_on "Network" + +  def setup +  end + +  def test_00_Are_daemons_running? +    assert_running 'tapicero' +    assert_running 'bin/beam' +    assert_running 'bin/epmd' +    pass +  end + +  # +  # check to make sure we can get welcome response from local couchdb +  # +  def test_01_Is_CouchDB_running? +    assert_get(couchdb_url) do |body| +      assert_match /"couchdb":"Welcome"/, body, "Could not get welcome message from #{couchdb_url}. Probably couchdb is not running." +    end +    pass +  end + +  # +  # compare the configured nodes to the nodes that are actually listed in bigcouch +  # +  def test_02_Is_cluster_membership_ok? +    url = couchdb_backend_url("/nodes/_all_docs") +    neighbors = assert_property('couch.bigcouch.neighbors') +    neighbors << assert_property('domain.full') +    neighbors.sort! +    assert_get(url) do |body| +      response = JSON.parse(body) +      nodes_in_db = response['rows'].collect{|row| row['id'].sub(/^bigcouch@/, '')}.sort +      assert_equal neighbors, nodes_in_db, "The couchdb replication node list is wrong (/nodes/_all_docs)" +    end +    pass +  end + +  # +  # all configured nodes are in 'cluster_nodes' +  # all nodes online and communicating are in 'all_nodes' +  # +  # this seems backward to me, so it might be the other way around. +  # +  def test_03_Are_configured_nodes_online? +    url = couchdb_url("/_membership") +    assert_get(url) do |body| +      response = JSON.parse(body) +      nodes_configured_but_not_available = response['cluster_nodes'] - response['all_nodes'] +      nodes_available_but_not_configured = response['all_nodes'] - response['cluster_nodes'] +      if nodes_configured_but_not_available.any? +        warn "These nodes are configured but not available:", nodes_configured_but_not_available +      end +      if nodes_available_but_not_configured.any? +        warn "These nodes are available but not configured:", nodes_available_but_not_configured +      end +      if response['cluster_nodes'] == response['all_nodes'] +        pass +      end +    end +  end + +  def test_04_Do_ACL_users_exist? +    acl_users = ['_design/_auth', 'leap_mx', 'nickserver', 'soledad', 'tapicero', 'webapp'] +    url = couchdb_backend_url("/_users/_all_docs") +    assert_get(url) do |body| +      response = JSON.parse(body) +      assert_equal 6, response['total_rows'] +      actual_users = response['rows'].map{|row| row['id'].sub(/^org.couchdb.user:/, '') } +      assert_equal acl_users.sort, actual_users.sort +    end +    pass +  end + +  def test_05_Do_required_databases_exist? +    dbs_that_should_exist = ["customers","identities","keycache","sessions","shared","tickets","tokens","users"] +    dbs_that_should_exist.each do |db_name| +      assert_get(couchdb_url("/"+db_name)) do |body| +        assert response = JSON.parse(body) +        assert_equal db_name, response['db_name'] +      end +    end +    pass +  end + +  private + +  def couchdb_url(path="", port=nil) +    @port ||= begin +      assert_property 'couch.port' +      $node['couch']['port'] +    end +    @password ||= begin +      assert_property 'couch.users.admin.password' +      $node['couch']['users']['admin']['password'] +    end +    "http://admin:#{@password}@localhost:#{port || @port}#{path}" +  end + +  def couchdb_backend_url(path="") +    couchdb_url(path, "5986") # TODO: admin port is hardcoded for now but should be configurable. +  end + +end diff --git a/tests/white-box/dummy.rb b/tests/white-box/dummy.rb new file mode 100644 index 00000000..a3e8ad68 --- /dev/null +++ b/tests/white-box/dummy.rb @@ -0,0 +1,71 @@ +# only run in the dummy case where there is no hiera.yaml file. +raise SkipTest unless $node["dummy"] + +class Robot +  def can_shoot_lasers? +    "OHAI!" +  end + +  def can_fly? +    "YES!" +  end +end + +class TestDummy < LeapTest +  def setup +    @robot = Robot.new +  end + +  def test_lasers +    assert_equal "OHAI!", @robot.can_shoot_lasers? +    pass +  end + +  def test_fly +    refute_match /^no/i, @robot.can_fly? +    pass +  end + +  def test_fail +    fail "fail" +    pass +  end + +  def test_01_will_be_skipped +    skip "test this later" +    pass +  end + +  def test_socket_failure +    assert_tcp_socket('localhost', 900000) +    pass +  end + +  def test_warn +    block_test do +      warn "not everything", "is a success or failure" +    end +  end + +  # used to test extracting the proper caller even when in a block +  def block_test +    yield +  end + +  def test_socket_success +    fork { +      Socket.tcp_server_loop('localhost', 12345) do |sock, client_addrinfo| +        begin +          sock.write('hi') +        ensure +          sock.close +          exit +        end +      end +    } +    sleep 0.2 +    assert_tcp_socket('localhost', 12345) +    pass +  end + +end diff --git a/tests/white-box/network.rb b/tests/white-box/network.rb new file mode 100644 index 00000000..955857dc --- /dev/null +++ b/tests/white-box/network.rb @@ -0,0 +1,60 @@ +require 'socket' + +raise SkipTest if $node["dummy"] + +class Network < LeapTest + +  def setup +  end + +  def test_01_Can_connect_to_internet? +    assert_get('http://www.google.com/images/srpr/logo11w.png') +    pass +  end + +  # +  # example properties: +  # +  # stunnel: +  #   ednp_clients: +  #     elk_9002: +  #       accept_port: 4003 +  #       connect: elk.dev.bitmask.i +  #       connect_port: 19002 +  #   couch_server: +  #     accept: 15984 +  #     connect: "127.0.0.1:5984" +  # +  def test_02_Is_stunnel_running? +    if $node['stunnel'] +      good_stunnel_pids = [] +      $node['stunnel'].each do |stunnel_type, stunnel_configs| +        if stunnel_type =~ /_clients?$/ +          stunnel_configs.each do |stunnel_name, stunnel_conf| +            config_file_name = "/etc/stunnel/#{stunnel_name}.conf" +            processes = pgrep(config_file_name) +            assert_equal 6, processes.length, "There should be six stunnel processes running for `#{config_file_name}`" +            good_stunnel_pids += processes.map{|ps| ps[:pid]} +            assert port = stunnel_conf['accept_port'], 'Field `accept_port` must be present in `stunnel` property.' +            assert_tcp_socket('localhost', port) +          end +        elsif stunnel_type =~ /_server$/ +          config_file_name = "/etc/stunnel/#{stunnel_type}.conf" +          processes = pgrep(config_file_name) +          assert_equal 6, processes.length, "There should be six stunnel processes running for `#{config_file_name}`" +          good_stunnel_pids += processes.map{|ps| ps[:pid]} +          assert accept = stunnel_configs['accept'], "Field `accept` must be present in property `stunnel.#{stunnel_type}`" +          assert_tcp_socket('localhost', accept) +          assert connect = stunnel_configs['connect'], "Field `connect` must be present in property `stunnel.#{stunnel_type}`" +          assert_tcp_socket(*connect.split(':')) +        else +          skip "Unknown stunnel type `#{stunnel_type}`" +        end +      end +      all_stunnel_pids = pgrep('/usr/bin/stunnel').collect{|process| process[:pid]}.uniq +      assert_equal good_stunnel_pids.sort, all_stunnel_pids.sort, "There should not be any extra stunnel processes that are not configured in /etc/stunnel" +      pass +    end +  end + +end diff --git a/tests/white-box/openvpn.rb b/tests/white-box/openvpn.rb new file mode 100644 index 00000000..5eb2bdb5 --- /dev/null +++ b/tests/white-box/openvpn.rb @@ -0,0 +1,16 @@ +raise SkipTest unless $node["services"].include?("openvpn") + +class Openvpn < LeapTest +  depends_on "Network" + +  def setup +  end + +  def test_01_Are_daemons_running? +    assert_running '/usr/sbin/openvpn .* /etc/openvpn/tcp_config.conf' +    assert_running '/usr/sbin/openvpn .* /etc/openvpn/udp_config.conf' +    assert_running '/usr/sbin/unbound' +    pass +  end + +end diff --git a/tests/white-box/webapp.rb b/tests/white-box/webapp.rb new file mode 100644 index 00000000..142ac2de --- /dev/null +++ b/tests/white-box/webapp.rb @@ -0,0 +1,63 @@ +raise SkipTest unless $node["services"].include?("webapp") + +require 'socket' + +class Webapp < LeapTest +  depends_on "Network" + +  HAPROXY_CONFIG = '/etc/haproxy/haproxy.cfg' + +  def setup +  end + +  # +  # example properties: +  # +  # stunnel: +  #   couch_client: +  #     couch1_5984: +  #       accept_port: 4000 +  #       connect: couch1.bitmask.i +  #       connect_port: 15984 +  # +  def test_01_Can_contact_couchdb? +    assert_property('stunnel.couch_client') +    $node['stunnel']['couch_client'].values.each do |stunnel_conf| +      assert port = stunnel_conf['accept_port'], 'Field `accept_port` must be present in `stunnel` property.' +      local_stunnel_url = "http://localhost:#{port}" +      remote_ip_address = TCPSocket.gethostbyname(stunnel_conf['connect']).last +      msg = "(stunnel to %s:%s, aka %s)" % [stunnel_conf['connect'], stunnel_conf['connect_port'], remote_ip_address] +      assert_get(local_stunnel_url, nil, error_msg: msg) do |body| +        assert_match /"couchdb":"Welcome"/, body, "Request to #{local_stunnel_url} should return couchdb welcome message." +      end +    end +    pass +  end + +  # +  # example properties: +  # +  # haproxy: +  #   servers: +  #     couch1: +  #       backup: false +  #       host: localhost +  #       port: 4000 +  #       weight: 10 +  # +  def test_02_Is_haproxy_working? +    port = file_match(HAPROXY_CONFIG, /^  bind localhost:(\d+)$/) +    url = "http://localhost:#{port}" +    assert_get(url) do |body| +      assert_match /"couchdb":"Welcome"/, body, "Request to #{url} should return couchdb welcome message." +    end +    pass +  end + +  def test_03_Are_daemons_running? +    assert_running '/usr/sbin/apache2' +    assert_running '/usr/bin/nickserver' +    pass +  end + +end  | 
