spectre-core 1.11.0 → 1.12.0
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 +4 -4
- data/exe/spectre +516 -524
- data/lib/spectre/assertion.rb +33 -14
- data/lib/spectre/bag.rb +21 -19
- data/lib/spectre/curl.rb +397 -391
- data/lib/spectre/diagnostic.rb +39 -29
- data/lib/spectre/environment.rb +30 -26
- data/lib/spectre/helpers.rb +133 -134
- data/lib/spectre/http/basic_auth.rb +5 -2
- data/lib/spectre/http/keystone.rb +76 -73
- data/lib/spectre/http.rb +82 -76
- data/lib/spectre/logger/console.rb +143 -142
- data/lib/spectre/logger/file.rb +1 -1
- data/lib/spectre/logger.rb +3 -1
- data/lib/spectre/mixin.rb +58 -34
- data/lib/spectre/reporter/console.rb +102 -104
- data/lib/spectre/reporter/junit.rb +100 -100
- data/lib/spectre/resources.rb +49 -46
- data/lib/spectre.rb +440 -438
- metadata +3 -3
data/lib/spectre/diagnostic.rb
CHANGED
@@ -1,29 +1,39 @@
|
|
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
|
-
end
|
1
|
+
require_relative '../spectre'
|
2
|
+
|
3
|
+
module Spectre
|
4
|
+
module Diagnostic
|
5
|
+
module Stopwatch
|
6
|
+
@@duration = 0.0
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def start_watch
|
10
|
+
@@start_time = Time.now
|
11
|
+
end
|
12
|
+
|
13
|
+
def stop_watch
|
14
|
+
@@end_time = Time.now
|
15
|
+
end
|
16
|
+
|
17
|
+
def measure
|
18
|
+
start_watch
|
19
|
+
yield
|
20
|
+
stop_watch
|
21
|
+
end
|
22
|
+
|
23
|
+
def duration
|
24
|
+
@@end_time - @@start_time
|
25
|
+
end
|
26
|
+
|
27
|
+
def started_at
|
28
|
+
@@start_time
|
29
|
+
end
|
30
|
+
|
31
|
+
def finished_at
|
32
|
+
@@end_time
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
Spectre.delegate :start_watch, :stop_watch, :duration, :measure, to: self
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/spectre/environment.rb
CHANGED
@@ -1,26 +1,30 @@
|
|
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
|
-
end
|
1
|
+
require_relative '../spectre'
|
2
|
+
|
3
|
+
require 'ostruct'
|
4
|
+
|
5
|
+
def to_recursive_ostruct(hash)
|
6
|
+
OpenStruct.new(
|
7
|
+
hash.each_with_object({}) do |(key, val), memo|
|
8
|
+
memo[key] = val.is_a?(Hash) ? to_recursive_ostruct(val) : val
|
9
|
+
end
|
10
|
+
)
|
11
|
+
end
|
12
|
+
|
13
|
+
module Spectre
|
14
|
+
module Environment
|
15
|
+
class << self
|
16
|
+
@@environment = OpenStruct.new
|
17
|
+
|
18
|
+
def env
|
19
|
+
@@environment
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
Spectre.register do |config|
|
24
|
+
@@environment = to_recursive_ostruct(config)
|
25
|
+
@@environment.freeze
|
26
|
+
end
|
27
|
+
|
28
|
+
Spectre.delegate :env, to: self
|
29
|
+
end
|
30
|
+
end
|
data/lib/spectre/helpers.rb
CHANGED
@@ -1,134 +1,133 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require '
|
4
|
-
require '
|
5
|
-
require '
|
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
|
-
file_content
|
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
|
-
end
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
end
|
125
|
-
|
126
|
-
|
127
|
-
def uuid length = 5
|
128
|
-
SecureRandom.uuid().gsub('-', '')[0..length-1]
|
129
|
-
end
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
end
|
1
|
+
require_relative '../spectre'
|
2
|
+
|
3
|
+
require 'securerandom'
|
4
|
+
require 'json'
|
5
|
+
require 'date'
|
6
|
+
require 'ostruct'
|
7
|
+
require 'jsonpath'
|
8
|
+
|
9
|
+
class ::String
|
10
|
+
def as_json
|
11
|
+
JSON.parse(self, object_class: OpenStruct)
|
12
|
+
end
|
13
|
+
|
14
|
+
def as_date
|
15
|
+
DateTime.parse(self)
|
16
|
+
end
|
17
|
+
|
18
|
+
def as_timestamp
|
19
|
+
DateTime.parse(self).to_time.to_i
|
20
|
+
end
|
21
|
+
|
22
|
+
def with mapping
|
23
|
+
return self unless mapping and mapping.is_a? Hash
|
24
|
+
|
25
|
+
new_string = self
|
26
|
+
|
27
|
+
mapping.each do |key, value|
|
28
|
+
new_string = new_string.gsub('#{' + key.to_s + '}', value.to_s)
|
29
|
+
end
|
30
|
+
|
31
|
+
new_string
|
32
|
+
end
|
33
|
+
|
34
|
+
def trim size = 50
|
35
|
+
if (self.length + 3) > size
|
36
|
+
return self[0..size-4] + '...'
|
37
|
+
end
|
38
|
+
|
39
|
+
self
|
40
|
+
end
|
41
|
+
|
42
|
+
def pick path
|
43
|
+
raise ArgumentError.new("`path' must not be nil or empty") if path.nil? or path.empty?
|
44
|
+
|
45
|
+
begin
|
46
|
+
JsonPath.on(self, path)
|
47
|
+
rescue MultiJson::ParseError
|
48
|
+
# do nothing and return nil
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# File helpers
|
53
|
+
|
54
|
+
def content with: nil
|
55
|
+
fail "'#{self}' is not a file path, or the file does not exist." unless File.exists? self
|
56
|
+
|
57
|
+
file_content = File.read(self)
|
58
|
+
|
59
|
+
if with
|
60
|
+
file_content.with(with)
|
61
|
+
else
|
62
|
+
file_content
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def file_size
|
67
|
+
fail "'#{self}' is not a file path, or the file does not exist." unless File.exists? self
|
68
|
+
|
69
|
+
File.size(self)
|
70
|
+
end
|
71
|
+
|
72
|
+
def exists?
|
73
|
+
File.exists? self
|
74
|
+
end
|
75
|
+
|
76
|
+
def remove!
|
77
|
+
fail "'#{self}' is not a file path, or the file does not exist." unless File.exists? self
|
78
|
+
|
79
|
+
File.delete self
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class ::OpenStruct
|
84
|
+
def to_json *args, **kwargs
|
85
|
+
self.to_h.inject({}) { |memo, (k,v)| memo[k] = v.is_a?(OpenStruct) ? v.to_h : v; memo }.to_json(*args, **kwargs)
|
86
|
+
end
|
87
|
+
|
88
|
+
def pick path
|
89
|
+
raise ArgumentError.new("`path' must not be nil or empty") if path.nil? or path.empty?
|
90
|
+
|
91
|
+
JsonPath.on(self, path)
|
92
|
+
end
|
93
|
+
|
94
|
+
def default_to! defaults
|
95
|
+
defaults.each_key do |key|
|
96
|
+
unless self[key] != nil
|
97
|
+
self[key] = defaults[key]
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
alias :defaults_to! :default_to!
|
103
|
+
end
|
104
|
+
|
105
|
+
class ::Hash
|
106
|
+
def symbolize_keys
|
107
|
+
self.inject({}) { |memo, (k,v)| memo[k.to_sym] = v; memo }
|
108
|
+
end
|
109
|
+
|
110
|
+
def default_to! defaults
|
111
|
+
defaults.each_key do |key|
|
112
|
+
unless self[key] != nil
|
113
|
+
self[key] = defaults[key]
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
alias :defaults_to! :default_to!
|
119
|
+
end
|
120
|
+
|
121
|
+
class ::Array
|
122
|
+
def last_element
|
123
|
+
self[-1]
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def uuid length = 5
|
128
|
+
SecureRandom.uuid().gsub('-', '')[0..length-1]
|
129
|
+
end
|
130
|
+
|
131
|
+
def now
|
132
|
+
Time.now
|
133
|
+
end
|
@@ -1,7 +1,9 @@
|
|
1
|
+
require_relative '../http'
|
2
|
+
|
1
3
|
module Spectre::Http
|
2
4
|
class SpectreHttpRequest
|
3
5
|
def basic_auth username, password
|
4
|
-
@__req['basic_auth'] = {}
|
6
|
+
@__req['basic_auth'] = {} unless @__req.key? 'basic_auth'
|
5
7
|
|
6
8
|
@__req['basic_auth']['username'] = username
|
7
9
|
@__req['basic_auth']['password'] = password
|
@@ -11,8 +13,9 @@ module Spectre::Http
|
|
11
13
|
end
|
12
14
|
|
13
15
|
module BasicAuth
|
14
|
-
def self.on_req
|
16
|
+
def self.on_req _http, net_req, req
|
15
17
|
return unless req.key? 'basic_auth' and req['auth'] == 'basic_auth'
|
18
|
+
|
16
19
|
basic_auth_cfg = req['basic_auth']
|
17
20
|
net_req.basic_auth(basic_auth_cfg['username'], basic_auth_cfg['password'])
|
18
21
|
end
|
@@ -1,98 +1,101 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
1
|
+
require_relative '../http'
|
2
|
+
|
3
|
+
module Spectre::Http
|
4
|
+
class SpectreHttpRequest
|
5
|
+
def keystone url, username, password, project, domain, cert=nil
|
6
|
+
@__req['keystone'] = {} unless @__req.key? 'keystone'
|
7
|
+
|
8
|
+
@__req['keystone']['url'] = url
|
9
|
+
@__req['keystone']['username'] = username
|
10
|
+
@__req['keystone']['password'] = password
|
11
|
+
@__req['keystone']['project'] = project
|
12
|
+
@__req['keystone']['domain'] = domain
|
13
|
+
@__req['keystone']['cert'] = cert
|
14
|
+
|
15
|
+
@__req['auth'] = 'keystone'
|
16
|
+
end
|
13
17
|
end
|
14
|
-
end
|
15
18
|
|
19
|
+
module Keystone
|
20
|
+
@@cache = {}
|
16
21
|
|
17
|
-
|
18
|
-
|
22
|
+
def self.on_req _http, net_req, req
|
23
|
+
return unless req.key? 'keystone' and req['auth'] == 'keystone'
|
19
24
|
|
20
|
-
|
21
|
-
return unless req.key? 'keystone' and req['auth'] == 'keystone'
|
25
|
+
keystone_cfg = req['keystone']
|
22
26
|
|
23
|
-
|
27
|
+
if @@cache.key? keystone_cfg
|
28
|
+
token = @@cache[keystone_cfg]
|
29
|
+
else
|
30
|
+
token, _ = authenticate(
|
31
|
+
keystone_cfg['url'],
|
32
|
+
keystone_cfg['username'],
|
33
|
+
keystone_cfg['password'],
|
34
|
+
keystone_cfg['project'],
|
35
|
+
keystone_cfg['domain'],
|
36
|
+
keystone_cfg['cert'],
|
37
|
+
)
|
24
38
|
|
25
|
-
|
26
|
-
|
27
|
-
else
|
28
|
-
token, _ = authenticate(
|
29
|
-
keystone_cfg['url'],
|
30
|
-
keystone_cfg['username'],
|
31
|
-
keystone_cfg['password'],
|
32
|
-
keystone_cfg['project'],
|
33
|
-
keystone_cfg['domain'],
|
34
|
-
keystone_cfg['cert'],
|
35
|
-
)
|
39
|
+
@@cache[keystone_cfg] = token
|
40
|
+
end
|
36
41
|
|
37
|
-
|
42
|
+
net_req['X-Auth-Token'] = token
|
38
43
|
end
|
39
44
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
domain: {
|
55
|
-
name: domain,
|
45
|
+
private
|
46
|
+
|
47
|
+
def self.authenticate keystone_url, username, password, project, domain, cert
|
48
|
+
auth_data = {
|
49
|
+
auth: {
|
50
|
+
identity: {
|
51
|
+
methods: ['password'],
|
52
|
+
password: {
|
53
|
+
user: {
|
54
|
+
name: username,
|
55
|
+
password: password,
|
56
|
+
domain: {
|
57
|
+
name: domain,
|
58
|
+
},
|
56
59
|
},
|
57
60
|
},
|
58
61
|
},
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
62
|
+
scope: {
|
63
|
+
project: {
|
64
|
+
name: project,
|
65
|
+
domain: {
|
66
|
+
name: domain,
|
67
|
+
},
|
65
68
|
},
|
66
69
|
},
|
67
70
|
},
|
68
|
-
}
|
69
|
-
}
|
71
|
+
}
|
70
72
|
|
71
|
-
|
73
|
+
keystone_url = keystone_url + '/' unless keystone_url.end_with? '/'
|
72
74
|
|
73
|
-
|
74
|
-
|
75
|
+
base_uri = URI(keystone_url)
|
76
|
+
uri = URI.join(base_uri, 'auth/tokens?nocatalog=true')
|
75
77
|
|
76
|
-
|
78
|
+
http = Net::HTTP.new(base_uri.host, base_uri.port)
|
77
79
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
80
|
+
if cert
|
81
|
+
http.use_ssl = true
|
82
|
+
http.ca_file = cert
|
83
|
+
end
|
82
84
|
|
83
|
-
|
84
|
-
|
85
|
-
|
85
|
+
req = Net::HTTP::Post.new(uri)
|
86
|
+
req.body = JSON.pretty_generate(auth_data)
|
87
|
+
req.content_type = 'application/json'
|
86
88
|
|
87
|
-
|
89
|
+
res = http.request(req)
|
88
90
|
|
89
|
-
|
91
|
+
raise "error while authenticating: #{res.code} #{res.message}\n#{res.body}" if res.code != '201'
|
90
92
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
93
|
+
[
|
94
|
+
res['X-Subject-Token'],
|
95
|
+
JSON.parse(res.body),
|
96
|
+
]
|
97
|
+
end
|
96
98
|
|
97
|
-
|
99
|
+
Spectre::Http.register(self)
|
100
|
+
end
|
98
101
|
end
|