ruby-cute 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|