ruby-cute 0.0.1 → 0.0.2
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 +7 -0
- data/.gitignore +6 -0
- data/.yardopts +2 -0
- data/Gemfile +6 -0
- data/README.md +137 -6
- data/Rakefile +48 -0
- data/bin/cute +22 -0
- data/debian/changelog +5 -0
- data/debian/compat +1 -0
- data/debian/control +15 -0
- data/debian/copyright +33 -0
- data/debian/ruby-cute.docs +2 -0
- data/debian/ruby-tests.rb +2 -0
- data/debian/rules +19 -0
- data/debian/source/format +1 -0
- data/debian/watch +2 -0
- data/examples/distem-bootstrap +516 -0
- data/examples/g5k_exp1.rb +41 -0
- data/examples/g5k_exp_virt.rb +129 -0
- data/lib/cute.rb +7 -2
- data/lib/cute/bash.rb +337 -0
- data/lib/cute/configparser.rb +404 -0
- data/lib/cute/execute.rb +272 -0
- data/lib/cute/extensions.rb +38 -0
- data/lib/cute/g5k_api.rb +1190 -0
- data/lib/cute/net-ssh.rb +144 -0
- data/lib/cute/net.rb +29 -0
- data/lib/cute/synchronization.rb +89 -0
- data/lib/cute/taktuk.rb +554 -0
- data/lib/cute/version.rb +3 -0
- data/ruby-cute.gemspec +32 -0
- data/spec/extensions_spec.rb +17 -0
- data/spec/g5k_api_spec.rb +192 -0
- data/spec/spec_helper.rb +66 -0
- data/spec/taktuk_spec.rb +129 -0
- data/test/test_bash.rb +71 -0
- metadata +204 -47
data/lib/cute/version.rb
ADDED
data/ruby-cute.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
lib = File.expand_path('../lib', __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require 'cute/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "ruby-cute"
|
7
|
+
s.version = Cute::VERSION
|
8
|
+
s.authors = ["Algorille team"]
|
9
|
+
s.email = "ruby-cute-staff@lists.gforge.inria.fr"
|
10
|
+
s.homepage = "http://ruby-cute.gforge.inria.fr/"
|
11
|
+
s.summary = "Critically Useful Tools for Experiments"
|
12
|
+
s.description = "Ruby library for controlling experiments"
|
13
|
+
s.required_rubygems_version = ">= 1.3.6"
|
14
|
+
s.files = `git ls-files -z`.split("\x0")
|
15
|
+
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
16
|
+
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
s.add_development_dependency "bundler", "~> 1.7"
|
19
|
+
s.add_development_dependency "rake", "~> 10.0"
|
20
|
+
s.add_development_dependency "rspec", "~> 3.1"
|
21
|
+
s.add_development_dependency "pry", "~> 0.10"
|
22
|
+
s.add_development_dependency "webmock", "~> 1.20"
|
23
|
+
s.add_development_dependency "yard", "~> 0.8"
|
24
|
+
|
25
|
+
s.add_dependency 'rest-client', '1.6.7'
|
26
|
+
s.add_dependency 'json', '~> 1.8'
|
27
|
+
s.add_dependency 'ipaddress', '~>0.8'
|
28
|
+
s.add_dependency 'net-ssh-multi', '~>1.2'
|
29
|
+
|
30
|
+
s.extra_rdoc_files = ['README.md', 'LICENSE']
|
31
|
+
s.license = 'CeCILL-B'
|
32
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
|
4
|
+
describe "Monkey patch to class String" do
|
5
|
+
|
6
|
+
it "converts walltime format into seconds" do
|
7
|
+
digits = []
|
8
|
+
|
9
|
+
(0..9).each{ |x| digits.push(x.to_s)}
|
10
|
+
time = digits.combination(2).to_a.map{ |x| x.join("")}.select{ |h| h.to_i < 60 }
|
11
|
+
walltime = time.combination(3).to_a.map{ |x| x.join(":")}
|
12
|
+
|
13
|
+
expect {walltime.each{ |t| t.to_secs}}.not_to raise_error
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,192 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
# These tests can be executed either real or using mocking through WebMock
|
3
|
+
# Real tests can be activated by setting the shell variable TEST_REAL
|
4
|
+
describe Cute::G5K::API do
|
5
|
+
|
6
|
+
subject { g5k = ENV['TEST_REAL'].nil?? Cute::G5K::API.new(:user => "test") : Cute::G5K::API.new() }
|
7
|
+
|
8
|
+
let(:sites) { subject.site_uids}
|
9
|
+
|
10
|
+
before :each do
|
11
|
+
# Choosing a random site based on the date
|
12
|
+
day = Time.now.day
|
13
|
+
index = ((day/31.to_f)*sites.length).to_i
|
14
|
+
index = 1 if index == 0
|
15
|
+
@rand_site = sites[index]
|
16
|
+
@env = subject.environment_uids(@rand_site).first
|
17
|
+
if ENV['TEST_REAL']
|
18
|
+
WebMock.disable!
|
19
|
+
puts "Testing in real Grid'5000 using site: #{@rand_site}"
|
20
|
+
puts "Warning G5K_USER environment variable has to be defined for some tests" if ENV['G5K_USER'].nil?
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
it "checks initialization of G5K::API" do
|
25
|
+
expect(subject.rest).to be_an_instance_of(Cute::G5K::G5KRest)
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
it "returns an array with the site ids" do
|
30
|
+
expect(sites.length).to be > 0
|
31
|
+
end
|
32
|
+
|
33
|
+
it "returns an array with the clusters ids" do
|
34
|
+
clusters = subject.cluster_uids(@rand_site)
|
35
|
+
expect(clusters.length).to be > 0
|
36
|
+
end
|
37
|
+
|
38
|
+
it "returns a JSON Hash with the status of a site" do
|
39
|
+
expect(subject.site_status(@rand_site)).to be_an_instance_of(Cute::G5K::G5KJSON)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "returns a Hash with nodes status" do
|
43
|
+
expect(subject.nodes_status(@rand_site)).to be_an_instance_of(Hash)
|
44
|
+
expect(subject.nodes_status(@rand_site).length).to be > 0
|
45
|
+
end
|
46
|
+
|
47
|
+
it "returns an array with site status" do
|
48
|
+
expect(subject.sites).to be_an_instance_of(Cute::G5K::G5KArray)
|
49
|
+
end
|
50
|
+
|
51
|
+
it "returns jobs in the site" do
|
52
|
+
expect(subject.get_jobs(@rand_site)).to be_an_instance_of(Array)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "return my_jobs in the site" do
|
56
|
+
expect(subject.get_my_jobs(@rand_site)).to be_an_instance_of(Array)
|
57
|
+
end
|
58
|
+
|
59
|
+
it "returns all deployments" do
|
60
|
+
expect(subject.get_deployments(@rand_site)).to be_an_instance_of(Cute::G5K::G5KArray)
|
61
|
+
end
|
62
|
+
|
63
|
+
it "raises an authentication error" do
|
64
|
+
expect{Cute::G5K::API.new(:user => "fake", :pass => "fake") }.to raise_error
|
65
|
+
end
|
66
|
+
|
67
|
+
it "raises a non found error" do
|
68
|
+
expect{subject.get_jobs("non-found")}.to raise_error(Cute::G5K::NotFound)
|
69
|
+
end
|
70
|
+
|
71
|
+
it "raises a bad request error" do
|
72
|
+
expect{ subject.reserve(:site => @rand_site, :resources =>"/slash_22=1+{nonsense}")}.to raise_error(Cute::G5K::BadRequest)
|
73
|
+
# expect{ subject.reserve(:site => @rand_site, :resources =>"{ib30g='YES'}/nodes=2")}.to raise_error(Cute::G5K::BadRequest)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "raises an exception at deploying" do
|
77
|
+
expect{ subject.reserve(:site => @rand_site, :nodes => 1, :env => "nonsense")}.to raise_error(Cute::G5K::RequestFailed)
|
78
|
+
end
|
79
|
+
|
80
|
+
it "raises argument errors" do
|
81
|
+
job = Cute::G5K::G5KJSON.new
|
82
|
+
expect {subject.deploy(:env => "env")}.to raise_error(ArgumentError)
|
83
|
+
expect {subject.deploy(job)}.to raise_error(ArgumentError)
|
84
|
+
expect {subject.reserve(:non_existing => "site")}.to raise_error(ArgumentError)
|
85
|
+
end
|
86
|
+
|
87
|
+
it "raises invalid nodes format" do
|
88
|
+
job = Cute::G5K::G5KJSON.new
|
89
|
+
expect{subject.deploy(job,:env => "env")}.to raise_error(RuntimeError,"Unrecognized nodes format, use an Array")
|
90
|
+
end
|
91
|
+
|
92
|
+
it "raises error vlan" do
|
93
|
+
expect {subject.reserve(:site => @rand_site, :vlan => :nonsense)}.to raise_error(ArgumentError,'Option for vlan not recognized')
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
it "reserves and returns a valid job" do
|
98
|
+
job = subject.reserve(:site => @rand_site)
|
99
|
+
expect(job).to be_an_instance_of(Cute::G5K::G5KJSON)
|
100
|
+
subject.release(job)
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
it "reserves with vlan and get vlan hostnames" do
|
105
|
+
job = subject.reserve(:site => @rand_site, :nodes => 1, :type => :deploy, :vlan => :routed)
|
106
|
+
expect(subject.get_vlan_nodes(job)).to be_an_instance_of(Array)
|
107
|
+
subject.release(job)
|
108
|
+
end
|
109
|
+
|
110
|
+
it "vlan returns nil" do
|
111
|
+
job = Cute::G5K::G5KJSON.new
|
112
|
+
expect(subject.get_vlan_nodes(job)).to be_nil
|
113
|
+
end
|
114
|
+
|
115
|
+
it "performs an advanced reservation" do
|
116
|
+
time_schedule = Time.now + 60*30
|
117
|
+
job =subject.reserve(:site => @rand_site, :nodes => 1, :reservation => time_schedule.strftime("%Y-%m-%d %H:%M:%S"))
|
118
|
+
subject.release(job)
|
119
|
+
end
|
120
|
+
|
121
|
+
it "gets subnets from job" do
|
122
|
+
job = subject.reserve(:site => @rand_site, :nodes => 1, :subnets => [22,2])
|
123
|
+
expect(subject.get_subnets(job).first).to be_an_instance_of(IPAddress::IPv4)
|
124
|
+
subject.release(job)
|
125
|
+
end
|
126
|
+
|
127
|
+
|
128
|
+
it "does not deploy immediately" do
|
129
|
+
job = subject.reserve(:site => @rand_site, :type => :deploy )
|
130
|
+
expect(job).to include("types" => ["deploy"])
|
131
|
+
expect(job).to_not have_key("deploy")
|
132
|
+
end
|
133
|
+
|
134
|
+
it "tests deploy with keys option" do
|
135
|
+
# Getting a deploy job
|
136
|
+
job = subject.get_my_jobs(@rand_site).select{ |j| j.has_value?(["deploy"])}.first
|
137
|
+
fake_key = Tempfile.new(["keys",".pub"])
|
138
|
+
fake_key_path = fake_key.path.split(".pub").first
|
139
|
+
expect(subject.deploy(job,:env => @env,:wait => true, :keys => fake_key_path)).to be_an_instance_of(Cute::G5K::G5KJSON)
|
140
|
+
fake_key.delete
|
141
|
+
end
|
142
|
+
|
143
|
+
it "waits for a deploy" do
|
144
|
+
job = subject.get_my_jobs(@rand_site).select{ |j| j.has_value?(["deploy"])}.first
|
145
|
+
# It verifies that the job has been submitted with deploy
|
146
|
+
expect(subject.deploy_status(job)).to be_an_instance_of(Array)
|
147
|
+
subject.wait_for_deploy(job)
|
148
|
+
expect(subject.deploy_status(job)).to be_an_instance_of(Array)
|
149
|
+
|
150
|
+
#deploying again
|
151
|
+
# subject.deploy(job, :env => @env)
|
152
|
+
# subject.wait_for_deploy(job)
|
153
|
+
# expect(subject.deploy_status(job).uniq).to eq(["terminated"])
|
154
|
+
end
|
155
|
+
|
156
|
+
|
157
|
+
it "submits a job and then deploy" do
|
158
|
+
expect(subject.reserve(:site => @rand_site, :env => @env)).to have_key("deploy")
|
159
|
+
end
|
160
|
+
|
161
|
+
|
162
|
+
it "returns the same information" do
|
163
|
+
#low level REST access
|
164
|
+
jobs_running = subject.rest.get_json("sid/sites/#{@rand_site}/jobs/?state=running").items.length
|
165
|
+
expect(subject.get_jobs(@rand_site,nil,"running").length).to eq(jobs_running)
|
166
|
+
end
|
167
|
+
|
168
|
+
it "submit and does not wait for the reservation" do
|
169
|
+
cluster = subject.cluster_uids(@rand_site).first
|
170
|
+
job = subject.reserve(:site => @rand_site, :wait => false)
|
171
|
+
job = subject.wait_for_job(job, :wait_time => 600)
|
172
|
+
expect(job).to include('state' => "running")
|
173
|
+
end
|
174
|
+
|
175
|
+
|
176
|
+
it "should submit a job with OAR hierarchy" do
|
177
|
+
|
178
|
+
job1 = subject.reserve(:site => @rand_site, :switches => 2, :nodes=>1, :cpus => 1, :cores => 1,
|
179
|
+
:keys => "/home/#{ENV['G5K_USER']}/.ssh/id_rsa",:walltime => '00:10:00')
|
180
|
+
job2 = subject.reserve(:site => @rand_site, :resources => "/switch=2/nodes=1/cpu=1/core=1",
|
181
|
+
:keys => "/home/#{ENV['G5K_USER']}/.ssh/id_rsa",:walltime => '00:10:00')
|
182
|
+
|
183
|
+
expect(job1).to be_an_instance_of(Cute::G5K::G5KJSON)
|
184
|
+
expect(job2).to be_an_instance_of(Cute::G5K::G5KJSON)
|
185
|
+
|
186
|
+
end
|
187
|
+
|
188
|
+
it "releases all jobs in a site" do
|
189
|
+
expect(subject.release_all(@rand_site)).to be true
|
190
|
+
end
|
191
|
+
|
192
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
require 'webmock/rspec'
|
3
|
+
|
4
|
+
SimpleCov.start
|
5
|
+
# The SimpleCov.start must be issued before any of the application code is required!
|
6
|
+
require 'cute'
|
7
|
+
|
8
|
+
# Disabling all external requests
|
9
|
+
WebMock.disable_net_connect!(allow_localhost: true)
|
10
|
+
|
11
|
+
|
12
|
+
class FakeG5KResponse < Hash
|
13
|
+
MEDIA_TYPE = {'uid' => "1",
|
14
|
+
'id' => "1",
|
15
|
+
'user' => "test",
|
16
|
+
'items' => [{'uid' => "item1"},{'uid' => "item2"}],
|
17
|
+
'total' => [2],
|
18
|
+
'offset' => 2,
|
19
|
+
'links' => [{"rel" => "self","href" => "path", "type"=>"application/vnd.grid5000.collection+json"},
|
20
|
+
{"rel" => "parent","href" => "path", "type"=>"application/vnd.grid5000.collection+json"}],
|
21
|
+
'state' => "running",
|
22
|
+
'started_at' => Time.now,
|
23
|
+
'created_at' => Time.now,
|
24
|
+
'status' => "terminated",
|
25
|
+
'types' => ["deploy"],
|
26
|
+
'assigned_nodes' => ["node1","node2"],
|
27
|
+
'resources_by_type' => {"res" => "val1","subnets" => ["10.140.0.0/22"], "vlans"=>["4"]},
|
28
|
+
'nodes' => {"node1" => {"hard"=> "alive", "soft"=>"busy"}}
|
29
|
+
}
|
30
|
+
def initialize(num_items = 2)
|
31
|
+
MEDIA_TYPE.each { |key,value| self[key] = value}
|
32
|
+
self['items'] = []
|
33
|
+
num_items.times.each{ self['items'].push(MEDIA_TYPE) }
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
RSpec.configure do |config|
|
40
|
+
config.fail_fast = true
|
41
|
+
|
42
|
+
g5k_media_type = FakeG5KResponse.new
|
43
|
+
# Example using addressable templates
|
44
|
+
# uri_sites = Addressable::Template.new "https://{user}:{password}@api.grid5000.fr/{version}/sites"
|
45
|
+
config.before(:each) do
|
46
|
+
|
47
|
+
stub_request(:any,/^https:\/\/.*\:.*@api.grid5000.fr\/.*/).
|
48
|
+
to_return(:status => 200, :body => g5k_media_type.to_json, :headers => {})
|
49
|
+
|
50
|
+
stub_request(:any,/^https:\/\/fake:fake@api.grid5000.fr\.*/).
|
51
|
+
to_return(:status => 401)
|
52
|
+
|
53
|
+
stub_request(:any,/^https:\/\/.*\:.*@api.grid5000.fr\/...\/sites\/non-found\/.*/).
|
54
|
+
to_return(:status => 404)
|
55
|
+
|
56
|
+
stub_request(:post, /^https:\/\/.*\:.*@api.grid5000.fr\/.*/).
|
57
|
+
with(:body => hash_including("resources" => "/slash_22=1+{nonsense},walltime=01:00")).
|
58
|
+
to_return(:status => 400, :body => "Oarsub failed: please verify your request syntax")
|
59
|
+
|
60
|
+
stub_request(:post, /^https:\/\/.*\:.*@api.grid5000.fr\/.*/).
|
61
|
+
with(:body => hash_including("environment" => "nonsense")).
|
62
|
+
to_return(:status => 500, :body => "Invalid environment specification")
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
data/spec/taktuk_spec.rb
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Cute::TakTuk::Stream do
|
4
|
+
|
5
|
+
subject { Cute::TakTuk::Stream.new([:output, :error, :status ]) }
|
6
|
+
|
7
|
+
def random_string(length)
|
8
|
+
valid_chars = []
|
9
|
+
(32..126).each{ |x| valid_chars.push(x.chr)}
|
10
|
+
(1..length).map{ valid_chars[rand(valid_chars.length-1)]}.join
|
11
|
+
end
|
12
|
+
|
13
|
+
it "creates an stream" do
|
14
|
+
stream = Cute::TakTuk::Stream.new
|
15
|
+
expect(stream.types.empty?).to be true
|
16
|
+
end
|
17
|
+
|
18
|
+
it "checking types" do
|
19
|
+
stream = Cute::TakTuk::Stream.new([:output, :error, :status ])
|
20
|
+
expect(stream.types.length).to be 3
|
21
|
+
end
|
22
|
+
|
23
|
+
it "returns empty result" do
|
24
|
+
string = random_string(50)
|
25
|
+
expect(subject.parse(string).empty?).to be true
|
26
|
+
end
|
27
|
+
|
28
|
+
it "returns empty value" do
|
29
|
+
string ="machine.fr/output/aaaaaaaaaa"
|
30
|
+
result = subject.parse(string)
|
31
|
+
expect(result.values.first[:output].length).to be 0
|
32
|
+
end
|
33
|
+
|
34
|
+
it "parses simple string" do
|
35
|
+
value = random_string(50)
|
36
|
+
string ="machine.fr/output/123:#{value}\n"
|
37
|
+
expect(subject.parse(string).empty?).to be false
|
38
|
+
end
|
39
|
+
|
40
|
+
it "parses string with number" do
|
41
|
+
string = "machine/output/1:1\n"
|
42
|
+
expect(subject.parse(string).empty?).to be false
|
43
|
+
end
|
44
|
+
|
45
|
+
it "parses the same line twice" do
|
46
|
+
string = "machine/output/1:1\n output/machine/1:2\n"
|
47
|
+
expect(subject.parse(string).empty?).to be false
|
48
|
+
end
|
49
|
+
|
50
|
+
it "has just one key" do
|
51
|
+
string = "machine/output/1:1\n"
|
52
|
+
expect(subject.parse(string).keys.length).to be 1
|
53
|
+
end
|
54
|
+
|
55
|
+
it "has two keys" do
|
56
|
+
string = "machine1/output/1:1\nmachine2/output/1:2\n"
|
57
|
+
expect(subject.parse(string).keys.length).to be 2
|
58
|
+
end
|
59
|
+
|
60
|
+
it "returns the same output" do
|
61
|
+
value = random_string(100)
|
62
|
+
stdout = "1:"+value
|
63
|
+
string = "machine.fr/output/#{stdout}"
|
64
|
+
result = subject.parse(string)
|
65
|
+
expect(result.values.first[:output]).to eq(value)
|
66
|
+
end
|
67
|
+
|
68
|
+
it "parses very long output" do
|
69
|
+
value = random_string(1000)
|
70
|
+
stdout = "1:"+value
|
71
|
+
string = "machine.fr/output/#{stdout}"
|
72
|
+
result = subject.parse(string)
|
73
|
+
expect(result.values.first[:output]).to eq(value)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "parses hostname and ip" do
|
77
|
+
value = random_string(1000)
|
78
|
+
stdout = "1:"+value
|
79
|
+
machines =["machine.fr","192.168.101.56"]
|
80
|
+
string = "#{machines[0]}/output/#{stdout} \n#{machines[1]}/output/#{stdout}"
|
81
|
+
result = subject.parse(string)
|
82
|
+
expect(result.keys).to eq(machines)
|
83
|
+
end
|
84
|
+
|
85
|
+
it "concatenates stdouts" do
|
86
|
+
value = random_string(100)
|
87
|
+
stdout = "1:"+value # by default streams are formated /machine_name/stream/something:output
|
88
|
+
# the "something:" it is just for making the execution time of the regex shorter.
|
89
|
+
string = "machine.fr/output/#{stdout}\nmachine.fr/output/#{stdout}\n"
|
90
|
+
expect(subject.parse(string).values.first[:output].length).to be 2*value.length + 1
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
describe "TakTuk" do
|
96
|
+
it "raises an argument error" do
|
97
|
+
expect{Cute::TakTuk::TakTuk.new()}.to raise_error(ArgumentError)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "raises an argument error" do
|
101
|
+
expect{Cute::TakTuk::TakTuk.new("aaa","aaa")}.to raise_error(ArgumentError)
|
102
|
+
end
|
103
|
+
|
104
|
+
it "does not raise error" do
|
105
|
+
# TakTuk validate options at the beginning of the execution.
|
106
|
+
expect{Cute::TakTuk::TakTuk.new("aaa",{:aaa => "aaa"})}.not_to raise_error
|
107
|
+
end
|
108
|
+
|
109
|
+
it "raises an argu" do
|
110
|
+
tak = Cute::TakTuk::TakTuk.new("aaa",{:aaa => "aaa"})
|
111
|
+
expect{ tak.exec!("haha")}.to raise_error(ArgumentError)
|
112
|
+
end
|
113
|
+
|
114
|
+
it "raises error due to a non existing file " do
|
115
|
+
tak = Cute::TakTuk::TakTuk.new("aaa",{:user => "aaa"})
|
116
|
+
expect{ tak.exec!("haha")}.to raise_error
|
117
|
+
end
|
118
|
+
|
119
|
+
it "raises er" do
|
120
|
+
tak = Cute::TakTuk::TakTuk.new(["aaa"],{:user => "aaa"})
|
121
|
+
expect{ tak.exec!("haha")}.not_to raise_error
|
122
|
+
end
|
123
|
+
|
124
|
+
it "raises er" do
|
125
|
+
tak = Cute::TakTuk::TakTuk.new(["aaa"],{:user => "aaa", :config => "conf_ssh_vagrant"})
|
126
|
+
expect{ tak.exec!("haha")}.not_to raise_error
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
data/test/test_bash.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
|
2
|
+
require 'test/unit'
|
3
|
+
require 'cute/bash'
|
4
|
+
|
5
|
+
class TestBash < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def with_bash(cmd = 'bash', &block)
|
8
|
+
return Cute::Bash.bash(cmd, &block)
|
9
|
+
end
|
10
|
+
|
11
|
+
def assert_status_error(&block)
|
12
|
+
throws = false
|
13
|
+
begin
|
14
|
+
with_bash(&block)
|
15
|
+
rescue Cute::Bash::StatusError
|
16
|
+
throws = true
|
17
|
+
end
|
18
|
+
assert_equal throws, true
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_files_dirs
|
22
|
+
with_bash do
|
23
|
+
cd '/'
|
24
|
+
assert pwd == '/'
|
25
|
+
assert dirs.include?('bin')
|
26
|
+
cd 'tmp'
|
27
|
+
assert pwd == '/tmp'
|
28
|
+
run 'rm -rf /tmp/bash_tests'
|
29
|
+
mkdir 'bash_tests'
|
30
|
+
cd 'bash_tests'
|
31
|
+
assert ls == []
|
32
|
+
touch 'file'
|
33
|
+
assert ls == [ 'file' ]
|
34
|
+
assert ls == files
|
35
|
+
mv 'file', 'backup'
|
36
|
+
assert ls == [ 'backup' ]
|
37
|
+
mkdir 'subdir'
|
38
|
+
assert ls.length == 2
|
39
|
+
assert dirs == [ 'subdir' ]
|
40
|
+
cp 'backup', 'subdir/whatever'
|
41
|
+
cd 'subdir'
|
42
|
+
assert ls == [ 'whatever' ]
|
43
|
+
cd '..'
|
44
|
+
assert abspath('subdir/hmmm') == '/tmp/bash_tests/subdir/hmmm'
|
45
|
+
|
46
|
+
f = tmp_file()
|
47
|
+
assert exists(f)
|
48
|
+
assert get_type(f) == :file
|
49
|
+
assert get_type('/var') == :dir
|
50
|
+
append_line f, "1st"
|
51
|
+
append_lines f, [ "2nd", "3rd" ]
|
52
|
+
assert cat(f) == contents(f)
|
53
|
+
lines = cat(f)
|
54
|
+
assert lines == "1st\n2nd\n3rd\n"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_utils
|
59
|
+
with_bash do
|
60
|
+
assert (echo 'anybody?') == ("anybody?\n")
|
61
|
+
assert (bc '2 + 2 * 2') == '6'
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_error
|
66
|
+
assert_status_error do
|
67
|
+
rm '/'
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|