serverspec-extended-types 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +15 -0
- data/.gitignore +22 -0
- data/.rspec +2 -0
- data/.travis.yml +13 -0
- data/.yardopts +1 -0
- data/CHANGES.md +5 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +249 -0
- data/Rakefile +53 -0
- data/lib/serverspec_extended_types.rb +4 -0
- data/lib/serverspec_extended_types/bitlbee.rb +204 -0
- data/lib/serverspec_extended_types/http_get.rb +159 -0
- data/lib/serverspec_extended_types/version.rb +3 -0
- data/lib/serverspec_extended_types/virtualenv.rb +161 -0
- data/serverspec-extended-types.gemspec +31 -0
- data/spec/spec_helper.rb +42 -0
- data/spec/types/bitlbee_spec.rb +189 -0
- data/spec/types/http_get_spec.rb +75 -0
- data/spec/types/virtualenv_spec.rb +201 -0
- metadata +223 -0
@@ -0,0 +1,159 @@
|
|
1
|
+
##############################################################################
|
2
|
+
# serverspec-extended-types - http_get
|
3
|
+
#
|
4
|
+
# <https://github.com/jantman/serverspec-extended-types>
|
5
|
+
#
|
6
|
+
# Copyright (C) 2015 Jason Antman <jason@jasonantman.com>
|
7
|
+
#
|
8
|
+
# Licensed under the MIT License - see LICENSE.txt
|
9
|
+
#
|
10
|
+
##############################################################################
|
11
|
+
|
12
|
+
require 'timeout'
|
13
|
+
require 'faraday'
|
14
|
+
require 'serverspec_extended_types/version'
|
15
|
+
|
16
|
+
module Serverspec
|
17
|
+
module Type
|
18
|
+
|
19
|
+
# Perform an HTTP GET request against the serverspec target
|
20
|
+
# using {http://www.rubydoc.info/gems/faraday/ Faraday}.
|
21
|
+
class Http_Get < Base
|
22
|
+
|
23
|
+
# Initialize a bunch of instance variables, then call {#getpage}
|
24
|
+
#
|
25
|
+
# Calls {#getpage} within a {Timeout::timeout} block;
|
26
|
+
# If {#getpage} times out, set ``timed_out_status`` to [True]
|
27
|
+
#
|
28
|
+
# @param port [Int] the port to connect to HTTP over
|
29
|
+
# @param host_header [String] the value to set in the 'Host' HTTP request header
|
30
|
+
# @param path [String] the URI/path to request from the server
|
31
|
+
# @param timeout_sec [Int] how many seconds to allow request to run before timing out and setting @timed_out_status to True
|
32
|
+
#
|
33
|
+
# @example
|
34
|
+
# describe http_get(80, 'myhostname', '/') do
|
35
|
+
# # tests here
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# @api public
|
39
|
+
# @return [nil]
|
40
|
+
def initialize(port, host_header, path, timeout_sec=10)
|
41
|
+
@ip = ENV['TARGET_HOST']
|
42
|
+
@port = port
|
43
|
+
@host = host_header
|
44
|
+
@path = path
|
45
|
+
@timed_out_status = false
|
46
|
+
@content_str = nil
|
47
|
+
@headers_hash = nil
|
48
|
+
@response_code_int = nil
|
49
|
+
begin
|
50
|
+
Timeout::timeout(timeout_sec) do
|
51
|
+
getpage
|
52
|
+
end
|
53
|
+
rescue Timeout::Error
|
54
|
+
@timed_out_status = true
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Private method to actually get the page; must be called within a timeout block
|
59
|
+
#
|
60
|
+
# Gets the page using {http://www.rubydoc.info/gems/faraday/ Faraday} and then sets instance variables for the various attribute readers.
|
61
|
+
#
|
62
|
+
# @api private
|
63
|
+
# @return [nil]
|
64
|
+
def getpage
|
65
|
+
ip = @ip
|
66
|
+
port = @port
|
67
|
+
conn = Faraday.new("http://#{ip}:#{port}/")
|
68
|
+
version = ServerspecExtendedTypes::VERSION
|
69
|
+
conn.headers[:user_agent] = "Serverspec::Type::Http_Get/#{version} (https://github.com/jantman/serverspec-extended-types)"
|
70
|
+
conn.headers[:Host] = @host
|
71
|
+
response = conn.get(@path)
|
72
|
+
@response_code_int = response.status
|
73
|
+
@content_str = response.body
|
74
|
+
@headers_hash = Hash.new('')
|
75
|
+
response.headers.each do |header, val|
|
76
|
+
@headers_hash[header] = val
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Whether or not the request timed out
|
81
|
+
#
|
82
|
+
# @example
|
83
|
+
# describe http_get(80, 'myhostname', '/') do
|
84
|
+
# it { should_not be_timed_out }
|
85
|
+
# end
|
86
|
+
#
|
87
|
+
# @api public
|
88
|
+
# @return [Boolean]
|
89
|
+
def timed_out?
|
90
|
+
@timed_out_status
|
91
|
+
end
|
92
|
+
|
93
|
+
# Returns the HTTP response headers as a hash
|
94
|
+
#
|
95
|
+
# @example
|
96
|
+
# describe http_get(80, 'myhostname', '/') do
|
97
|
+
# its(:headers) { should include('HeaderName' => /value regex/) }
|
98
|
+
# end
|
99
|
+
#
|
100
|
+
# @api public
|
101
|
+
# @return [Hash]
|
102
|
+
def headers
|
103
|
+
@headers_hash
|
104
|
+
end
|
105
|
+
|
106
|
+
# Returns the HTTP status code, or 0 if timed out
|
107
|
+
#
|
108
|
+
# @example
|
109
|
+
# describe http_get(80, 'myhostname', '/') do
|
110
|
+
# its(:status) { should eq 200 }
|
111
|
+
# end
|
112
|
+
#
|
113
|
+
# @api public
|
114
|
+
# @return [Int]
|
115
|
+
def status
|
116
|
+
if @timed_out_status
|
117
|
+
0
|
118
|
+
else
|
119
|
+
@response_code_int
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# Returns the body/content of the HTTP response
|
124
|
+
#
|
125
|
+
# @example
|
126
|
+
# describe http_get(80, 'myhostname', '/') do
|
127
|
+
# its(:body) { should match /<html>/ }
|
128
|
+
# end
|
129
|
+
#
|
130
|
+
# @api public
|
131
|
+
# @return [String]
|
132
|
+
def body
|
133
|
+
@content_str
|
134
|
+
end
|
135
|
+
|
136
|
+
private :getpage
|
137
|
+
end
|
138
|
+
|
139
|
+
# ServerSpec Type wrapper for http_get
|
140
|
+
#
|
141
|
+
# @example
|
142
|
+
# describe http_get(80, 'myhostname', '/') do
|
143
|
+
# # tests here
|
144
|
+
# end
|
145
|
+
#
|
146
|
+
# @param port [Int] the port to connect to HTTP over
|
147
|
+
# @param host_header [String] the value to set in the 'Host' HTTP request header
|
148
|
+
# @param path [String] the URI/path to request from the server
|
149
|
+
# @param timeout_sec [Int] how many seconds to allow request to run before timing out and setting @timed_out_status to True
|
150
|
+
#
|
151
|
+
# @api public
|
152
|
+
# @return [Serverspec::Type::Http_Get]
|
153
|
+
def http_get(port, host_header, path, timeout_sec=10)
|
154
|
+
Http_Get.new(port, host_header, path, timeout_sec=timeout_sec)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
include Serverspec::Type
|
@@ -0,0 +1,161 @@
|
|
1
|
+
##############################################################################
|
2
|
+
# serverspec-extended-types - virtualenv
|
3
|
+
#
|
4
|
+
# <https://github.com/jantman/serverspec-extended-types>
|
5
|
+
#
|
6
|
+
# Copyright (C) 2015 Jason Antman <jason@jasonantman.com>
|
7
|
+
#
|
8
|
+
# Licensed under the MIT License - see LICENSE.txt
|
9
|
+
#
|
10
|
+
##############################################################################
|
11
|
+
|
12
|
+
module Serverspec::Type
|
13
|
+
class Virtualenv < Base
|
14
|
+
|
15
|
+
# Test whether this appears to be a working venv
|
16
|
+
#
|
17
|
+
# Tests performed:
|
18
|
+
# - venv_path/bin/pip executable by root?
|
19
|
+
# - venv_path/bin/python executable by root?
|
20
|
+
# - venv_path/bin/activate executable by root?
|
21
|
+
# - 'export VIRTUAL_ENV' in venv_path/bin/activate?
|
22
|
+
#
|
23
|
+
# @example
|
24
|
+
# describe virtualenv('/path/to/venv') do
|
25
|
+
# it { should be_virtualenv }
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# @api public
|
29
|
+
# @return [Boolean]
|
30
|
+
def virtualenv?
|
31
|
+
pip_path = ::File.join(@name, 'bin', 'pip')
|
32
|
+
python_path = ::File.join(@name, 'bin', 'python')
|
33
|
+
act_path = ::File.join(@name, 'bin', 'activate')
|
34
|
+
cmd = "grep -q 'export VIRTUAL_ENV' #{act_path}"
|
35
|
+
@runner.check_file_is_executable(pip_path, 'root') and
|
36
|
+
@runner.check_file_is_executable(python_path, 'root') and
|
37
|
+
@runner.check_file_is_executable(act_path, 'root') and
|
38
|
+
@runner.run_command(cmd).exit_status.to_i == 0
|
39
|
+
end
|
40
|
+
|
41
|
+
# Return the version of pip installed in the virtualenv
|
42
|
+
#
|
43
|
+
# @example
|
44
|
+
# describe virtualenv('/path/to/venv') do
|
45
|
+
# its(:pip_version) { should match /^6\.0\.6$/ }
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
# @api public
|
49
|
+
# @return [String]
|
50
|
+
def pip_version
|
51
|
+
@pip_version || get_pip_version
|
52
|
+
end
|
53
|
+
|
54
|
+
# Return the version of python installed in the virtualenv
|
55
|
+
#
|
56
|
+
# @example
|
57
|
+
# describe virtualenv('/path/to/venv') do
|
58
|
+
# its(:python_version) { should match /^2\.7\.9$/ }
|
59
|
+
# end
|
60
|
+
#
|
61
|
+
# @api public
|
62
|
+
# @return [String]
|
63
|
+
def python_version
|
64
|
+
@python_version || get_python_version
|
65
|
+
end
|
66
|
+
|
67
|
+
# Return a hash of all packages present in `pip freeze` output for the venv
|
68
|
+
#
|
69
|
+
# Note that any editable packages (`-e something`) are returned as hash keys
|
70
|
+
# with an empty value
|
71
|
+
#
|
72
|
+
# @example
|
73
|
+
# describe virtualenv('/path/to/venv') do
|
74
|
+
# its(:pip_freeze) { should include('wsgiref' => '0.1.2') }
|
75
|
+
# its(:pip_freeze) { should include('requests') }
|
76
|
+
# its(:pip_freeze) { should include('pytest' => /^2\.6/) }
|
77
|
+
# its(:pip_freeze) { should include('-e git+git@github.com:jantman/someproject.git@1d8a380e3af9d081081d7ef685979200a7db4130#egg=someproject') }
|
78
|
+
# end
|
79
|
+
#
|
80
|
+
# @api public
|
81
|
+
# @return [Hash]
|
82
|
+
def pip_freeze
|
83
|
+
@pip_freeze || get_pip_freeze
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
# Get a hash for the `pip freeze` output; set @pip_freeze
|
88
|
+
#
|
89
|
+
# @api private
|
90
|
+
# @return [nil]
|
91
|
+
def get_pip_freeze()
|
92
|
+
pip_path = ::File.join(@name, 'bin', 'pip')
|
93
|
+
tmp = @runner.run_command("#{pip_path} freeze")
|
94
|
+
@pip_freeze = Hash.new()
|
95
|
+
if tmp.exit_status.to_i != 0
|
96
|
+
return @pip_freeze
|
97
|
+
end
|
98
|
+
lines = tmp.stdout.split("\n")
|
99
|
+
lines.each do |line|
|
100
|
+
line.strip!
|
101
|
+
if line =~ /^-e /
|
102
|
+
@pip_freeze[line] = ''
|
103
|
+
next
|
104
|
+
end
|
105
|
+
parts = line.split(/==/)
|
106
|
+
@pip_freeze[parts[0]] = parts[1]
|
107
|
+
end
|
108
|
+
@pip_freeze
|
109
|
+
end
|
110
|
+
|
111
|
+
private
|
112
|
+
# Get the pip version from the venv; set @pip_version
|
113
|
+
#
|
114
|
+
# @api private
|
115
|
+
# @return [nil]
|
116
|
+
def get_pip_version()
|
117
|
+
pip_path = ::File.join(@name, 'bin', 'pip')
|
118
|
+
pip_path = ::File.join(@name, 'bin', 'pip')
|
119
|
+
tmp = @runner.run_command("#{pip_path} --version")
|
120
|
+
if ( tmp.stdout =~ /^pip (\d+\S+)/ )
|
121
|
+
@pip_version = $1
|
122
|
+
else
|
123
|
+
@pip_version = ''
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
private
|
128
|
+
# Get the python version from the venv; set @python_version
|
129
|
+
#
|
130
|
+
# @api private
|
131
|
+
# @return [nil]
|
132
|
+
def get_python_version()
|
133
|
+
python_path = ::File.join(@name, 'bin', 'python')
|
134
|
+
tmp = @runner.run_command("#{python_path} --version")
|
135
|
+
if ( tmp.stderr =~ /^[Pp]ython (\d+\S+)/ )
|
136
|
+
@python_version = $1
|
137
|
+
elsif ( tmp.stdout =~ /^[Pp]ython (\d+\S+)/ )
|
138
|
+
@python_version = $1
|
139
|
+
else
|
140
|
+
@python_version = ''
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# Serverspec Type wrapper method for Serverspec::Type::Virtualenv
|
146
|
+
#
|
147
|
+
# @example
|
148
|
+
# describe virtualenv('/path/to/venv') do
|
149
|
+
# # tests here
|
150
|
+
# end
|
151
|
+
#
|
152
|
+
# @param name [String] the absolute path to the virtualenv root
|
153
|
+
#
|
154
|
+
# @api public
|
155
|
+
# @return {Serverspec::Type::Virtualenv}
|
156
|
+
def virtualenv(name)
|
157
|
+
Virtualenv.new(name)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
include Serverspec::Type
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'serverspec_extended_types/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "serverspec-extended-types"
|
8
|
+
spec.version = ServerspecExtendedTypes::VERSION
|
9
|
+
spec.authors = ["Jason Antman"]
|
10
|
+
spec.email = ["jason@jasonantman.com"]
|
11
|
+
spec.summary = %q{A set of extended types for ServerSpec 2.x}
|
12
|
+
spec.description = %q{This gem provides some purpose-specific types for ServerSpec 2.x beyond the default ones. It is in no way associated with the ServerSpec project or developers.}
|
13
|
+
spec.homepage = "https://github.com/jantman/serverspec-extended-types"
|
14
|
+
spec.license = "MIT"
|
15
|
+
spec.files = `git ls-files -z`.split("\x0")
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
spec.add_dependency "serverspec", "~> 2"
|
20
|
+
spec.add_dependency "specinfra", "~> 2"
|
21
|
+
spec.add_dependency 'rspec', '>= 3.0'
|
22
|
+
spec.add_dependency 'faraday'
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
25
|
+
spec.add_development_dependency "rake"
|
26
|
+
spec.add_development_dependency 'simplecov'
|
27
|
+
spec.add_development_dependency 'codecov'
|
28
|
+
spec.add_development_dependency 'yard'
|
29
|
+
spec.add_development_dependency 'yardstick'
|
30
|
+
spec.add_development_dependency 'redcarpet'
|
31
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
2
|
+
|
3
|
+
require 'simplecov'
|
4
|
+
SimpleCov.start do
|
5
|
+
add_filter "/vendor/"
|
6
|
+
end
|
7
|
+
|
8
|
+
require 'codecov'
|
9
|
+
if ENV['CI']=='true'
|
10
|
+
SimpleCov.formatter = SimpleCov::Formatter::Codecov
|
11
|
+
end
|
12
|
+
|
13
|
+
require 'specinfra'
|
14
|
+
require 'rspec/mocks/standalone'
|
15
|
+
require 'rspec/its'
|
16
|
+
require 'specinfra/helper/set'
|
17
|
+
include Specinfra::Helper::Set
|
18
|
+
|
19
|
+
set :backend, :exec
|
20
|
+
|
21
|
+
set :os, :family => 'linux'
|
22
|
+
|
23
|
+
module Specinfra
|
24
|
+
module Backend
|
25
|
+
class Ssh
|
26
|
+
def run_command(cmd, opts={})
|
27
|
+
CommandResult.new :stdout => nil, :exit_status => 0
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
module GetCommand
|
34
|
+
def get_command(method, *args)
|
35
|
+
Specinfra.command.get(method, *args)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
include GetCommand
|
40
|
+
|
41
|
+
|
42
|
+
require 'serverspec_extended_types'
|
@@ -0,0 +1,189 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'serverspec_extended_types/http_get'
|
3
|
+
|
4
|
+
describe 'Serverspec::Type.bitlbee' do
|
5
|
+
it 'instantiates the class with the correct parameters' do
|
6
|
+
expect(Serverspec::Type::Bitlbee).to receive(:new).with(1, 'mynick', 'mypass', false)
|
7
|
+
bitlbee(1, 'mynick', 'mypass')
|
8
|
+
end
|
9
|
+
it 'returns the new object' do
|
10
|
+
expect(Serverspec::Type::Bitlbee).to receive(:new).and_return("foo")
|
11
|
+
expect(bitlbee(1, 'foo', 'bar')).to eq "foo"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
describe 'Serverspec::Type::Bitlbee' do
|
15
|
+
context '#initialize' do
|
16
|
+
it 'sets instance variables' do
|
17
|
+
stub_const('ENV', ENV.to_hash.merge('TARGET_HOST' => 'myhost'))
|
18
|
+
x = bitlbee(1, 'foo', 'bar')
|
19
|
+
expect(x.instance_variable_get(:@port)).to eq 1
|
20
|
+
expect(x.instance_variable_get(:@host)).to eq 'myhost'
|
21
|
+
expect(x.instance_variable_get(:@nick)).to eq 'foo'
|
22
|
+
expect(x.instance_variable_get(:@password)).to eq 'bar'
|
23
|
+
expect(x.instance_variable_get(:@connected_status)).to eq false
|
24
|
+
expect(x.instance_variable_get(:@version_str)).to eq ''
|
25
|
+
expect(x.instance_variable_get(:@timed_out_status)).to eq false
|
26
|
+
expect(x.instance_variable_get(:@started)).to eq false
|
27
|
+
expect(x.instance_variable_get(:@use_ssl)).to eq false
|
28
|
+
end
|
29
|
+
it 'sets use_ssl instance variable' do
|
30
|
+
stub_const('ENV', ENV.to_hash.merge('TARGET_HOST' => 'myhost'))
|
31
|
+
x = bitlbee(1, 'foo', 'bar', use_ssl=true)
|
32
|
+
expect(x.instance_variable_get(:@use_ssl)).to eq true
|
33
|
+
end
|
34
|
+
end
|
35
|
+
context 'start' do
|
36
|
+
it 'calls connect_ssl if use_ssl=true' do
|
37
|
+
x = bitlbee(1, 'foo', 'bar', use_ssl=true)
|
38
|
+
expect(x).to receive(:connect_ssl).once
|
39
|
+
expect(x).to_not receive(:connect)
|
40
|
+
x.start
|
41
|
+
expect(x.instance_variable_get(:@timed_out_status)).to eq false
|
42
|
+
expect(x.instance_variable_get(:@connected_status)).to eq false
|
43
|
+
expect(x.instance_variable_get(:@started)).to eq true
|
44
|
+
end
|
45
|
+
it 'calls connect if use_ssl=false' do
|
46
|
+
x = bitlbee(1, 'foo', 'bar')
|
47
|
+
expect(x).to receive(:connect).once
|
48
|
+
expect(x).to_not receive(:connect_ssl)
|
49
|
+
x.start
|
50
|
+
expect(x.instance_variable_get(:@timed_out_status)).to eq false
|
51
|
+
expect(x.instance_variable_get(:@connected_status)).to eq false
|
52
|
+
expect(x.instance_variable_get(:@started)).to eq true
|
53
|
+
end
|
54
|
+
it 'runs with a timeout' do
|
55
|
+
x = bitlbee(1, 'foo', 'bar')
|
56
|
+
expect(Timeout).to receive(:timeout).with(10)
|
57
|
+
x.start
|
58
|
+
expect(x.instance_variable_get(:@timed_out_status)).to eq false
|
59
|
+
expect(x.instance_variable_get(:@connected_status)).to eq false
|
60
|
+
expect(x.instance_variable_get(:@started)).to eq true
|
61
|
+
expect(x.timed_out?).to eq false
|
62
|
+
end
|
63
|
+
it 'sets timed_out_status on timeout' do
|
64
|
+
x = bitlbee(1, 'foo', 'bar')
|
65
|
+
expect(Timeout).to receive(:timeout).with(10).and_raise(Timeout::Error)
|
66
|
+
x.start
|
67
|
+
expect(x.instance_variable_get(:@timed_out_status)).to eq true
|
68
|
+
expect(x.instance_variable_get(:@connected_status)).to eq false
|
69
|
+
expect(x.instance_variable_get(:@started)).to eq true
|
70
|
+
expect(x.timed_out?).to eq true
|
71
|
+
expect(x.connectable?).to eq false
|
72
|
+
end
|
73
|
+
it 'sets connected_status on ECONNREFUSED' do
|
74
|
+
x = bitlbee(1, 'foo', 'bar')
|
75
|
+
expect(x).to receive(:connect).and_raise(Errno::ECONNREFUSED)
|
76
|
+
x.start
|
77
|
+
expect(x.instance_variable_get(:@timed_out_status)).to eq false
|
78
|
+
expect(x.instance_variable_get(:@connected_status)).to eq false
|
79
|
+
expect(x.instance_variable_get(:@started)).to eq true
|
80
|
+
expect(x.timed_out?).to eq false
|
81
|
+
expect(x.connectable?).to eq false
|
82
|
+
end
|
83
|
+
end
|
84
|
+
context '#connect_ssl' do
|
85
|
+
it 'calls communicate' do
|
86
|
+
stub_const('ENV', ENV.to_hash.merge('TARGET_HOST' => 'myhost'))
|
87
|
+
sock_dbl = double
|
88
|
+
expect(TCPSocket).to receive(:open).with('myhost', 1).and_return(sock_dbl)
|
89
|
+
sslctx_dbl = double
|
90
|
+
expect(OpenSSL::SSL::SSLContext).to receive(:new).and_return(sslctx_dbl)
|
91
|
+
expect(sslctx_dbl).to receive(:set_params).with(verify_mode: OpenSSL::SSL::VERIFY_NONE).ordered
|
92
|
+
sslsock_dbl = double
|
93
|
+
expect(sslsock_dbl).to receive(:sync_close=).ordered.with(true)
|
94
|
+
expect(sslsock_dbl).to receive(:connect).ordered
|
95
|
+
expect(sslsock_dbl).to receive(:puts).ordered.with("communicate")
|
96
|
+
expect(sslsock_dbl).to receive(:puts).ordered.with("QUIT :\"outta here\"\n")
|
97
|
+
expect(sslsock_dbl).to receive(:close).ordered
|
98
|
+
expect(OpenSSL::SSL::SSLSocket).to receive(:new).with(sock_dbl, sslctx_dbl).and_return(sslsock_dbl)
|
99
|
+
#expect_any_instance_of(Serverspec::Type::Bitlbee).to receive(:communicate)
|
100
|
+
x = bitlbee(1, 'foo', 'bar')
|
101
|
+
x.stub(:communicate) do
|
102
|
+
x.instance_variable_get(:@socket).puts("communicate")
|
103
|
+
end
|
104
|
+
x.connect_ssl
|
105
|
+
expect(x.instance_variable_get(:@socket)).to eq sslsock_dbl
|
106
|
+
end
|
107
|
+
end
|
108
|
+
context '#connect' do
|
109
|
+
it 'calls communicate' do
|
110
|
+
stub_const('ENV', ENV.to_hash.merge('TARGET_HOST' => 'myhost'))
|
111
|
+
sock_dbl = double
|
112
|
+
expect(TCPSocket).to receive(:open).with('myhost', 1).and_return(sock_dbl)
|
113
|
+
expect(sock_dbl).to receive(:puts).ordered.with("communicate")
|
114
|
+
expect(sock_dbl).to receive(:puts).ordered.with("QUIT :\"outta here\"\n")
|
115
|
+
expect(sock_dbl).to receive(:close).ordered
|
116
|
+
x = bitlbee(1, 'foo', 'bar')
|
117
|
+
x.stub(:communicate) do
|
118
|
+
x.instance_variable_get(:@socket).puts("communicate")
|
119
|
+
end
|
120
|
+
x.connect
|
121
|
+
expect(x.instance_variable_get(:@socket)).to eq sock_dbl
|
122
|
+
end
|
123
|
+
end
|
124
|
+
context '#communicate' do
|
125
|
+
it 'logs in' do
|
126
|
+
x = bitlbee(1, 'foo', 'bar')
|
127
|
+
sock = double
|
128
|
+
x.instance_variable_set(:@socket, sock)
|
129
|
+
x.instance_variable_set(:@started, true)
|
130
|
+
expect(sock).to receive(:puts).ordered.with("PASS bar\n")
|
131
|
+
expect(sock).to receive(:puts).ordered.with("NICK foo\n")
|
132
|
+
expect(sock).to receive(:puts).ordered.with("USER foo foo servername :TestUser\n")
|
133
|
+
expect(sock).to receive(:readpartial).ordered.with(1024).and_return("Welcome to the foo")
|
134
|
+
expect(sock).to receive(:puts).ordered.with("MODE foo +i\n")
|
135
|
+
expect(sock).to receive(:readpartial).ordered.with(1024).and_return("If you've never something something")
|
136
|
+
expect(sock).to receive(:puts).ordered.with("PRIVMSG &bitlbee :identify bar\n")
|
137
|
+
expect(sock).to receive(:readpartial).ordered.with(1024).and_return("PING servername")
|
138
|
+
expect(sock).to receive(:puts).ordered.with(":servername PONG servername :servername\n")
|
139
|
+
expect(sock).to receive(:readpartial).ordered.with(1024).and_return("MODE foo :\+i")
|
140
|
+
expect(sock).to receive(:puts).ordered.with("PRIVMSG root :\001VERSION\001\n")
|
141
|
+
expect(sock).to receive(:readpartial).ordered.with(1024).and_return("foo bar baz blam\n")
|
142
|
+
expect(sock).to receive(:readpartial).ordered.with(1024).and_return("VERSION x.y.z\n")
|
143
|
+
x.communicate
|
144
|
+
expect(x.instance_variable_get(:@connected_status)).to eq true
|
145
|
+
expect(x.version).to eq 'x.y.z'
|
146
|
+
expect(x.connectable?).to eq true
|
147
|
+
expect(x.timed_out?).to eq false
|
148
|
+
end
|
149
|
+
end
|
150
|
+
context '#timed_out?' do
|
151
|
+
it 'calls start if not started' do
|
152
|
+
x = bitlbee(1, 'foo', 'bar')
|
153
|
+
expect(x).to receive(:start).once
|
154
|
+
expect(x.timed_out?).to eq false
|
155
|
+
end
|
156
|
+
it 'doesnt call start if started' do
|
157
|
+
x = bitlbee(1, 'foo', 'bar')
|
158
|
+
x.instance_variable_set(:@started, true)
|
159
|
+
expect(x).to_not receive(:start)
|
160
|
+
expect(x.timed_out?).to eq false
|
161
|
+
end
|
162
|
+
end
|
163
|
+
context '#connectable?' do
|
164
|
+
it 'calls start if not started' do
|
165
|
+
x = bitlbee(1, 'foo', 'bar')
|
166
|
+
expect(x).to receive(:start).once
|
167
|
+
expect(x.connectable?).to eq false
|
168
|
+
end
|
169
|
+
it 'doesnt call start if started' do
|
170
|
+
x = bitlbee(1, 'foo', 'bar')
|
171
|
+
x.instance_variable_set(:@started, true)
|
172
|
+
expect(x).to_not receive(:start)
|
173
|
+
expect(x.connectable?).to eq false
|
174
|
+
end
|
175
|
+
end
|
176
|
+
context '#version?' do
|
177
|
+
it 'calls start if not started' do
|
178
|
+
x = bitlbee(1, 'foo', 'bar')
|
179
|
+
expect(x).to receive(:start).once
|
180
|
+
expect(x.version).to eq ""
|
181
|
+
end
|
182
|
+
it 'doesnt call start if started' do
|
183
|
+
x = bitlbee(1, 'foo', 'bar')
|
184
|
+
x.instance_variable_set(:@started, true)
|
185
|
+
expect(x).to_not receive(:start)
|
186
|
+
expect(x.version).to eq ""
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|