[{{mminutes}}:{{sseconds}}] X
Пользователь приглашает вас присоединиться к открытой игре игре с друзьями .
Ruby
(0)       Используют 3 человека

Комментарии

Ни одного комментария.
Написать тут
Описание:
From ActiveSupport
Автор:
trolle
Создан:
7 марта 2023 в 16:00 (текущая версия от 17 марта 2023 в 09:12)
Публичный:
Нет
Тип словаря:
Фразы
В этом режиме перемешиваться будут не слова, а целые фразы, разделенные переносом строки.
Содержание:
1 sh 'cspell lint --no-progress "**/*"'
2 puts "--- Running #{gem} specs"
3 sh("bundle install --jobs=3 --retry=3")
4 RSpec::Core::RakeTask.new(:spec) do |t|
5 t.rspec_opts = %w{--profile}
6 t.pattern = FileList["spec/**/*_spec.rb"]
7 RSpec::Core::RakeTask.new(:all) do |t|
8 RSpec::Core::RakeTask.new(:doc) do |t|
9 t.rspec_opts = %w{--format specdoc --dry-run --profile}
10 puts "--- Running chef #{sub} specs"
11 t.rspec_opts = %w{--profile --format doc}
12 t.pattern = FileList["spec/#{sub}/**/*_spec.rb"]
13 STDERR.puts "
*** RSpec not available. (sudo) gem install rspec to run unit tests. ***

"
14 $:.unshift(File.expand_path(File.join(__dir__, "lib")))
15 return nil if default.nil? || default == "" || default == "lazy default"
16 return default.inspect unless default[0] == ":" || default.end_with?(".")
17 text = ""
18 text << "#{resource_name} 'name' do
"
19 text << friendly_types_list(p["is"])
20 text << " # default value: 'name' unless specified" if p["name_property"]
21 text << "
"
22 text << "end"
23 properties.max_by { |x| x["name"].size }["name"].size
24 prop_list = [
25 ]
26 props = arr.map { |x| "`#{x["name"]}`" }
27 props[-1] = "and #{props[-1]}"
28 text = props.size == 2 ? props.join(" ") : props.join(", ")
29 text << ( props.size > 1 ? " are the properties" : " is the property" )
30 fixed_arr = Array(arr).map do |x|
31 fixed_arr.compact.join(", ")
32 return nil if property["default"].nil? || property["default"] == ""
33 actions = actions.to_h { |k, v| [k.to_sym, { "markdown" => k == default_action.first ? "#{v} (default)" : v } ] }
34 values = {}
35 values["allowed_values"] = property["equal_to"].join(", ") unless property["equal_to"].empty?
36 properties = {}
37 return [{ "markdown" => nil }] if text.nil?
38 description_pattern = /(Note:|Warning:)?((?:(?!Note:|Warning:).)*)/m
39 description = []
40 element = { "markdown" => body }
41 when "Note:"
42 description << { "note" => element }
43 description << { "warning" => element }
44 raise "Unexpected thing happened! preface: '#{preface}', body: '#{body}'"
45 properties = data["properties"].reject { |v| %w{name sensitive}.include?(v["name"]) || v["deprecated"] }.sort_by! { |v| v["name"] }
46 r = {}
47 r["resource"] = name
48 r["actions_list"] = action_list(data["actions"], data["default_action"] )
49 r["examples"] = data["examples"]
50 puts "=========="
51 File.open("docs_site/#{resource}.yaml", "w") { |f| f.write(YAML.dump(resource_data)) }
52 task update: %w{
53 }
54 rm_f "#{dir}/Gemfile.lock"
55 )
56 let(:value1) { { name: "one", type: :string, data: "1" } }
57 let(:value1_upcase_name) { { name: "ONE", type: :string, data: "1" } }
58 let(:key) { "Software\\OpscodeNumbers" }
59 let(:key_parent) { "Software" }
60 let(:key_to_delete) { "OpscodeNumbers" }
61 let(:sub_key) { "OpscodePrimes" }
62 let(:missing_key_path) { "HKCU\\Software" }
63 let(:reg_mock) { double("reg") }
64 expect(reg_mock).to receive(:write).with("one", 1, "1")
65 expect(reg_mock).to receive(:each).with(no_args).and_yield("one", 1, "1")
66 expect(reg_mock).to receive(:each).with(no_args).and_yield("one", 1, "2")
67 described_class.symlink("a", "b")
68 let(:input) { "1.2.3" }
69 it { is_expected.to eq "1.2.3" }
70 it { is_expected.to eql "1.2.3" }
71 it { is_expected.to be == "1.2.3" }
72 it { is_expected.to be < "abc" }
73 it { is_expected.to be > "0" }
74 it { is_expected.to eq described_class.new("1.2.3") }
75 it { is_expected.to be == described_class.new("1.2.3") }
76 context "with !=" do
77 subject { described_object != "1.2.4" }
78 it { is_expected.to be true }
79 context "with +" do
80 it { is_expected.to eq "1.2.3asdf" }
81 context "with *" do
82 it { is_expected.to eq "1.2.31.2.31.2.3" }
83 subject { described_class.new("1.02.3") }
84 it { is_expected.to be > "1.2.2" }
85 it { is_expected.to be > "1.2.3a" }
86 it { is_expected.to be < "1.2.4" }
87 subject { described_object =~ /^1/ }
88 it { is_expected.to eq 0 }
89 subject { described_object =~ Gem::Requirement.create("~> 1.0") }
90 subject { described_object =~ "~> 1.0" }
91 subject { /^2/ =~ described_object }
92 it { is_expected.to be nil }
93 subject { "~> 1.0" =~ described_object }
94 bad_version = [">= 1.2.z", "> 1.2.3 < 5.0", "> 1.2.3, < 5.0"]
95 bad_op = ["> >", ">$ 1.2.3", "! 3.4"]
96 it "should raise #{v_error} when given #{s}" do
97 bad_op.each do |s|
98 it "should raise #{o_error} when given #{s}" do
99 expect(vc.to_s).to eq("= 1.2.3")
100 it "should default to >= 0.0.0" do
101 expect(vc.to_s).to eq(">= 0.0.0")
102 expect(Chef::VersionConstraint.new(nil).to_s).to eq(">= 0.0.0")
103 expect(Chef::VersionConstraint.new(">=1.2.3")).to eql(Chef::VersionConstraint.new(">= 1.2.3"))
104 expect(Chef::VersionConstraint.new("<=1.2.3")).to eql(Chef::VersionConstraint.new("<= 1.2.3"))
105 @vc = Chef::VersionConstraint.new "> 1.2.3"
106 expect(@vc).to include "1.4"
107 cv = Chef::CookbookVersion.new("alice", "/tmp/blah.txt")
108 cv.version = "1.4"
109 vc = Chef::VersionConstraint.new "< 1.2.3"
110 expect(vc).not_to include "1.3.0"
111 expect(vc).not_to include "1.2.3"
112 expect(vc).to include "1.2.2"
113 vc = Chef::VersionConstraint.new "> 1.2.3"
114 expect(vc).to include "1.3.0"
115 expect(vc).not_to include "1.2.2"
116 vc = Chef::VersionConstraint.new "<= 1.2.3"
117 expect(vc).to include "1.2.3"
118 vc = Chef::VersionConstraint.new ">= 1.2.3"
119 it "equal to" do
120 vc = Chef::VersionConstraint.new "= 1.2.3"
121 expect(vc).not_to include "0.3.0"
122 it "pessimistic ~> x.y.z" do
123 vc = Chef::VersionConstraint.new "~> 1.2.3"
124 expect(vc).to include "1.2.4"
125 expect(vc).not_to include "2.0.0"
126 it "pessimistic ~> x.y" do
127 vc = Chef::VersionConstraint.new "~> 1.2"
128 expect(vc).to include "1.3.3"
129 vc = Chef::VersionConstraint.new "~> 1.2.0"
130 expect(vc.to_s).to eq("~> 1.2.0")
131 expect(vc.to_s).to eq("~> 1.2")
132 expect(vc.inspect).to eq("(~> 1.2.0)")
133 expect(vc.inspect).to eq("(~> 1.2)")
134 it "pessimistic ~> x" do
135 @v0 = Chef::Version.new "0.0.0"
136 @v123 = Chef::Version.new "1.2.3"
137 expect(@v0.to_s).to eq("0.0.0")
138 expect(@v123.to_s).to eq("1.2.3")
139 a = Chef::Version.new(@v123.to_s)
140 expect(a).to eq(@v123)
141 expect(Chef::Version.new("1.2").to_s).to eq("1.2.0")
142 a = Chef::Version.new "01.002.0003"
143 good_versions = %w{1.2 1.2.3 1000.80.50000 0.300.25 001.02.00003}
144 it "should accept '#{v}'" do
145 bad_versions = ["1.2.3.4", "1.2.a4", "1", "a", "1.2 3", "1.2 a",
146 it "should raise #{the_error} when given '#{v}'" do
147 describe "<=>" do
148 expect(Chef::Version.new("1.2")).to eq(Chef::Version.new("1.2.0"))
149 expect(Chef::Version.new("1.04")).to eq(Chef::Version.new("1.4"))
150 expect(Chef::Version.new("2.0")).to be < Chef::Version.new("11.0")
151 examples = [
152 ["1.0", "2.0"],
153 ["1.2.3", "1.2.4"],
154 ["1.2.3", "1.3.0"],
155 ["1.2.3", "1.3"],
156 ["1.2.3", "2.1.1"],
157 ["1.2.3", "2.1"],
158 ["1.2", "1.2.4"],
159 ["1.2", "1.3.0"],
160 ["1.2", "1.3"],
161 ["1.2", "2.1.1"],
162 ["1.2", "2.1"],
163 expect(sm).to be < lg
164 expect(lg).to be > sm
165 a = %w{0.0.0 0.0.1 0.1.0 0.1.1 1.0.0 1.1.0 1.1.1}.map do |s|
166 got = a.sort.map(&:to_s)
167 expect(got).to eq(%w{0.0.0 0.0.1 0.1.0 0.1.1 1.0.0 1.1.0 1.1.1})
168 a = %w{9.8.7 1.0.0 1.2.3 4.4.6 4.5.6 0.8.6 4.5.5 5.9.8 3.5.7}.map do |s|
169 expect(got).to eq(%w{0.8.6 1.0.0 1.2.3 3.5.7 4.4.6 4.5.5 4.5.6 5.9.8 9.8.7})
170 [
171 [ "0.0.0", :>, "0.0.0", false ],
172 [ "0.0.0", :>=, "0.0.0", true ],
173 [ "0.0.0", :==, "0.0.0", true ],
174 [ "0.0.0", :<=, "0.0.0", true ],
175 [ "0.0.0", :<, "0.0.0", false ],
176 [ "0.0.0", :>, "0.0.1", false ],
177 [ "0.0.0", :>=, "0.0.1", false ],
178 [ "0.0.0", :==, "0.0.1", false ],
179 [ "0.0.0", :<=, "0.0.1", true ],
180 [ "0.0.0", :<, "0.0.1", true ],
181 [ "0.0.1", :>, "0.0.1", false ],
182 [ "0.0.1", :>=, "0.0.1", true ],
183 [ "0.0.1", :==, "0.0.1", true ],
184 [ "0.0.1", :<=, "0.0.1", true ],
185 [ "0.0.1", :<, "0.0.1", false ],
186 [ "0.1.0", :>, "0.1.0", false ],
187 [ "0.1.0", :>=, "0.1.0", true ],
188 [ "0.1.0", :==, "0.1.0", true ],
189 [ "0.1.0", :<=, "0.1.0", true ],
190 [ "0.1.0", :<, "0.1.0", false ],
191 [ "0.1.1", :>, "0.1.1", false ],
192 [ "0.1.1", :>=, "0.1.1", true ],
193 [ "0.1.1", :==, "0.1.1", true ],
194 [ "0.1.1", :<=, "0.1.1", true ],
195 [ "0.1.1", :<, "0.1.1", false ],
196 [ "1.0.0", :>, "1.0.0", false ],
197 [ "1.0.0", :>=, "1.0.0", true ],
198 [ "1.0.0", :==, "1.0.0", true ],
199 [ "1.0.0", :<=, "1.0.0", true ],
200 [ "1.0.0", :<, "1.0.0", false ],
201 [ "1.0.0", :>, "0.0.1", true ],
202 [ "1.0.0", :>=, "1.9.2", false ],
203 [ "1.0.0", :==, "9.7.2", false ],
204 [ "1.0.0", :<=, "1.9.1", true ],
205 [ "1.0.0", :<, "1.9.0", true ],
206 [ "1.2.2", :>, "1.2.1", true ],
207 [ "1.2.2", :>=, "1.2.1", true ],
208 [ "1.2.2", :==, "1.2.1", false ],
209 [ "1.2.2", :<=, "1.2.1", false ],
210 [ "1.2.2", :<, "1.2.1", false ],
211 ].each do |spec|
212 it "(#{spec.first(3).join(" ")}) should be #{spec[3]}" do
213 got = Chef::Version.new(spec[0]).send(spec[1],
214 expect(got).to eq(spec[3])
215 v = Chef::Version::Platform.new("1.1")
216 expect(Chef::Version::Platform.new("1").to_s).to eq("1.0.0")
217 bad_versions = ["1.2.3.4", "1.2.a4", "a", "1.2 3", "1.2 a",
218 expect(Chef::Version::Platform.new("1")).to eq(Chef::Version::Platform.new("1.0.0"))
219 let(:session_user) { nil }
220 let(:session_domain) { nil }
221 let(:password) { nil }
222 let(:password) { "ponies" }
223 let(:session_domain) { "fairyland" }
224 let(:session_user) { "chalena" }
225 5.times { queue << job }
226 allow(ENV).to receive(:[]).with("PATHEXT").and_return(nil)
227 expected_paths = ENV["PATH"].split(File::PATH_SEPARATOR) + %w{/usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /sbin /bin}
228 let(:path) { "/path/to/awesome directory" }
229 let(:username) { "foo" }
230 let(:hosts_content) { "" }
231 expect(editor.lines).to be == IO.readlines(__FILE__)
232 array = []
233 let(:input_lines) { %w{one two two three} }
234 subject(:execute) { editor.append_line_after("two", "new") }
235 expect(editor.append_line_after(/^ee/, "new")).to be == 0
236 expect(editor.append_line_after(/ee$/, "new")).to be == 1
237 it "adds a line to the end" do
238 subject(:execute) { editor.append_line_if_missing("one", "new") }
239 expect(editor.append_line_if_missing(/ee$/, "new")).to be == 0
240 expect(editor.append_line_if_missing(/^ee/, "new")).to be == 1
241 expect(editor.lines).to be == %w{one three}
242 expect(editor.remove_lines(/^ee/)).to be == 0
243 expect(editor.remove_lines(/ee$/)).to be == 1
244 subject(:execute) { editor.replace("missing", "new") }
245 subject(:execute) { editor.replace("two", "new") }
246 expect(editor.replace(/^ee/, "new")).to be == 0
247 expect(editor.replace(/ee$/, "new")).to be == 1
248 subject(:execute) { editor.replace_lines("missing", "new") }
249 subject(:execute) { editor.replace_lines("two", "new") }
250 expect(editor.replace_lines(/^ee/, "new")).to be == 0
251 expect(editor.replace_lines(/ee$/, "new")).to be == 1
252 expect(editor.lines).to be == %w{one two two new}
253 {
254 expect(resource_store.find("foo")).to eql([])
255 let(:lcm_errors) { [] }
256 let(:lcm_command_ps4) { ps4_base_command + " -whatif; if (! $?) { exit 1 }" }
257 let(:lcm_result) { "" }
258 let(:lcm_errors) { [no_whatif_lcm_output] }
259 let(:lcm_result) { "some output" }
260 let(:lcm_errors) { ["Abort, Retry, Fail?"] }
261 expect(resources[0].name).to eq("[name]")
262 expect(resources[0].change_log).to match_array(["[name]", "[message]", "[name]"])
263 expect(resources[0].name).to eql("[name]")
264 expect(resources[1].name).to eql("[name2]")
265 %w{! @ # $ % ^ & * & * ( ) - = + \{ \} . ? < > \\ /}.each do |sym|
266 %w{` " # '}.each do |c|
267 it "escapes #{c}" do
268 expect(conf_man.send(:escape_parameter_value, "stuff #{c}")).to eql("stuff `#{c}")
269 conf_man.send(:command_switches_string, { "foo" => "bar" })
270 conf_man.send(:command_switches_string, { foo!: "bar" })
271 expect(conf_man.send(:command_switches_string, { foo: false })).to eql("")
272 expect(conf_man.send(:command_switches_string, { foo: "bar" })).to eql("-foo 'bar'")
273 expect(conf_man.send(:command_switches_string, { foo: "" })).to eql("-foo ''")
274 expect(conf_man.send(:command_switches_string, { foo: 1 })).to eql("-foo 1")
275 expect(conf_man.send(:command_switches_string, { foo: 1.0 })).to eql("-foo 1.0")
276 expect(conf_man.send(:command_switches_string, { foo: true })).to eql("-foo")
277 merged = conf_man.send(:get_merged_configuration_flags!, { "flag" => "a" }, "hello")
278 expect(merged[:flag]).to eql("a")
279 conf_man.send(:get_merged_configuration_flags!, { "outputpath" => "a" }, "hello")
280 conf_man.send(:get_merged_configuration_flags!, { "OutputPath" => "a" }, "hello")
281 merged = conf_man.send(:get_merged_configuration_flags!, { "FLAG" => "a" }, "hello")
282 merged = conf_man.send(:get_merged_configuration_flags!, { flag: "a" }, "hello")
283 merged = conf_man.send(:get_merged_configuration_flags!, { FLAG: "a" }, "hello")
284 let(:file_like_object) { double("file like object") }
285 allow(File).to receive(:join) do |a, b|
286 [a, b].join("++")
287 allow(Dir).to receive(:entries).with("tmp++hello") { ["f1", "f2", "hello.mof", "f3"] }
288 allow(Dir).to receive(:entries).with("tmp++hello") { %w{f1 f2 f3} }
289 dsc = conf_man.send(:configuration_code, "archive{}", "hello", {})
290 dsc.split(";").each do |command|
291 if /\s*configuration\s+'hello'\s*\{\s*node\s+'localhost'\s*\{\s*archive\s*\{\s*\}\s*\}\s*\}\s*/.match?(command.downcase)
292 dsc = conf_man.send(:configuration_code, "archive{}", "hello", { "FooModule" => [] })
293 dsc = conf_man.send(:configuration_code, "archive{}", "hello", { "FooModule" => ["FooResource", "*", "BarResource"] })
294 dsc = conf_man.send(:configuration_code, "archive{}", "hello", { "FooModule" => %w{FooResource BarResource} })
295 dsc = conf_man.send(:configuration_code, "archive{}", "hello", { "FooModule" => %w{FooResource BarResource}, "BazModule" => [] })
296 let!(:old_tempfile) { Tempfile.new("chef-util diff-spec") }
297 let!(:new_tempfile) { Tempfile.new("chef-util diff-spec") }
298 let!(:old_tempfile) { Tempfile.new("chef-util-diff-spec") }
299 let!(:new_tempfile) { Tempfile.new("chef-util-diff-spec") }
300 expect(differ.for_output).to eql(["(no diff)"])
301 old_tempfile.write("#{0x01.chr}#{0xFF.chr}")
302 new_tempfile.write("#{0x01.chr}#{0xFF.chr}")
303 expect(differ.for_output.join("\
")).to match(/\A--- .*\
\+\+\+ .*\
@@/m)
304 expect(differ.for_reporting).to match(/\A--- .*\
\+\+\+ .*\
@@/m)
305 let!(:old_file) { old_tempfile.path }
306 let!(:new_file) { new_tempfile.path }
307 let(:utf_8) { "testing utf-8 unicode...


on a new line: \xE2\x80\x93
" } # unicode em-dash
308 let(:latin_1) { "It is more metal.
if you have an #{0xFD.chr}mlaut.
" } # NB: changed to y-with-diaresis, but i'm American so I don't know the difference
309 let(:shift_jis) { "I have no idea what this character is:
#{0x83.chr}#{0x80.chr}.
" } # seriously, no clue, but \x80 is nice and illegal in other encodings
310 expect(@backup).to receive(:path).and_return("/a/b/c.txt")
311 expect(@backup.send(:backup_filename)).to match(%r|^/a/b/c.txt.chef-\d{14}.\d{6}$|)
312 expect(@backup).to receive(:path).and_return('c:\a\b\c.txt')
313 expect(@backup.send(:backup_filename)).to match(/^\\a\\b\\c.txt.chef-\d{14}.\d{6}$/)
314 expect(@backup).to receive(:path).and_return("c:/a/b/c.txt")
315 expect(@backup.send(:backup_path)).to match(%r|^/a/b/c.txt.chef-\d{14}.\d{6}$|)
316 expect(@backup.send(:backup_path)).to match(%r|^/backupdir[\\/]+a/b/c.txt.chef-\d{14}.\d{6}$|)
317 expect(@backup).to receive(:path).and_return("c:\\a\\b\\c.txt")
318 expect(@backup.send(:backup_path)).to match(%r|^c:\\backupdir[\\/]+a\\b\\c.txt.chef-\d{14}.\d{6}$|)
319 let(:method) { :create_key }
320 let(:method) { :public_key }
321 let(:method) { :private_key }
322 let(:method) { :display_name }
323 let(:method) { :first_name }
324 let(:method) { :middle_name }
325 let(:method) { :last_name }
326 let(:method) { :email }
327 let(:method) { :password }
328 @json = @user.to_json
329 expect(@json).to match(/^\{.+\}$/)
330 expect(@json).to include(%q{"username":"black"})
331 expect(@user.to_json).to include(%{"first_name":"char"})
332 expect(@user.to_json).to include(%{"middle_name":"man"})
333 @user.last_name("der")
334 expect(@user.to_json).to include(%{"last_name":"der"})
335 expect(@user.to_json).to include(%{"public_key":"crowes"})
336 let(:jsonable) { @user }
337 user = {
338 expect(@user.last_name).to eq("der")
339 let(:response_406) { OpenStruct.new(code: "406") }
340 email: "some_email",
341 let(:response_400) { OpenStruct.new(code: "400") }
342 let(:response_body_400) { '{"error":["Since Server API v1, all keys must be updated via the keys endpoint. "]}' }
343 let(:response_body_400) { '{"error":["Some other error. "]}' }
344 let(:http_verb) { :put }
345 let(:rest_v0) { @user.chef_root_rest_v0 }
346 let(:rest_v1) { @user.chef_root_rest_v1 }
347 expect(@user.chef_root_rest_v1).to receive(:post).with("users", payload.merge({ middle_name: "some_middle_name" })).and_return({})
348 let(:http_verb) { :post }
349 expect(@user.chef_root_rest_v0).to receive(:post).with("users", payload.merge({ middle_name: "some_middle_name" })).and_return({})
350 expect(@user.chef_root_rest_v0).to receive(:put).with("users/#{@user.username}", payload.merge({ "private_key" => true })).and_return({})
351 @osc_response = { "admin" => "http://www.example.com/users/admin" }
352 @ohc_response = [ { "user" => { "username" => "admin" } } ]
353 @osc_inflated_response = { "admin" => @user }
354 expect(@http_client).to receive(:get).with("users/foobar").and_return({ "username" => "foobar", "admin" => true, "public_key" => "pubkey" })
355 @user = Chef::User.new
356 it "should be a Chef::User" do
357 expect(@user.name("ops_master")).to eq("ops_master")
358 @user.name("black")
359 expect(@json).to include(%q{"name":"black"})
360 expect(@json).to include(%{"public_key":"crowes"})
361 expect(@json).to include(%q{"admin":false})
362 user = { "name" => "mr_spinks",
363 expect(@http_client).to receive(:post).with("users", { name: "foobar", admin: false, password: "password" }).and_return({})
364 expect(@http_client).to receive(:get).with("users/foobar").and_return({ "name" => "foobar", "admin" => true, "public_key" => "pubkey" })
365 user = Chef::User.load("foobar")
366 expect(@http_client).to receive(:put).with("users/foobar", { name: "foobar", admin: false }).and_return({})
367 let(:good_credentials) { { "switch.cisco.com" => { "user" => "cisco", "password" => "cisco", "enable_password" => "secret" } } }
368 allow(transport).to receive(:parse_credentials_file).and_return({ "foo" => { "example" => { "org" => {} } } })
369 expect(Chef::Log).to receive(:warn).with(/as a Hash/)
370 @conf = new_conf
371 Shell.irb_conf = {}
372 it "has a prompt like ``chef > '' in the default context" do
373 expect(conf.return_format).to eq(" => %s
")
374 it "has a prompt like ``chef:recipe > '' in recipe context" do
375 conf.main = Chef::Recipe.new(nil, nil, Chef::RunContext.new(Chef::Node.new, {}, events))
376 Shell::Extensions::Help.new("baz", "foo2the Bar")])
377 expect(@chef_object.help_banner).to match(/^\|\ Command\s+\|\ Description\s*$/)
378 expect(@chef_object.help_banner).to match(/^\|\ rspec_method\s+\|\ rspecin\'\s*$/)
379 let(:json_attribs) { { "a" => "b" } }
380 let(:chef_rest) { double("Chef::ServerAPI") }
381 let(:node) { Chef::Node.build("foo") }
382 sync_cookbooks: {})
383 let(:node) { Chef::Node.new }
384 let(:recipe) { Chef::Recipe.new(nil, nil, run_context) }
385 session.node_attributes = { "besnard_lakes" => "are_the_dark_horse" }
386 @job_manager.jobs = [[:thread, irb_session]]
387 @job_manager.jobs = []
388 node = double("node", attribute: { foo: :bar })
389 expect(@root_context).to receive(:pp).with({ foo: :bar })
390 it "says if echo is on or off" do
391 entries = %w{. .. someFile}
392 @root_context.ls "/tmp"
393 @run_context = Chef::RunContext.new(Chef::Node.new, {}, @events)
394 expect(@recipe_object).to receive(:pp).with(["file[foo]"])
395 @model = OpenStruct.new(name: "Chef::Node")
396 @node_1 = Chef::Node.new
397 @node_1.name("sammich")
398 @node_2 = Chef::Node.new
399 @node_2.name("yummy")
400 @server_response = { node_1: @node_1, node_2: @node_2 }
401 @searcher = double("Chef::Search::Query #{__FILE__}:#{__LINE__}")
402 expect(@wrapper.find(:all)).to include(@node_1, @node_2)
403 expect(@searcher).to receive(:search).with(:node, "name:app*").and_yield(@node_1).and_yield(@node_2)
404 expect(@wrapper.find("name:app*")).to include(@node_1, @node_2)
405 expect(@wrapper.find(:name => "app*", "name" => "app*")).to include(@node_1, @node_2)
406 Chef::ServerAPIVersions.instance.set_versions({ "min_version" => 0, "max_version" => 2 })
407 let(:url) { "http://chef.example.com:4000" }
408 let(:key_path) { "/tmp/foo" }
409 Chef::Config[:node_name] = "silent-bob"
410 post_body = { bar: "baz" }
411 stub_request(:post, "http://chef.example.com:4000/foo").with(body: post_body.to_json, headers: headers).to_return(status: 200, body: "", headers: {})
412 put_body = { bar: "baz" }
413 stub_request(:put, "http://chef.example.com:4000/foo").with(body: put_body.to_json, headers: headers).to_return(status: 200, body: "", headers: {})
414 stub_request(:get, "http://chef.example.com:4000/foo").with(headers: headers).to_return(status: 200, body: "", headers: {})
415 stub_request(:get, "http://chef.example.com:4000/foo").with(headers: { "X-Ops-Server-Api-Version" => "2" }).to_return(status: [406, "Not Acceptable"], body: body_406 )
416 stub_request(:get, "http://chef.example.com:4000/foo").with(headers: { "X-Ops-Server-Api-Version" => "0" }).to_return(status: 200, body: "", headers: {})
417 let(:fetcher_impl) { SecretFetcherImpl.new({}, nil) }
418 let(:fetcher) {
419 Chef::SecretFetcher.for_service(:example, { "key1" => "value1" }, nil)
420 fetcher.fetch("key1", "v1")
421 require_relative "../../spec_helper"
422 let(:node) { {} }
423 let(:run_context) { double("run_context", node: node) }
424 token: "t.1234abcd",
425 data: {
426 },
427 lease_id: "",
428 }))
429 let(:config) { { vault: "my-vault" } }
430 let(:secrets_response_body) { '{ "value" : "my secret value" }' }
431 rm = Net::HTTPSuccess.new("1.0", "400", "OK")
432 let(:http_mock) { instance_double("Net::HTTP", :use_ssl= => nil) }
433 let(:vault_name) { "my-vault" }
434 let(:secret_name) { "my-secret" }
435 let(:vault_secret_uri) { URI.parse("https://#{vault_name}.vault.azure.net/secrets/#{secret_name}/?api-version=7.2") }
436 let(:token_response_mock) { Net::HTTPBadRequest.new("1.0", "400", "Bad Request") }
437 let(:config) { { vault: "my-vault", object_id: object_id } }
438 let(:config) { { vault: "my-vault", client_id: client_id } }
439 let(:config) { { vault: "my-vault", mi_res_id: mi_res_id } }
440 expect(token_uri.query).to match(/mi_res_id=#{mi_res_id}/)
441 let(:config) { {} }
442 let(:secrets_response_body) { '{ "error" : { "code" : 404, "message" : "secret not found" } }' }
443 let(:aws_global_config) { {} }
444 let(:fetcher_config) { {} }
445 let(:fetcher_config) { { region: "region-from-caller" } }
446 let(:node) { { "ec2" => { "region" => "region-from-ohai-data" } } }
447 let(:rest) { double("Chef::ServerAPI") }
448 let(:query) { Chef::Search::Query.new }
449 let(:default_rows) { 1000 }
450 let(:args) { { filter_key => filter_hash } }
451 { "url" => "#{server_url}/my-name-is-node",
452 { "url" => "#{server_url}/my-name-is-jonas",
453 { "url" => "#{server_url}/my-name-is-flipper",
454 { "url" => "#{server_url}/my-name-is-butters",
455 ],
456 { "env" => "elysium", "ruby_plat" => "nudibranch" },
457 { "env" => "hades", "ruby_plat" => "i386-mingw32" },
458 { "env" => "elysium", "ruby_plat" => "centos" },
459 { "env" => "moon", "ruby_plat" => "solaris2" },
460 { "name" => "my-name-is-node",
461 { "name" => "my-name-is-jonas",
462 { "name" => "my-name-is-flipper",
463 { "name" => "my-name-is-butters",
464 r["start"] = 4
465 r["total"] = 8
466 expect { query.search(:node, "platform:rhel", total: 10) }
467 @call_me = double("blocky")
468 response["rows"].each { |r| expect(@call_me).to receive(:do).with(Chef::Node.from_hash(r)) }
469 query.search(:node) { |r| @call_me.do(r) }
470 query.search(:node, "*:*", start: 0, rows: 4) { |r| @call_me.do(r) }
471 query.search(:node, "platform:rhel") do |r|
472 query.search(:node, "platform:rhel", rows: 4) do |r|
473 query.search("node", "free.messi", fuzz: true)
474 let(:filter_key) { :filter_result }
475 start = query.search(:node, "platform:rhel", args)[1]
476 total = query.search(:node, "platform:rhel", args)[2]
477 @real_file = "/tmp/foo/bar/real/file"
478 f.owner("root")
479 f.group("root")
480 f.mode("0755")
481 @stat = double("File::Stat for #{@new_resource.path}", uid: 0, gid: 0, mode: 00100644)
482 @root_passwd = double("Struct::Passwd for uid 0", name: "root")
483 @group_entry = double("Struct::Group for wheel", name: "wheel")
484 @all_actions_called ||= []
485 @action = :fail
486 let(:node) do
487 let(:runner) { Chef::Runner.new(run_context) }
488 rescue => e
489 expected_message = <<~E
490 @node = Chef::Node.new
491 @run_context = Chef::RunContext.new(@node, {}, @events)
492 @end_time = @start_time + 23
493 default_cache_path = windows? ? 'C:\chef' : "/var/chef"
494 let(:lockfile) { "/tmp/chef-client-running.pid" }
495 @timeout = 0.1
496 describe "<<" do
497 @run_list << "recipe[needy]"
498 @run_list << "role[woot]"
499 @run_list << "needy"
500 @run_list << "recipe[needy@0.2.0]"
501 @run_list << "recipe[needy@0.1.0]"
502 describe "==" do
503 @run_list << "foo"
504 r << "foo"
505 expect(@run_list).to eq(r)
506 @run_list << "baz"
507 expect(@run_list).to eq(%w{foo baz})
508 @run_list << "chromeo"
509 describe "[]" do
510 @run_list << "recipe[loulou]"
511 expect(@run_list[0]).to eq("recipe[loulou]")
512 describe "[]=" do
513 @run_list[0] = "recipe[loulou]"
514 @run_list[0] = "loulou"
515 @run_list << "bar"
516 seen = []
517 @run_list.each { |r| seen << r }
518 to_add = [ "recipe[foo]", "recipe[bar]", "recipe[baz]" ]
519 to_add.each { |i| @run_list << i }
520 @run_list.each_index { |i| expect(@run_list[i]).to eq(to_add[i]) }
521 @run_list.include?("foo")
522 list.each { |i| expect(@run_list).to be_include(i) }
523 @role = Chef::Role.new
524 @role.run_list "one", "two"
525 @role.env_run_list["production"] = Chef::RunList.new( "one", "two", "five")
526 @rest = double("Chef::ServerAPI", { get: @role.to_hash, url: "/" })
527 @run_list << "role[stubby]"
528 @run_list << "kitty"
529 @run_list.expand("_default", "disk")
530 expansion = @run_list.expand("_default", "server")
531 @role.env_run_list["production"] << "role[prod-base]"
532 dog = Chef::Role.new
533 @role.run_list << "role[dog]"
534 expansion = @run_list.expand("_default", "disk")
535 dog.run_list "role[dog]", "three"
536 @run_list << "recipe[nagios::client]" << "role[production]" << "recipe[apache2]"
537 expect(@run_list.to_a).to eq(["recipe[nagios::client]", "role[production]", "recipe[apache2]"])
538 let(:jsonable) { @run_list }
539 expect(l).to eq([])
540 let(:versioned_recipes) { [] }
541 let(:recipes) { [] }
542 recipes.each { |r| list << r }
543 versioned_recipes.each { |r| list.add_recipe r[:name], r[:version] }
544 let(:recipes) { %w{ apt god apache2 } }
545 list.add_recipe "rails", "1.0.0"
546 expect(list.with_versions).to include({ name: "rails", version: "1.0.0" })
547 list.add_recipe "apt", "1.2.3"
548 expect(list.with_versions).to include({ name: "apt", version: "1.2.3" })
549 { name: "apt", version: "1.0.0" },
550 { name: "god", version: nil },
551 { name: "apache2", version: "0.0.1" },
552 { name: "apt", version: "~> 1.2.0" },
553 let(:recipes) { %w{ apache2 } }
554 expect(fq_names).to eq( %w{ apache2::default } )
555 let(:recipes) { %w{ mysql::server } }
556 expect(fq_names).to eq( %w{ mysql::server } )
557 expect(fq_names).to eq([ "apt::default@~> 1.2.0" ])
558 expect(list).to eq( [ "apt" ] )
559 { name: "apt::cacher", version: "~> 1.2.0" },
560 expect(fq_names).to eq([ "apt::cacher@~> 1.2.0" ])
561 expect(list).to eq( [ "apt::cacher" ] )
562 let(:recipes) { %w{ foo bar::default } }
563 item = Chef::RunList::RunListItem.new(type: "fuuu", name: "uuuu")
564 expect(item.to_s).to eq("fuuu[uuuu]")
565 expect(item.to_s).to eq("recipe[rage]")
566 expect(item.to_s).to eq("recipe[rage@0.1.0]")
567 expect(item.version).to eq("0.1.0")
568 expect(item.to_s).to eq("role[fist]")
569 @run_list << "recipe[lobster::mastercookbook@0.1.0]" << "role[rage]" << "recipe[fist@0.1]"
570 @rage_role = Chef::Role.new.tap do |r|
571 r.name("rage")
572 r.env_run_lists("_default" => [], "prod" => ["recipe[prod-only]"])
573 @first_role.default_attributes({ "foo" => "bar" })
574 @first_role.override_attributes({ "baz" => "qux" })
575 @second_role.default_attributes({ "foo" => "boo" })
576 @second_role.override_attributes({ "baz" => "bux" })
577 @json = '{"id":"_default","run_list":[{"type":"recipe","name":"lobster::mastercookbook","version":"0.1.0",'
578 expect(@expansion.default_attrs).to eq({ "foo" => "bar" })
579 expect(@expansion.override_attrs).to eq({ "baz" => "qux" })
580 node.run_list << "test" << "test::one" << "test::two"
581 it "has a node" do
582 let(:declared_type) { :alpaca }
583 let(:recipe) { "dependency1::default" }
584 f = Chef::Resource::File.new("hi", child)
585 src = Chef::Resource::File.new("hi", child)
586 dest = Chef::Resource::File.new("argh", child)
587 it "has a name" do
588 expect(@role.name("ops_master")).to eq("ops_master")
589 @role.run_list(%w{ nginx recipe[ree] role[base]})
590 expect(@role.run_list).to eq(%w{ nginx recipe[ree] role[base]})
591 @role.name("base")
592 @role.env_run_list["prod"] = Chef::RunList.new(*(@role.run_list.to_a << "recipe[prod-base]"))
593 expect(@role.run_list_for("_default")).to eq(@role.run_list)
594 expect(@role.run_list_for("prod")).to eq(Chef::RunList.new("recipe[nagios::client]", "recipe[tims-acl::bork]", "recipe[prod-base]"))
595 expect(@role.run_list_for("qa")).to eq(@role.run_list)
596 expect(@role.recipes(%w{one two})).to eq(%w{one two})
597 @role.recipes(%w{one two})
598 expect(@role.recipes).to eq(%w{one two})
599 @role.run_list([ "one", "role[two]"])
600 expect(@role.recipes).to eq([ "recipe[one]", "role[two]" ])
601 expect(@role.default_attributes({ one: "two" })).to eq({ one: "two" })
602 @role.default_attributes({ one: "two" })
603 expect(@role.default_attributes).to eq({ one: "two" })
604 expect(@role.override_attributes({ one: "two" })).to eq({ one: "two" })
605 @role.override_attributes({ one: "two" })
606 expect(@role.override_attributes).to eq({ one: "two" })
607 @role.run_list("one", "two", "role[a]")
608 @example.run_list("alpha", "bravo", "role[alpha]")
609 expect(Chef::JSONCompat.to_json(@role)).to match(/^\{.+\}$/)
610 expect(@serialized_role).to match(/"run_list":\["recipe\[one\]","recipe\[two\]","role\[a\]"\]/)
611 expect(@serialized_role["env_run_lists"]["production"]).to eq(["role[monitoring]", "role[auditing]", "role[apache]"])
612 expect(@serialized_role["env_run_lists"]["dev"]).to eq(["role[nginx]"])
613 let(:jsonable) { @role }
614 @role.default_attributes({ "el_groupo" => "nuevo" })
615 %w{
616 }.each do |t|
617 expect(@deserial.send(t.to_sym)).to eq(@role.send(t.to_sym))
618 expect(Dir).to receive(:glob).and_return(["#{Chef::Config[:role_path]}/memes", "#{Chef::Config[:role_path]}/memes/lolcat.json"])
619 expect(IO).to receive(:read).with(file_path).and_return('{"name": "ceiling_cat", "json_class": "Chef::Role" }')
620 expect(Dir).to receive(:glob).and_return(["#{Chef::Config[:role_path]}/memes", "#{Chef::Config[:role_path]}/memes/lolcat.rb"])
621 expect(Dir).to receive(:glob).and_return(["#{Chef::Config[:role_path]}/memes", "#{Chef::Config[:role_path]}/memes/lolcat.json", "#{Chef::Config[:role_path]}/memes/lolcat.rb"])
622 expect(IO).to receive(:read).with(js_path).and_return('{"name": "ceiling_cat", "json_class": "Chef::Role" }')
623 expect(Dir).to receive(:glob).and_return(["#{Chef::Config[:role_path]}/meme.rb"])
624 expect(Dir).to receive(:glob).and_return(["#{Chef::Config[:role_path]}/memes/lolcat.rb", "#{Chef::Config[:role_path]}/lolcat.rb"])
625 expect(Dir).to receive(:glob).and_return(["#{Chef::Config[:role_path]}/memes/lolcat.rb", "#{Chef::Config[:role_path]}/super_lolcat.rb"])
626 Chef::Config[:role_path] = ["/path1", "/path1/path2"]
627 let(:root) { windows? ? "C:/path1" : "/path1" }
628 expect(Dir).to receive(:glob).with(File.join(root, "**", "**")).exactly(1).times.and_return(["#{root}/lolcat.json"])
629 expect(IO).to receive(:read).with("#{root}/lolcat.json").and_return('{"name": "ceiling_cat", "json_class": "Chef::Role" }')
630 expect(Dir).to receive(:glob).with(File.join(root, "**", "**")).exactly(1).times.and_return([])
631 expect(Dir).to receive(:glob).with(File.join("#{root}/path2", "**", "**")).exactly(1).times.and_return(["#{root}/path2/lolcat.json"])
632 expect(IO).to receive(:read).with("#{root}/path2/lolcat.json").and_return('{"name": "ceiling_cat", "json_class": "Chef::Role" }')
633 expect(Dir).to receive(:glob).with(File.join(root, "**", "**")).exactly(1).times.and_return(["#{root}/lolcat.rb"])
634 expect(Dir).to receive(:glob).with(File.join("#{root}/path2", "**", "**")).exactly(1).times.and_return(["#{root}/path2/lolcat.rb"])
635 expect(Dir).to receive(:glob).with(File.join("#{root}/path2", "**", "**")).exactly(1).times.and_return([])
636 let(:resource_sans_id) { Chef::Resource.new("my-name") }
637 expect(resource.name %w{a b}).to eql("a, b")
638 expect(resource.delayed_notifications.detect { |e| e.resource.name == "coffee, tea" && e.action == :reload }).not_to be_nil
639 expect(zr.delayed_notifications.detect { |e| e.resource.name == "funk" && e.action == :reload }).not_to be_nil
640 r = c.new("hi")
641 r.declared_type = :d
642 let(:resource_class) { Class.new(Chef::Resource) { property :a, default: 1 } }
643 expect(hash.keys - expected_keys).to eq([])
644 expect(expected_keys - hash.keys).to eq([])
645 expect(hash[:name]).to eql("funk")
646 resource.only_if { snitch_var1 = 1 }
647 resource.only_if { snitch_var2 = 2 }
648 resource.only_if("true", cwd: "/tmp")
649 expect(resource.only_if.first.command_opts).to eq({ cwd: "/tmp" })
650 resource.not_if { puts "foo" }
651 resource.not_if("pwd" , cwd: "/tmp")
652 expect(resource.not_if.first.command_opts).to eq({ cwd: "/tmp" })
653 resource1.not_if { snitch_var1 = 2 }
654 resource1.not_if { snitch_var2 = 2 }
655 let(:klz) { Class.new(Chef::Resource) }
656 :dinobot, Chef::Resource::Klz, { platform: ["autobots"] }
657 it "adds mappings for all platforms", ruby: "< 2.7" do
658 :tape_deck, Chef::Resource::Klz, {}
659 it "adds mappings for all platforms", ruby: ">= 2.7" do
660 let(:klz1) { Class.new(Chef::Resource) }
661 let(:klz2) { Class.new(Chef::Resource) }
662 let(:klz3) { Class.new(Chef::Resource) }
663 let(:action) { :create }
664 let(:resource) { resource_class.new("test", nil) }
665 it { is_expected.to eq [:nothing] }
666 it { is_expected.to eq [:one] }
667 before { resource.action("two") }
668 it { is_expected.to eq [:two] }
669 before { resource.action(%i{two one}) }
670 it { is_expected.to eq %i{two one} }
671 before { resource.action = :one }
672 before { resource.action = %i{two one} }
673 let(:default_action) {}
674 let(:default_action) { :one }
675 let(:default_action) { "one" }
676 let(:default_action) { %i{two one} }
677 let(:klass) { Class.new(Chef::Resource) }
678 it "can be set to true" do
679 Chef::Recipe.new("hjk", "test", run_context)
680 let!(:original_umask) { ::File.umask }
681 it "is a no-op on Windows" do
682 actual_value = block_value.to_s(8).rjust(4, "0")
683 it "#resolve" do
684 it "#list" do
685 let(:rest_client) { double("Chef::ServerAPI (mock)") }
686 let(:new_resource) { Chef::Resource::File.new("/tmp/a-file.txt") }
687 let(:current_resource) { Chef::Resource::File.new("/tmp/a-file.txt") }
688 let(:run_context) { Chef::RunContext.new(node, {}, events) }
689 let(:start_time) { Time.new }
690 let(:end_time) { Time.new + 20 }
691 let(:run_list) { Chef::RunList.new }
692 let(:run_id) { run_status.run_id }
693 let(:cookbook_name) { "monkey" }
694 let(:cookbook_version) { double("Cookbook::Version", version: "1.2.3") }
695 run_list << "recipe[lobster]" << "role[rage]" << "recipe[fist]"
696 allow(rest_client).to receive(:raw_request).and_return({ "result" => "ok" })
697 allow(rest_client).to receive(:post).and_return({ "uri" => "https://example.com/reports/nodes/spitfire/runs/#{@run_id}" })
698 allow(@bad_resource).to receive(:name).and_return({ foo: :bar })
699 allow(@bad_resource).to receive(:path).and_return({ foo: :bar })
700 expect(@report["total_res_count"]).to eq("1")
701 expect(@report["data"]).to eq({})
702 resource.values([ { name: "rick", type: :binary, data: 255.chr * 1 } ])
703 @backtrace = ["foo.rb:1 in `foo!'", "bar.rb:2 in `bar!", "'baz.rb:3 in `baz!'"]
704 expect(@report["data"]["exception"]).to have_key("class")
705 expect(@report["data"]["exception"]).to have_key("message")
706 expect(@report["data"]["exception"]["message"]).to eq("Object not found")
707 @bad_resource = Chef::Resource::File.new("/tmp/a-file.txt")
708 it "sets before to {} instead of nil" do
709 expect(@first_update_report["before"]).to eq({})
710 it "sets after to {} instead of 'Running'" do
711 expect(@first_update_report["after"]).to eq({})
712 @response = Net::HTTPNotFound.new("a response body", "404", "Not Found")
713 .with("reports/nodes/spitfire/runs", { action: :start, run_id: @run_id,
714 start_time: start_time.to_s },
715 .with("reports/nodes/spitfire/runs", { action: :start, run_id: @run_id, start_time: start_time.to_s },
716 response = { "uri" => "https://example.com/reports/nodes/spitfire/runs/@run_id" }
717 response = { "result" => "ok" }
718 expect(headers).to eq({ "Content-Encoding" => "gzip",
719 })
720 dummy_no_desc: nil })
721 expect(subject[:properties].map { |n| n[:name] }).to include(:name, :first, :sensitive)
722 defn.define(:smoke, cigar: "cuban", cigarette: "marlboro") {}
723 expect(defn.params[:mind]).to eql("to fly")
724 defn.define :monkey, [] do
725 expect(defn.to_s).to eql("woot")
726 expect { rc[0] = resource }.not_to raise_error
727 rc[0] = resource
728 expect(rc[1]).to eql(zmr)
729 expect(rc[0]).to eql(zmr)
730 results = []
731 rc.each do |r|
732 expect(results[i]).to eql("dog")
733 expect(results[i]).to eql("cat")
734 rc.each_index do |i|
735 results << rc[i].name
736 rc << zmr
737 rc[0] = zmr
738 it "should find a resource by symbol and array of names (:zen_master => [a,b])" do
739 check_by_names(results, "monkey", "dog")
740 it "should find resources of multiple kinds (:zen_master => a, :file => b)" do
741 res = Chef::Resource.new("foo", nil)
742 let(:jsonable) { rc }
743 let(:parent_run_context) { Chef::RunContext.new(node, {}, nil) }
744 a.content("foo")
745 b.content("bar")
746 expect(results.detect { |res| res.name == res_name }).not_to eql(nil)
747 %w{dog cat monkey}.each do |n|
748 rc << Chef::Resource::File.new("something")
749 @simple_collection = [1, 2, 3, 4]
750 sum = 0
751 sum += int
752 collected_by_index = []
753 collected = {}
754 expect(collected).to eq({ 0 => 1, 1 => 2, 2 => 3, 3 => 4 })
755 @collection = []
756 @collection << lambda { @snitch_var = 23 }
757 @collection << lambda { @snitch_var = 42 }
758 @collection.insert(2, lambda { @snitch_var = 815 })
759 let(:zen_master_name) { "Neo" }
760 let(:zen_master2_name) { "Morpheus" }
761 let(:zen_follower_name) { "Squid" }
762 let(:zen_array) { Chef::Resource::ZenMaster.new( [ zen_master_name, zen_master2_name ]) }
763 it "should find resources of multiple kinds (:zen_master => a, :zen_follower => b)" do
764 check_by_names(collection.find(zzz: %w{name1 name2}, yyy: ["name3"]),
765 let(:zen_master_name) { "" }
766 expect(results.detect { |r| r.name == name }).to_not eq(nil)
767 it "should be able to insert with []=" do
768 current += 1
769 node.automatic[:os] = "linux"
770 os: "linux",
771 node.default["foo"] = %w{one two three}
772 expect { @resource.version[0] = "four" }.not_to raise_error
773 expect { @resource.arch[0] = "four" }.not_to raise_error
774 flush_hash = { before: false, after: false }
775 flush_hash = { before: true, after: true }
776 let(:resource) { Chef::Resource::YumPackage.new("foo") }
777 it "supports :add, :set, :clear, :remove actions" do
778 expect { resource.send(:validate_start_time, "2:30", :once) }.to raise_error(ArgumentError, "`start_time` property must be in the HH:mm format (e.g. 6:20pm -> 18:20).")
779 expect(resource.send(:sec_to_dur, 0)).to eql("PT0S")
780 expect(resource.send(:sec_to_dur, 1)).to eql("PT1S")
781 expect(resource.path).to eql("C:\\chef")
782 resource.path("C:\\chef")
783 { 2 => :automatic, 3 => :manual, 4 => :disabled }.each_pair do |k, v|
784 it "it coerces startup_type property #{type} to :#{type}" do
785 resource.send("#{prop}=", "some value")
786 resource.send("#{prop}=", 1)
787 resource.send("#{prop}=", true)
788 os: "windows",
789 [ "600", 600 ].each do |val|
790 [ "42", 42, [47, 48, 49] ].each do |val|
791 expect { resource.version ["1.2.3", "1.2.3.4"] }.not_to raise_error
792 let(:resource_source) { "https://foo.bar/solitare.msi" }
793 resource.remote_address(["10.17.3.101", "172.7.7.53"])
794 resource.remoteip(["8.8.8.8"])
795 it "sets a group" do
796 resource.remote_address(["8.8.8.8"])
797 resource.remote_address(["8.8.4.4"])
798 it "sets #{prop} to nil" do
799 it "sets #{prop} to false" do
800 %w{uid gid}.each do |attrib|
801 let(:resource) { Chef::Resource::User.new("root") }
802 expect(state[:uid]).to eq(123)
803 expect(state[:gid]).to eq(456)
804 expect(state[:home]).to eq("/usr/local/root/")
805 double("shell_out", stdout: "UTC
", exitstatus: 0, error?: false)
806 double("shell_out", exitstatus: 0, error?: false, stdout: <<-OUTPUT)
807 double("shell_out!", stdout: "Time Zone: UTC", exitstatus: 0, error?: false)
808 expect(state[:owner]).to eq("root")
809 expect(state[:group]).to eq("wheel")
810 expect(state[:mode]).to eq("0644")
811 expect(state[:checksum]).to eq("1" * 64)
812 resource.helper(:example_1) { "example_1" }
813 resource.helper(:example_2) { "example_2" }
814 modules.each { |m| o.extend(m) }
815 expect(o.shout("shout")).to eq("SHOUT")
816 resource.value [1, 2, 3]
817 it "coerces filename property values . & ~ to __" do
818 resource.group ["%foo"]
819 expect(resource.groups).to eql(["%foo"])
820 expect(resource.groups).to eql(["%group1", "%group2", "%group3", "%group4"])
821 resource.groups ["foo", "%bar"]
822 expect(resource.groups).to eql(["%foo", "%bar"])
823 os: "solaris2",
824 os: "linux"
825 let(:resource) { Chef::Resource::Service.new("chef") }
826 it "supports :disable, :enable, :mask, :reload, :restart, :start, :stop, :unmask actions" do
827 resource.pattern(/.*/)
828 param_hash = { something: nil }
829 resource.options ["-r", "-s"]
830 expect(resource.options).to eql(["-r", "-s"])
831 expect(resource.options).to eql(["-r"])
832 support_hash = { status: nil, restart: nil, reload: nil }
833 support_hash = { status: true, restart: true }
834 let(:semanage_list) { double("shellout", stdout: "") }
835 expect(resource.roles).to eq(%w{a b c})
836 expect(provider.semanage_user_args).to eq(" -L s0 -r s0 -R 'staff_r sysadm_r'")
837 expect(provider.semanage_user_args).to eq(" -L s0 -R 'staff_r sysadm_r'")
838 expect(provider.semanage_user_args).to eq(" -r s0 -R 'staff_r sysadm_r'")
839 file_type = "te"
840 it "checks 'a', 'f', 'd', 'c', 'b', 's', 'l', 'p' as valid file_type property values" do
841 let(:selinux_state) { double("shellout!", stdout: "permissive") }
842 let(:resource_name) { :script }
843 it "supports :checkout, :diff, :export, :log, :sync actions" do
844 let(:ten_seconds) { 10 }
845 expect(state[:revision]).to eq("1.2.3")
846 let(:test_environment) { { "CHEF_ENV" => "/tmp" } }
847 name: :git,
848 let(:resource) { Chef::Resource::Git.new("fakey_fakerton") }
849 end.call).to eql("foo")
850 %w{linux aix}.each do |os|
851 os: os
852 let(:resource) { Chef::Resource::RpmPackage.new("foo") }
853 let(:resource) { Chef::Resource::Route.new("10.0.0.10") }
854 let(:run_context) { Chef::RunContext.new(node, {}, event_dispatch) }
855 let(:cmd) { double("cmd") }
856 let(:serials) { { "pool1" => "serial1", "pool2" => "serial2" } }
857 let(:with_katello) { double("shell_out", stdout: <<~RPM) }
858 let(:without_katello) { double("shell_out", stdout: "") }
859 let(:satellite_host) { "sat-host" }
860 let(:train) {
861 resource.address = "192.0.2.1"
862 response = "{ data: nil }"
863 address: "192.0.2.1",
864 name: "set_address",
865 expect(provider.rest_identity_values).to eq({ "ip" => "192.0.2.1" })
866 let(:addresses_exists) { JSON.generate([{ "address": "192.0.2.1" }]) }
867 let(:addresses_other) { JSON.generate([{ "address": "172.16.32.85" }]) }
868 let(:address_exists) { JSON.generate({ "address": "192.0.2.1", "prefix": 24, "gateway": "192.0.2.1" }) }
869 let(:prefix_wrong) { JSON.generate({ "address": "192.0.2.1", "prefix": 25, "gateway": "192.0.2.1" }) }
870 .to_return(status: 200, body: address_exists, headers: { "Content-Type" => "application/json" })
871 .to_return(status: 200, body: prefix_wrong, headers: { "Content-Type" => "application/json" })
872 .with(
873 body: "{\"address\":\"192.0.2.1\",\"prefix\":25}",
874 headers: {
875 .to_return(status: 200, body: "[]", headers: { "Content-Type" => "application/json" })
876 body: "{\"address\":\"192.0.2.1\",\"prefix\":24,\"ip\":\"192.0.2.1\"}"
877 .to_return(status: 404, body: "", headers: {})
878 .to_return(status: 200, body: "", headers: {})
879 expect(provider.rest_identity_values).to eq({ "address" => "192.0.2.1" })
880 @long_cat = Chef::Resource::Cat.new("long_cat")
881 @cheez_cat = Chef::Resource::Cat.new("cheez_cat")
882 expect(resource.source).to eql([ "http://opscode.com/" ])
883 expect(resource.source).to eql([ "\\\\fakey\\fakerton\\fake.txt" ])
884 resource.source("file:///C:/foo bar")
885 expect(resource.source).to eql(["file:///C:/foo bar"])
886 resource.source([ "http://opscode.com/", "http://puppetlabs.com/" ])
887 expect(resource.source).to eql([ "http://opscode.com/", "http://puppetlabs.com/" ])
888 resource.source Chef::DelayedEvaluator.new { [ "http://opscode.com/", "http://puppetlabs.com/" ] }
889 resource.source(["http://opscode.com/", Chef::DelayedEvaluator.new { "http://opscode.com/" }])
890 expect(state[:rights]).to eq([{ permissions: :read, principals: "Everyone" }])
891 expect(state[:mode]).to eq("0664")
892 expect(state[:checksum]).to eq("1" * 26)
893 expect(state[:files_mode]).to eq("0664")
894 resource.values( { name: "poosh", type: :string, data: "carmen" } )
895 expect(resource.values).to eql([ { name: "poosh", type: :string, data: "carmen" } ])
896 resource.values [ { name: "poosh", type: :string, data: "carmen" } ]
897 resource.values( { name: "poosh", type: :binary, data: 255.chr * 1 })
898 expect { resource.values [ { type: :string, data: "carmen" } ] }.to raise_error(ArgumentError)
899 expect { resource.values [ { name: "poosh", type: :string, data: "carmen", screwdriver: "sonic" } ] }.to raise_error(ArgumentError)
900 expect { resource.values([ { name: 123, type: :string, data: "carmen" } ]) }.to raise_error(ArgumentError)
901 expect { resource.values([ { name: "123", type: :string, data: "carmen" } ]) }.to_not raise_error
902 expect { resource.values([ { name: "123", data: "carmen" } ]) }.to_not raise_error
903 expect { resource.values([ { name: "123", type: "string", data: "carmen" } ]) }.to raise_error(ArgumentError)
904 expect { resource.values([ { "name" => "123", "type" => :string, "data" => "carmen" } ]) }.to_not raise_error
905 it "allows #{arch} as a symbol" do
906 key_values = [ { name: "poosh", type: :binary, data: 255.chr * 1 } ]
907 resource.values([ { name: "poosh", type: :binary, data: 255.chr * 1 } ])
908 let(:resource) { Chef::Resource::Reboot.new("reboot me!") }
909 node.default["kernel"] = {}
910 node.default["kernel"][:machine] = :x86_64.to_s
911 expect(resource.version).to eql(["1.2.3"])
912 resource.version(["1.2.3", "4.5.6"])
913 expect(resource.version).to eql(["1.2.3", "4.5.6"])
914 it "provider_name accepts 'Programs', 'msi', 'NuGet', 'msu', 'PowerShellGet', 'psl', 'chocolatey', 'winget'" do
915 expect(resource.plistbuddy_command(:print, "Foo Bar Baz", "path/to/file.plist")).to eq "/usr/libexec/PlistBuddy -c 'Print :\"Foo Bar Baz\"' \"path/to/file.plist\""
916 expect(resource.plistbuddy_command(:add, "Foo Bar Baz", "path/to/file.plist", true)).to eq "/usr/libexec/PlistBuddy -c 'Add :\"Foo Bar Baz\" bool' \"path/to/file.plist\""
917 let(:resource) { Chef::Resource::Package.new("emacs") }
918 resource.options "-a -b 'arg with spaces' -b \"and quotes\""
919 expect(resource.options).to eql(["-a", "-b", "arg with spaces", "-b", "and quotes"])
920 expect(state[:version]).to eq("10.9.8")
921 expect(state[:options]).to eq(["-al"])
922 resource.options [ "-a", "-l" ]
923 expect(resource.options).to eq(["-a", "-l" ])
924 test_profile = { "profile" => false }
925 { "_computerlevel" => [{ "ProfileDisplayName" => "Finder Settings",
926 <?xml version="1.0" encoding="UTF-8"?>
927 <plist version="1.0">
928 <dict>
929 </dict>
930 </array>
931 </plist>
932 {}
933 { "_computerlevel" => [{ "ProfileDisplayName" => "ScreenSaver Settings",
934 it "has a default key_type of 'ec'" do
935 it "has a default key_type of 'rsa'" do
936 it "has a default mode of '0640'" do
937 it "has a default mode of '0600'" do
938 Chef::Config[:node_name] = @fqdn
939 mock_ohai = {
940 fqdn: @fqdn,
941 data2: {
942 expect(resource.mount_point).to eql("127.0.0.1:/")
943 it "sets fsck_device to '-' by default" do
944 support_hash = { remount: false }
945 support_array = [ :remount ]
946 support_hash = { remount: true }
947 resource.devices ["/dev/sda", "/dev/sdb"]
948 expect(resource.devices).to eql(["/dev/sda", "/dev/sdb"])
949 expect(state[:level]).to eq(1)
950 os: "mac_os_x"
951 let(:test_value) { "fakest_key_value" }
952 let(:test_key) { "fakest_key" }
953 let(:resource) {
954 let(:log_str) { "this is my string to log" }
955 let(:resource) { Chef::Resource::Log.new(log_str) }
956 it "has a name of log" do
957 let(:resource) { Chef::Resource::Log.new("ery day I'm loggin-in") }
958 it "is non empty" do
959 expect { resource.lc_env({ "LC_TIME" => "" }) }.to raise_error(validation)
960 expect { resource.lc_env({ "LC_TIME" => " XX" }) }.to raise_error(validation)
961 expect { resource.lc_env({ "LC_TIMES" => " XX" }) }.to raise_error(validation)
962 expect { resource.lc_env({ "Lc_Time" => " XX" }) }.to raise_error(validation)
963 expect(provider.new_content.split("
").map { |x| x.split("=") }.collect(&:first)).to eq(%w{LANG LC_MESSAGES LC_TIME})
964 expect(provider.new_content[-1]).to eq("
")
965 expect(state[:to]).to eq("/to/dir/file.tar")
966 expect(state[:group]).to eq("0664")
967 let(:resource) { Chef::Resource::Ksh.new("fakey_fakerton") }
968 Chef::RunContext.new(node, {}, events).tap do |rc|
969 { "ssh-01": {
970 } }
971 [ssh-01]
972 { "ssh-01" => {
973 resource.name "acme_comp.*::ssh.*"
974 resource.name "evil_comp.*::etcd.*"
975 it "loads a Hash" do
976 { "ssh_custom_path": "/whatever2" }
977 { ssh_custom_path: "/whatever2" }
978 expect(state[:inet_addr]).to eq("434.2343.23")
979 expect(state[:mask]).to eq("255.255.545")
980 @node.automatic_attrs[:os] = "linux"
981 it "supports :delete, :get, :head, :options, :patch, :post, :put actions" do
982 resource.headers({ "head" => "tail" })
983 let(:brew_update_cmd) { %w{homebrew update} }
984 let(:user) { "Captain Picard" }
985 let(:user) { 1001 }
986 it "(#{method}) allows an Array" do
987 it "(#{method}) does not allow a Hash" do
988 let(:resource) { Chef::Resource::GemPackage.new("foo") }
989 expect(state[:rights]).to eq([ { permissions: :read, principals: "Everyone" },
990 { permissions: :full_control, principals: "DOMAIN\User" } ])
991 let(:t_block) { Proc.new { true } }
992 let(:f_block) { Proc.new { false } }
993 let(:path_block) { Proc.new { |path| path } }
994 let(:temp_path) { "/tmp/foobar" }
995 let(:parent_resource) { Chef::Resource.new("llama") }
996 v = Chef::Resource::File::Verification.new(parent_resource, nil, {}) {}
997 expect { v.verify("/foo/bar") }.to_not raise_error
998 expect { v.verify("/foo/bar", { future: true }) }.to_not raise_error
999 expect(v.to_s).to eq("<Proc>")
1000 it "raises an error when \%{file} is used" do
1001 expect(v.to_s).to eq("some command --here")
1002 @valid_yaml = "valid-#{Time.now.to_i}.yaml"
1003 f = File.new(@valid_yaml, "w")
1004 @invalid_yaml = "invalid-#{Time.now.to_i}.yaml"
1005 f = File.new(@invalid_yaml, "w")
1006 @empty_yaml = "empty-#{Time.now.to_i}.yaml"
1007 File.new(@empty_yaml, "w").close
1008 let(:command) { "#{systemd_analyze_path} verify %{path}" }
1009 let(:opts) { { future: true } }
1010 let(:systemd_dir) { "/etc/systemd/system" }
1011 let(:temp_path) { "/tmp" }
1012 let(:unit_name) { "sysstat-collect.timer" }
1013 let(:unit_path) { "#{systemd_dir}/#{unit_name}" }
1014 let(:unit_temp_path) { "#{systemd_dir}/.chef-#{unit_name}" }
1015 let(:unit_test_path) { "#{temp_path}/#{unit_name}" }
1016 .with("chef-systemd-unit") { |&b| b.call temp_path }
1017 .and_return("foo")
1018 @valid_json = "valid-#{Time.now.to_i}.json"
1019 f = File.new(@valid_json, "w")
1020 f.write('{
1021 }')
1022 @invalid_json = "invalid-#{Time.now.to_i}.json"
1023 f = File.new(@invalid_json, "w")
1024 f.write("{
1025 }")
1026 @empty_json = "empty-#{Time.now.to_i}.json"
1027 File.new(@empty_json, "w").close
1028 let(:password) { "password" }
1029 let(:domain) { nil }
1030 let(:username) { "user@domain" }
1031 let(:username) { "domain\\user" }
1032 let(:username) { 499 }
1033 let(:username) { nil }
1034 let(:username) { "starchild" }
1035 let(:elevated) { false }
1036 let(:domain) { "mothership" }
1037 let(:password) { "we.funk!" }
1038 let(:username) { "user@domain@domain" }
1039 let(:domain) { "some_domain" }
1040 let(:elevated) { true }
1041 let(:username) { "user" }
1042 let(:resource_name) { "DSCTest" }
1043 let(:configuration_data) { '@{AllNodes = @( @{ NodeName = "localhost"; PSDscAllowPlainTextPassword = $true })}' }
1044 expect(module_imports).to eq(["*"])
1045 let(:dsc_test_resource_name) { "DSCTest" }
1046 let(:dsc_test_resource_module_version) { "2.7.2" }
1047 let(:dsc_test_timeout) { 101 }
1048 it "has a default action of `:run`" do
1049 let(:resource) { Chef::Resource::DnfPackage.new("foo") }
1050 resource.path("/tmp/foo/bar/")
1051 let(:resource) { Chef::Resource::Csh.new("fakey_fakerton") }
1052 let(:resource) { Chef::Resource::Cron.new("cronify") }
1053 expect(resource.send(x, "*")).to eql("*")
1054 expect(resource.send(x, "1-2,5")).to eql("1-2,5")
1055 expect(resource.send(x)).to eql("*")
1056 expect(state[:minute]).to eq("1")
1057 expect(state[:hour]).to eq("2")
1058 expect(state[:day]).to eq("3")
1059 expect(state[:month]).to eq("4")
1060 expect(state[:weekday]).to eq("5")
1061 expect(state[:user]).to eq("root")
1062 node.automatic_attrs[:os] = "aix"
1063 let(:resource) { Chef::Resource::CronAccess.new("bob") }
1064 it "has a default action of [:deny]" do
1065 @status.send(:"success?=", false)
1066 expect(Chef::Log).to receive(:warn).with("only_if block for [] returned \"some command\", did you mean to run a command? If so use 'only_if \"some command\"' in your code.")
1067 expect(Chef::Log).to receive(:warn).with("not_if block for [] returned \"some command\", did you mean to run a command? If so use 'not_if \"some command\"' in your code.")
1068 <?xml version="1.0" encoding="utf-8"?>
1069 </config>
1070 </sources>
1071 <apiKeys />
1072 [ 0, [0, 48, 49] ].each do |val|
1073 let(:resource) { Chef::Resource::ChefSleep.new("30") }
1074 name: :chef_gem,
1075 let(:resource) { Chef::Resource::ChefGem.new("foo") }
1076 Chef::RunContext.new(node, {}, nil)
1077 let(:root_path) { windows? ? "C:\\chef/client.rb" : "/etc/chef/client.rb" }
1078 resource.daemon_options ["--foo 1", "--bar 2"]
1079 expect(provider.chef_client_cmd).to eql("/opt/chef/bin/chef-client --foo 1 --bar 2 -c #{root_path}")
1080 resource.environment({ "foo" => "bar" })
1081 expect(provider.service_content["Service"]["Environment"]).to eq(["\"foo=bar\""])
1082 allow(ENV).to receive(:[]).with("COMSPEC").and_return("C:\\Windows\\System32\\cmd.exe")
1083 it "set splay to 0" do
1084 expect(provider.splay_sleep_time(300)).to satisfy { |v| v >= 0 && v <= 300 }
1085 expect(provider.client_cmd).to eql("C:/foo/bar/chef-client -L /etc/chef/log/client.log -c /etc/chef/client.rb") | eql("C:/foo/bar/chef-client -L C:\\chef/log/client.log -c C:\\chef/client.rb")
1086 expect(provider.format_handler([{ "class" => "Foo", "arguments" => ["'one'", "two", "three"] }])).to eql(["Foo.new('one',two,three)"])
1087 expect(resource.name).to match(/breakpoint_spec\.rb\:\d{2}\:in \`new\'$/)
1088 let(:resource_name) { :batch }
1089 let(:interpreter_file_name) { "cmd.exe" }
1090 let(:path) { File.expand_path("/tmp/foo.zip") }
1091 let(:entry_time) { Time.new(2021, 5, 25, 2, 2, 0, "-05:00") }
1092 let(:older_time) { entry_time - 100 }
1093 let(:newer_time) { entry_time + 100 }
1094 expect(FileUtils).to receive(:chown).with("root", "root", "#{destination}/folder-1/")
1095 let(:resource) { Chef::Resource::AptPackage.new("foo") }
1096 cookbook_repo = File.expand_path(File.join(__dir__, "..", "data", "cookbooks"))
1097 %w{monkey dog cat}.each do |name|
1098 expect(node.tags).to eql([])
1099 recipe.tag "foo", "bar"
1100 expect(node.tags).to eql([ "foo" ])
1101 expect(recipe.tag).to eql([ "foo" ])
1102 recipe.untag "bar", "foo"
1103 ---
1104 - one
1105 - type: "execute"
1106 expect(recipe).to receive(:from_hash).with({ "resources" => [{ "command" => "whoami", "type" => "execute" }] })
1107 resources = { "resources" => [
1108 { "name" => "running some commands", "type" => "execute", "command" => "whoami" },
1109 { "name" => "preparing the bits", "type" => "service", "action" => "start", "service_name" => "bit_launcher" },
1110 ] }
1111 let(:app) { Chef::Application.new }
1112 Chef::Config[:why_run] = true
1113 Chef::Config[:why_run] = false
1114 pub:-:2048:1:ABF5BD827BD9BF62:1313747554:1718374819::-:::scSC::::::23::0:
1115 gpg (GnuPG) 2.2.20
1116 let(:logger) { double("Mixlib::Log::Child").as_null_object }
1117 let(:gpg_20) do
1118 let(:gpg_22) do
1119 let(:gpg_ver) do
1120 result = {
1121 start_day: 2,
1122 end_month: 0,
1123 end_day: 0,
1124 end_year: 0,
1125 type: { once: nil },
1126 expect(result).to eq({ once: nil })
1127 expect(result).to eq({ days_interval: 2 })
1128 expect(result).to eq({ weeks_interval: 2, days_of_week: 4 })
1129 expect(result).to eq({ months: 4095, days: 1 })
1130 expect(result).to eq({ months: 4095, days_of_week: 4, weeks_of_month: 7 })
1131 it "returns the binary value 127 if day is set as 'Mon, tue, wed, thu, fri, sat, sun'" do
1132 new_resource.day "Mon, tue, wed, thu, fri, sat, sun"
1133 it "returns the binary value 4095 if day is set as 'jan, Feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec'" do
1134 new_resource.months "jan, Feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec"
1135 expect(provider.send(:get_day, "01/02/2018")).to eq("TUE")
1136 @new_resource.user("<System>")
1137 @new_resource.delim ";"
1138 @new_resource.value("C:/baz/bin")
1139 @new_resource.value("C:/foo/bin")
1140 @new_resource.value("C:/foo/bin;C:/bar/bin")
1141 @new_resource.value("C:/bar")
1142 @new_resource.delim(";")
1143 @current_resource.value("C:/bar;C:/foo;C:/baz")
1144 @current_resource.value("C:/biz;C:/foo/bin;C:/baz")
1145 @new_resource.value("C:/biz;C:/baz")
1146 @new_resource.value("C:/biz;C:/baz;C:/bin")
1147 @current_resource.value("C:/baz;C:/foo/bin;C:/biz")
1148 new_value = "C:/bar/bin"
1149 @new_resource.value("C:/foo;C:/bar;C:/baz")
1150 @current_resource.value("C:/bar;C:/baz;C:/foo/bar")
1151 expect(@new_resource.value).to eq("C:/foo;C:/bar;C:/baz;C:/foo/bar")
1152 @current_resource.value("C:/foo/bar;C:/baz;C:/bar")
1153 let(:system_root) { "%SystemRoot%" }
1154 let(:system_root_value) { "D:\\Windows" }
1155 stub_const("ENV", { "PATH" => "" })
1156 EtcPwnamIsh = Struct.new(:name, :passwd, :uid, :gid, :gecos, :dir, :shell, :change, :uclass, :expire)
1157 EtcGrnamIsh = Struct.new(:name, :passwd, :gid, :mem)
1158 @pw_user.gid = 1000
1159 @pw_user.uid = 1000
1160 @pw_user.shell = "/usr/bin/zsh"
1161 @pw_user.passwd = "*"
1162 user_attrib_map = {
1163 uid: :uid,
1164 gid: :gid,
1165 home: :dir,
1166 user = @pw_user.dup
1167 user.name = "root"
1168 user.passwd = "x"
1169 sp_warn: 7, sp_inact: -1, sp_expire: -1, sp_flag: -1)
1170 %w{uid gid}.each do |property|
1171 @group = EtcGrnamIsh.new("wheel", "*", 999, [])
1172 @net_user = double("Chef::Util::Windows::NetUser")
1173 it "should not pass -r" do
1174 expect(provider).to receive(:shell_out_compacted!).with( "useradd", "-m", "adam")
1175 let(:user_lock) { "adam:FOO:::::::" }
1176 user1:LK:::::::
1177 user2:NP:::::::
1178 let(:user_lock) { "other_user:FOO:::::::" }
1179 ].each do |shadow|
1180 context "for user 'adam' with entry '#{shadow}'" do
1181 let(:user_lock) { shadow }
1182 shell_return = shellcmdresult.new("", "", 0)
1183 field_list = {
1184 match_array = [ "adam" ]
1185 field_list.sort_by { |a| a[0] }.each do |property, option|
1186 match_array << "hola"
1187 match_array << "-m"
1188 expect(@provider).to receive(:shell_out_compacted!).with( "pw", "useradd", "adam", "-m").and_return(true)
1189 expect(@provider).to receive(:shell_out_compacted!).with( "pw", "usermod", "adam", "-m").and_return(true)
1190 let(:new_resource) { Chef::Resource::User::MacUser.new("jane") }
1191 expect( provider.useradd_options ).to eql(["-M"])
1192 expect( provider.useradd_options ).to eql(["-m"])
1193 expect( provider.universal_options ).to eql(["-e", "1982-04-16"])
1194 expect( provider.universal_options ).to eql(["-f", 90])
1195 cr.home "/home/adam"
1196 expect(provider).to receive(:shell_out_compacted!).with("useradd", "-g", "system", "adam")
1197 allow(provider).to receive(:shell_out_compacted!).with("usermod", "-d", "/home/adam", "adam")
1198 allow(provider).to receive(:shell_out_compacted!).with("usermod", "-d", "/mnt/home/adam", "adam")
1199 expect(FileUtils).to receive(:mv).with("/home/adam", "/mnt/home/adam")
1200 it "should not pass -m" do
1201 expect(provider).to receive(:shell_out_compacted!).with("usermod", "-d", "/home/adam", "adam")
1202 variables: {},
1203 helper_modules: [])
1204 name: "helpers.erb",
1205 let(:unit_name) { "sysstat-collect\\x2d.timer" }
1206 let(:user_name) { "joe" }
1207 user: "joe",
1208 .with(systemctl_path, "--user", "daemon-reload", **user_cmd_opts, default_env: false)
1209 .with(systemctl_path, "--user", "preset", unit_name, **user_cmd_opts)
1210 .with(systemctl_path, "--user", "revert", unit_name, **user_cmd_opts)
1211 .with(systemctl_path, "--system", "preset", unit_name)
1212 .with(systemctl_path, "--system", "revert", unit_name)
1213 .with(systemctl_path, "--user", "reenable", unit_name, **user_cmd_opts)
1214 .with(systemctl_path, "--user", "enable", unit_name, **user_cmd_opts)
1215 .with(systemctl_path, "--user", "disable", unit_name, **user_cmd_opts)
1216 .with(systemctl_path, "--system", "reenable", unit_name)
1217 .with(systemctl_path, "--system", "enable", unit_name)
1218 .with(systemctl_path, "--system", "disable", unit_name)
1219 .with(systemctl_path, "--user", "mask", unit_name, **user_cmd_opts)
1220 .with(systemctl_path, "--user", "unmask", unit_name, **user_cmd_opts)
1221 .with(systemctl_path, "--system", "mask", unit_name)
1222 .with(systemctl_path, "--system", "unmask", unit_name)
1223 .with(systemctl_path, "--user", "start", unit_name, **user_cmd_opts, default_env: false)
1224 .with(systemctl_path, "--user", "stop", unit_name, **user_cmd_opts, default_env: false)
1225 .with(systemctl_path, "--system", "start", unit_name, default_env: false)
1226 .with(systemctl_path, "--system", "stop", unit_name, default_env: false)
1227 .with(systemctl_path, "--user", "restart", unit_name, **user_cmd_opts, default_env: false)
1228 .with(systemctl_path, "--user", "reload", unit_name, **user_cmd_opts, default_env: false)
1229 .with(systemctl_path, "--user", "try-restart", unit_name, **user_cmd_opts, default_env: false)
1230 .with(systemctl_path, "--user", "reload-or-restart", unit_name, **user_cmd_opts, default_env: false)
1231 systemctl_show = [systemctl_path, instance, "show", "-p", "UnitFileState", "-p", "ActiveState", unit_name]
1232 nil_and_inactive_h = {
1233 systemctl_show = [systemctl_path, "--system", "show", "-p", "UnitFileState", "-p", "ActiveState", "foo@.service"]
1234 expect(@provider.run_options).to eq({ user: "deployninja", environment: { "HOME" => "/home/deployninja" } })
1235 @stdout = double("stdout")
1236 @stderr = double("stderr")
1237 expect(::File).to receive(:exist?).with("/my/deploy/dir/.svn").and_return(false)
1238 example_svn_info = "Path: .
" +
1239 expected_command = ["svn info", { cwd: "/my/deploy/dir", returns: [0, 1] }]
1240 expect(::File).to receive(:exist?).with("/my/deploy/dir/.svn").and_return(true)
1241 allow(::File).to receive(:exist?).with("/my/deploy/dir/.svn").and_return(false)
1242 allow(::File).to receive(:exist?).with("/my/deploy/dir").and_return(true)
1243 allow(::Dir).to receive(:entries).with("/my/deploy/dir").and_return([".", "..", "foo", "bar"])
1244 expect(@provider).to receive(:shell_out!).with(expected_cmd, { user: "whois", group: "thisis", environment: { "HOME" => "/home/whois" } })
1245 let(:http_proxy_uri) { "http://somehost:1" }
1246 let(:http_no_proxy) { "svn.example.org" }
1247 let(:repository_url) { "http://svn.example.org/trunk/" }
1248 let(:repository_url) { "https://svn.example.org/trunk/" }
1249 ENV["http_proxy"] = nil
1250 ENV["no_proxy"] = http_no_proxy
1251 let(:chef_service_name) { "chef-client" }
1252 load_order_group: "",
1253 tag_id: 0,
1254 wait_hint: 0,
1255 pid: 0,
1256 it "does not set #{prop}" do
1257 provider.new_resource.send("#{attr}=", "new value")
1258 provider.new_resource.send("#{attr}=", 2)
1259 let(:start_command) { "sc start #{chef_service_name}" }
1260 let(:username) { "unit_test_user" }
1261 @node.automatic_attrs[:command] = { ps: "ps -ax" }
1262 @status = double("Status", exitstatus: 0, stdout: "", stderr: "")
1263 @new_resource.parameters({ "OSD_ID" => "2" })
1264 let(:service_name) { "rsyslog\\x2d.service" }
1265 let(:service_name_escaped) { "rsyslog\\\\x2d.service" }
1266 double("shell_out", exitstatus: 0, error?: false, stdout: "")
1267 double("shell_out", exitstatus: 1, error?: true, stdout: "")
1268 systemctl_show = [systemctl_path, "--system", "show", "-p", "UnitFileState", "-p", "ActiveState", service_name]
1269 systemctl_isenabled = [systemctl_path, "--system", "is-enabled", service_name, "--quiet"]
1270 ].join("
")
1271 @enabled_svc_status = double("Status", exitstatus: 0, stdout: enabled_svc_stdout, stdin: "", stderr: "")
1272 @disabled_svc_status = double("Status", exitstatus: 0, stdout: disabled_svc_stdout, stdin: "", stderr: "")
1273 @no_svc_status = double("Status", exitstatus: 1, stdout: "", stdin: "", stderr: "svcs: Pattern 'chef' doesn't match any instances
")
1274 @success = double("clear", exitstatus: 0, stdout: "", stdin: "", stderr: "")
1275 expect(@provider).to receive(:shell_out!).with("/bin/svcs", "-l", "chef", { returns: [0, 1] }).and_return(@enabled_svc_status)
1276 expect(@provider).to receive(:shell_out!).twice.with("/bin/svcs", "-l", "chef", { returns: [0, 1] }).and_return(@enabled_svc_status)
1277 expect(@provider).to receive(:shell_out!).twice.with("/bin/svcs", "-l", "chef", { returns: [0, 1] }).and_return(@maintenance_svc_status)
1278 expect(@provider).to receive(:shell_out!).with("/usr/sbin/svcadm", "enable", "-s", "-r", @current_resource.service_name).and_return(@success)
1279 @new_resource.options(["-r", "-t"])
1280 expect(@provider).to receive(:shell_out!).with("/usr/sbin/svcadm", "enable", "-s", "-r", "-t", @current_resource.service_name).and_return(@success)
1281 expect(@provider).to receive(:shell_out!).with("/bin/svcs", "-l", "chef", { returns: [0, 1] }).and_return(@disabled_svc_status)
1282 expect(@provider).to receive(:shell_out!).with("/usr/sbin/svcadm", "disable", "-s", "chef").and_return(@success)
1283 expect(@provider).to receive(:shell_out!).with("/usr/sbin/svcadm", "disable", "-s", "-t", "chef").and_return(@success)
1284 allow(@provider).to receive(:shell_out!).with("/bin/svcs", "-l", "chef", { returns: [0, 1] }).and_return(@enabled_svc_status)
1285 expect(@provider).to receive(:shell_out!).with("/usr/sbin/svcadm", "refresh", "chef")
1286 expect(@provider).to receive(:shell_out!).with("/bin/svcs", "-l", "chef", { returns: [0, 1] }).and_return(@no_svc_status)
1287 @node.automatic_attrs[:command] = { ps: "ps -ef" }
1288 @node.automatic_attrs[:command] = { ps: nil }
1289 @node.automatic_attrs[:command] = { ps: "" }
1290 status = double("Status", exitstatus: 0, stdout: "" , stderr: "")
1291 @node.automatic_attrs[:command] = { ps: "foo" }
1292 @new_resource.supports( { status: false } )
1293 @new_resource.run_levels([1, 2])
1294 @new_resource.run_levels([ 2 ])
1295 @new_resource.send("#{action}_command", "/etc/init.d/chef #{action}")
1296 node.automatic_attrs[:command] = { ps: "ps -ax" }
1297 let(:supports) { { status: false } }
1298 allow(::File).to receive(:read).with("/etc/rc.conf").and_return("")
1299 allow(::File).to receive(:read).with("/etc/rc.conf.local").and_return("")
1300 let(:status) { double(stdout: "", exitstatus: 0) }
1301 let(:supports) { { status: true } }
1302 expect(::File).to receive(:open).with("/etc/rc.d/#{new_resource.service_name}")
1303 let(:lines) { [ %Q{#{provider.builtin_service_enable_variable_name}="#{setting}"} ] }
1304 let(:lines) { [ %Q{thing_#{provider.builtin_service_enable_variable_name}_enable="YES"} ] }
1305 let(:lines) { [ %Q{#{provider.builtin_service_enable_variable_name}_thing_enable="YES"} ] }
1306 let(:lines) { [] }
1307 let(:supports) { { restart: true } }
1308 expect(::File).to receive(:write).with("/etc/rc.conf.local", /^(?!#{provider.builtin_service_enable_variable_name})$/)
1309 provider.rc_conf = ""
1310 expect(::File).to receive(:write).with("/etc/rc.conf.local", "
pkg_scripts=\"#{new_resource.service_name}\"
")
1311 expect(::File).to receive(:write).with("/etc/rc.conf.local", /^(?!#{new_resource.service_name})$/)
1312 let(:plutil_stdout) { String.new <<~XML }
1313 <key>Label</key>
1314 let(:session) { StringIO.new }
1315 if service_type == "Agent"
1316 let(:session) { "-S Aqua " }
1317 let(:su_cmd) { "su -l igor -c" }
1318 allow(Dir).to receive(:glob).and_return([plist], [])
1319 @stat = double("File::Stat", { uid: 501 })
1320 @getpwuid = double("Etc::Passwd", { name: "mikedodge04" })
1321 allow(node).to receive(:[]).with("platform_version").and_return("10.11.1")
1322 .with(/(#{su_cmd} '#{cmd}'|#{cmd})/, default_env: false)
1323 allow(File).to receive(:exist?).and_return([true], [])
1324 allow(Dir).to receive(:glob).and_return([])
1325 .with(/plutil -convert xml1 -o/)
1326 );
1327 };
1328 allow(Dir).to receive(:glob).and_return([(plist).to_s], [])
1329 cmd = "/bin/launchctl load -w " + session + plist
1330 .with(/(#{su_cmd} .#{cmd}.|#{cmd})/, default_env: false)
1331 cmd = "/bin/launchctl unload -w " + plist
1332 @stdout = StringIO.new(<<~PS)
1333 @status = double("Process::Status mock", exitstatus: 0, stdout: "")
1334 allow(Dir).to receive(:glob).with("/etc/rc*/**/S*initgrediant").and_return([])
1335 node.automatic_attrs[:command] = { ps: "" }
1336 expect(::File).to receive(:exist?).with("/etc/rc.conf").and_return(false)
1337 expect(::File).to receive(:exist?).with("/etc/rc.conf").and_return(true)
1338 let(:lines) { [ %Q{#{new_resource.service_name}_enable="#{setting}"} ] }
1339 let(:lines) { [ %Q{#{new_resource.service_name}_enable="alskdjflasdkjflakdfj"} ] }
1340 %Q{#{new_resource.service_name}_enable="NO"},
1341 %Q{#{new_resource.service_name}_enable="YES"},
1342 let(:lines) { [ %Q{thing_#{new_resource.service_name}_enable="YES"} ] }
1343 let(:lines) { [ %Q{#{new_resource.service_name}_thing_enable="YES"} ] }
1344 rcvar_stdout = <<~EOF
1345 expect(provider).to receive(:read_rc_conf).and_return([ "foo", "#{new_resource.service_name}_enable=\"NO\"", "bar" ])
1346 expect(provider).to receive(:write_rc_conf).with(["foo", "bar", "#{new_resource.service_name}_enable=\"YES\""])
1347 expect(provider).to receive(:read_rc_conf).and_return([ "foo", "thing_#{new_resource.service_name}_enable=\"NO\"", "bar" ])
1348 expect(provider).to receive(:write_rc_conf).with(["foo", "thing_#{new_resource.service_name}_enable=\"NO\"", "bar", "#{new_resource.service_name}_enable=\"YES\""])
1349 expect(provider).to receive(:read_rc_conf).and_return([ "foo", "bar", "\# #{new_resource.service_name}_enable=\"YES\"", "\# #{new_resource.service_name}_enable=\"NO\""])
1350 expect(provider).to receive(:read_rc_conf).and_return([ "foo", "#{new_resource.service_name}_enable=\"YES\"", "bar" ])
1351 expect(provider).to receive(:write_rc_conf).with(["foo", "bar", "#{new_resource.service_name}_enable=\"NO\""])
1352 expect(provider).to receive(:read_rc_conf).and_return([ "foo", "thing_#{new_resource.service_name}_enable=\"YES\"", "bar" ])
1353 expect(provider).to receive(:write_rc_conf).with(["foo", "thing_#{new_resource.service_name}_enable=\"YES\"", "bar", "#{new_resource.service_name}_enable=\"NO\""])
1354 @node.automatic_attrs[:command] = { ps: "fuuuu" }
1355 @pid, @stdin, @stdout, @stderr = nil, nil, nil, nil
1356 [0, 1, 6].each do |stop|
1357 allow(Dir).to receive(:glob).with("/etc/rc#{stop}.d/[SK][0-9][0-9]chef").and_return(["/etc/rc#{stop}.d/K20chef"])
1358 [2, 3, 4, 5].each do |start|
1359 allow(Dir).to receive(:glob).with("/etc/rc#{start}.d/[SK][0-9][0-9]chef").and_return(["/etc/rc#{start}.d/S20chef"])
1360 allow(Dir).to receive(:glob).with("/etc/rc#{stop}.d/[SK][0-9][0-9]chef").and_return([])
1361 allow(Dir).to receive(:glob).with("/etc/rc#{start}.d/[SK][0-9][0-9]chef").and_return([])
1362 ])
1363 @new_resource.priority(2 => [:start, 20], 3 => [:stop, 55])
1364 allow(::File).to receive(:exist?).with("/etc/rc.d/chef").and_return(false)
1365 allow(::File).to receive(:exist?).with("/etc/rc.conf").and_return(true)
1366 allow(::File).to receive(:exist?).with("/etc/rc.conf").and_return(false)
1367 allow(::File).to receive(:read).with("/etc/rc.conf").and_return("DAEMONS=(network !apache ssh)")
1368 expect(@provider.daemons).to eq(["network", "!apache", "ssh"])
1369 allow(::File).to receive(:read).with("/etc/rc.conf").and_return("DAEMONS=(network)")
1370 allow(::File).to receive(:read).with("/etc/rc.conf").and_return("DAEMONS=(network chef)")
1371 allow(Dir).to receive(:glob).with(["/etc/rc.d/rc2.d/[SK][0-9][0-9]#{@new_resource.service_name}", "/etc/rc.d/rc2.d/[SK]#{@new_resource.service_name}"]).and_return([])
1372 expect(@provider).to receive(:create_symlink).with(2, "S", "")
1373 priority = { 2 => [:start, 20], 3 => [:stop, 10] }
1374 expect(@provider).to receive(:create_symlink).with(2, "K", "")
1375 @priority = { 2 => [:start, 20], 3 => [:stop, 10] }
1376 files = ["/etc/rc.d/rc2.d/S20apache"]
1377 allow(Dir).to receive(:glob).with(["/etc/rc.d/rc2.d/[SK][0-9][0-9]#{@new_resource.service_name}", "/etc/rc.d/rc2.d/[SK]chef"]).and_return(files)
1378 files = ["/etc/rc.d/rc2.d/K20apache"]
1379 @priority = { 2 => [:stop, 20] }
1380 @files = ["/etc/rc.d/rc2.d/S20apache", "/etc/rc.d/rc2.d/K80apache"]
1381 @priority = { 2 => [:stop, 80] }
1382 allow(Dir).to receive(:glob).with(["/etc/rc.d/rc2.d/[SK][0-9][0-9]#{@new_resource.service_name}", "/etc/rc.d/rc2.d/[SK]chef"]).and_return(@files)
1383 files = ["/etc/rc.d/rc2.d/Sapache"]
1384 allow(Dir).to receive(:glob).with(["/etc/rc.d/rc2.d/[SK][0-9][0-9]#{@new_resource.service_name}", "/etc/rc.d/rc2.d/[SK]#{@new_resource.service_name}"]).and_return(files)
1385 files = ["/etc/rc.d/rc2.d/Kapache"]
1386 @priority = { 2 => [:stop, ""] }
1387 files = ["/etc/rc.d/rc2.d/Sapache", "/etc/rc.d/rc2.d/Kapache"]
1388 new_resource.code "$| = 1; print 'i like beans'"
1389 expect(provider.command).to eq(%q{"perl" -f})
1390 opts = {
1391 input: "$| = 1; print 'i like beans'",
1392 it "accepts `create' as an alias for `run'" do
1393 @new_resource = Chef::Resource::Route.new("10.0.0.10")
1394 resource = Chef::Resource::Route.new("10.10.10.0/24")
1395 @resource_add = Chef::Resource::Route.new("192.168.1.0/24 via 192.168.0.1")
1396 expect(route_file.string).to match(%r{^192\.168\.1\.0/24 via 192\.168\.0\.1$})
1397 expect(@provider.generate_command(:add).join(" ")).to match(%r{/\d{1,2}})
1398 expect(@provider.generate_command(:add).join(" ")).not_to match(%r{/\d{1,2}})
1399 expect(@default_provider.generate_command(:add).join(" ")).to match(/10.0.0.10/)
1400 expect(@provider.generate_command(:delete).join(" ")).to match(%r{/\d{1,2}})
1401 expect(@provider.generate_command(:delete).join(" ")).not_to match(%r{/\d{1,2}})
1402 expect(@provider.config_file_contents(:add, target: @new_resource.target)).not_to match(%r{/\d{1,2}.*
$})
1403 r.target "192.168.4.0"
1404 r.gateway "192.168.0.1"
1405 expect(route_file.string).to match(%r{^192\.168\.2\.0/24 via 192\.168\.0\.1$})
1406 expect(route_file.string).to match(%r{^192\.168\.3\.0/24 via 192\.168\.0\.1$})
1407 expect(route_file.string).to match(%r{^192\.168\.4\.0/24 via 192\.168\.0\.1$})
1408 let(:sftp) do
1409 sftp = double(Net::SFTP, {})
1410 uri.userinfo = "conan:"
1411 uri.user = "conan"
1412 uri.path = ""
1413 uri.path = "/"
1414 uri.path = "/the/whole/path/"
1415 let(:source) { "\\\\foohost\\fooshare\\Foo.tar.gz" }
1416 let(:tempfile) { double("Tempfile", path: "/tmp/foo/bar/Foo.tar.gz", close: nil) }
1417 let(:source_file) { double("::File", read: nil) }
1418 let(:uri) { URI.parse("file:///nyan_cat.png") }
1419 let(:uri) { URI.parse("file:///z:/windows/path/file.txt") }
1420 let(:uri) { URI.parse(Addressable::URI.encode("file:///z:/windows/path/foo & bar.txt")) }
1421 let(:uri) { URI.parse("file:////server/share/windows/path/file.txt") }
1422 let(:uri) { URI.parse(Addressable::URI.encode("file:////server/share/windows/path/foo & bar.txt")) }
1423 let(:tempfile) { double("Tempfile", path: "/tmp/foo/bar/nyan.png", close: nil) }
1424 let(:uri) { URI.parse("http://opscode.com/seattle.txt") }
1425 expect(fetcher.headers).to eq({ "x-myapp-header" => "custom-header-value" })
1426 let(:etag) { "\"a-strong-unique-identifier\"" }
1427 let(:mtime) { "Tue, 21 May 2013 19:19:23 GMT" }
1428 let(:expected_http_opts) { {} }
1429 let(:last_response) { {} }
1430 let(:rest) do
1431 let(:last_response) { { "etag" => nil } }
1432 let(:last_response) { { "etag" => "abc123" } }
1433 let(:last_response) { { "date" => nil, "last_modified" => nil } }
1434 { "date" => "Fri, 17 May 2013 23:23:23 GMT", "last_modified" => "Fri, 17 May 2013 11:11:11 GMT" }
1435 { "date" => "Fri, 17 May 2013 23:23:23 GMT", "last_modified" => nil }
1436 let(:uri) { URI.parse("http://opscode.com/tarball.tgz") }
1437 let(:expected_http_opts) { { disable_gzip: true } }
1438 let(:ftp) do
1439 ftp = double(Net::FTP, {})
1440 let(:uri) { URI.parse("ftp://opscode.com/seattle.txt") }
1441 uri.typecode = "d"
1442 let(:uri) { URI.parse("ftp://opscode.com:8021/seattle.txt") }
1443 let(:uri) { URI.parse("ftp://opscode.com/the/whole/path/seattle.txt") }
1444 stub_const("ENV", "ftp_proxy" => "socks5://bill:ted@socks.example.com:5000")
1445 let(:new_resource) { double("new resource") }
1446 let(:source) { "\\\\127.0.0.1\\fooshare\\Foo.tar.gz" }
1447 let(:uri) { double("uri", scheme: "http" ) }
1448 let(:uri) { double("uri", scheme: "https" ) }
1449 let(:uri) { double("uri", scheme: "ftp" ) }
1450 let(:uri) { double("uri", scheme: "file" ) }
1451 let(:uri) { double("uri", scheme: "xyzzy" ) }
1452 let(:source) { [ "http://opscode.com/seattle.txt" ] }
1453 let(:run_context) { double("Chef::RunContext") }
1454 @uri = double("URI")
1455 let(:mtime) { Time.now }
1456 let(:tempfile) { double("Tempfile") }
1457 exception_class.new("message", { "something" => 1 })
1458 let(:source) { [ "http://opscode.com/seattle.txt", "http://opscode.com/nyc.txt" ] }
1459 @uri0 = double("URI0")
1460 @uri1 = double("URI1")
1461 1 +
1462 let(:uri) { URI.parse("http://www.google.com/robots.txt") }
1463 let(:uri) { URI.parse("http://bob:password@example.org/") }
1464 let(:etag) { "\"a-strong-identifier\"" }
1465 cache = {}
1466 cache["etag"] = etag
1467 cache["mtime"] = mtime
1468 let(:cache_json_data) { '{"foo",,"bar" []}' }
1469 let(:cache_json_data) { "" }
1470 data = {}
1471 data["etag"] = etag
1472 data["mtime"] = mtime
1473 let(:uri) { URI.parse(long_remote_path) }
1474 File.open(@destination_dir + "/remote_dir_file1.txt", "a") { |f| f.puts "blah blah blah" }
1475 File.open(@destination_dir + "/remotesubdir/remote_subdir_file1.txt", "a") { |f| f.puts "blah blah blah" }
1476 expect(::File.exist?(@destination_dir + "/a/foo.txt")).to be_falsey
1477 ::File.open(@destination_dir + "/remote_dir_file1.txt", "a") { |f| f.puts "blah blah blah" }
1478 ::File.open(@destination_dir + "/remotesubdir/remote_subdir_file1.txt", "a") { |f| f.puts "blah blah blah" }
1479 let(:keyname) { "HKLM\\Software\\Opscode\\Testing\\Safe" }
1480 let(:testval1) { { name: "one", type: :string, data: "1" } }
1481 let(:testval1_wrong_type) { { name: "one", type: :multi_string, data: "1" } }
1482 let(:testval1_wrong_data) { { name: "one", type: :string, data: "2" } }
1483 let(:testval2) { { name: "two", type: :string, data: "2" } }
1484 let(:testval1) { { name: "one", type: :binary, data: 255.chr * 1 } }
1485 let(:testval1_wrong_type) { { name: "one", type: :string, data: 255.chr * 1 } }
1486 let(:testval1_wrong_data) { { name: "one", type: :binary, data: 254.chr * 1 } }
1487 let(:testval2) { { name: "two", type: :binary, data: 0.chr * 1 } }
1488 let(:keyname) { "hklm\\software\\opscode\\testing\\dword" }
1489 let(:dword_passed_as_integer) { { name: "one", type: :dword, data: 12345 } }
1490 let(:testval1) { { name: "one", type: :dword, data: "12345" } }
1491 { name: "one", type: :string, data: "initial value" },
1492 { name: "two", type: :dword, data: 9001 },
1493 let(:testval1) { { name: "one", type: :string, data: "first_value" } }
1494 let(:testval1) { { name: "two", type: :dword, data: 12345 } }
1495 let(:events) { double("Chef::Events").as_null_object }
1496 [ { name: "input1_value1", type: :string, data: "my_value1" },
1497 { name: "input1_value2", type: :string, data: "my_value2" },
1498 [ { name: "input2_value1", data: "my_value1" },
1499 { name: "input2_value2", data: "my_value2" },
1500 [ { name: "input3_value1", data: "my_value1" },
1501 { name: "input3_value2", type: :string, data: "my_value2" },
1502 [ { name: "input4_value1", type: :string },
1503 { name: "input4_value2", type: :string },
1504 [ { name: "input5_value1", type: :string, data: "my_value1" },
1505 { name: "input5_value2", type: :string },
1506 [ { name: "input6_value1" },
1507 { name: "input6_value2" },
1508 let(:run_context) { Chef::RunContext.new(Chef::Node.new, {}, events) }
1509 expected = <<~CMD.strip
1510 let(:candidate_version) { "1.0" }
1511 provider.candidate_version = [ "1.0" ]
1512 [ "vim" ],
1513 [ "1.0" ]
1514 [ nil ]
1515 let(:new_resource) { Chef::Resource::Package.new(%w{emacs vi}) }
1516 let(:candidate_version) { [ "1.0", "6.2" ] }
1517 %w{emacs vi},
1518 ["1.0", "6.2"]
1519 [ "vi" ],
1520 [ "6.2" ]
1521 current_resource.version(["1.0", "6.1"])
1522 new_resource.version(["1.0", "6.2"])
1523 current_resource.version(["1.0", "6.2"])
1524 current_resource.version(["1.1", "6.2"])
1525 new_resource.version(["1.0", "6.1"])
1526 new_resource.version ["1.0", "6.2"]
1527 provider.candidate_version = ["1.0", "6.2"]
1528 current_resource.version ["0.9", "6.1"]
1529 current_resource.version ["1.0", "6.1"]
1530 ["vi"],
1531 ["6.2"]
1532 current_resource.version ["1.0", "6.2"]
1533 expect(provider).to receive(:remove_package).with(%w{emacs vi}, ["1.0", "6.2"])
1534 new_resource.version ["0.5", "6.2"]
1535 expect(provider).to receive(:remove_package).with(%w{emacs vi}, ["0.5", "6.2"])
1536 new_resource.version ["0.5", "6.0"]
1537 expect(provider).to receive(:purge_package).with(%w{emacs vi}, ["1.0", "6.2"])
1538 expect(provider).to receive(:purge_package).with(%w{emacs vi}, ["0.5", "6.2"])
1539 expect(provider.version_compare("1.3", "1.3")).to eql(0)
1540 expect(provider.version_compare("1.2", "1.3")).to eql(-1)
1541 expect(provider.version_compare("1.5", "1.3")).to eql(1)
1542 expect(provider.version_compare("1.10", "1.2")).to eql(1)
1543 expect(provider.version_compare("1.3_3", "1.3")).to eql(0)
1544 let(:status) { double(stdout: "
", exitstatus: 0) }
1545 let(:source) { "/tmp/wget_1.11.4-1ubuntu1_amd64.rpm" }
1546 allow(provider).to receive(:`).and_return("2.0")
1547 options[:timeout] ||= 900
1548 provider.install_package(["emacs"], ["1.0"])
1549 provider.upgrade_package(["emacs"], ["1.0"])
1550 provider.remove_package(["emacs"], ["1.0"])
1551 provider.purge_package(["emacs"], ["1.0"])
1552 Mixlib::ShellOut, stdout: "1 | somethingelse | package | (any)"
1553 ))
1554 Mixlib::ShellOut, stdout: "1 | cups | package | (any)"
1555 provider.lock_package(["emacs"], [nil])
1556 allow(provider).to receive(:`).and_return("0.11.6")
1557 provider.install_package(%w{emacs vim}, ["1.0", "2.0"])
1558 provider.remove_package(%w{emacs vim}, ["1.0", "2.0"])
1559 expect( python_helper ).to receive(:package_query).with(:whatavailable, "foo", arch: nil).and_return( yum_version("foo", "1.2.3-1", "x86_64") )
1560 expect( python_helper ).to receive(:package_query).with(:whatavailable, "foo", version: "1.2.3", arch: nil).and_return( yum_version("foo", nil, nil) )
1561 expect( yum_cache.version_available?("foo", "1.2.3") ).to be false
1562 expect( python_helper ).to receive(:package_query).with(:whatavailable, "foo", version: "1.2.3", arch: nil).and_return( yum_version("foo", "1.2.3-1", "x86_64") )
1563 expect( yum_cache.version_available?("foo", "1.2.3") ).to be true
1564 expect( python_helper ).to receive(:package_query).with(:whatavailable, "foo", version: "1.2.3", arch: "x86_64").and_return( yum_version("foo", nil, nil) )
1565 expect( yum_cache.version_available?("foo", "1.2.3", "x86_64") ).to be false
1566 expect( python_helper ).to receive(:package_query).with(:whatavailable, "foo", version: "1.2.3", arch: "x86_64").and_return( yum_version("foo", "1.2.3-1", "x86_64") )
1567 expect( yum_cache.version_available?("foo", "1.2.3", "x86_64") ).to be true
1568 expect( python_helper ).to receive(:package_query).with(:whatinstalled, "foo", arch: nil).and_return( yum_version("foo", "1.2.3-1", "x86_64") )
1569 expect( yum_cache.installed_version("foo") ).to eql("1.2.3-1.x86_64")
1570 expect( python_helper ).to receive(:package_query).with(:whatinstalled, "foo", arch: "x86_64").and_return( yum_version("foo", "1.2.3-1", "x86_64") )
1571 expect( yum_cache.installed_version("foo", "x86_64") ).to eql("1.2.3-1.x86_64")
1572 expect( yum_cache.available_version("foo") ).to eql("1.2.3-1.x86_64")
1573 expect( python_helper ).to receive(:package_query).with(:whatavailable, "foo", arch: "x86_64").and_return( yum_version("foo", "1.2.3-1", "x86_64") )
1574 expect( yum_cache.available_version("foo", "x86_64") ).to eql("1.2.3-1.x86_64")
1575 let(:resource_name) { "calculator" }
1576 let(:installer_type) { nil }
1577 let(:cache_path) { "c:\\cache\\" }
1578 installed_version: "1.0", package_version: "2.0"))
1579 [{
1580 }]
1581 let(:uninstall_key) { "blah" }
1582 entries = []
1583 let(:uninstall_key) { "blah_is1" }
1584 let(:resource_source) { "setup.exe" }
1585 let(:resource_name) { "blah" }
1586 let(:resource_source) { "blah.exe" }
1587 let(:installer_type) { :inno }
1588 let(:resource_source) { nil }
1589 let(:installer_type) { :msi }
1590 before { new_resource.version("5.5.5") }
1591 allow(provider).to receive(:current_version_array).and_return([ ["5.5.5", "4.3.0", "1.1.1"] ])
1592 allow(provider).to receive(:current_version_array).and_return([ ["5.5.0", "4.3.0", "1.1.1"] ])
1593 let(:resource_source) { "C:/a_missing_file.exe" }
1594 let(:hkey) { :hkey } # mock all the methods
1595 let(:key) { :key }
1596 let(:package_name) { nil }
1597 let(:package_name) { " " }
1598 let(:package_name) { "hive" }
1599 let(:package_name) { "Chef" }
1600 let(:package_name) { "Chef Client" }
1601 let(:display_name) { "Chef Client" }
1602 let(:node) { double("Chef::Node") }
1603 let(:run_context) { double("Chef::RunContext", node: node, events: events) }
1604 let(:package_name) { "calculator" }
1605 let(:resource_version) { nil }
1606 expect(provider.expand_options("--train nope --town no_way")).to eql(" --train nope --town no_way")
1607 it "calls msiexec /qn /i" do
1608 expect(provider).to receive(:shell_out!).with(%r{msiexec /qn /i \"#{Regexp.quote(new_resource.source)}\"}, kind_of(Hash))
1609 it "calls msiexec /qn /x" do
1610 expect(provider).to receive(:shell_out!).with(%r{msiexec /qn /x \"#{Regexp.quote(new_resource.source)}\"}, kind_of(Hash))
1611 expect(provider).to receive(:shell_out!).with(%r{msiexec /x {guid} /q}, kind_of(Hash))
1612 expect(provider).to receive(:shell_out!).with(%r{msiexec /x {guid2} /q}, kind_of(Hash))
1613 before { new_resource.options("/Q") }
1614 expect(provider).to receive(:shell_out!).with(%r{msiexec /x {guid} /Q}, kind_of(Hash))
1615 before { new_resource.options("/qn") }
1616 expect(provider).to receive(:shell_out!).with(%r{msiexec /x {guid} /qn}, kind_of(Hash))
1617 let(:uninstall_hash) { [] }
1618 expect(provider).to receive(:shell_out!).with(%r{start \"\" /wait \"uninst_dir/uninst_file\" /S /NCRC & exit %%%%ERRORLEVEL%%%%}, kind_of(Hash))
1619 expect(provider).to receive(:shell_out!).with(%r{start \"\" /wait \"uninst_dir2/uninst_file2\" /S /NCRC & exit %%%%ERRORLEVEL%%%%}, kind_of(Hash))
1620 expect(provider).to receive(:shell_out!).with(%r{start \"\" /wait \"uninst_dir1/uninst_file1\" /S /NCRC & exit %%%%ERRORLEVEL%%%%}, kind_of(Hash))
1621 @status = double("Status", stdout: "", exitstatus: 0)
1622 expect(@provider).to receive(:shell_out_compacted).with("pkginfo", "-l", "-d", "/tmp/bash.pkg", "SUNWbash", { timeout: 900 }).and_return(status)
1623 expect(@provider).to receive(:shell_out_compacted).with("pkginfo", "-l", "SUNWbash", { timeout: 900 }).and_return(@status)
1624 expect(@provider).to receive(:shell_out_compacted).with("pkginfo", "-l", "-d", "/tmp/bash.pkg", "SUNWbash", { timeout: 900 }).and_return(@status)
1625 status = double(stdout: "", exitstatus: -1)
1626 status = double(stdout: "", exitstatus: 0)
1627 status = double(stdout: "", exitstatus: 1)
1628 expect(@provider).to receive(:shell_out_compacted!).with("pkgadd", "-n", "-d", "/tmp/bash.pkg", "all", { timeout: 900 })
1629 expect(@provider).to receive(:shell_out_compacted!).with("pkgadd", "-n", "-a", "/tmp/myadmin", "-d", "/tmp/bash.pkg", "all", { timeout: 900 })
1630 expect(@provider).to receive(:shell_out_compacted!).with("pkgrm", "-n", "SUNWbash", { timeout: 900 })
1631 expect(@provider).to receive(:shell_out_compacted!).with("pkgrm", "-n", "-a", "/tmp/myadmin", "SUNWbash", { timeout: 900 })
1632 let(:package) { "hello" }
1633 let(:source) { "/tmp/hello_20.snap" }
1634 version: 2.10 -
1635 --foo
1636 options = {}
1637 let(:source) { nil }
1638 snap_names = ["hello"]
1639 expect(actual).to eq("action" => "install", "snaps" => ["hello"], "channel" => "stable")
1640 @stdout = "varnish-2.1.5nb2
"
1641 @pid = 10
1642 @shell_out = double("shell_out!", stdout: search)
1643 expect(@provider).to receive(:shell_out_compacted!).with("/opt/local/bin/pkgin", "se", "varnish", env: nil, returns: [0, 1], timeout: 900).and_return(@shell_out)
1644 expect(@provider).to receive(:shell_out_compacted!).with("/opt/local/sbin/pkg_info", "-E", "varnish*", { env: nil, returns: [0, 1], timeout: 900 }).and_return(@shell_out)
1645 expect(@provider).to receive(:shell_out_compacted!).with("/opt/local/bin/pkgin", "-y", "install", "varnish-2.1.5nb2", { env: nil, timeout: 900 }).and_return(out)
1646 Gem::Specification.new { |s| s.name = name; s.version = version }
1647 stubs.select! { |stub| stub.name == "rspec-core" && Gem::Dependency.new("rspec-core", ">= 0").requirement.satisfied_by?(stub.version) }
1648 gems = [gemspec("rspec-core", Gem::Version.new("1.2.9")), gemspec("rspec-core", Gem::Version.new("1.3.0"))]
1649 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new("2.7")
1650 dep = Gem::Dependency.new("sexp_processor", ">= 0")
1651 dep = Gem::Dependency.new("nonexistent_gem", ">= 0")
1652 dep = Gem::Dependency.new("lksdjflksdjflsdkfj", ">= 0")
1653 @gem_env.install(Gem::Dependency.new("rspec", ">= 0"), install_dir: "/foo/bar", sources: ["http://gems.example.com"])
1654 @gem_env.uninstall("rspec", "1.2.3")
1655 gem_env_output = ["/path/to/gems", "/another/path/to/gems"].join(File::PATH_SEPARATOR)
1656 expect(@gem_env.gem_paths).to eq(["/path/to/gems", "/another/path/to/gems"])
1657 expected = ["/path/to/gems", "/another/path/to/gems"]
1658 allow(@gem_env).to receive(:gem_paths).and_return(["/path/to/gems", "/another/path/to/gems"])
1659 gems = [gemspec("rspec", Gem::Version.new("1.2.9")), gemspec("rspec", Gem::Version.new("1.3.0"))]
1660 actual = gem_env.installed_versions(Gem::Dependency.new("rspec-core", nil)).map { |s| [s.name, s.version] }
1661 - RUBY VERSION: 1.8.7 (2010-05-12 patchlevel 249) [java]
1662 - ruby
1663 - /Users/you/.rvm/gems/jruby-1.5.0
1664 - :update_sources => true
1665 - :verbose => true
1666 - :benchmark => false
1667 - :backtrace => false
1668 - :bulk_threshold => 1000
1669 - "install" => "--env-shebang"
1670 - "update" => "--env-shebang"
1671 - "gem" => "--no-rdoc --no-ri"
1672 - :sources => ["https://rubygems.org/", "http://gems.github.com/"]
1673 - https://rubygems.org/
1674 - http://gems.github.com/
1675 expected = ["ruby", Gem::Platform.new("universal-java-1.6")]
1676 @gem_env.with_gem_platforms(["ruby", Gem::Platform.new("sparc64-java-1.7")]) do
1677 let(:target_version) { nil }
1678 let(:gem_name) { "rspec-core" }
1679 let(:gem_binary) { nil }
1680 let(:bindir) { "/usr/bin" }
1681 let(:options) { nil }
1682 let(:current_resource) { nil }
1683 _ = provider
1684 let(:gem_binary) { "/usr/weird/bin/gem" }
1685 let(:options) { { fail: :burger } }
1686 let(:bindir) { "/opt/opscode/embedded/bin" }
1687 let(:bindir) { "/opt/chef/embedded/bin" }
1688 allow(ENV).to receive(:[]).with("PATH").and_return("/usr/bin:/usr/sbin:/opt/chef/embedded/bin")
1689 let(:bindir) { "d:/opscode/chef/embedded/bin" }
1690 allow(ENV).to receive(:[]).with("PATH").and_return('C:\windows\system32;C:\windows;C:\Ruby186\bin')
1691 let(:target_version) { "~> 9000.0.2" }
1692 let(:target_version) { "9000.0.2" }
1693 let(:gem_name) { "no-such-gem-should-exist-with-this-name" }
1694 let(:target_version) { ">= 0" }
1695 .and_return(Gem::Version.new("9000.0.2"))
1696 Chef::Config[:rubygems_url] = "https://mirror1/"
1697 .with(gem_dep, "https://mirror1/")
1698 let(:source) { "http://mygems.example.com" }
1699 let(:source) { [ "https://mirror1", "https://mirror2" ] }
1700 .with(gem_dep, *source)
1701 let(:gem_name) { "chef-integration-test" }
1702 let(:source) { CHEF_SPEC_DATA + "/gems/chef-integration-test-0.1.0.gem" }
1703 let(:current_version) { nil }
1704 let(:candidate_version) { "9000.0.2" }
1705 let(:source) { "http://gems.example.org" }
1706 let(:gem_name) { CHEF_SPEC_DATA + "/gems/chef-integration-test-0.1.0.gem" }
1707 let(:options) { "-i /alt/install/location" }
1708 expected = "gem install rspec-core -q --no-document -v \"#{target_version}\" --source=https://rubygems.org #{options}"
1709 expected = "gem install rspec-core -q --no-rdoc --no-ri -v \"#{target_version}\" --source=https://rubygems.org #{options}"
1710 let(:gem_binary) { "/foo/bar" }
1711 expected = "#{gem_binary} install rspec-core -q --no-document -v \"#{target_version}\" --clear-sources --source=https://mirror1"
1712 let(:source) { "http://mirror.ops.rhcloud.com/mirror/ruby" }
1713 expected = "#{gem_binary} install rspec-core -q --no-document -v \"#{target_version}\" --clear-sources --source=#{source}"
1714 expected = "#{gem_binary} install rspec-core -q --no-document -v \"#{target_version}\" --clear-sources --source=#{source} --source=https://rubygems.org"
1715 let(:source) { [ "https://mirror1" , "https://mirror2" ] }
1716 expected = "#{gem_binary} install rspec-core -q --no-document -v \"#{target_version}\" --clear-sources --source=https://mirror1 --source=https://mirror2"
1717 expected = "#{gem_binary} install rspec-core -q --no-document -v \"#{target_version}\" --clear-sources --source=https://mirror1 --source=https://mirror2 --source=https://rubygems.org"
1718 expected = "#{gem_binary} install rspec-core -q --no-document -v \"#{target_version}\" --source=#{source}"
1719 expected = "gem install rspec-core -q --no-document -v \"#{candidate_version}\" --source=https://rubygems.org #{options}"
1720 let(:options) { { install_dir: "/alt/install/location" } }
1721 let(:target_version) { ">=2.3.0" }
1722 let(:current_version) { "2.3.3" }
1723 let(:target_version) { "~>2.3.0" }
1724 expect(provider).to receive(:shell_out_compacted!).with("#{gem_binary} install rspec-core -q --no-rdoc --no-ri -v \"#{target_version}\" --source=https://rubygems.org", env: nil, timeout: 900)
1725 expect(provider).to receive(:shell_out_compacted!).with("#{gem_binary} install #{source} -q --no-document -v \"#{target_version}\"", env: nil, timeout: 900)
1726 expect(provider).to receive(:shell_out_compacted!).with("#{gem_binary} install #{gem_name} -q --no-document -v \"#{target_version}\"", env: nil, timeout: 900)
1727 let(:gem_name) { "rspec" }
1728 let(:current_version) { "1.2.3" }
1729 let(:target_version) { "1.2.3" }
1730 let(:package_source) { "/tmp/ImageMagick-c++-6.5.4.7-7.el6_5.x86_64.rpm" }
1731 let(:package_name) { "ImageMagick-c++" }
1732 let(:package_source) { "foobar://example.com/ImageMagick-c++-6.5.4.7-7.el6_5.x86_64.rpm" }
1733 .with("rpm", "-qp", "--queryformat", "%{NAME} %{VERSION}-%{RELEASE}
", package_source, timeout: 900)
1734 .with("rpm", "-q", "--queryformat", "%{NAME} %{VERSION}-%{RELEASE}
", package_name, timeout: 900)
1735 let(:rpm_qp_stdout) { "ImageMagick-c++ 6.5.4.7-7.el6_5" }
1736 let(:rpm_q_stdout) { "" }
1737 let(:rpm_qp_exitstatus) { 0 }
1738 let(:rpm_q_exitstatus) { -1 }
1739 let(:rpm_q_stdout) { "ImageMagick-c++ 6.5.4.7-7.el6_5" }
1740 let(:rpm_q_exitstatus) { 0 }
1741 let(:action) { :install }
1742 expect(provider).to_not receive(:shell_out_compacted!).with("rpm", "-i", "/tmp/imagemagick-c++-6.5.4.7-7.el6_5.x86_64.rpm", timeout: 900)
1743 let(:rpm_q_stdout) { "imagemagick-c++ 0.5.4.7-7.el6_5" }
1744 expect(provider).to receive(:shell_out_compacted!).with("rpm", "-U", "--oldpackage", "/tmp/ImageMagick-c++-6.5.4.7-7.el6_5.x86_64.rpm", timeout: 900)
1745 let(:rpm_q_stdout) { "imagemagick-c++ 21.4-19.el6_5" }
1746 let(:action) { :upgrade }
1747 let(:action) { :remove }
1748 expect(provider).to receive(:shell_out_compacted!).with("rpm", "-e", "ImageMagick-c++-6.5.4.7-7.el6_5", timeout: 900)
1749 let(:package_name) { "supermarket" }
1750 let(:package_source) { "/tmp/supermarket-1.10.1~alpha.0-1.el5.x86_64.rpm" }
1751 let(:rpm_qp_stdout) { "supermarket 1.10.1~alpha.0-1.el5" }
1752 let(:rpm_q_stdout) { "supermarket 1.10.1~alpha.0-1.el5" }
1753 let(:package_name) { "chef-server-core" }
1754 let(:package_source) { "#{scheme}://example.com/ImageMagick-c++-6.5.4.7-7.el6_5.x86_64.rpm" }
1755 let(:package_name) { "openssh-askpass" }
1756 let(:package_source) { "/tmp/openssh-askpass-1.2.3-4.el6_5.x86_64.rpm" }
1757 let(:rpm_qp_stdout) { "openssh-askpass 1.2.3-4.el6_5" }
1758 expect(provider).to receive(:shell_out_compacted!).with("rpm", "--dbpath", "/var/lib/rpm", "-i", package_source, timeout: 900)
1759 expect(provider).to_not receive(:shell_out_compacted!).with("rpm", "-e", "ImageMagick-c++-6.5.4.7-7.el6_5", timeout: 900)
1760 expect(provider).to receive(:shell_out_compacted!).with("rpm", "-i", "/tmp/ImageMagick-c++-6.5.4.7-7.el6_5.x86_64.rpm", timeout: 900)
1761 provider.install_package("/tmp/ImageMagick-c++-6.5.4.7-7.el6_5.x86_64.rpm", "6.5.4.7-7.el6_5")
1762 provider.upgrade_package("/tmp/ImageMagick-c++-6.5.4.7-7.el6_5.x86_64.rpm", "6.5.4.7-7.el6_5")
1763 let(:timeout) { 900 }
1764 double("powershell_exec", result: "2.1.0.0\r
")
1765 double("powershell_exec", result: "2.0.0.0\r
")
1766 double("powershell_exec", result: "2.12.0.0\r
")
1767 double("powershell_exec", result: "2.11.0.0\r
")
1768 double("powershell_exec", result: "16.02\r
")
1769 new_resource.package_name(["7-Zip 16.02 (x64)"])
1770 new_resource.version(["2.0.0.0"])
1771 expect(provider.candidate_version).to eql(["2.1.0.0", "2.12.0.0"])
1772 let(:timeout) { 3600 }
1773 new_resource.version(["2.11.0.0"])
1774 new_resource.version([nil, "2.11.0.0"])
1775 new_resource.version(["2.1.0.0", nil])
1776 new_resource.version(["2.1.0.0"])
1777 allow(::Dir).to receive(:[]).with("/var/db/pkg/dev-util/git-*").and_return(["/var/db/pkg/dev-util/git-1.0.0"])
1778 allow(::Dir).to receive(:[]).with("/var/db/pkg/dev-util/git-*").and_return(["/var/db/pkg/dev-util/git-foobar-0.9", "/var/db/pkg/dev-util/git-1.0.0"])
1779 allow(::Dir).to receive(:[]).with("/var/db/pkg/dev-util/git-*").and_return(["/var/db/pkg/dev-util/git-1.0.0-r1"])
1780 allow(::Dir).to receive(:[]).with("/var/db/pkg/dev-util/git-*").and_return(["/var/db/pkg/dev-util/git-1.0.0d"])
1781 allow(::Dir).to receive(:[]).with("/var/db/pkg/dev-util/git-*").and_return(["/var/db/pkg/dev-util/notgit-1.0.0"])
1782 allow(::Dir).to receive(:[]).with("/var/db/pkg/*/git-*").and_return(["/var/db/pkg/dev-util/git-foobar-0.9", "/var/db/pkg/dev-util/git-1.0.0"])
1783 allow(::Dir).to receive(:[]).with("/var/db/pkg/*/git-*").and_return(["/var/db/pkg/dev-util/notgit-1.0.0"])
1784 allow(::Dir).to receive(:[]).with("/var/db/pkg/*/git-*").and_return(["/var/db/pkg/dev-util/git-1.0.0", "/var/db/pkg/funny-words/git-1.0.0"])
1785 allow(::Dir).to receive(:[]).with("/var/db/pkg/dev-util/git-*").and_return(["/var/db/pkg/dev-util/git-1.0.0", "/var/db/pkg/funny-words/git-1.0.0"])
1786 allow(::Dir).to receive(:[]).with("/var/db/pkg/*/git-*").and_return(["/var/db/pkg/dev-util/git-1.0.0", "/var/db/pkg/dev-util/git-1.0.1"])
1787 status = double(stdout: "", stderr: "", exitstatus: 1)
1788 status = double(stdout: "dev-vcs/git-2.16.2", exitstatus: 0)
1789 stderr_output = <<~EOF
1790 expect(@provider).to receive(:shell_out_compacted!).with("emerge", "-g", "--color", "n", "--nospinner", "--quiet", "=dev-util/git-1.0.0", timeout: 3600)
1791 @provider.install_package("dev-util/git", "1.0.0")
1792 expect(@provider).to receive(:shell_out_compacted!).with("emerge", "-g", "--color", "n", "--nospinner", "--quiet", "~dev-util/git-1.0.0", timeout: 3600)
1793 @provider.install_package("dev-util/git", "~1.0.0")
1794 expect(@provider).to receive(:shell_out_compacted!).with("emerge", "--unmerge", "--color", "n", "--nospinner", "--quiet", "dev-util/git", timeout: 3600)
1795 expect(@provider).to receive(:shell_out_compacted!).with("emerge", "--unmerge", "--color", "n", "--nospinner", "--quiet", "=dev-util/git-1.0.0", timeout: 3600)
1796 @provider.remove_package("dev-util/git", "1.0.0")
1797 @pid = 12345
1798 expect(@provider).to receive(:shell_out_compacted!).with("cave", "-L", "warning", "resolve", "-x", "=net/ntp-4.2.6_p5-r2", { timeout: @new_resource.timeout || 900 })
1799 @provider.install_package("net/ntp", "4.2.6_p5-r2")
1800 expect(@provider).to receive(:shell_out_compacted!).with("cave", "-L", "warning", "resolve", "-x", "=sys-process/lsof-4.87", { timeout: @new_resource.timeout || 900 })
1801 @provider.upgrade_package("net/ntp", "4.2.6_p5-r2")
1802 expect(@provider).to receive(:shell_out_compacted!).with("cave", "-L", "warning", "uninstall", "-x", "=net/ntp-4.2.6_p5-r2", timeout: 900)
1803 @provider.remove_package("net/ntp", "4.2.6_p5-r2")
1804 [core]
1805 include_examples "current_resource", ["sed"], ["3.234-1"], ["3.234-2"]
1806 include_examples "current_resource", ["emacs"], ["0.12.0-1"], ["0.12.0-1"]
1807 include_examples "current_resource", ["nano"], [nil], ["3.450-1"]
1808 include_examples "current_resource", %w{nano sed}, [nil, "3.234-1"], ["3.450-1", "3.234-2"]
1809 node.default["kernel"] = { "name" => "OpenBSD", "release" => "5.5", "machine" => "amd64" }
1810 let(:name) { "ihavetoes" }
1811 let(:version) { "0.0" }
1812 allow(provider).to receive(:shell_out_compacted!).with("pkg_info", "-e", "#{name}->0", anything).and_return(instance_double("shellout", stdout: ""))
1813 instance_double("shellout", stdout: "#{name}-#{version}
")
1814 { env: { "PKG_PATH" => "http://ftp.OpenBSD.org/pub/OpenBSD/5.5/packages/amd64/" }, timeout: 900 }
1815 ) { OpenStruct.new status: true }
1816 let(:flavor_a) { "flavora" }
1817 let(:flavor_b) { "flavorb" }
1818 instance_double("shellout", stdout: "#{name}-#{version}-#{flavor_a}
#{name}-#{version}-#{flavor_b}
")
1819 let(:flavor) { "flavora" }
1820 let(:package_name) { "ihavetoes" }
1821 let(:name) { "#{package_name}--#{flavor}" }
1822 expect(provider).to receive(:shell_out_compacted!).with("pkg_info", "-e", "#{package_name}->0", anything).and_return(instance_double("shellout", stdout: ""))
1823 instance_double("shellout", stdout: "#{name}-#{version}-#{flavor}
")
1824 expect(provider).to receive(:shell_out_compacted!).with("pkg_info", "-I", "#{name}-#{version}-#{flavor_b}", anything).and_return(
1825 instance_double("shellout", stdout: "#{name}-#{version}-#{flavor_a}
")
1826 new_resource.version("#{version}-#{flavor_b}")
1827 @name = "ihavetoes"
1828 let(:timeout) {}
1829 cab_file = "c:\\temp\\test6.1-kb2664825-v3-x64.cab"
1830 expect(path).to be == "C:\\chef\\abc\\package\\Test6.1-KB2664825-v3-x64.msu"
1831 stdout = <<~EOF
1832 openssl @0.9.8k_0 (active)
1833 status = double(stdout: "version: 4.2.7
", exitstatus: 0)
1834 expect(@provider).to receive(:shell_out_compacted!).with("port", "install", "zsh", "@4.2.7", timeout: 900)
1835 @provider.install_package("zsh", "4.2.7")
1836 expect(@provider).to receive(:shell_out_compacted!).with("port", "-f", "install", "zsh", "@4.2.7", timeout: 900)
1837 expect(@provider).to receive(:shell_out_compacted!).with("port", "uninstall", "zsh", "@4.2.7", timeout: 900)
1838 @provider.purge_package("zsh", "4.2.7")
1839 expect(@provider).to receive(:shell_out_compacted!).with("port", "-f", "uninstall", "zsh", "@4.2.7", timeout: 900)
1840 expect(@provider).to receive(:shell_out_compacted!).with("port", "deactivate", "zsh", "@4.2.7", timeout: 900)
1841 @provider.remove_package("zsh", "4.2.7")
1842 expect(@provider).to receive(:shell_out_compacted!).with("port", "-f", "deactivate", "zsh", "@4.2.7", timeout: 900)
1843 expect(@provider).to receive(:shell_out_compacted!).with("port", "upgrade", "zsh", "@4.2.7", timeout: 900)
1844 @provider.upgrade_package("zsh", "4.2.7")
1845 expect(@provider).to receive(:shell_out_compacted!).with("port", "-f", "upgrade", "zsh", "@4.2.7", timeout: 900)
1846 stdout = ""
1847 Version: 1.8.4.1 (1.8.4p1)
1848 stderr = ""
1849 Branch: 0.175.0.0.0.2.537
1850 expect(@provider).to receive(:shell_out_compacted!).with("pkg", "install", "-q", "crypto/gnupg@2.0.17", timeout: 900)
1851 expect(@provider).to receive(:shell_out_compacted!).with("pkg", "--no-refresh", "install", "-q", "crypto/gnupg@2.0.17", timeout: 900)
1852 expect(@provider).to receive(:shell_out_compacted!).with("pkg", "install", "-q", "--accept", "crypto/gnupg@2.0.17", timeout: 900).and_return(local_output)
1853 expect(@provider).to receive(:shell_out_compacted!).with("pkg", "uninstall", "-q", "crypto/gnupg@2.0.17", timeout: 900)
1854 expect(@provider).to receive(:shell_out_compacted!).with("pkg", "--no-refresh", "uninstall", "-q", "crypto/gnupg@2.0.17", timeout: 900)
1855 let(:homebrew_uid) { 1001 }
1856 { "openssl@1.1" =>
1857 { "name" => "openssl@1.1",
1858 { "stable" =>
1859 { "rebuild" => 0,
1860 { "name" => "kubernetes-cli",
1861 { "name" => "vim",
1862 [{ "version" => "8.2.0550",
1863 [{ "full_name" => "gettext", "version" => "0.20.1" },
1864 { "full_name" => "lua", "version" => "5.3.5" },
1865 { "full_name" => "perl", "version" => "5.30.2" },
1866 { "full_name" => "gdbm", "version" => "1.18.1" },
1867 { "full_name" => "openssl@1.1", "version" => "1.1.1f" },
1868 { "full_name" => "readline", "version" => "8.0.4" },
1869 { "full_name" => "sqlite", "version" => "3.31.1" },
1870 { "full_name" => "xz", "version" => "5.2.5" },
1871 { "full_name" => "python", "version" => "3.7.7" },
1872 { "full_name" => "libyaml", "version" => "0.2.2" },
1873 { "full_name" => "ruby", "version" => "2.7.1" }],
1874 { "name" => "curl",
1875 expect(provider.candidate_version).to eql(["1.0", "1.0"])
1876 expect(provider.brew_info).to eq("bogus" => {})
1877 let(:new_resource) { Chef::Resource::Package.new("emacs") }
1878 expect(provider).to receive(:brew_cmd_output).with("install", ["--cocoa"], ["curl"])
1879 expect(provider).to receive(:brew_cmd_output).with("upgrade", [ "--cocoa" ], ["openssl"])
1880 @pkg_info = OpenStruct.new(stdout: "zsh-3.1.7
")
1881 expect(@provider).to receive(:shell_out_compacted!).with("pkg", "info", "zsh", env: nil, returns: [0, 70], timeout: 900).and_return(@pkg_info)
1882 expect(@provider).to receive(:shell_out_compacted!).with("make", "-V", "PORTVERSION", cwd: "/usr/ports/shells/zsh", env: nil, returns: [0, 1], timeout: 900)
1883 .with("make", "-DBATCH", "install", "clean", timeout: 1800, cwd: "/usr/ports/shells/zsh", env: nil)
1884 @provider.install_package("zsh", "5.0.5")
1885 .with("make", "deinstall", timeout: 300, cwd: "/usr/ports/shells/zsh", env: nil)
1886 @provider.remove_package("zsh", "5.0.5")
1887 expect(@provider).to receive(:shell_out_compacted!).with("pkg", "info", "zsh", env: nil, returns: [0, 1, 70], timeout: 900).and_return(@pkg_info)
1888 pkg_query = OpenStruct.new(stdout: "5.0.5
", exitstatus: 0)
1889 expect(@provider).to receive(:shell_out_compacted!).with("pkg", "rquery", "%v", "zsh", env: nil, timeout: 900).and_return(pkg_query)
1890 pkg_query = OpenStruct.new(stdout: "5.0.3
", exitstatus: 0)
1891 expect(@provider).to receive(:shell_out_compacted!).with("pkg", "rquery", "-r", "LocalMirror", "%v", "zsh", env: nil, timeout: 900).and_return(pkg_query)
1892 .with("pkg", "add", "/nas/pkg/repo/zsh-5.0.1.txz", env: { "LC_ALL" => nil }, timeout: 900)
1893 @provider.install_package("zsh", "5.0.1")
1894 .with("pkg", "add", "http://repo.example.com/zsh-5.0.1.txz", env: { "LC_ALL" => nil }, timeout: 900)
1895 .with("pkg", "install", "-y", "zsh", env: { "LC_ALL" => nil }, timeout: 900).and_return(@install_result)
1896 .with("pkg", "install", "-y", "-r", "LocalMirror", "zsh", env: { "LC_ALL" => nil }, timeout: 900).and_return(@install_result)
1897 .with("pkg", "delete", "-y", "zsh-5.0.1", env: nil, timeout: 900).and_return(@install_result)
1898 @provider.remove_package("zsh", "5.0.1")
1899 let(:package) { "wget" }
1900 let(:source) { "/tmp/wget_1.11.4-1ubuntu1_amd64.deb" }
1901 let(:dpkg_deb_version) { "1.11.4" }
1902 let(:dpkg_deb_status) { status = double(stdout: "#{package}\t#{dpkg_deb_version}", exitstatus: 0) }
1903 let(:dpkg_s_version) { "1.11.4-1ubuntu1" }
1904 Depends: libc6 (>= 2.8~20080505), libssl0.9.8 (>= 0.9.8f-5)
1905 allow(provider).to receive(:shell_out_compacted!).with("dpkg", "-s", package, timeout: 900, returns: [0, 1]).and_return(double(stdout: "", exitstatus: 1))
1906 check_version("1.11.4")
1907 check_version("1:1.8.3-2")
1908 describe "when the package name has `-', `+' or `.' characters" do
1909 let(:package) { "f.o.o-pkg++2" }
1910 describe "when the package version has `~', `-', `+' or `.' characters" do
1911 let(:package) { "b.a.r-pkg++1" }
1912 let(:dpkg_s_version) { "1.2.3+3141592-1ubuntu1~lucid" }
1913 exitstatus: 1, stdout: "", stderr: <<~EOF
1914 exitstatus: 0, stderr: "", stdout: <<~EOF
1915 provider.upgrade_package(["wget"], ["1.11.4-1ubuntu1"])
1916 provider.remove_package(["wget"], ["1.11.4-1ubuntu1"])
1917 provider.purge_package(["wget"], ["1.11.4-1ubuntu1"])
1918 let(:path) { "preseed/wget" }
1919 let(:tmp_path) { "/tmp/preseed/wget" }
1920 let(:package_name) { "wget" }
1921 let(:package_version) { "1.11.4" }
1922 let(:response) { "wget.response" }
1923 let(:tmp_preseed_path) { "/tmp/preseed/wget/wget-1.11.4.seed" }
1924 let(:preseed_path) { "/preseed--wget--wget-1.11.4.seed" }
1925 exclude_test = !(%w{rhel fedora amazon}.include?(ohai[:platform_family]) && File.exist?("/usr/bin/dnf"))
1926 expect(helper.compare_versions("0:1.8.29-6.el8.x86_64", "0:1.8.29-6.el8_3.1.x86_64")).to eql(-1)
1927 let(:choco_exe) { "#{choco_install_path}\\bin\\choco.exe" }
1928 allow(provider).to receive(:shell_out_compacted!).with(choco_exe, "list", "-l", "-r", { returns: [0, 2], timeout: timeout }).and_return(local_list_obj)
1929 Git|2.6.1
1930 Git|2.6.2
1931 allow(provider).to receive(:shell_out_compacted!).with(choco_exe, "list", "-r", pkg, *args, { returns: [0, 2], timeout: timeout }).and_return(remote_list_obj)
1932 allow(provider).to receive(:shell_out_compacted!).with(choco_exe, "list", "-r", pkg, { returns: [0, 2], timeout: timeout }).and_return(remote_list_obj)
1933 allow_remote_list(["git"])
1934 allow_remote_list(["vim"])
1935 expect(provider.candidate_version).to eql(["15.10.25.1", "0.9.9.11"])
1936 { "chocolatey" => "0.9.9.11", "conemu" => "15.10.25.0" }
1937 { "chocolatey" => "0.9.9.11", "conemu" => "15.10.25.1", "git" => "2.6.2", "munin-node" => "1.6.1.20130823" }
1938 expect(provider.current_resource.version).to eql(["15.10.25.0", "0.9.9.11"])
1939 expect(provider).to receive(:shell_out_compacted!).with(choco_exe, "install", "-y", "git", { returns: [0, 2], timeout: timeout }).and_return(double)
1940 expect(provider).to receive(:shell_out_compacted!).with(choco_exe, "install", "-y", "--version", "15.10.25.1", "conemu", { returns: [0, 2], timeout: timeout }).and_return(double)
1941 new_resource.version([nil, "15.10.25.1"])
1942 new_resource.version(["15.10.25.1", nil])
1943 expect(provider).to receive(:shell_out_compacted!).with(choco_exe, "install", "-y", "git", "munin-node", { returns: [0, 2], timeout: timeout }).and_return(double)
1944 allow_remote_list(["git"], ["-source", "localpackages"])
1945 expect(provider).to receive(:shell_out_compacted!).with(choco_exe, "install", "-y", "-source", "localpackages", "git", { returns: [0, 2], timeout: timeout }).and_return(double)
1946 expect(provider).to receive(:shell_out_compacted!).with(choco_exe, "install", "-y", "-force", "git", { returns: [0, 2], timeout: timeout }).and_return(double)
1947 allow_remote_list(["git"], ["-source", "auth_source", "--user", "ubuntu", "--password", "ubuntu@123"])
1948 allow_remote_list(["package-invalid-auth"], ["-source", "auth_source", "--user", "ubuntu", "--password", "ubuntu@123"])
1949 allow_remote_list(["git"], ["-source", "auth_source", "--user", "ubuntu", "--password", "ubuntu@123", "--local-only"])
1950 expect(provider).to receive(:shell_out_compacted!).with(choco_exe, "upgrade", "-y", "git", { returns: [0, 2], timeout: timeout }).and_return(double)
1951 expect(provider).to receive(:shell_out_compacted!).with(choco_exe, "upgrade", "-y", "conemu", { returns: [0, 2], timeout: timeout }).and_return(double)
1952 expect(provider).not_to receive(:shell_out_compacted!).with(choco_exe, "upgrade", "-y", "chocolatey", { returns: [0, 2], timeout: timeout })
1953 expect(provider).to receive(:shell_out_compacted!).with(choco_exe, "upgrade", "-y", "--version", "2.6.2", "git", { returns: [0, 2], timeout: timeout })
1954 expect(provider).to receive(:shell_out_compacted!).with(choco_exe, "upgrade", "-y", "conemu", "git", { returns: [0, 2], timeout: timeout }).and_return(double)
1955 expect(provider).to receive(:shell_out_compacted!).with(choco_exe, "uninstall", "-y", "ConEmu", { returns: [0, 2], timeout: timeout }).and_return(double)
1956 expect(provider).to receive(:shell_out_compacted!).with(choco_exe, "uninstall", "-y", "conemu", { returns: [0, 2], timeout: timeout }).and_return(double)
1957 new_resource.source = File.join((ENV["TEMP"]).to_s, "test6.1-kb2664825-v3-x64.cab")
1958 expect(path).to be == File.join((ENV["TEMP"]).to_s, "\\", "Test6.1-KB2664825-v3-x64.cab")
1959 expect(path).to be == File.join((ENV["TEMP"]).to_s, "Test6.1-KB2664825-v3-x64.cab")
1960 expect(path).to be == File.join((ENV["TEMP"].downcase).to_s, "\\", "test6.1-kb2664825-v3-x64.cab")
1961 expect(path).to be == File.join((ENV["TEMP"]).to_s, "test6.1-kb2664825-v3-x64.cab")
1962 @empty_status = double("Status", stdout: "", exitstatus: 0)
1963 expect(@provider).to receive(:shell_out_compacted).with("installp", "-L", "-d", "/tmp/samba.base", timeout: 900).and_return(status)
1964 status = double("Status", stdout: "", exitstatus: 1, format_for_exception: "")
1965 status = double(stdout: "", exitstatus: -1, format_for_exception: "")
1966 @status = double(stdout: "", exitstatus: 1, format_for_exception: "")
1967 expect(@provider).to receive(:shell_out_compacted!).with("installp", "-aYF", "-d", "/tmp/samba.base", "samba.base", timeout: 900)
1968 expect(@provider).to receive(:shell_out_compacted!).with("installp", "-aYF", "-d", "/tmp/samba.base", "/tmp/samba.base", timeout: 900)
1969 @provider.install_package("/tmp/samba.base", "3.3.12.0")
1970 expect(@provider).to receive(:shell_out_compacted!).with("installp", "-aYF", "-e/tmp/installp.log", "-d", "/tmp/samba.base", "samba.base", timeout: 900)
1971 @provider.remove_package("samba.base", "3.3.12.0")
1972 expect(@provider).to receive(:shell_out_compacted!).with("installp", "-u", "-e/tmp/installp.log", "samba.base", timeout: 900)
1973 @run_context = Chef::RunContext.new(node, {}, events)
1974 @stderr = ""
1975 allow(@provider).to receive(:shell_out).with("dpkg", "--compare-versions", "1.6~beta1", "gt", "1.1.0").and_return(so2)
1976 allow(@provider).to receive(:shell_out).with("dpkg", "--compare-versions", "1.0.1ubuntu2", "gt", "1.1.0").and_return(so2)
1977 allow(@provider).to receive(:shell_out).with("dpkg", "--compare-versions", "1.0.1ubuntu2", "eq", "1.1.0").and_return(so2)
1978 candidate_version: "0.8.12-7",
1979 @provider.install_package(["irssi"], ["0.8.12-7"])
1980 @new_resource.options('--force-yes -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confnew"')
1981 expect(@provider).to receive(:install_package).with(["irssi"], ["0.8.12-7"])
1982 @provider.upgrade_package(["irssi"], ["0.8.12-7"])
1983 @provider.remove_package(["irssi"], ["0.8.12-7"])
1984 @provider.purge_package(["irssi"], ["0.8.12-7"])
1985 let(:path) { "preseed/irssi" }
1986 let(:tmp_path) { "/tmp/preseed/irssi" }
1987 let(:package_name) { "irssi" }
1988 let(:package_version) { "1.0.5-1" }
1989 let(:response) { "irssi.response" }
1990 let(:tmp_preseed_path) { "/tmp/preseed/irssi/irssi-1.0.5-1.seed" }
1991 let(:preseed_path) { "/preseed--irssi--irssi-1.0.5-1.seed" }
1992 file = "/tmp/irssi-0.8.12-7.seed"
1993 file = @provider.get_preseed_file("irssi", "0.8.12-7")
1994 @provider.lock_package("irssi", "0.8.12-7")
1995 @provider.unlock_package("irssi", "0.8.12-7")
1996 GUID = "\\\\?\\Volume{578e72b5-6e70-11df-b5c5-000c29d4a7d9}\\".freeze
1997 REMOTE = "\\\\server-name\\path".freeze
1998 @new_resource = Chef::Resource::Mount.new("X:")
1999 @net_use = double("Chef::Util::Windows::NetUse")
2000 @vol = double("Chef::Util::Windows::Volume")
2001 let(:device_type) { :device }
2002 let(:fstype) { "ufs" }
2003 let(:device) { "/dev/dsk/c0t2d0s7" }
2004 let(:fsck_device) { "/dev/rdsk/c0t2d0s7" }
2005 let(:mountpoint) { "/mnt/foo" }
2006 let(:fstype) { ft }
2007 let(:fsck_device) { "-" }
2008 let(:device) { "something_that_is_not_a_file" }
2009 let(:fstype) { "nfs" }
2010 let(:device) { "cartman:/share2" }
2011 let(:mountpoint) { "/cartman" }
2012 let(:target) { "/dev/mapper/target" }
2013 let(:target) { "foo" }
2014 expect(provider).to receive(:shell_out_compacted!).with("mount", "-F", fstype, "-o", "rw", device, mountpoint)
2015 let(:this_mount) { "/dev/dsk/c0t2d0s7\t/dev/rdsk/c0t2d0s7\t/mnt/foo\tufs\t2\tyes\t-
" }
2016 let(:vfstab_file_contents) { [other_mount].join("
") }
2017 let(:this_mount) { "/dev/dsk/c0t2d0s7\t/dev/rdsk/c0t2d0s7\t/mnt/foo\tufs\t2\tno\t-
" }
2018 let(:options) { "noauto" }
2019 let(:vfstab_file_contents) { [existing_mount].join("
") }
2020 let(:options) { "-" }
2021 let(:options) { "-,noauto" }
2022 let(:vfstab_file_contents) { [other_mount, this_mount].join("
") }
2023 let(:vfstab_file_contents) { [other_mount, this_mount, comment].join("
") }
2024 let(:vfstab_file_contents) { [this_mount, other_mount, this_mount].join("
") }
2025 expect(IO.read(vfstab_file.path)).to eql( "#{this_mount}
#{other_mount}
" )
2026 @new_resource = Chef::Resource::Mount.new("/tmp/foo")
2027 allow(::File).to receive(:realpath).with("/dev/sdz1").and_return "/dev/sdz1"
2028 allow(::File).to receive(:realpath).with("/tmp/foo").and_return "/tmp/foo"
2029 allow(::File).to receive(:exist?).with("/etc/fstab").and_return(true)
2030 allow(::File).to receive(:foreach).with("/etc/fstab")
2031 @status = double(stdout: "/dev/sdz1
", exitstatus: 1)
2032 @stdout_findfs = double("STDOUT", first: "/dev/sdz1")
2033 { "nfs" => "nfsserver:/vol/path",
2034 allow(@provider).to receive(:shell_out!).and_return(OpenStruct.new(stdout: "#{fs_spec}/ on /tmp/foo type #{type} (rw)
"))
2035 expect(::File).to receive(:exists?).with("").and_return(false)
2036 target = "xsdz1"
2037 mount = "/dev/sdy1 on #{@new_resource.mount_point} type ext3 (rw)
"
2038 mount << "#{@new_resource.device} on #{@new_resource.mount_point} type ext3 (rw)
"
2039 mount = "#{@new_resource.device} on #{@new_resource.mount_point} type ext3 (rw)
"
2040 mount << "/dev/sdy1 on #{@new_resource.mount_point} type ext3 (rw)
"
2041 fstab = "#{@new_resource.device} #{@new_resource.mount_point} #{@new_resource.fstype} #{options} 1 2
"
2042 fstab = "#{target} #{@new_resource.mount_point} #{@new_resource.fstype} #{options} 1 2
"
2043 expect(@provider).to receive(:shell_out_compacted!).with("mount", "-t", "ext3", "-o", "defaults", "/dev/sdz1", "/tmp/foo")
2044 expect(@provider).to receive(:shell_out_compacted!).with("mount", "-t", "ext3", "-o", "rw,noexec,noauto", "/dev/sdz1", "/tmp/foo")
2045 status = double(stdout: "/dev/sdz1
", exitstatus: 1)
2046 expect(@provider).to receive(:shell_out!).with("umount", "/tmp/foo")
2047 @provider.node.override[:os] = "aix"
2048 allow(::File).to receive(:open).with("/etc/fstab", "a").and_yield(@fstab)
2049 expect(@fstab.string).to match(%r{^/dev/sdz1\s+/tmp/foo\s+ext3\s+defaults\s+0\s+2\s*$})
2050 expect(::File).not_to receive(:open).with("/etc/fstab", "a")
2051 expect(::File).to receive(:open).once.with("/etc/fstab", "w").and_yield(@fstab)
2052 allow(::File).to receive(:open).with("/etc/fstab", "w").and_yield(fstab_write)
2053 allow(::File).to receive(:open).with("/etc/fstab", "w").and_yield(@fstab_write)
2054 allow(::File).to receive(:readlines).with("/etc/fstab").and_return([])
2055 @new_resource = Chef::Resource::Mount.new("/tmp/bar")
2056 allow(::File).to receive(:realpath).with("/tmp/bar").and_return "/tmp/foo"
2057 expect(@fstab.string).to match(%r{^cephserver:6789:/\s+/tmp/bar\s+cephfs\s+defaults\s+0\s+2\s*$})
2058 allow(::File).to receive(:open).with("/etc/fstab", "a").and_yield(fstab_write)
2059 mount = "#{new_resource.mount_point} /dev/sdy1 type ext3 (rw)
"
2060 mount << "#{new_resource.mount_point} #{new_resource.device} type ext3 (rw)
"
2061 mount = "#{new_resource.device} on #{new_resource.mount_point} type ext3 (rw)
"
2062 mount << "/dev/sdy1 on #{new_resource.mount_point} type ext3 (rw)
"
2063 mount = "/tmp/foo //192.168.11.102/Share/backup[/backup] cifs rw
"
2064 losetup = "/dev/loop16 0 0 1 1 /dev/sdz1
"
2065 @mounted_output = <<~MOUNT
2066 @test_wrong_output = <<~WRONG
2067 /tmp/abc:
2068 expect(filesystems.string).to match(%r{^

/tmp/foo:
\tdev\t\t= /dev/sdz1
\tvfs\t\t= jfs2
\tmount\t\t= false
\toptions\t\t= nodev,rw
$})
2069 /tmp/foo:
2070 expect(filesystems.string).to match(%r{^/tmp/abc:\s+dev\s+= /dev/sdz2\s+vfs\s+= jfs2\s+mount\s+= true\s+options\s+= rw
$})
2071 @new_resource.devices ["/dev/sdz1", "/dev/sdz2", "/dev/sdz3"]
2072 allow(@provider).to receive(:shell_out_compacted!).with("mdadm", "--detail", "--test", "/dev/md1", returns: [0, 4]).and_return(OpenStruct.new(status: 0))
2073 allow(@provider).to receive(:shell_out_compacted!).with("mdadm", "--detail", "--test", "/dev/md1", returns: [0, 4]).and_return(OpenStruct.new(status: 4))
2074 expected_command = "yes | mdadm --create /dev/md1 --level 5 --chunk=16 --metadata=0.90 --raid-devices 3 /dev/sdz1 /dev/sdz2 /dev/sdz3"
2075 expected_command = "yes | mdadm --create /dev/md1 --level 5 --chunk=16 --metadata=0.90 --bitmap=grow --raid-devices 3 /dev/sdz1 /dev/sdz2 /dev/sdz3"
2076 expected_command = "yes | mdadm --create /dev/md1 --level 5 --chunk=16 --metadata=0.90 --layout=rs --raid-devices 3 /dev/sdz1 /dev/sdz2 /dev/sdz3"
2077 expected_command = "yes | mdadm --create /dev/md1 --level 1 --metadata=0.90 --raid-devices 3 /dev/sdz1 /dev/sdz2 /dev/sdz3"
2078 expected_mdadm_cmd = "yes | mdadm --stop /dev/md1"
2079 let(:log_str) { "this is my test string to log" }
2080 run_context = Chef::RunContext.new(node, {}, @events)
2081 ChefUtils.windows? ? path.tr("/", "\\") : path
2082 lstat = double("stats", ino: 5)
2083 stat = double("stats", ino: 5)
2084 stat = double("stats", ino: 6)
2085 let(:label) { "call.mom.weekly" }
2086 let(:test_plist) { String.new <<~XML }
2087 \t<key>Label</key>
2088 \t<key>Program</key>
2089 \t<dict>
2090 \t\t<key>Hour</key>
2091 \t\t<key>Weekday</key>
2092 \t</dict>
2093 \t<key>TimeOut</key>
2094 \t<array>
2095 \t\t<dict>
2096 \t\t\t<key>Hour</key>
2097 \t\t\t<key>Weekday</key>
2098 \t\t\t<integer>1</integer>
2099 \t\t</dict>
2100 \t\t\t<integer>2</integer>
2101 \t</array>
2102 allowed = (1..2).collect do |num|
2103 allowed = {
2104 end.to raise_error(/Invalid value.*\(1-2\)/)
2105 @new_resource = Chef::Resource::Ifconfig.new("10.0.0.1", @run_context)
2106 let(:net_tools_version) { StringIO.new <<~EOS }
2107 let(:net_tools_version2) { StringIO.new <<~EOS }
2108 expect(arg).to match(/^\s*DEVICE=eth0\s*$/)
2109 expect(arg).to match(/^\s*IPADDR=10\.0\.0\.1\s*$/)
2110 expect(arg).to match(/^\s*NETMASK=255\.255\.254\.0\s*$/)
2111 expect(arg).to match(/^\s*ETHTOOL_OPTS="-A eth0 autoneg off"\s*$/)
2112 expect(arg).to match(/^\s*MASTER=bond0\s*$/)
2113 expect(arg).to match(/^\s*SLAVE=yes\s*$/)
2114 expect(arg).to match(/^\s*VLAN=yes\s*$/)
2115 let(:current_resource) { Chef::Resource::Ifconfig.new("10.0.0.1", run_context) }
2116 expect(File.read(config_filename_ifcfg)).to match(/^\s+address 10\.0\.0\.1\s*$/)
2117 expect(File.read(config_filename_ifcfg)).to match(/^\s+netmask 255\.255\.254\.0\s*$/)
2118 expect(config_file_ifcfg.string).not_to match(/^\s+address 10\.0\.0\.1\s*$/)
2119 expect(config_file_ifcfg.string).not_to match(/^\s+netmask 255\.255\.254\.0\s*$/)
2120 inet6 ::1%1/0
2121 command = "chdev -l #{@new_resource.device} -a netaddr=#{@new_resource.name}"
2122 command = "chdev -l #{@new_resource.device} -a state=down"
2123 let(:http) do
2124 expect(http).to receive(:get).with("http://www.opscode.com/", {})
2125 expect(http).to receive(:put).with("http://www.opscode.com/", "return", {})
2126 expect(http).to receive(:post).with("http://www.opscode.com/", "return", {})
2127 expect(http).to receive(:delete).with("http://www.opscode.com/", {})
2128 expect(http).to receive(:head).with("http://www.opscode.com/", {}).and_return(nil)
2129 expect(http).to receive(:head).with("http://www.opscode.com/", {}).and_return("")
2130 expect(http).to receive(:head).with("http://www.opscode.com/", { "If-Modified-Since" => if_modified_since }).and_return(false)
2131 @pw_group = double("Struct::Group",
2132 name: "wheel",
2133 gid: 20,
2134 mem: %w{root aj})
2135 expect(@provider.change_desc).to eq([ "change gid #{@current_resource.gid} to #{@new_resource.gid}" ])
2136 expect(@provider.change_desc).to eq([ ])
2137 @new_resource.members([ "us" ])
2138 platforms = {
2139 expect(@provider).to receive(:shell_out_compacted!).with("groupmod", "-U", "all,your,base", "wheel")
2140 expect(@provider).to receive(:shell_out_compacted!).with("usermod", *flags, "+wheel", "all")
2141 expect(@provider).to receive(:shell_out_compacted!).with("usermod", *flags, "+wheel", "your")
2142 expect(@provider).to receive(:shell_out_compacted!).with("usermod", *flags, "+wheel", "base")
2143 expect(@provider).to receive(:shell_out_compacted!).with("usermod", *flags, "-wheel", "are")
2144 expect(@provider).to receive(:shell_out_compacted!).with("usermod", *flags, "-wheel", "to")
2145 expect(@provider).to receive(:shell_out_compacted!).with("usermod", *flags, "-wheel", "us")
2146 expect(@provider.set_options).to eql(["wheel", "-g", 42])
2147 expect(@provider).to receive(:shell_out_compacted!).with("pw", "groupadd", "wheel", "-g", "23", "-M", "root,aj").and_return(true)
2148 expect(@provider).to receive(:shell_out_compacted!).with("pw", "groupmod", "wheel", "-g", "42", "-m", "someone").and_return(true)
2149 expect(@provider).to receive(:shell_out_compacted!).with("pw", "groupmod", "wheel", "-g", "42", "-d", "root,aj").and_return(true)
2150 expect(@provider.set_members_options).to eql([ ["-d", "all,your,base"] ])
2151 expect(@provider.set_members_options).to eql([[ "-m", "all,your,base" ]])
2152 expect(@provider).to receive(:shell_out_compacted!).with("group", "mod", "-n", "wheel_bak", "wheel")
2153 expect(@provider).to receive(:shell_out_compacted!).with("group", "add", "-g", "123", "-o", "wheel")
2154 expect(@provider).to receive(:shell_out_compacted!).with("user", "mod", "-G", "wheel", "lobster")
2155 expect(@provider).to receive(:shell_out_compacted!).with("group", "add", "-g", "123", "wheel")
2156 expect(@provider).to receive(:shell_out_compacted!).with("user", "mod", "-G", "wheel", "rage")
2157 expect(@provider).to receive(:shell_out_compacted!).with("user", "mod", "-G", "wheel", "fist")
2158 Chef::Resource::Group.new("aj").tap do |r|
2159 gid: "-g",
2160 match_array = []
2161 match_array << "aj"
2162 before { node.automatic["platform"] = "solaris2" }
2163 expect { provider.send(m, [ ]) }.to raise_error(Chef::Exceptions::Group, "you must override #{m} in #{provider}")
2164 expect(@provider).to receive(:shell_out_compacted!).with("gpasswd", "-M", "", "wheel")
2165 expect(@provider).to receive(:shell_out_compacted!).with("gpasswd", "-M", "lobster,rage,fist", "wheel")
2166 expect(@provider).to receive(:shell_out_compacted!).with("gpasswd", "-a", "lobster", "wheel")
2167 expect(@provider).to receive(:shell_out_compacted!).with("gpasswd", "-a", "rage", "wheel")
2168 expect(@provider).to receive(:shell_out_compacted!).with("gpasswd", "-a", "fist", "wheel")
2169 @status = double(stdout: "
", stderr: "", exitstatus: 0)
2170 expect(@provider).to receive(:shell_out_compacted).with("dscl", ".", "-cmd", "/Path", "arg1", "arg2")
2171 @provider.dscl("cmd", "/Path", "arg1", "arg2")
2172 expect(dscl_retval).to eq(["dscl . -cmd /Path args", @status, "
", ""])
2173 allow(@provider).to receive(:dscl).and_return(["cmd", @status, "stdout", "stderr"])
2174 expect(@provider).to receive(:dscl).with(*"cmd /Path args".split(" "))
2175 @provider.safe_dscl(*"cmd /Path args".split(" "))
2176 safe_dscl_retval = @provider.safe_dscl(*"delete /Path args".split(" "))
2177 allow(@provider).to receive(:dscl).and_return(["cmd", @status, "No such key: ", "stderr"])
2178 safe_dscl_retval = @provider.safe_dscl(*"cmd /Path args".split(" "))
2179 expect(@provider).to receive(:safe_dscl).with(*"list /Groups gid".split(" "))
2180 expect(@provider).to receive(:safe_dscl).with("create", "/Groups/aj", "GroupMembers", "").and_return(true)
2181 expect(@provider).to receive(:safe_dscl).with(*"create /Groups/aj Password *".split(" "))
2182 expect(@provider).to receive(:safe_dscl).with(*"create /Groups/aj".split(" "))
2183 @output = <<~EOF
2184 allow(@provider).to receive(:safe_dscl).with(*"read /Groups/aj".split(" ")).and_return(@output)
2185 Chef::Log.level = :info
2186 @resource = Chef::Resource::Git.new("web2.0 app")
2187 expect(::File).to receive(:exist?).with("/my/deploy/dir/.git").and_return(false)
2188 expect(::File).to receive(:exist?).with("/my/deploy/dir/.git").and_return(true)
2189 @stdout = ""
2190 .with("git --version", log_tag: "git[web2.0 app]")
2191 @git_ls_remote = "git ls-remote \"git://github.com/opscode/chef.git\" "
2192 expect(@provider).to receive(:shell_out!).with(@git_ls_remote + "\"v1.0*\"", { log_tag: "git[web2.0 app]" }).and_return(double("ShellOut result", stdout: @stdout))
2193 expect(@provider).to receive(:shell_out!).with(@git_ls_remote + "\"refs/pulls/v1.0*\"", { log_tag: "git[web2.0 app]" }).and_return(double("ShellOut result", stdout: @stdout))
2194 expect(@provider).to receive(:shell_out!).with(@git_ls_remote + "\"refs/heads/v1.0*\"", { log_tag: "git[web2.0 app]" }).and_return(double("ShellOut result", stdout: @stdout))
2195 expect(@provider).to receive(:shell_out!).with(@git_ls_remote + "\"0.8-alpha*\"", { log_tag: "git[web2.0 app]" }).and_return(double("ShellOut result", stdout: @stdout))
2196 expect(@provider).to receive(:shell_out!).with(@git_ls_remote + "\"HEAD\"", { log_tag: "git[web2.0 app]" }).and_return(double("ShellOut result", stdout: @stdout))
2197 let(:expected_cmd) { 'git clone "git://github.com/opscode/chef.git" "/my/deploy/dir"' }
2198 environment: { "GIT_SSH" => wrapper, "HOME" => "/home/deployNinja" },
2199 log_tag: "git[web2.0 app]",
2200 let(:seconds) { 10 }
2201 { "HOME" => "/home/masterNinja" }
2202 environment: { "GIT_SSH" => wrapper, "HOME" => "/home/masterNinja" },
2203 user: 123,
2204 environment: { "HOME" => "/home/deployNinja" },
2205 environment: { "HOME" => "/home/masterNinja" },
2206 environment: { "HOME" => "/home/deployNinja",
2207 expected_cmd = "git clone --depth 5 \"git://github.com/opscode/chef.git\" \"/my/deploy/dir\""
2208 expected_cmd = "git clone --depth 5 --no-single-branch \"git://github.com/opscode/chef.git\" \"/my/deploy/dir\""
2209 expected_cmd = "git clone -o opscode \"git://github.com/opscode/chef.git\" \"/my/deploy/dir\""
2210 log_tag: "git[web2.0 app]").ordered
2211 log_tag: "git[web2.0 app]")
2212 expect(@provider).to receive(:shell_out!).with(expected_cmd, cwd: "/my/deploy/dir", log_tag: "git[web2.0 app]")
2213 expect(@provider).to receive(:shell_out!).with(expected_cmd1, cwd: "/my/deploy/dir", log_tag: "git[web2.0 app]")
2214 expect(@provider).to receive(:shell_out!).with(expected_cmd2, cwd: "/my/deploy/dir", log_tag: "git[web2.0 app]")
2215 expect(@provider).to receive(:shell_out!).with(expected_cmd3, cwd: "/my/deploy/dir", log_tag: "git[web2.0 app]")
2216 user: "whois", group: "thisis",
2217 environment: { "HOME" => "/home/whois" })
2218 expect(@provider).to receive(:shell_out!).with(fetch_command1, cwd: "/my/deploy/dir", log_tag: "git[web2.0 app]")
2219 expect(@provider).to receive(:shell_out!).with(fetch_command2, cwd: "/my/deploy/dir", log_tag: "git[web2.0 app]")
2220 expect(@provider).to receive(:shell_out!).with(fetch_command3, cwd: "/my/deploy/dir", log_tag: "git[web2.0 app]")
2221 cwd: "/my/deploy/dir",
2222 user: "whois",
2223 group: "thisis",
2224 environment: { "HOME" => "/home/whois" },
2225 it "adds a new remote " do
2226 allow(::File).to receive(:exist?).with("/my/deploy/dir/.git").and_return(false)
2227 allow(::Dir).to receive(:entries).with("/my/deploy/dir").and_return([".", ".."])
2228 allow(::Dir).to receive(:entries).with("/my/deploy/dir").and_return(["..", "."])
2229 expect(@provider).not_to receive(:shell_out!).with("huzzah!", cwd: "/my/deploy/dir")
2230 allow(new_resource).to receive(:content).and_return("Do do do do, do do do do, do do do do, do do do do")
2231 let(:opts) do
2232 Chef::Log.level = :warn
2233 ["1.0", "2.0", "3.0"].each do |version|
2234 let(:resource_result) { double("PowerShell", result: { "InDesiredState" => true }, verbose: ["description"]) }
2235 let(:resource_records) { [] }
2236 .and_return(double(result: { "RebootRequired" => true }))
2237 .and_return(double(stdout: "", result: {}))
2238 let(:resource_records) { [{}] }
2239 let(:resource_records) { [{ "Module" => { "Name" => "ModuleName" } }] }
2240 { "Module" => { "Name" => "ModuleName1", "Version" => "1.0.0.0" } },
2241 { "Module" => { "Name" => "ModuleName1", "Version" => "2.0.0.0" } },
2242 [:run].each do |action|
2243 expect(response).to be == "@{ModuleName='my_module';ModuleVersion='1.3.1'}"
2244 let(:tmp_dir) { Dir.mktmpdir }
2245 let(:dir_stat) { File::Stat.new(tmp_dir) }
2246 let(:expected_uid) { dir_stat.uid }
2247 let(:expected_gid) { dir_stat.gid }
2248 let(:expected_mode) { "0%o" % ( dir_stat.mode & 007777 ) }
2249 before { Chef::Config[:why_run] = true }
2250 after { Chef::Config[:why_run] = false }
2251 expect(File.exist?("#{tmp_dir}/foobar")).to be true
2252 allow(Dir).to receive(:mkdir).and_return([true], [])
2253 0 2 * * * /some/other/command
2254 2 * 1 * * /bin/false
2255 expect(cron.path).to eq("/bin:/foo")
2256 expect(cron.home).to eq("/home/foo")
2257 expect(cron.environment).to eq({ "TEST" => "lol", "FLAG" => "1" })
2258 21 */4 * * * some_prog 1234567
2259 expect(cron.minute).to eq("*")
2260 expect(cron.hour).to eq("5")
2261 expect(cron.day).to eq("*")
2262 expect(cron.month).to eq("1")
2263 expect(cron.weekday).to eq("*")
2264 expect(cron.hour).to eq("*")
2265 expect(cron.month).to eq("*")
2266 30 * * * * /bin/true
2267 30 * * 3 * /bin/true
2268 1 1 1 1 1 /bin/true
2269 @new_resource.hour("1")
2270 @new_resource.day("1")
2271 @new_resource.environment = { "SHELL" => "/bash", "ENV" => "environment" }
2272 @new_resource.environment = { "ENV" => "environment" }
2273 expect(@provider).to receive(:shell_out!).with("crontab -l -u #{@new_resource.user}", returns: [0, 1]).and_return(@status)
2274 @status = double("Status", exitstatus: 1, stdout: "")
2275 expect(@provider).to receive(:shell_out!).with("crontab -u #{@new_resource.user} -", input: "Foo").and_return(@status)
2276 let(:mailto) { "foo@example.com" }
2277 expect(@provider.send(:duration_str)).to eq("1 * * * *")
2278 expect(@provider.send(:duration_str)).to eq("1 2 3 4 5")
2279 let(:time_out_str_val) { " timeout 10;" }
2280 @new_resource.time_out "duration" => "10"
2281 @new_resource.time_out "duration" => "10", "foreground" => "true", "signal" => "FOO"
2282 expect(@provider.send(:cmd_str)[-1]).to eq("
")
2283 expect(@provider.send(:cmd_str)).to eq(" bin/true
")
2284 expect(@provider.send(:cmd_str)).to eq("
")
2285 let(:username) { "root" }
2286 let(:exitstatus) { 0 }
2287 let(:stderr) { "" }
2288 let(:exitstatus) { 1 }
2289 let(:exitstatus) { 2 }
2290 let(:stdout) { "" }
2291 let(:tempfile) { double("foo", path: "/tmp/foo", close: true) }
2292 expect(tempfile).to have_received(:<<).with("Foo
# wibble
wah!!")
2293 let(:basepath) { "C:\\Windows\\system32\\" }
2294 let(:interpreter) { File.join(basepath, "cmd.exe") }
2295 expect(command).to eq(%Q{"#{interpreter}" /f /c "#{script_file_path}"})
2296 let(:config_dir) { Dir.mktmpdir("apt_update_apt_conf_d") }
2297 let(:apt_update_cmd) { %w{apt-get -q update} }
2298 expect(File.read(config_file)).to match(/^APT::Update.*#{stamp_dir}/)
2299 describe "#is_key_id?" do
2300 let(:file) { "/tmp/remote-gpg-keyfile" }
2301 .with("gpg", "--with-fingerprint", "--with-colons", file)
2302 expect(provider.keyserver_install_cmd("ABC", "gpg.mit.edu")).to eq("apt-key adv --no-tty --recv --keyserver hkp://gpg.mit.edu:80 ABC")
2303 expect(provider.keyserver_install_cmd("ABC", "hkp://gpg.mit.edu")).to eq("apt-key adv --no-tty --recv --keyserver hkp://gpg.mit.edu ABC")
2304 let(:url) { "https://launchpad.net/api/1.0/~chef/+archive/main" }
2305 it "gets a key" do
2306 allow(simples).to receive(:get).and_return("\"#{key}\"")
2307 expect(provider.build_repo("http://test/uri", "unstable", "main", false, nil)).to eql(target)
2308 expect(provider.build_repo("http://test/uri", nil, "main", false, nil)).to eql(target)
2309 expect(provider.build_repo("http://test/uri", "unstable", "main", false, nil, true)).to eql(target)
2310 expect(provider.build_repo("http://test/uri", "unstable", "main", true, nil)).to eql(target)
2311 let(:pref_dir) { Dir.mktmpdir("apt_pref_d") }
2312 new_resource.pin = "1.0.1"
2313 @i = 0
2314 @current_index += 1
2315 return "<nothing>" if values.size == 0
2316 tags_index = properties.find_index { |p| !p.is_a?(String) }
2317 tags = []
2318 resource_class.class_eval("property #{property_str}", __FILE__, __LINE__)
2319 it "can be set" do
2320 it "nil does a set" do
2321 it "can be set with =" do
2322 it "can be set to nil with =" do
2323 it "can be updated with =" do
2324 it "y is there" do
2325 expect(subresource.x = "20").to eq "20"
2326 with_property ":x, default: lazy { 10 }" do
2327 it "when x is set, property_is_set?(:x) is true" do
2328 it "when x is set with =, property_is_set?(:x) is true" do
2329 it "when x is set to a lazy value, property_is_set?(:x) is true" do
2330 resource.x lazy { 10 }
2331 it "when x is not set, it returns 10" do
2332 resource.instance_eval { @x = nil }
2333 with_property ":x, default: 1, identity: true", ":y, default: 2, identity: true" do
2334 with_property ":x, default: ''" do
2335 it "when x is not set, it returns ''" do
2336 resource.x << "foo"
2337 expect(resource_class.new("other").x).to eq ""
2338 with_property ":x, default: lazy { '' }" do
2339 with_property ":x, default: {}" do
2340 it "when x is not set, it returns {}" do
2341 expect(resource.x).to eq({})
2342 resource.x["plants"] = "zombies"
2343 expect(resource.x).to eq({ "plants" => "zombies" })
2344 expect(resource_class.new("other").x).to eq({})
2345 with_property ":x, default: lazy { {} }" do
2346 expect(value).to eq({})
2347 with_property ":x, default: [{foo: 'bar'}]" do
2348 it "when x is not set, it returns [{foo: 'bar'}]" do
2349 expect(resource.x).to eq([{ foo: "bar" }])
2350 resource.x[0][:foo] << "baz"
2351 expect(resource.x).to eq([{ foo: "barbaz" }])
2352 expect(resource_class.new("other").x).to eq([{ foo: "bar" }])
2353 with_property ":x, default: lazy { blah }" do
2354 with_property ':x, default: lazy { |x| "#{blah}#{x.blah}" }' do
2355 expect(resource.x "hi").to eq "hi"
2356 with_property ":x, default: lazy { Namer.next_index.to_s }, is: proc { |v| Namer.next_index; true }" do
2357 with_property ":x, default: lazy { Namer.next_index.to_s.freeze }, is: proc { |v| Namer.next_index; true }" do
2358 with_property ':x, coerce: proc { |v| "#{v}#{next_index}" }, default: 10' do
2359 expect(resource.x "hi").to eq "hi1"
2360 with_property ':x, coerce: proc { |v| "#{v}#{next_index}".freeze }, default: 10' do
2361 with_property ':x, coerce: proc { |v| "#{v}#{next_index}" }, default: lazy { 10 }' do
2362 with_property ':x, coerce: proc { |v| "#{v}#{next_index}".freeze }, default: lazy { "10" }' do
2363 with_property ':x, proc { |v| Namer.next_index; true }, coerce: proc { |v| "#{v}#{next_index}" }, default: lazy { 10 }' do
2364 with_property ':x, String, coerce: proc { |v| "#{v}#{next_index}" }, default: 10' do
2365 with_property ':x, Integer, coerce: proc { |v| "#{v}#{next_index}" }, default: 10' do
2366 with_property ':x, String, coerce: proc { |v| "#{v}#{next_index}" }, default: lazy { 10 }' do
2367 with_property ':x, Integer, coerce: proc { |v| "#{v}#{next_index}" }, default: lazy { 10 }' do
2368 l = lazy { Namer.next_index }
2369 it 'retrieving lazy { |x| "#{blah}#{x.blah}" } gets the example and instance variables' do
2370 resource.x lazy { |x| "#{blah}#{x.blah}" }
2371 l = lazy { |x| "#{blah}#{x.blah}" }
2372 with_property ':x, coerce: proc { |v| "#{v}#{Namer.next_index}" }' do
2373 with_property ":x, is: proc { |v| Namer.next_index; true }" do
2374 with_property ':x, Integer, coerce: proc { |v| "#{v}#{Namer.next_index}" }' do
2375 with_property ':x, coerce: proc { |v| "#{v}#{Namer.next_index}" }, is: proc { |v| Namer.next_index; true }' do
2376 with_property ':x, String, coerce: proc { |v| "#{v}#{Namer.next_index}" }' do
2377 with_property ":x, coerce: proc { |x| x }" do
2378 with_property ':x, coerce: proc { |x| Namer.next_index; raise "hi" if x == 10; x }, is: proc { |x| Namer.next_index; x != 10 }' do
2379 with_property ":x, is: proc { |v| Namer.next_index; v.is_a?(Integer) }" do
2380 with_property ":x, #{name}: true" do
2381 with_property ":x, #{name}: false" do
2382 with_property ":x, #{name}: nil" do
2383 it "emits an error for property :x, default: 10, #{name}: true" do
2384 it "emits an error for property :x, default: nil, #{name}: true" do
2385 it "emits an error for property :x, #{name}: true, default: 10" do
2386 it "emits an error for property :x, #{name}: true, default: nil" do
2387 property_type(is: %i{a b}, default: :c)
2388 property_type(is: %i{a b}, default: :b)
2389 context "With property_type ABType (is: [:a, :b]) and CDType (is: [:c, :d])" do
2390 ABType = property_type(is: %i{a b})
2391 CDType = property_type(is: %i{c d})
2392 expect(resource.x :a).to eq(:a)
2393 expect(resource.x :c).to eq(:c)
2394 resource_class.class_eval(property_str, __FILE__, __LINE__)
2395 with_property ":x, #{validation}", *tags do
2396 it "value #{v.inspect} is valid" do
2397 resource.instance_eval { @x = "default" }
2398 with_property ":x, #{validation}, default: nil" do
2399 expect { resource_class.class_eval("property :x, #{validation}, default: nil", __FILE__, __LINE__) }.not_to raise_error
2400 expect(resource.x "str").to eq "str"
2401 it "set to nil does a set" do
2402 with_property ":x, [ String, nil ]" do
2403 it "set(nil) does a set" do
2404 [ "hi" ],
2405 [ 10 ]
2406 [ :a ],
2407 [ :b ]
2408 validation_test ":a, is: :b",
2409 %i{a b},
2410 [ :c ]
2411 validation_test ":a, is: [ :b, :c ]",
2412 %i{a b c},
2413 [ :d ]
2414 validation_test "[ :a, :b ], is: :c",
2415 validation_test "[ :a, :b ], is: [ :c, :d ]",
2416 %i{a b c d},
2417 [ :e ]
2418 [ ],
2419 validation_test "[ nil ]",
2420 validation_test "[]",
2421 [],
2422 [ :a ]
2423 validation_test "[ String, nil ], nillable: true",
2424 [ nil, "thing" ],
2425 [ :nope, false ],
2426 [ "a", "" ],
2427 [ :a, 1 ]
2428 validation_test "is: :a",
2429 validation_test "is: [ :a, :b ]",
2430 [ %i{a b} ]
2431 validation_test "is: [ [ :a, :b ] ]",
2432 [ %i{a b} ],
2433 %i{a b}
2434 validation_test "is: /abc/",
2435 [ "", "abac" ]
2436 validation_test "is: Chef::Property.new(is: :a)",
2437 [ 10 ],
2438 [ 1 ]
2439 validation_test "is: proc { |x| x }",
2440 [ true, 1 ],
2441 [ false ],
2442 validation_test "is: proc { |x| x > blah }",
2443 [ -1 ],
2444 [ "a" ],
2445 validation_test "is: [ String, nil ]",
2446 [ :b ],
2447 validation_test "is: []",
2448 validation_test 'kind_of: String, equal_to: "a"',
2449 [ "b" ],
2450 validation_test "equal_to: [ :a, :b ]",
2451 validation_test "equal_to: [ [ :a, :b ] ]",
2452 validation_test 'equal_to: [ "a", nil ]',
2453 validation_test 'equal_to: [ nil, "a" ]',
2454 validation_test "equal_to: []",
2455 validation_test "kind_of: [ String, Symbol ]",
2456 [ "a", :b ],
2457 [ 1 ],
2458 validation_test "kind_of: [ Symbol, String ]",
2459 validation_test "kind_of: []",
2460 [ "xabcy" ],
2461 [ "gbh", 123 ],
2462 validation_test "regex: [ /abc/, /z/ ]",
2463 %w{xabcy aza},
2464 validation_test "regex: [ /z/, /abc/ ]",
2465 validation_test "regex: [ [ /z/, /abc/ ], [ /n/ ] ]",
2466 %w{xabcy aza ana},
2467 validation_test "regex: []",
2468 validation_test 'callbacks: { "a" => proc { |x| x > 10 }, "b" => proc { |x| x%2 == 0 } }',
2469 [ 12 ],
2470 [ 11, 4 ],
2471 validation_test 'callbacks: { "a" => proc { |x| x%2 == 0 }, "b" => proc { |x| x > 10 } }',
2472 validation_test 'callbacks: { "a" => proc { |x| x.nil? } }',
2473 validation_test "respond_to: [ :split, :to_s ]",
2474 validation_test "respond_to: [ :to_s, :split ]",
2475 validation_test "respond_to: []",
2476 [ 1, [1, 2], { a: 10 } ],
2477 [ [] ],
2478 validation_test "cannot_be: [ :empty, :nil ]",
2479 validation_test 'cannot_be: [ "empty", "nil" ]',
2480 validation_test "cannot_be: [ :nil, :empty ]",
2481 validation_test "cannot_be: [ :empty, :nil, :blahblah ]",
2482 validation_test "cannot_be: []",
2483 with_property ":x, required: %i{doit}" do
2484 it "value '1' is valid" do
2485 expect(resource.x "1").to eq "1"
2486 with_property ":x, [String, nil], required: true" do
2487 it "value '2' is valid" do
2488 expect(resource.x "2").to eq "2"
2489 with_property ":x, String, default: '1'" do
2490 with_property ":x, [ String, nil ] , default: '1'" do
2491 if _pv_opts_lookup(opts, key) != value
2492 it "value '1' is invalid" do
2493 expect(resource.x "woo").to eq "woo"
2494 expect(subresource.identity).to eq(x: "foo", y: "bar")
2495 it "y is part of state" do
2496 @blarghle ? @blarghle * 3 : nil
2497 @blarghle = x * 2
2498 with_property ":x, identity: true, default: 'xxx'",
2499 expect(resource.identity).to eq(x: "foo", y: "bar", z: "baz")
2500 expect(resource.identity).to eq(x: "xxx", y: "yyy", z: "zzz")
2501 with_property ":x", ":y", ":z" do
2502 with_property ":x", ":y, desired_state: false", ":z, desired_state: true" do
2503 with_property ":x, default: 1" do
2504 @blah * 3
2505 def x=(value)
2506 @blah = value * 2
2507 let(:node_name) { "joe_node" }
2508 let(:ohai_data) { { "platform" => "ubuntu", "platform_version" => "13.04", "fqdn" => "joenode.example.com" } }
2509 let(:json_attribs) { { "custom_attr" => "custom_attr_value" } }
2510 let(:override_runlist) { nil }
2511 major = sha1_id[0...14]
2512 minor = sha1_id[14...28]
2513 patch = sha1_id[28..40]
2514 decimal_integers = [major, minor, patch].map { |hex| hex.to_i(16) }
2515 before { Chef::Config[:solo_legacy_mode] = true }
2516 let(:override_runlist) { "recipe[foo],recipe[bar]" }
2517 before { Chef::Config[:environment] = "blurch" }
2518 let(:api_service) { double("Chef::ServerAPI") }
2519 let(:primary_runlist) { nil }
2520 let(:original_default_attrs) { { "default_key" => "default_value" } }
2521 let(:original_override_attrs) { { "override_key" => "override_value" } }
2522 expected = [
2523 parsed_policyfile_json["run_list"] = ["role[foo]"]
2524 parsed_policyfile_json["run_list"] = ["recipe[foo]"]
2525 ["recipe[test::default]",
2526 id: "_policy_node",
2527 run_list: [
2528 { type: "recipe", name: "test::default", skipped: false, version: nil },
2529 { type: "recipe", name: "test::other", skipped: false, version: nil },
2530 let(:extra_chef_config) { {} }
2531 p["named_run_lists"] = {
2532 expect(node[:roles]).to eq( [] )
2533 expect(node[:recipes]).to eq( ["example1::default"] )
2534 let(:override_runlist) { [ "recipe[example2::server]" ] }
2535 expect( node["top_level_attr"] ).to eql("hat")
2536 expect( node["baseline_attr"]["one"] ).to eql(1)
2537 expect( node["baseline_attr"]["two"] ).to eql(2)
2538 expect( node["baseline_attr"]["deep"]["three"] ).to eql(333)
2539 expect( node["baseline_attr"]["deep"]["four"] ).to eql([4])
2540 expect( node["baseline_attr"]["deep"]["five"] ).to eql([5])
2541 expect( node["top_level_attr"] ).to eql("cat")
2542 expect( node["baseline_attr"]["one"]).to eql(111)
2543 expect( node["baseline_attr"]["deep"]["four"] ).to eql([444])
2544 let(:json_attribs) { { "run_list" => [ "recipe[something::default]" ] } }
2545 let(:json_attribs) { { "run_list" => [] } }
2546 let(:override_runlist) { "recipe[foo::default]" }
2547 let(:node) { Chef::Node.new.tap { |n| n.name(node_name) } }
2548 it "has a node_name" do
2549 node.run_list(["recipe[a::default]", "recipe[b::server]"])
2550 let(:json_attribs) { nil }
2551 let(:primary_runlist) { ["recipe[primary::default]"] }
2552 expect(node["fqdn"]).to eq(ohai_data["fqdn"])
2553 let(:primary_runlist) { ["role[some_role]"] }
2554 let(:json_attribs) { { "run_list" => ["recipe[json_attribs::default]"], "json_attribs_key" => "json_attribs_value" } }
2555 environment = Chef::Environment.new.tap { |e| e.name("prod") }
2556 let(:chef_http) { double("Chef::ServerAPI") }
2557 let(:cookbook_resolve_post_data) { { run_list: ["first::default", "second::default"] } }
2558 let(:node) { base_node }
2559 let(:json_attribs) { {} }
2560 let(:json_attribs) { { "foo" => "bar" } }
2561 let(:json_attribs) { { "policy_name" => "example-policy", "policy_group" => "testing" } }
2562 ["1.0", "2.0", "3.0", "4.0", "5.0.10017.9"].each do |version|
2563 let(:node) { instance_double("Chef::Node") }
2564 let(:org) { Chef::Org.new("an_org") }
2565 it "is a Chef::Org" do
2566 expect(org.name).to eq("sg1")
2567 let(:json) do
2568 expect(json).to match(/^\{.+\}$/)
2569 expect(json).to include(%q{"name":"black"})
2570 let(:org) do
2571 o = { "name" => "turtle",
2572 r = double("rest")
2573 o = Chef::Org.new("foobar")
2574 let(:response) { { "foobar" => "http://www.example.com/organizations/foobar" } }
2575 let(:inflated_response) { { "foobar" => org } }
2576 expect(rest).to receive(:post).with("organizations", { name: "foobar", full_name: "foo bar bat" }).and_return({})
2577 expect(rest).to receive(:get).with("organizations/foobar").and_return({ "name" => "foobar", "full_name" => "foo bar bat", "private_key" => "private" })
2578 org = Chef::Org.load("foobar")
2579 expect(rest).to receive(:put).with("organizations/foobar", { name: "foobar", full_name: "foo bar bat" }).and_return({})
2580 let(:org) { Chef::Org.new("myorg") }
2581 @rest = double("rest")
2582 .and_return({ anything: "goes" })
2583 node = Chef::Node.build("solo-node")
2584 n1 = Chef::Node.build("alpha")
2585 n2 = Chef::Node.build("beta")
2586 n3 = Chef::Node.build("omega")
2587 expect([n3, n1, n2].sort).to eq([n1, n2, n3])
2588 n1 = Chef::Node.build("foo")
2589 n2 = Chef::Node.build("foo")
2590 n3 = Chef::Node.build("bar")
2591 expect(n1).to eq(n2)
2592 n = Chef::Node.new
2593 it "should not accept name doesn't match /^[\-[:alnum:]_:.]+$/" do
2594 node.normal["battles"]["people"]["wonkey"] = true
2595 expect(node["battles"]["people"].attribute?("wonkey")).to eq(true)
2596 node.default["h4sh"] = { foo: "bar" }
2597 node.default["array"] = []
2598 node.default["h4sh"] = {}
2599 node.normal[:snoopy][:is_a_puppy] = true
2600 expect(node[:snoopy][:is_a_puppy]).to eq(true)
2601 node.attributes.normal = { snoopy: { is_a_puppy: nil } }
2602 node.normal[:snoopy][:is_a_puppy] = "what"
2603 node.normal["tags"] = %w{one two}
2604 node.tag("three", "four")
2605 expect(node["tags"]).to eq(%w{one two three four})
2606 node.normal["a"]["r1"] = nil
2607 node.consume_attributes({ "a" => { "r2" => nil } })
2608 expect(node["a"]["r1"]).to be_nil
2609 expect(node["a"]["r2"]).to be_nil
2610 node.default[:snoopy][:is_a_puppy] = "what"
2611 node.env_default["a"]["r1"]["g"]["u"] = "u1"
2612 node.default_unless["a"]["r1"]["g"]["r"] = "r"
2613 expect(node["a"]["r1"]["g"]["u"]).to eql("u1")
2614 node.default_unless["foo"]["bar"] = "NK-19V"
2615 expect(node["foo"]["bar"]).to eql("NK-19V")
2616 node.default_unless["foo"]["baz"] = "NK-33"
2617 expect(node["foo"]["baz"]).to eql("NK-33")
2618 node.normal_unless["foo"]["bar"] = "NK-19V"
2619 node.normal_unless["foo"]["baz"] = "NK-33"
2620 node.override_unless["foo"]["bar"] = "NK-19V"
2621 node.override_unless["foo"]["baz"] = "NK-33"
2622 node.role_default["mysql"]["server"]["port"] = 1234
2623 node.normal["mysql"]["server"]["port"] = 2345
2624 node.override["mysql"]["server"]["port"] = 3456
2625 expect( node.rm("mysql", "server", "port") ).to eql(3456)
2626 expect( node["mysql"]["server"]["port"] ).to be_nil
2627 expect( node["mysql"]["server"] ).to eql({})
2628 node.default["mysql"]["client"]["client_setting"] = "foo"
2629 expect( node.rm("mysql", "server") ).to eql( { "port" => 3456 } )
2630 expect( node["mysql"] ).to eql( { "client" => { "client_setting" => "foo" } } )
2631 expect( node.rm("no", "such", "thing") ).to be_nil
2632 expect( node.rm("mysql") ).to eql({ "server" => { "port" => 3456 } })
2633 expect( node.rm("mysql", "server", "port") ).to eql(nil)
2634 expect( node.rm("mysql", "server") ).to eql(nil)
2635 expect( node.rm("mysql") ).to eql(true)
2636 node.role_default["mysql"]["server"][0]["port"] = 1234
2637 node.normal["mysql"]["server"][0]["port"] = 2345
2638 node.override["mysql"]["server"][0]["port"] = 3456
2639 node.override["mysql"]["server"][1]["port"] = 3456
2640 expect( node.rm("mysql", "server", 0, "port") ).to eql(3456)
2641 expect( node["mysql"]["server"][0]["port"] ).to be_nil
2642 expect( node["mysql"]["server"][1]["port"] ).to eql(3456)
2643 node.role_default["mysql"]["server"] = [ {
2644 } ]
2645 node.normal["mysql"]["server"] = [ {
2646 node.override["mysql"]["server"] = [ {
2647 node.rm("mysql", "server", "port")
2648 expect(node["mysql"]["server"][0]["port"]).to eql(3456)
2649 node.default["mysql"]["server"]["port"] = 2345
2650 node.force_default["mysql"]["server"]["port"] = 3456
2651 expect( node.rm_default("mysql", "server", "port") ).to eql(3456)
2652 expect( node["mysql"]["server"]["port"] ).to eql(nil)
2653 expect( node.default_attrs["mysql"]["server"]["port"] ).to eql({})
2654 expect( node.rm_default("mysql", "server", "port") ).to eql(nil)
2655 expect( node.rm_default("mysql", "server") ).to eql(nil)
2656 node.override["mysql"]["server"]["port"] = 9999
2657 expect( node["mysql"]["server"]["port"] ).to eql(9999)
2658 node.role_override["mysql"]["server"]["port"] = 9876
2659 node.force_override["mysql"]["server"]["port"] = 6669
2660 expect( node.rm_override("mysql", "server", "port") ).to eql(6669)
2661 expect( node["mysql"]["server"]["port"] ).to eql(2345)
2662 expect( node.override_attrs["mysql"]["server"]["port"] ).to eql({})
2663 expect( node.rm_default("no", "such", "thing") ).to be_nil
2664 expect( node.rm_normal("no", "such", "thing") ).to be_nil
2665 expect( node.rm_override("no", "such", "thing") ).to be_nil
2666 node.default!["mysql"]["server"] = { "data_dir" => "/my_raid_volume/lib/mysql" }
2667 expect( node["mysql"]["server"] ).to eql({ "data_dir" => "/my_raid_volume/lib/mysql" })
2668 node.default["mysql"]["server"]["service_name"] = "fancypants-sql"
2669 expect( node["mysql"]["server"]["port"] ).to eql(3456)
2670 expect( node["mysql"]["server"]["service_name"] ).to be_nil
2671 expect( node["mysql"]["server"]["data_dir"] ).to eql("/my_raid_volume/lib/mysql")
2672 expect( node["mysql"]["server"] ).to eql({ "port" => 3456, "data_dir" => "/my_raid_volume/lib/mysql" })
2673 expect( node["mysql"]["server"] ).to eql({ "service_name" => "fancypants-sql", "port" => 3456, "data_dir" => "/my_raid_volume/lib/mysql" })
2674 node.force_default["mysql"]["server"]["port"] = 2345
2675 node.force_default!["mysql"]["server"] = {
2676 expect( node["mysql"]["server"] ).to eql({
2677 node.role_override["mysql"]["server"]["port"] = 1234
2678 node.override["mysql"]["server"]["port"] = 2345
2679 node.force_override["mysql"]["server"]["port"] = 3456
2680 node.force_override!["mysql"]["server"] = {
2681 node.default["chef_attribute_hell"]["attr2"] = "#{node[:chef_attribute_hell][:attr1]}/attr2"
2682 expect { node.default["chef_attribute_hell"]["attr3"] = "#{node[:chef_attribute_hell][:attr2]}/attr3" }.not_to raise_error
2683 node.force_default[:solr][:version] = "4.10.2"
2684 node.force_default[:solr][:data_dir] = "/opt/solr-#{node["solr"][:version]}/example/solr"
2685 node.force_default[:solr][:xms] = "512M"
2686 expect(node[:solr][:xms]).to eql("512M")
2687 expect(node["solr"][:xms]).to eql("512M")
2688 node.default["passenger"]["root_path_2"] = "passenger-#{node[:passenger]["version"]}"
2689 expect(node["passenger"]["root_path_2"]).to eql("passenger-4.0.57")
2690 expect(node[:passenger]["root_path_2"]).to eql("passenger-4.0.57")
2691 node.default["canada"] = "is a nice place"
2692 seen_attributes = {}
2693 node.default["foo"]["bar"] = "baz"
2694 expect(node.exist?("foo", "bar")).to be true
2695 expect(node.exist?("bar", "foo")).to be false
2696 node.override["foo"]["bar"] = "baz"
2697 expect(node.read("foo", "bar")).to eql("baz")
2698 expect(node.read("bar", "foo")).to eql(nil)
2699 expect(node.read!("foo", "bar")).to eql("baz")
2700 node.write(:default, "foo", "bar", "baz")
2701 expect(node.default["foo"]["bar"]).to eql("baz")
2702 node.write!(:default, "foo", "bar", "baz")
2703 node.default["bar"] = true
2704 expect(node.unlink(:default, "foo", "bar")).to eql("baz")
2705 expect(node.unlink(:default, "bar", "foo")).to eql(nil)
2706 expect(node.unlink!(:default, "foo", "bar")).to eql("baz")
2707 @ohai_data = { platform: "foo", platform_version: "bar" }
2708 attrs = { "run_list" => [ "role[base]", "recipe[chef::server]" ], "foo" => "bar" }
2709 expect(node.consume_run_list(attrs)).to eq({ "foo" => "bar" })
2710 expect(node.run_list).to eq([ "role[base]", "recipe[chef::server]" ])
2711 attrs = { "chef_environment" => "foo_environment", "bar" => "baz" }
2712 expect(node.consume_chef_environment(attrs)).to eq({ "bar" => "baz" })
2713 node.consume_run_list "recipes" => %w{one two}
2714 node.consume_run_list "recipes" => [ "three" ]
2715 expect(node.run_list).to eq([ "three" ])
2716 node.run_list << "one"
2717 node.run_list << "role[database]"
2718 node.consume_run_list "foo" => "bar"
2719 node.consume_external_attrs(@ohai_data, { "one" => "two", "three" => "four" })
2720 expect(node["one"]).to eql("two")
2721 expect(node["three"]).to eql("four")
2722 expect(node.tags).to eql([ "radiohead" ])
2723 node.attributes.normal = { "tags" => nil }
2724 node.normal[:tags] = "string"
2725 expect(node.tags).to eql(["string"])
2726 node.normal[:tags] = {}
2727 node.consume_external_attrs(@ohai_data, "one" => { "two" => { "three" => "four" } })
2728 expect(node["one"].to_hash).to eq({ "two" => { "three" => "four" } })
2729 node.consume_external_attrs(@ohai_data, "one" => { "abc" => "123" })
2730 node.consume_external_attrs(@ohai_data, "one" => { "two" => { "foo" => "bar" } })
2731 expect(node["one"].to_hash).to eq({ "two" => { "three" => "four", "foo" => "bar" }, "abc" => "123" })
2732 node.consume_external_attrs(@ohai_data, "one" => { "two" => { "three" => "forty-two" } })
2733 expect(node["one"].to_hash).to eq({ "two" => { "three" => "forty-two" } })
2734 node.consume_ohai_data({ "platform_version" => "6.3" })
2735 expect(node["platform_version"] =~ "~> 6.1").to be true
2736 @ohai_data = { platform: "foobuntu", platform_version: "23.42" }
2737 node.consume_external_attrs(@ohai_data, { "run_list" => ["recipe[unicorn]"] })
2738 node.consume_external_attrs(@ohai_data, { "foo" => "bar" })
2739 expect(node.normal_attrs).to eq({ "foo" => "bar", "tags" => [] })
2740 expect(node[:platform_version] =~ "~> 23.6").to be true
2741 e.name("rspec_env")
2742 @expansion.recipes << "recipe[chef::client]" << "recipe[nginx::default]"
2743 @expansion.instance_variable_set(:@applied_roles, { "arf" => nil, "countersnark" => nil })
2744 node.automatic_attrs[:recipes] = [ "nginx::module" ]
2745 node.run_list << "recipe[nginx::module]"
2746 node.run_list << "role[base]"
2747 node.default[:foo] = "default"
2748 node.normal[:foo] = "normal"
2749 expect(node[:foo]).to eq("normal")
2750 @environment.default_attributes = { default: "from env", d_env: "env only" }
2751 expect(node[:d_role]).to eq("role only")
2752 expect(node[:o_role]).to eq("role only")
2753 expect(node[:o_env]).to eq("env only")
2754 node.automatic["roles"] = %w{one two}
2755 expect(node.role?("one")).to eql(true)
2756 expect(node.role?("two")).to eql(true)
2757 expect(node.run_list?("recipe[baz]")).to eql(true)
2758 node.run_list "recipe[baz]", "role[foo]"
2759 expect(node.run_list?("role[foo]")).to eql(true)
2760 expect(node["sunshine"]).to eql("in")
2761 expect(node["something"]).to eql("else")
2762 node.default_attrs = { "one" => { "two" => "three", "four" => "five", "eight" => "nine" } }
2763 node.override_attrs = { "one" => { "two" => "three", "four" => "six" } }
2764 node.normal_attrs = { "one" => { "two" => "seven" } }
2765 node.run_list << "role[marxist]"
2766 node.run_list << "role[leninist]"
2767 @example.default_attrs = { "alpha" => { "bravo" => "charlie", "delta" => "echo" } }
2768 @example.override_attrs = { "alpha" => { "bravo" => "foxtrot", "delta" => "golf" } }
2769 @example.normal_attrs = { "alpha" => { "bravo" => "hotel" } }
2770 @example.run_list << "role[comedy]"
2771 @example.run_list << "role[drama]"
2772 h = node.to_hash
2773 expect(h["one"]["two"]).to eq("three")
2774 expect(h["one"]["four"]).to eq("six")
2775 expect(h["one"]["eight"]).to eq("nine")
2776 expect(h["role"]).to be_include("marxist")
2777 expect(h["role"]).to be_include("leninist")
2778 expect(h["run_list"]).to be_include("role[marxist]")
2779 expect(h["run_list"]).to be_include("role[leninist]")
2780 expect(h["chef_environment"]).to eq("dev")
2781 expect(node.to_hash["run_list"]).to eq([])
2782 node.run_list << { "type" => "role", "name" => "Cthulu" }
2783 node.run_list << { "type" => "role", "name" => "Hastur" }
2784 expect(json).to match(/\"run_list\":\[\"role\[Cthulu\]\",\"role\[Hastur\]\"\]/)
2785 expect(json).to match(/\"run_list\":\[\"role\[marxist\]\",\"role\[leninist\]\"\]/)
2786 @rest = double("Chef::ServerAPI")
2787 @query = double("Chef::Search::Query")
2788 n1 = double("Chef::Node", name: "one")
2789 allow(n1).to receive(:is_a?).with(Chef::Node) { true }
2790 r = Chef::Node.list(true)
2791 expect(r["one"]).to eq(n1)
2792 expect(@rest).to receive(:get).and_return({ "one" => "http://foo" })
2793 r = Chef::Node.list
2794 expect(r["one"]).to eq("http://foo")
2795 expect(@rest).to receive(:put).with("nodes/monkey", {}).and_return("foo")
2796 exception = double("404 error", code: "404")
2797 expect(@rest).to receive(:post).with("nodes", {})
2798 ["filesystem", "/dev/disk0s2"],
2799 node.default = {
2800 node.automatic = {}
2801 node.normal = {}
2802 node.override = {}
2803 let(:response_body) { %q[{"error":["Invalid key policy_name in request body"]}] }
2804 Net::HTTPResponse.send(:response_class, "400").new("1.0", "400", "Bad Request").tap do |r|
2805 node.default["foo"] = "bar"
2806 node.default["foo"] = { "bar" => { "baz" => "qux" } }
2807 expect(node["foo"]["bar"].__path__).to eql(%w{foo bar})
2808 expect(node.default["foo"]["bar"].__path__).to eql(%w{foo bar})
2809 node.default["foo"] = [ { "bar" => { "baz" => "qux" } } ]
2810 expect(node["foo"][0].__path__).to eql(["foo", 0])
2811 expect(node["foo"][0]["bar"].__path__).to eql(["foo", 0, "bar"])
2812 expect(node.default["foo"][0].__path__).to eql(["foo", 0])
2813 expect(node.default["foo"][0]["bar"].__path__).to eql(["foo", 0, "bar"])
2814 a = node.default["foo"]
2815 node.default["fizz"] = a
2816 expect(node["fizz"]["bar"].__path__).to eql(%w{fizz bar})
2817 a["duptest"] = true
2818 expect(node["fizz"]["duptest"]).to be true
2819 expect(node["foo"]["bar"].__root__).to eql(node.attributes)
2820 expect(node.default["foo"]["bar"].__root__).to eql(node.attributes)
2821 expect(node["foo"][0].__root__).to eql(node.attributes)
2822 expect(node["foo"][0]["bar"].__root__).to eql(node.attributes)
2823 expect(node.default["foo"][0].__root__).to eql(node.attributes)
2824 expect(node.default["foo"][0]["bar"].__root__).to eql(node.attributes)
2825 node.default["v1"] = 1
2826 expect(node["a"]).to eql(nil)
2827 node.default["a"] = node["v1"]
2828 expect(node["a"]).to eql(1)
2829 a = node.default["a"]
2830 expect(node["a"]).to eql({})
2831 node.default["b"] = 0
2832 a["key"] = 1
2833 expect(node["a"]["key"]).to eql(1)
2834 node.default["foo"]["bar"]["baz"] = "fizz"
2835 node.env_default["foo"]["bar"]["quux"] = "buzz"
2836 node.default["foo"]["bar"].tap do |bar|
2837 bar["test"] = "wrong"
2838 node["foo"]["bar"]["test"]
2839 bar["test"] = "right"
2840 expect(node["foo"]["bar"]["test"]).to eql("right")
2841 node.env_default["foo"]["bar"]["baz"] = "fizz"
2842 node.default["foo"]["bar"]["quux"] = "buzz"
2843 node.env_default["foo"]["bar"].tap do |bar|
2844 default["foo"]["bar"] = lazy { node["fizz"]["buzz"] }
2845 default["fizz"]["buzz"] = "works"
2846 expect(node["foo"]["bar"]).to eql("works")
2847 node.default["fizz"]["buzz"] = "still works"
2848 expect(node["foo"]["bar"]).to eql("still works")
2849 default["cool"]["beans"] = lazy { node["foo"]["bar"] }
2850 expect(node["cool"]["beans"]).to eql("works")
2851 expect(node["cool"]["beans"]).to eql("still works")
2852 default["cool"] = lazy { node["foo"] }
2853 default["foo"] = lazy { node["fizz"] }
2854 default["fizz"] = "works"
2855 expect(node["cool"]).to eql("works")
2856 node.default["fizz"] = "still works"
2857 expect(node["cool"]).to eql("still works")
2858 override["bar"]["cool"] = lazy { node["bar"]["foo"] }
2859 override["bar"]["foo"] = lazy { node["bar"]["fizz"] }
2860 override["bar"]["fizz"] = "works"
2861 expect(node["bar"]["cool"]).to eql("works")
2862 node.override["bar"]["fizz"] = "still works"
2863 expect(node["bar"]["cool"]).to eql("still works")
2864 role_override["bar"] = { "cool" => "bad", "foo" => "bad", "fizz" => "bad" }
2865 force_override["bar"]["cool"] = lazy { node["bar"]["foo"] }
2866 force_override["bar"]["foo"] = lazy { node["bar"]["fizz"] }
2867 force_override["bar"]["fizz"] = "works"
2868 node.force_override["bar"]["fizz"] = "still works"
2869 default["bar"] = { "cool" => "bad", "foo" => "bad", "fizz" => "bad" }
2870 let(:node_map) { Chef::NodeMap.new }
2871 node_map.set(:thing, :foo)
2872 node_map.set(:thing, :foo, os: ["windows"])
2873 node_map.set(:thing, :bar, os: "linux")
2874 allow(node).to receive(:[]).with(:os).and_return("windows")
2875 allow(node).to receive(:[]).with(:os).and_return("linux")
2876 allow(node).to receive(:[]).with(:os).and_return("freebsd")
2877 node_map.set(:thing, :foo, os: "!windows")
2878 node_map.set(:thing, :bar, os: "linux", platform_family: "rhel")
2879 node.automatic["os"] = "linux"
2880 node_map.set(:thing, :foo, platform_family: "rhel", platform_version: ">= 7")
2881 allow(node).to receive(:[]).with(:platform_version).and_return("7.19.2.2F")
2882 allow(node).to receive(:[]).with(:platform_version).and_return("4.19.2.2F")
2883 expect( node_map.delete_class(Bar) ).to include({ thing: [{ klass: Bar, target_mode: nil }] })
2884 expect( node_map.get(node, :thing) ).to eql(nil)
2885 expect( node_map.delete_class(Bar) ).to eql({ thing: [{ klass: Bar, target_mode: nil }] })
2886 expect( node_map.get(node, :thing) ).to eql(Foo)
2887 expect( node_map.delete_class(Bar) ).to eql({ thing1: [{ klass: Bar, target_mode: nil }], thing2: [{ klass: Bar, target_mode: nil }] })
2888 expect( node_map.get(node, :thing1) ).to eql(nil)
2889 expect( node_map.get(node, :thing2) ).to eql(Foo)
2890 node_map.set(:thing, :foo, platform_family: "rhel") do |node|
2891 node[:platform_version].to_i >= 7
2892 { "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil },
2893 { "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil }
2894 expect(vivid["one"]["two"].__root__).to eql(vivid)
2895 vivid["one"]["foo"] = "bar"
2896 context "#[]" do
2897 expect(vivid["array"][1, 2]).to eql([1, 2])
2898 context "#[]=" do
2899 vivid["array"][3, 2] = [ 3, 4 ]
2900 expect(vivid["array"]).to eql([0, 1, 2, 3, 4])
2901 vivid["foo"] = [ { bar: true } ]
2902 expect(vivid["foo"][0]["bar"]).to be true
2903 vivid["foo"] = [ [ { bar: true } ] ]
2904 expect(vivid["foo"][0][0].class).to eql(Chef::Node::VividMash)
2905 expect(vivid["foo"][0][0]["bar"]).to be true
2906 vivid["foo"] = { baz: { bar: true } }
2907 expect(vivid["foo"]["baz"]["bar"]).to be true
2908 expect(vivid.read("one", "two", "three")).to eql("four")
2909 expect(vivid.read("one", "five", "six")).to eql(nil)
2910 expect(vivid.read("array", 5, "one")).to eql(nil)
2911 expect(vivid.read("array", "one", "two")).to eql(nil)
2912 expect(vivid.read("nil", "one", "two")).to eql(nil)
2913 context "#exist?" do
2914 expect(vivid.exist?("one", "two", "three")).to be true
2915 expect(vivid.exist?("array", 1)).to be true
2916 expect(vivid.exist?("one", "five", "six")).to be false
2917 expect(vivid.exist?("one", "two", "three", "four")).to be false
2918 expect(vivid.exist?("nil", "foo", "bar")).to be false
2919 context "#read!" do
2920 expect(vivid.read!("one", "two", "three")).to eql("four")
2921 expect(vivid.read!("array", 1)).to eql(1)
2922 expect { vivid.read!("one", "five", "six") }.to raise_error(Chef::Exceptions::NoSuchAttribute, "one.five.six")
2923 expect { vivid.read!("one", "two", "three", "four") }.to raise_error(Chef::Exceptions::NoSuchAttribute, "one.two.three.four")
2924 vivid.write("one", "five", "six")
2925 expect(vivid["one"]["five"]).to eql("six")
2926 vivid.write("one", "five", "six", "seven", "eight", "nine", "ten")
2927 expect(vivid["one"]["five"]["six"]["seven"]["eight"]["nine"]).to eql("ten")
2928 vivid.write("array", "five", "six")
2929 vivid.write("array", "five", "six", "seven")
2930 vivid.write("one", "two", "three", "four", "five")
2931 vivid.write("one", "two", "three", "four", "five", "six")
2932 vivid.write("nil", "one", "two")
2933 vivid.write("nil", "one", "two", "three")
2934 vivid.write("one", "five") { "six" }
2935 context "#write!" do
2936 vivid.write!("one", "five", "six")
2937 vivid.write!("one", "five", "six", "seven", "eight", "nine", "ten")
2938 expect { vivid.write!("one", "two", "three", "four", "five") }.to raise_error(Chef::Exceptions::AttributeTypeMismatch)
2939 expect { vivid.write!("one", "two", "three", "four", "five", "six") }.to raise_error(Chef::Exceptions::AttributeTypeMismatch)
2940 vivid.write!("one", "five") { "six" }
2941 expect(vivid.unlink("five", "six", "seven", "eight")).to eql(nil)
2942 expect( vivid.unlink("one") ).to eql({ "two" => { "three" => "four" } })
2943 expect(vivid).to eql({ "array" => [ 0, 1, 2 ], "nil" => nil })
2944 expect(vivid.unlink("array", 2)).to eql(2)
2945 expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1 ], "nil" => nil })
2946 expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ] })
2947 expect(vivid.unlink("nil", "foo")).to eql(nil)
2948 expect( vivid.unlink!("one") ).to eql({ "two" => { "three" => "four" } })
2949 expect(vivid.unlink!("array", 2)).to eql(2)
2950 expect(vivid.unlink!("nil")).to eql(nil)
2951 %w{zero one two},
2952 context "#<<" do
2953 array << { "three" => "four" }
2954 array << [ { "three" => [ 0, 1] } ]
2955 array[0] = { "zero" => "zero2" }
2956 array.push({ "three" => "four" })
2957 array.unshift({ "zero" => "zero2" })
2958 array.insert(1, { "zero" => "zero2" })
2959 array.collect! { |x| { "zero" => "zero2" } }
2960 context "#map!" do
2961 array.map! { |x| { "zero" => "zero2" } }
2962 [ nil, { "one" => "two" }, nil ],
2963 array.fill({ "one" => "two" })
2964 [ [ { "one" => "two" } ], [ { "one" => "two" } ] ],
2965 array.replace([ { "foo" => "bar" } ])
2966 let(:copy) { @immutable_mash.send(param) }
2967 expect(copy["top_level_4"]["level2"]).to be_is_a(Hash)
2968 expect { copy["m"] = "m" }.not_to raise_error
2969 expect(copy[2]).to be_is_a(Hash)
2970 expect { copy << "m" }.not_to raise_error
2971 @data_in = { "top" => { "second_level" => "some value" },
2972 @mash = Chef::Node::ImmutableMash.new({ test: "foo", "test2" => "bar" })
2973 expect(@mash[:test]).to eql("foo")
2974 expect(@mash["test2"]).to eql("bar")
2975 let(:copy) { @immutable_mash.to_yaml }
2976 %i{
2977 []=
2978 }.each do |mutator|
2979 mutable[:new_key] = :value
2980 @immutable_array = Chef::Node::ImmutableArray.new(%w{foo bar baz} + Array(1..3) + [nil, true, false, [ "el", 0, nil ] ])
2981 immutable_mash = Chef::Node::ImmutableMash.new({ "m" => "m" })
2982 <<
2983 mutable[0] = :value
2984 describe "#[]" do
2985 expect(@immutable_array[1, 2]).to eql(%w{bar baz})
2986 { "dmi" => {},
2987 @default_hash = {
2988 @override_hash = {
2989 @automatic_hash = { "week" => "friday" }
2990 expect { Chef::Node::Attribute.new({}, {}, {}, {}) }.not_to raise_error
2991 it "should set #{accessor}" do
2992 na = Chef::Node::Attribute.new({ normal: true }, { default: true }, { override: true }, { automatic: true })
2993 expect(na.send(accessor)).to eq({ accessor.to_s => true })
2994 @attributes.default[:foo][:bar] = "default"
2995 @attributes.normal[:foo][:bar] = "normal"
2996 @attributes.default["foo"] = [ { "bar" => "baz" } ]
2997 ["default", { "bar" => "baz" }],
2998 ["env_default", :not_present],
2999 ["role_default", :not_present],
3000 ["force_default", :not_present],
3001 ["normal", :not_present],
3002 ["override", :not_present],
3003 ["role_override", :not_present],
3004 ["env_override", :not_present],
3005 ["force_override", :not_present],
3006 ["automatic", :not_present],
3007 @attributes.env_default["array"] = %w{env}
3008 expect(@attributes["array"]).to eq(%w{env role})
3009 @attributes.env_override["array"] = %w{env}
3010 expect(@attributes["array"]).to eq(%w{role env})
3011 @attributes.normal["array"] = %w{normal}
3012 expect(@attributes["array"]).to eq(%w{normal})
3013 expect(@attributes["array"]).to eq(%w{role})
3014 @attributes = Chef::Node::Attribute.new({}, {}, {}, {})
3015 @attributes.env_default = { "a" => { "b" => { "default" => "default" } } }
3016 @attributes.normal = { "a" => { "b" => { "normal" => "normal" } } }
3017 @attributes.override = { "a" => { "override" => "role" } }
3018 @attributes.automatic = { "a" => { "automatic" => "auto" } }
3019 expect(@attributes["a"]).to eq({ "b" => { "default" => "default", "normal" => "normal" },
3020 expect(@attributes["macaddress"]).to eq("00:00:00:00:00:00")
3021 expect(@attributes["platform"]).to eq("mac_os_x")
3022 expect(@attributes["command"]["ps"]).to eq("ps -ef")
3023 expect(@attributes["music"]["mastodon"]).to eq("rocks")
3024 expect(@attributes["music"]["mars_volta"]).to eq("cicatriz")
3025 expect(@attributes["music"]["jimmy_eat_world"]).to eq("nice")
3026 expect(@attributes["hot"]["day"]).to eq("sunday")
3027 @attributes.normal["the_ghost"] = {}
3028 @attributes.normal["the_ghost"] = { "exterminate" => "the future" }
3029 @attributes.normal["deftones"]["hunters"]["nap"] = "surfing"
3030 expect(@attributes.normal["deftones"]["hunters"]["nap"]).to eq("surfing")
3031 expect { @attributes["foo"]["bar"] = :baz }.to raise_error(NoMethodError)
3032 @attributes.normal["foo"]["bar"] = :baz
3033 expect(@attributes.normal["foo"]["bar"]).to eq(:baz)
3034 @attributes.normal["foo"]["bar"] ||= "stop the world"
3035 expect(@attributes.normal["foo"]["bar"]).to eq({})
3036 hash = @attributes["hot"].to_hash
3037 expect(hash["day"]).to eq("sunday")
3038 @attributes.default["foo"]["bar"]["baz"] = "fizz"
3039 hash = @attributes["foo"].to_hash
3040 expect(hash).to eql({ "bar" => { "baz" => "fizz" } })
3041 hash["bar"]["baz"] = "buzz"
3042 expect(hash).to eql({ "bar" => { "baz" => "buzz" } })
3043 expect(@attributes.default["foo"]).to eql({ "bar" => { "baz" => "fizz" } })
3044 @attributes.default["foo"]["bar"] = ["fizz"]
3045 expect(hash).to eql({ "bar" => [ "fizz" ] })
3046 hash["bar"].push("buzz")
3047 expect(hash).to eql({ "bar" => %w{fizz buzz} })
3048 expect(@attributes.default["foo"]).to eql({ "bar" => [ "fizz" ] })
3049 hash["bar"]["baz"] << "buzz"
3050 expect(hash).to eql({ "bar" => { "baz" => "fizzbuzz" } })
3051 @attributes.default["foo"]["bar"] = [ "fizz" ]
3052 hash["bar"][0] << "buzz"
3053 expect(hash).to eql({ "bar" => [ "fizzbuzz" ] })
3054 @attributes.default[:foo] = %w{foo bar baz} + Array(1..3) + [nil, true, false, [ "el", 0, nil ] ]
3055 hash = @attributes["foo"].dup
3056 expect(@attributes["music"].key?("apophis")).to eq(true)
3057 expect(@attributes["music"]["this"]["apparatus"]).not_to have_key("this")
3058 expect(@attributes["music"]["this"]).not_to have_key("must")
3059 %i{include? key? member?}.each do |method|
3060 collect = []
3061 collect << k
3062 @attributes["one"].each_key do |k|
3063 expect { @attributes["place"].keys { |k| } }.not_to raise_error
3064 collect = {}
3065 @attributes.each do |k, v|
3066 collect[k] = v
3067 expect(collect["one"]).to eq("six")
3068 expect(collect["hut"]).to eq("three")
3069 expect(collect["snakes"]).to eq("on a plane")
3070 collect << v
3071 @empty = Chef::Node::Attribute.new({}, {}, {}, {})
3072 }.each do |k, v|
3073 expect(@attributes.fetch("lol", "blah")).to eq("blah")
3074 expect(@attributes.fetch("lol") { |x| "#{x}, blah" }).to eq("lol, blah")
3075 describe "index", ruby: "< 3.0.0" do
3076 expect(@attributes.index("six")).to eq("one")
3077 expect(@attributes.select { nil }).to eq({}.select { nil })
3078 %w{hut three},
3079 %w{one six},
3080 ["snakes", "on a plane"],
3081 expect(attributes.to_s).to eq("{}")
3082 default_hash = {
3083 expect(attributes.to_s).to eq('{"a"=>1, "b"=>3, "c"=>4}')
3084 expect(@attributes.inspect).to match(/@automatic=\{.*\}/)
3085 expect(@attributes.inspect).to match(/@normal=\{.*\}/)
3086 @attributes.default[:foo].dup[:bar] = "set on dup"
3087 @attributes.default["foo"] = "bar"
3088 @attributes.normal = {}
3089 @attributes.normal["foo"] = "bar"
3090 @attributes.override["foo"] = "bar"
3091 @attributes.automatic["foo"] = "bar"
3092 @attributes.default = { "arglebargle" => { "foo" => "bar" } }
3093 @attributes.override = { "arglebargle" => { "fizz" => "buzz" } }
3094 expect(@attributes.merged_attributes[:arglebargle]).to eq({ "foo" => "bar", "fizz" => "buzz" })
3095 expect(@attributes.default[:arglebargle]).to eq({ "foo" => "bar" })
3096 expect(@attributes.override[:arglebargle]).to eq({ "fizz" => "buzz" })
3097 @attributes.default = { "arglebargle" => [ 1, 2, 3 ] }
3098 @attributes.override = { "arglebargle" => [ 4, 5, 6 ] }
3099 expect(@attributes.default[:arglebargle]).to eq([ 1, 2, 3 ])
3100 expect(@attributes.override[:arglebargle]).to eq([ 4, 5, 6 ])
3101 @attributes.role_default = { "arglebargle" => { "fizz" => "buzz" } }
3102 expect(@attributes.role_default[:arglebargle]).to eq({ "fizz" => "buzz" })
3103 @attributes.role_default = { "arglebargle" => [ 4, 5, 6 ] }
3104 expect(@attributes.merged_attributes[:arglebargle]).to eq([ 1, 2, 3, 4, 5, 6 ])
3105 expect(@attributes.role_default[:arglebargle]).to eq([ 4, 5, 6 ])
3106 it "raises an error when using []=" do
3107 @attributes.default[:foo] = [ { bar: true } ]
3108 expect(@attributes["foo"][0]["bar"]).to be true
3109 @attributes.default[:foo] = [ [ { bar: true } ] ]
3110 expect(@attributes["foo"][0][0]["bar"]).to be true
3111 @attributes.default[:foo] = { baz: { bar: true } }
3112 expect(@attributes["foo"]["baz"]["bar"]).to be true
3113 it "sets __root__ correctly" do
3114 @attributes.default["foo"]["bar"]["baz"] = "quux"
3115 expect(@attributes["foo"].__root__).to eql(@attributes)
3116 expect(@attributes["foo"]["bar"].__root__).to eql(@attributes)
3117 expect(@attributes.default["foo"]["bar"].__root__).to eql(@attributes)
3118 it "sets __node__ correctly" do
3119 expect(@attributes["foo"].__node__).to eql(node)
3120 expect(@attributes["foo"]["bar"].__node__).to eql(node)
3121 expect(@attributes.default["foo"].__node__).to eql(node)
3122 expect(@attributes.default["foo"]["bar"].__node__).to eql(node)
3123 it "sets __path__ correctly" do
3124 expect(@attributes["foo"].__path__).to eql(["foo"])
3125 expect(@attributes["foo"]["bar"].__path__).to eql(%w{foo bar})
3126 expect(@attributes.default["foo"].__path__).to eql(["foo"])
3127 expect(@attributes.default["foo"]["bar"].__path__).to eql(%w{foo bar})
3128 expect(@attributes["foo"]["bar"].__precedence__).to eql(:merged)
3129 expect(@attributes.default["foo"]["bar"].__precedence__).to eql(:default)
3130 expect(events).to receive(:attribute_changed).with(:default, ["foo"], {})
3131 expect { @attributes["foo"]["bar"]["baz"] << "buzz" }.to raise_error(FrozenError, /can't modify frozen String/)
3132 expect { @attributes["foo"]["bar"][0] << "buzz" }.to raise_error(FrozenError, /can't modify frozen String/)
3133 expect(@attributes["foo"]).to eql("bar")
3134 json = @attributes["hot"].to_json
3135 expect(@attributes["hot"].to_json).to eq("{\"day\":\"sunday\"}")
3136 json = @attributes["hot"].to_yaml
3137 expect(@attributes["hot"].to_yaml).to eq("---
day: sunday
")
3138 expect(@escaper.xml_escape("&")).to eq("&amp;")
3139 it "escapes angle brackets to &lt; or &gt;" do
3140 expect(@escaper.xml_escape("<")).to eq("&lt;")
3141 expect(@escaper.xml_escape(">")).to eq("&gt;")
3142 expect(@escaper.xml_escape("foobarbaz!@\#$%^*()")).to eq("foobarbaz!@\#$%^*()")
3143 expect(@escaper.xml_escape("\x00")).to eq("*")
3144 expect(@escaper.xml_escape("\xC2\xA9")).to eq("&#169;")
3145 expect(@escaper.xml_escape((0x80.chr).to_s)).to eq("&#8364;")
3146 @invalid_architectures = [ "i386", "x86_64", :x64, :x86, :arm ]
3147 @node_x86_64 = Chef::Node.new
3148 new_node.default["kernel"] = {}
3149 a.assertion { raise "boom1" }
3150 a.failure_message("#{raise "boom2"}")
3151 a.whyrun("#{raise "boom3"}")
3152 let(:test) { TestClass.new }
3153 expect(test).to receive(:env_path).and_return(["/dir1", "/dir2" ].join(File::PATH_SEPARATOR))
3154 ["/dir1", "/dir2", "/bin", "/usr/bin", "/sbin", "/usr/sbin" ].each do |dir|
3155 test_which("finds `foo1` in #{dir} when it is stubbed", "foo1", finds: "#{dir}/foo1")
3156 test_which("finds the first arg", "foo1", "foo2", finds: "/dir2/foo1")
3157 test_which("finds the second arg", "foo1", "foo2", finds: "/dir2/foo2")
3158 test_which("finds the first arg when there's both", "foo1", "foo2", finds: "/dir2/foo1", others: [ "/dir1/foo2" ])
3159 test_which("and the directory order can be reversed", "foo1", "foo2", finds: "/dir1/foo1", others: [ "/dir2/foo2" ])
3160 test_which("or be the same", "foo1", "foo2", finds: "/dir1/foo1", others: [ "/dir1/foo2" ])
3161 test_which("doesnt find it if its false", "foo1", others: [ "/dir1/foo1" ]) do |f|
3162 test_which("finds it if its true", "foo1", finds: "/dir1/foo1") do |f|
3163 test_which("passes in the filename as the arg", "foo1", finds: "/dir1/foo1") do |f|
3164 raise "bad arg to block" unless f == "/dir1/foo1"
3165 test_which("arrays with blocks", "foo1", "foo2", finds: "/dir2/foo1", others: [ "/dir1/foo2" ]) do |f|
3166 raise "bad arg to block" unless ["/dir2/foo1", "/dir1/foo2"].include?(f)
3167 def self.test_where(description, *args, finds: [], others: [], &block)
3168 test_where("finds `foo1` in #{dir} when it is stubbed", "foo1", finds: [ "#{dir}/foo1" ])
3169 test_where("finds `foo1` in all directories", "foo1", finds: [ "/dir1/foo1", "/dir2/foo1" ])
3170 test_where("finds the first arg", "foo1", "foo2", finds: [ "/dir2/foo1" ])
3171 test_where("finds the second arg", "foo1", "foo2", finds: [ "/dir2/foo2" ])
3172 test_where("finds foo1 before foo2", "foo1", "foo2", finds: [ "/dir2/foo1", "/dir1/foo2" ])
3173 test_where("finds foo1 before foo2 if the dirs are reversed", "foo1", "foo2", finds: [ "/dir1/foo1", "/dir2/foo2" ])
3174 test_where("finds them both in the same directory", "foo1", "foo2", finds: [ "/dir1/foo1", "/dir1/foo2" ])
3175 test_where("finds foo2 first if they're reversed", "foo2", "foo1", finds: [ "/dir1/foo2", "/dir1/foo1" ])
3176 test_where("finds foo1 and foo2 if they exist and the block is true", "foo1", "foo2", finds: [ "/dir1/foo2", "/dir2/foo2" ]) do
3177 test_where("does not finds foo1 and foo2 if they exist and the block is false", "foo1", "foo2", others: [ "/dir1/foo2", "/dir2/foo2" ]) do
3178 let(:uris) { Chef::UrisTest.new }
3179 it "matches 'scheme://foo.com'" do
3180 expect(uris.uri_scheme?("scheme://foo.com")).to eq(true)
3181 it "does not match 'c:/foo.com'" do
3182 expect(uris.uri_scheme?("c:/foo.com")).to eq(false)
3183 it "does not match '/usr/bin/foo.com'" do
3184 it "does not match 'c:/foo.com://bar.com'" do
3185 expect(uris.uri_scheme?("c:/foo.com://bar.com")).to eq(false)
3186 expect { uris.as_uri("file:///c:/foo bar.txt") }.not_to raise_exception
3187 expect( uris.as_uri("file:///c:/foo bar.txt") ).to be_a(URI)
3188 let(:message) { "Test Message" }
3189 unformatter.write("[time] foo: #{message}")
3190 unformatter.write("[time] FOO: #{message}")
3191 let(:sep) { ChefUtils.windows? ? "\r
" : "
" }
3192 @context[:foo] = "bar"
3193 output = @context.render_template_from_string("<%= @foo %>")
3194 template_contents = [ "Fancy\r
Template\r
\r
",
3195 expect(line).to end_with("\r
")
3196 expect(line).to end_with("
")
3197 @context[:node] = "tehShizzle"
3198 output = @context.render_template_from_string("<%= @node %>")
3199 output = @template_context.render_template_from_string("before {<%= render '#{tf.path}', :local => true %>} after")
3200 output = @template_context.render_template_from_string("before {<%= render('test.erb', :cookbook => 'openldap').strip %>} after")
3201 output = @template_context.render_template_from_string("before {<%= render 'something', :local => true, :source => '#{tf.path}' %>} after")
3202 output = @template_context.render_template_from_string("before {<%= render 'nested_openldap_partials.erb', :variables => {:hello => 'Hello World!' } %>} after")
3203 output == "before {Hello World!} after"
3204 output = @template_context.render_template_from_string("before {<%= render 'openldap_variable_stuff.conf.erb', :variables => {:secret => 'two' } %>} after <%= @secret %>")
3205 output = @template_context.render_template_from_string("before {<%= render('#{path}', :local => true).strip %>} after")
3206 expect { @context.render_template_from_string("<%= node %>") { |r| r } }.to raise_error(Chef::Mixin::Template::TemplateError)
3207 let(:shell_out_class) { Class.new { include Chef::Mixin::ShellOut } }
3208 let(:retobj) { instance_double(Mixlib::ShellOut, "error!" => false) }
3209 let(:cmd) { "echo '#{rand(1000)}'" }
3210 describe "##{method}" do
3211 options = { environment: { "LC_ALL" => nil, "LANGUAGE" => nil, "LANG" => nil, env_path => nil } }
3212 options = { environment: { "HOME" => "/Users/morty" } }
3213 options = { env: { "LC_ALL" => nil, "LANG" => nil, "LANGUAGE" => nil, env_path => nil } }
3214 options = { env: { "HOME" => "/Users/morty" } }
3215 env: {
3216 expect(options[:env].key?("LC_ALL")).to be false
3217 options = { user: "morty" }
3218 user: "morty",
3219 options = { environment: { "LC_ALL" => nil } }
3220 options = { environment: { "LC_ALL" => "en_US.UTF-8" } }
3221 options = { env: { "LC_ALL" => nil } }
3222 provider.send(method, "foo", timeout: 1, env: nil)
3223 let(:new_resource) { Chef::Resource::Package.new("foo") }
3224 load File.join(__dir__, "..", "..", "..", "lib", "chef", "mixin", "securable.rb")
3225 it "should not accept group/owner names starting with '-', '+', or '~'" do
3226 expect { @securable.rights :read, ["The Dude", "Donny"] }.not_to raise_error
3227 let(:host) { "host" }
3228 let(:port) { 7979 }
3229 let(:http_uri) { "http://somehost:1" }
3230 let(:https_uri) { "https://somehost:1" }
3231 let(:no_proxy_spec) { nil }
3232 ENV["https_proxy"] = nil
3233 ENV["https_proxy"] = https_uri
3234 ENV["http_proxy"] = http_uri
3235 let(:proxy_uri) { https_uri }
3236 ENV["no_proxy"] = no_proxy_spec
3237 let(:proxy_uri) { http_uri }
3238 property :a, "a", default: "a"
3239 property :ab, %w{a b}, default: "a"
3240 property :ac, %w{a c}, default: "a"
3241 property :d, "d", description: "The d property", introduced: "14.0"
3242 property :b, "b", default: "b"
3243 property :ab, default: "b"
3244 property :bc, %w{b c}, default: "c"
3245 class C < A
3246 property :c, "c", default: "c"
3247 property :ac, default: "c"
3248 property :bc, default: "c"
3249 it "A.properties has a, ab, and ac with types 'a', ['a', 'b'], and ['b', 'c']" do
3250 it "B.properties has b, ab, and bc with types 'b', nil and ['b', 'c']" do
3251 expect(C.properties.keys).to eq %i{a ab ac d b bc c}
3252 let(:c) { C.new }
3253 expect(c.ab).to eq("b")
3254 expect(c.ac).to eq("c")
3255 expect(c.bc).to eq("c")
3256 expect(test_class.translate_type("foo")).to eq("'foo'")
3257 ["'", '"', "#", "`"].each do |c|
3258 expect(test_class.translate_type({ "a" => 1, "b" => 1.2, "c" => false, "d" => true
3259 })).to eq("@{a=1;b=1.2;c=$false;d=$true}")
3260 expect(test_class.translate_type([true, false])).to eq("@($true,$false)")
3261 node.default[:test] = { "a" => 1, "b" => 1.2, "c" => false, "d" => true }
3262 expect(test_class.translate_type(node[:test])).to eq("@{a=1;b=1.2;c=$false;d=$true}")
3263 node.default[:test] = [ true, false ]
3264 expect(test_class.translate_type(node[:test])).to eq("@($true,$false)")
3265 expect(result.stderr).to be == ""
3266 expect { @vo.validate({ one: "two" }, {}) }.not_to raise_error
3267 expect { @vo.validate({ one: "two" }, { one: true }) }.not_to raise_error
3268 expect { @vo.validate({ one: "two" }, { "one" => true }) }.not_to raise_error
3269 expect { @vo.validate({ one: "two" }, { {} => true }) }.to raise_error(ArgumentError)
3270 expect { @vo.validate({}, { one: false }) }.not_to raise_error
3271 { one: "string" },
3272 one: {
3273 { two: "string" },
3274 { one: @vo },
3275 arguments = {}
3276 { one: "is good" },
3277 regex: /^is good$/,
3278 regex: /^is bad$/,
3279 a == "is good"
3280 { one: "is bad" },
3281 args = { one: "is good", two: "is bad" }
3282 respond_to: %i{to_s upcase},
3283 regex: /^is good/,
3284 two: {
3285 three: { default: "neato mosquito" },
3286 { one: "two" },
3287 busted: "check",
3288 @vo.validate({ "one" => "two" }, { one: { regex: /^two$/ } })
3289 kind_of: [ String, Array ],
3290 { one: ["string"] },
3291 { one: {} },
3292 @vo.validate({ not_blank: "should pass" },
3293 { not_blank: { cannot_be: %i{nil empty} } })
3294 @vo.validate({ not_blank: "" },
3295 { not_blank: { cannot_be: %i{nil empty}, validation_message: "my validation message" } })
3296 value = "meow"
3297 expect(@vo.set_or_return(:test, value, {}).object_id).to eq(value.object_id)
3298 expect(@vo.set_or_return(:test, nil, {}).object_id).to eq(value.object_id)
3299 expect(@vo.set_or_return(:test, nil, {}).object_id).not_to eq(value.object_id)
3300 expect(@vo.set_or_return(:test, nil, {})).to eql(value)
3301 @vo.set_or_return(:test, nil, { required: true })
3302 @vo.set_or_return(:test, nil, { required: false })
3303 expect(@vo.set_or_return(:name, value, {}).object_id).to eq(value.object_id)
3304 @vo.set_or_return(:test, value, { kind_of: Numeric })
3305 @vo.set_or_return(:test, nil, { kind_of: Numeric })
3306 @vo.set_or_return(:delayed, @vo.lazy { "test" }, {})
3307 value = "fubar"
3308 @vo.set_or_return(:test, @vo.lazy { value }, {})
3309 expect(@vo.set_or_return(:test, nil, {})).to eq("fubar")
3310 value = "foobar"
3311 expect(@vo.set_or_return(:test, nil, {})).to eq("foobar")
3312 expect(@vo.set_or_return(:test, nil, {})).to eq("fauxbar")
3313 value = lambda { "test" }
3314 @vo.set_or_return(:test, value, {})
3315 expect(@vo.set_or_return(:test, nil, {})).to be_a(Proc)
3316 @dhparam_file.puts("I_am_not_a_key_I_am_a_free_man")
3317 cipher = ::OpenSSL::Cipher.new("des3")
3318 @keyfile.write("I_am_not_a_key_I_am_a_free_man")
3319 @crlfile.write("I_am_not_a_crl_I_am_a_free_man")
3320 instance.encrypt_rsa_key("abcd", "efgh", "des3")
3321 instance.encrypt_ec_key("abcd", "efgh", "des3")
3322 @encrypted_key = instance.encrypt_ec_key(@ec_key, "oink", "des3")
3323 instance.gen_x509_extensions("pouet" => { "values" => [ "keyCertSign" ], "wrong_key" => true })
3324 instance.gen_x509_extensions("keyUsage" => { "values" => "keyCertSign", "critical" => true })
3325 instance.gen_x509_extensions("keyUsage" => { "values" => [ "keyCertSign" ], "critical" => "yes" })
3326 @x509_extension = instance.gen_x509_extensions("keyUsage" => { "values" => [ "keyCertSign" ], "critical" => true })
3327 @ec_request = @instance.gen_x509_request(OpenSSL::X509::Name.new([%w{CN ECCert}]), @ec_key)
3328 @x509_extension = @instance.gen_x509_extensions("keyUsage" => { "values" => [ "keyCertSign" ], "critical" => true })
3329 @ca_cert.version = 2
3330 @ca_cert.serial = 1
3331 @ca_cert.subject = OpenSSL::X509::Name.new [%w{CN TestCA}]
3332 @ca_cert.not_after = @ca_cert.not_before + 365 * 24 * 60 * 60
3333 @ca_cert.sign(@ca_key, OpenSSL::Digest.new("SHA256"))
3334 @info_with_issuer = { "validity" => 365, "issuer" => @ca_cert }
3335 @info_without_issuer = { "validity" => 365 }
3336 it "Get 5" do
3337 expect(@next_crl == 5).to be_truthy
3338 it "get true" do
3339 @info = { "validity" => 8, "issuer" => @ca_cert }
3340 instance.gen_x509_crl(@ca_key, "abc" => "def", "validity" => 8)
3341 instance.gen_x509_crl(@ca_key, "issuer" => "abc", "validity" => 8)
3342 instance.gen_x509_crl(@ca_key, "issuer" => @ca_cert, "validity" => "abc")
3343 @x509_crl = instance.gen_x509_crl(@ca_key, @info)
3344 @crl = @instance.gen_x509_crl(@ca_key, @info)
3345 instance.renew_x509_crl("abc", @ca_key, @info)
3346 instance.renew_x509_crl(@crl, "abc", @info)
3347 instance.renew_x509_crl(@crl, @ca_key, "abc")
3348 instance.renew_x509_crl(@crl, @ca_key, "abc" => "def", "validity" => 8)
3349 instance.renew_x509_crl(@crl, @ca_key, "issuer" => "abc", "validity" => 8)
3350 instance.renew_x509_crl(@crl, @ca_key, "issuer" => @ca_cert, "validity" => "abc")
3351 @renewed_crl = instance.renew_x509_crl(@crl, @ca_key, @info)
3352 @revoke_info = { "serial" => 1, "reason" => 0 }
3353 instance.revoke_x509_crl("abc", @crl, @ca_key, @info)
3354 instance.revoke_x509_crl(@revoke_info, @crl, @ca_key, "abc")
3355 instance.revoke_x509_crl({ "abc" => "def", "ghi" => "jkl" }, @crl, @ca_key, @info)
3356 instance.revoke_x509_crl({ "serial" => [], "reason" => 0 }, @crl, @ca_key, @info)
3357 instance.revoke_x509_crl({ "serial" => 1, "reason" => "abc" }, @crl, @ca_key, @info)
3358 instance.revoke_x509_crl(@revoke_info, @crl, @ca_key, "abc" => "def", "validity" => 8)
3359 instance.revoke_x509_crl(@revoke_info, @crl, @ca_key, "issuer" => "abc", "validity" => 8)
3360 instance.revoke_x509_crl(@revoke_info, @crl, @ca_key, "issuer" => @ca_cert, "validity" => "abc")
3361 @certfile.write("I_am_not_a_cert_I_am_a_free_man")
3362 let(:uid) { 1001 }
3363 let(:user) { "foo" }
3364 let(:user) { nil }
3365 let(:brew_owner) { 2001 }
3366 let(:default_brew_path) { "/usr/local/bin/brew" }
3367 d = double
3368 let(:brew_owner) { 0 }
3369 @resource = Chef::Resource::File.new("#{@tmpdir}/madeup.txt")
3370 uid: 0, gid: 0, dir: "/root",
3371 shell: "/bin/bash")
3372 group_struct = OpenStruct.new(name: "root", passwd: "x", gid: 0)
3373 Chef::Log.init(@log_io)
3374 @ruby_bindir = "/some/ruby/bin"
3375 @gem_bindir = "/some/gem/bin"
3376 env = {}
3377 expect(env["PATH"]).to eq("#{@gem_bindir}:#{@ruby_bindir}:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin")
3378 env = { "PATH" => "" }
3379 env = { "PATH" => "/usr/bin:/sbin:/bin" }
3380 expect(env["PATH"]).to eq("#{@gem_bindir}:#{@ruby_bindir}:/usr/bin:/sbin:/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin")
3381 env = { "PATH" => "/usr/bin:/sbin:/bin:/b#{0x81.chr}t".force_encoding("ISO-8859-1") }
3382 expect(env["PATH"].encoding.to_s).to eq("UTF-8")
3383 ruby_bindir = "/usr/bin"
3384 gem_bindir = "/yo/gabba/gabba"
3385 env = { "PATH" => gem_bindir }
3386 expect(env["PATH"]).to eq("/usr/bin:/yo/gabba/gabba:/usr/local/sbin:/usr/local/bin:/usr/sbin:/sbin:/bin")
3387 ruby_bindir = 'C:\ruby\bin'
3388 gem_bindir = 'C:\gems\bin'
3389 env = { "PATH" => "C:\\Windows\\system32;C:\\mr\\softie" }
3390 expect(env["PATH"]).to eq("#{gem_bindir};#{ruby_bindir};C:\\Windows\\system32;C:\\mr\\softie")
3391 @field_ko_prefix = "!merge"
3392 hash_src = { "id" => "2" }
3393 hash_dst = {}
3394 hash_src = { "region" => { "id" => %w{227 2} } }
3395 hash_src = {}
3396 hash_dst = { "property" => %w{2 4} }
3397 expect(hash_dst).to eq({ "property" => %w{2 4} })
3398 hash_src = { "property" => %w{2 4} }
3399 hash_src = { "name" => "value" }
3400 hash_dst = { "name" => "value1" }
3401 expect(hash_dst).to eq({ "name" => "value" })
3402 hash_src = { "property" => %w{1 3} }
3403 expect(hash_dst).to eq({ "property" => %w{2 4 1 3} })
3404 hash_src = { "property" => { "bedroom_count" => %w{1 2}, "bathroom_count" => ["1", "4+"] } }
3405 hash_dst = { "property" => { "bedroom_count" => %w{3 2}, "bathroom_count" => ["2"] } }
3406 expect(hash_dst).to eq({ "property" => { "bedroom_count" => %w{3 2 1}, "bathroom_count" => ["2", "1", "4+"] } })
3407 hash_dst = { "property" => { "bedroom_count" => "3", "bathroom_count" => ["2"] } }
3408 expect(hash_dst).to eq({ "property" => { "bedroom_count" => %w{1 2}, "bathroom_count" => ["2", "1", "4+"] } })
3409 hash_src = { "property" => { "bedroom_count" => "3", "bathroom_count" => ["1", "4+"] } }
3410 hash_dst = { "property" => { "bedroom_count" => %w{1 2}, "bathroom_count" => ["2"] } }
3411 expect(hash_dst).to eq({ "property" => { "bedroom_count" => "3", "bathroom_count" => ["2", "1", "4+"] } })
3412 hash_dst = { "property" => { "bedroom_count" => { "king_bed" => 2, "queen_bed" => 4 }, "bathroom_count" => ["2"] } }
3413 hash_src = { "property" => "1" }
3414 expect(hash_dst).to eq({ "property" => "1" })
3415 hash_src = { "property" => { "bedroom_count" => { "king_bed" => [3], "queen_bed" => [1] }, "bathroom_count" => "1" } }
3416 hash_src = { "property" => { "bedroom_count" => { "king_bed" => 3, "queen_bed" => [1] }, "bathroom_count" => ["1"] } }
3417 hash_src = { "property" => { "bedroom_count" => { "king_bed" => [3] }, "bathroom_count" => ["1"] } }
3418 hash_src = { "property" => { "bedroom_count" => { 2 => 3, "king_bed" => [3] }, "bathroom_count" => ["1"] } }
3419 expect(hash_dst).to eq({ "property" => { "bedroom_count" => { 2 => 3, "king_bed" => [3] }, "bathroom_count" => ["1"] } })
3420 hash_src = { %w{1 2 3} => %w{1 2} }
3421 hash_dst = { %w{4 5} => ["3"] }
3422 expect(hash_dst).to eq({ %w{1 2 3} => %w{1 2}, %w{4 5} => ["3"] })
3423 hash_src = { "property" => { "bedroom_count" => ["1", "2,3"] } }
3424 expect(hash_dst).to eq({ "property" => { "bedroom_count" => ["1", "2,3"] } })
3425 hash_src = { "action" => "browse", "controller" => "results" }
3426 hash_src = { "amenity" => { "id" => ["26,27"] } }
3427 expect(hash_dst).to eq({ "amenity" => { "id" => ["26,27"] } })
3428 hash_src = { "item" => [{ "1" => "3" }, { "2" => "4" }] }
3429 hash_dst = { "item" => [{ "3" => "5" }] }
3430 expect(hash_dst).to eq({ "item" => [{ "3" => "5" }, { "1" => "3" }, { "2" => "4" }] })
3431 hash_src = { "valid" => false }
3432 hash_dst = { "valid" => true }
3433 expect(hash_dst).to eq({ "valid" => false })
3434 hash_src = { "valid" => true }
3435 hash_dst = { "valid" => false }
3436 expect(hash_dst).to eq({ "valid" => true })
3437 hash_src = { "item" => " " }
3438 hash_dst = { "item" => "orange" }
3439 expect(hash_dst).to eq({ "item" => " " })
3440 hash_src = { "item" => "orange" }
3441 hash_dst = { "item" => " " }
3442 expect(hash_dst).to eq({ "item" => "orange" })
3443 hash_src = { "item" => nil }
3444 expect(hash_dst).to eq({ "item" => nil })
3445 expect(@dm.merge(hash_dst, hash_src)).to eq({ "name" => "value" })
3446 expect(@dm.merge(hash_dst, hash_src)).to eq({ "property" => %w{2 4 1 3} })
3447 hash_dst = { "property" => { "values" => { "are" => "falling", "can" => "change" } } }
3448 hash_src = { "property" => { "values" => { "are" => "stable", "may" => "rise" } } }
3449 hash_dst = { "property" => %w{1 2 3} }
3450 hash_src = { "property" => %w{4 5 6} }
3451 ret = @dm.merge(hash_dst, hash_src)
3452 expect(hash_dst).to eq({ "property" => %w{1 2 3} })
3453 expect(hash_src).to eq({ "property" => %w{4 5 6} })
3454 expect(ret).to eq({ "property" => %w{1 2 3 4 5 6} })
3455 @dm.deep_merge(nil, 4)
3456 expect(merged_result["top_level_a"]["1_deep_a"]).to eq("1-a-merge-ee")
3457 expect(merged_result["top_level_a"]["1_deep_b"]).to eq("1-deep-b-merged-onto")
3458 expect(merged_result["top_level_a"]["1_deep_c"]).to eq("1-deep-c-merged-onto")
3459 expect(merged_result["top_level_a"]["1_deep_b"]).to eq(%w{B B B})
3460 merge_ee_hash = { "top_level_a" => "top-level-a-mergee", "top_level_b" => "top-level-b-merge-ee" }
3461 expect(merged_result["top_level_a"]["1_deep_a"]).to be_nil
3462 merge_with_hash = { "top_level_a" => { "1_deep_a" => { "2_deep_a" => { "3_deep_b" => "bar" } } } }
3463 expect(merge_ee_hash).to eq({ "top_level_a" => { "1_deep_a" => { "2_deep_a" => { "3_deep_a" => "foo" } } } })
3464 expect(merge_with_hash).to eq({ "top_level_a" => { "1_deep_a" => { "2_deep_a" => { "3_deep_b" => "bar" } } } })
3465 merge_ee_hash = { "top_level_a" => 1, "top_level_b" => false }
3466 merge_with_hash = { "top_level_a" => 2, "top_level_b" => true }
3467 expect(merged_result).to eq({ "item" => nil })
3468 @stat = double("File::Stat", { mtime: Time.at(0) })
3469 let(:object) { dummy_class.new }
3470 let(:default_supported_client_versions) { [0, 1, 2] }
3471 let(:response) { OpenStruct.new(code: "405") }
3472 .to be_nil
3473 let(:response) { OpenStruct.new(code: "406") }
3474 let(:min_server_version) { 2 }
3475 let(:max_server_version) { 4 }
3476 .to be_a_kind_of(Array)
3477 .to eq(0)
3478 let(:supported_client_versions) { [5, 6, 7] }
3479 let(:supported_client_versions) { [0, 1] }
3480 let(:supported_client_versions) { [1, 2, 3, 4, 5] }
3481 .to eq([2, 3, 4])
3482 let(:supported_client_versions) { [0, 1, 2] }
3483 .to eq([2])
3484 let(:supported_client_versions) { [4, 5, 6] }
3485 .to eq([4])
3486 Chef::Resource::LWRPBase.class_eval { @loaded_lwrps = {} }
3487 run_context = Chef::RunContext.new(node, {}, nil)
3488 raise "hi"
3489 @lwrp_path = File.join(@tmpdir, "foo.rb")
3490 content = IO.read(File.expand_path("../data/lwrp/resources/foo.rb", __dir__))
3491 content = IO.read(File.expand_path("../data/lwrp_override/resources/foo.rb", __dir__))
3492 Dir[File.expand_path(File.join(__dir__, "..", "data", "lwrp", "resources", "*"))].each do |file|
3493 expect(get_lwrp(:lwrp_foo).new("blah").to_s).to eq "lwrp_foo[blah]"
3494 expect(get_lwrp(:lwrp_foo).new("blah").action).to eq([:pass_buck])
3495 Dir[File.expand_path(File.join(__dir__, "..", "data", "lwrp", "resources_with_default_attributes", "*"))].each do |file|
3496 attribute :drink, default: lazy { |r| "Drink after #{r.food}!" }
3497 let(:instance) { klass.new("kitchen") }
3498 let(:lwrp) do
3499 Chef::Node.new.tap do |n|
3500 let(:lwrp_cookbook_name) { "lwrp" }
3501 Chef::Provider::LWRPBase.class_eval { @loaded_lwrps = {} }
3502 Dir[File.expand_path(File.expand_path("../data/lwrp/resources/*", __dir__))].each do |file|
3503 Dir[File.expand_path(File.expand_path("../data/lwrp/providers/*", __dir__))].each do |file|
3504 let(:lwrp_cookbook_name) { "l_w_r_p" }
3505 let(:lwrp_cookbook_name) { "l-w-r-p" }
3506 let(:test_lwrp_class) { @test_lwrp_class }
3507 @tmpdir = File.join(@tmpparent, "lwrp")
3508 lwrp = get_lwrp(:lwrp_once).new("hi")
3509 expect(get_lwrp(:lwrp_once) === lwrp).to be_truthy
3510 lwrp = subclass.new("hi")
3511 expect(lwrp.class === get_lwrp(:lwrp_once))
3512 it "get_lwrp(:lwrp_once).new is *not* a subclass" do
3513 let(:winevt) { Chef::Log::WinEvt.new(evtlog) }
3514 data: ["*** Chef 12.4.0.dev.0 ***"]
3515 Chef::Log.info("*** Chef 12.4.0.dev.0 ***")
3516 let(:syslog) { Chef::Log::Syslog.new }
3517 expect(syslog).to receive(:add).with(1, "*** Chef 12.4.0.dev.0 ***", nil)
3518 let(:key) { Chef::Key.new("original_actor", "user") }
3519 it "should be a Chef::Key" do
3520 let(:field) { :actor }
3521 let(:valid_input) { "new_field_value" }
3522 let(:field) { :name }
3523 let(:field) { :private_key }
3524 let(:field) { :public_key }
3525 let(:valid_input) { "2020-12-24T21:00:00Z" }
3526 let(:valid_input) { "infinity" }
3527 let(:new_key) { Chef::Key.new("original_actor", "user") }
3528 let(:new_key) { Chef::Key.new("original_actor", "client") }
3529 let(:key) do
3530 o = { "user" => "turtle",
3531 o = { "client" => "turtle",
3532 o = Chef::Key.new("foobar", "user")
3533 o = Chef::Key.new("foobar", "client")
3534 let(:response) { [{ "uri" => "http://www.example.com/users/keys/foobar", "name" => "foobar", "expired" => false }] }
3535 let(:inflated_response) { { "foobar" => user_key } }
3536 let(:inflated_response) { { "foobar" => client_key } }
3537 { "name" => "12:3e:33:73:0b:f4:ec:72:dc:f0:4c:51:62:27:08:76:96:24:f4:4a",
3538 { "name" => key.name,
3539 $expected_output = {
3540 actor_type => "foobar",
3541 $expected_input = {
3542 allow(rest).to receive(:post).with(url, $expected_input).and_return({ "private_key" => "this_private_key" })
3543 let(:url) { "users/#{key.actor}/keys" }
3544 let(:key) { user_key }
3545 let(:actor_type) { "user" }
3546 let(:url) { "clients/#{client_key.actor}/keys" }
3547 let(:key) { client_key }
3548 let(:actor_type) { "client" }
3549 let(:url) { "users/#{key.actor}/keys/#{key.name}" }
3550 let(:update_name_url) { "users/#{key.actor}/keys/old_name" }
3551 let(:url) { "clients/#{client_key.actor}/keys/#{key.name}" }
3552 let(:update_name_url) { "clients/#{client_key.actor}/keys/old_name" }
3553 expect(rest).to receive(:get).with(url).and_return({ "user" => "foobar", "name" => "test_key_name", "public_key" => public_key_string, "expiration_date" => "infinity" })
3554 key = Chef::Key.send(load_method, "foobar", "test_key_name")
3555 let(:load_method) { :load_by_user }
3556 let(:url) { "users/foobar/keys/test_key_name" }
3557 let(:load_method) { :load_by_client }
3558 let(:url) { "clients/foobar/keys/test_key_name" }
3559 end # load
3560 let(:json) { %Q{{
/* comment */
// comment 2
"json_class": "Chef::Role"}} }
3561 def to_json(*a)
3562 Chef::JSONCompat.to_json({ "foo" => 1234, "bar" => { "baz" => 5678 } }, *a)
3563 f = Foo.new
3564 let(:jsonable) { Foo.new }
3565 v = 252.times.inject(hash) do |memo, _|
3566 memo["key"]
3567 expect(v).to eq("test")
3568 let(:uri) { URI("chefzero://localhost:1") }
3569 subject(:http) { Chef::HTTP.new(uri) }
3570 http = Chef::HTTP.new(uri)
3571 http = Chef::HTTP.new(uri, { nethttp: { "continue_timeout" => 5 } })
3572 http = Chef::HTTP.new("http://www.getchef.com")
3573 http = Chef::HTTP.new("http://www.getchef.com/")
3574 expect { http.create_url("HTTP://www1.chef.io/") }.not_to raise_error
3575 expect(http.create_url("HTTP://www2.chef.io/")).to eql(URI.parse("http://www2.chef.io/"))
3576 http = Chef::HTTP.new("")
3577 expect(http.head("http://www.getchef.com/")).to eql(nil)
3578 resp = Net::HTTPNotModified.new("1.1", 304, "Not Modified")
3579 end # head
3580 let!(:low_level_client) { http.http_client(URI(uri)) }
3581 allow(r).to receive(:read_body).and_return("")
3582 http.get("/")
3583 expect { http.get("/") }.to raise_error(exception.class)
3584 let(:method) { "GET" }
3585 let(:url) { "http://dummy.com" }
3586 let(:headers) { {} }
3587 let(:data) { false }
3588 let(:request) {}
3589 let(:return_value) { "200" }
3590 let(:request_type) { :streaming }
3591 let(:content_length_value) { 23 }
3592 let(:streaming_length) { 23 }
3593 let(:response_body) { "Thanks for checking in." }
3594 allow(m).to receive(:[]) do |key|
3595 chunk_size = data_length > 10 ? 10 : data_length
3596 let(:request_type) { :direct }
3597 let(:response_headers) { {} }
3598 let(:request_type) { req_type.to_sym }
3599 let(:content_length_value) { "-1" }
3600 let(:content_length_value) { 25 }
3601 let(:streaming_length) { 12 }
3602 Chef::Config[:ssl_ca_path] = "/dev/null/nothing_here"
3603 Chef::Config[:ssl_ca_file] = "/dev/null/nothing_here"
3604 Chef::Config[:ssl_client_cert] = __FILE__
3605 File.write(bad_cert_file, File.read(__FILE__))
3606 let(:relative_url) { "" }
3607 let(:uri_str) { "chefzero://localhost:1/#{relative_url}" }
3608 let(:uri) { URI(uri_str) }
3609 it "has a host" do
3610 it "has a port" do
3611 let(:method) { :GET }
3612 let(:relative_url) { "clients" }
3613 let(:headers) { { "Accept" => "application/json" } }
3614 let(:body) { false }
3615 let(:expected_body_str) { "" }
3616 let(:rack_req) { zero_client.req_to_rack(method, uri, body, headers) }
3617 let(:method) { :PUT }
3618 let(:relative_url) { "clients/foo" }
3619 let(:body) { "bunch o' JSON" }
3620 let(:expected_body_str) { "bunch o' JSON" }
3621 let(:code) { 200 }
3622 let(:headers) { { "Content-Type" => "Application/JSON" } }
3623 let(:body) { [ "bunch o' JSON" ] }
3624 expect(net_http_response.read_body { |chunk| chunk }).to eq("bunch o' JSON")
3625 let(:code) { 404 }
3626 let(:body) { [ "nope" ] }
3627 let(:headers) { { "Accept" => "application/json", "X-Ops-Server-API-Version" => "2" } }
3628 let(:response_code) { 200 }
3629 let(:response_headers) { { "Content-Type" => "Application/JSON" } }
3630 let(:response_body) { [ "bunch o' JSON" ] }
3631 let(:url) { URI.parse("http://example.com") }
3632 let(:http_method) { :get }
3633 let(:data) { nil }
3634 let(:http_method) { :put }
3635 let(:data) { { foo: "bar" } }
3636 let(:expected_data) { %q[{"foo":"bar"}] }
3637 let(:data) { "some arbitrary bytes" }
3638 expect(headers).to eq({ "content-type" => "application/x-binary" })
3639 expect(headers).to eq({ "Content-Type" => "application/x-binary" })
3640 request = Chef::HTTP::HTTPRequest.new(:GET, URI("http://dummy.com:8000"), "", { "Host" => "yourhost.com:8888" })
3641 uri = URI("http://dummy.com/foo?bar=baz")
3642 expect(uri).to eql(URI("http://dummy.com/foo?bar=baz"))
3643 request = Chef::HTTP::HTTPRequest.new(:GET, URI("http://dummy.com:8000"), "", { "Host" => "myhost.com:80" })
3644 let(:uri) { URI("https://example.com:4443") }
3645 net_http_mock = instance_double(Net::HTTP, proxy_address: nil, "proxy_port=" => nil, "read_timeout=" => nil, "open_timeout=" => nil)
3646 require_relative "../../../lib/chef/win32/registry"
3647 let(:data) { "" }
3648 let(:node_name) { "test" }
3649 cert_name = "chef-#{node_name}"
3650 d = Time.now
3651 end_date = Time.new + (3600 * 24 * 90)
3652 raw_data = password_blob.map { |x| x[:data] }
3653 vector = raw_data[2]
3654 values = { name: "PfxPass", type: :string, data: encrypted_pass }
3655 ::Chef::Config[:node_name] = "foo"
3656 .to include({ "X-Ops-Server-API-Version" => "2" })
3657 let(:class_instance) { Chef::HTTP::Authenticator.new({ api_version: "-10" }) }
3658 .to include({ "X-Ops-Server-API-Version" => "-10" })
3659 ).and_return({})
3660 let(:public_key) { <<~EOH }
3661 let(:url) { "http://localhost:60123" }
3662 let(:return_value) { "406" }
3663 Chef::ServerAPIVersions.instance.set_versions({ "min_version" => 1, "max_version" => 3 })
3664 @all_resources = [Chef::Resource::Cat.new("lolz"), Chef::Resource::ZenMaster.new("tzu")]
3665 @end_time = @start_time + 4.2
3666 @all_resources = [Chef::Resource::Cat.new("foo"), Chef::Resource::ZenMaster.new("moo")]
3667 class << self
3668 expect(reported_data["end_time"]).to eq((@expected_time + 5).to_s)
3669 let(:resource) { Chef::Resource.new("foo") }
3670 let(:run_context) { Chef::RunContext.new(node, nil, nil) }
3671 expect(args[0]).to match(/^"ruby"/)
3672 @node = Chef::Node.new.tap do |n|
3673 n.run_list("role[base]")
3674 @response = Net::HTTPForbidden.new("1.1", "403", "(response) forbidden")
3675 not_if("/bin/false")
3676 @trace = [
3677 @context[:chef] = "cool"
3678 @resource = template("/tmp/foo.txt") do
3679 source_file = [ "if true", "var = non_existent", "end" ]
3680 expect(@inspector.recipe_snippet).to match(/^# In C:\\Windows\\Temp\\packer\\/)
3681 @resource.source_line = "(irb#1):1:in `irb_binding'"
3682 source_line = "#{angry_bash_recipe}:1:in `<main>'"
3683 @response = Net::HTTPBadGateway.new("1.1", "502", "(response) bad gateway")
3684 @response_body = %q({"error": [{"message": "gtfo"}])
3685 @response_body = "{\"error\":[{\"non_existent_cookbooks\":[],\"cookbooks_with_no_versions\":[],\"message\":\"unable to solve dependencies in allotted time.\"}]}"
3686 let(:node_name) { "test-node.example.com" }
3687 let(:stdout) { StringIO.new }
3688 recipe_lines = BAD_RECIPE.split("
").map { |l| l << "
" }
3689 let(:path_to_failed_file) { nil }
3690 let(:full_path_to_failed_file) { "C:/opscode/chef#{path_to_failed_file}" }
3691 trace_with_upcase_drive.map { |line| line.gsub(/^C:/, "c:") }
3692 let(:full_path_to_failed_file) { "c:/opscode/chef#{path_to_failed_file}" }
3693 let(:response) { double("response") }
3694 let(:min_version) { "2" }
3695 let(:max_version) { "5" }
3696 let(:request_version) { "30" }
3697 let(:title) { "test title" }
3698 let(:section_heading) { "test heading" }
3699 let(:section_text) { "test text" }
3700 allow(subject).to receive(:caller) { Kernel.caller + ["/test/bin/chef-client:1:in `<main>'"] }
3701 ------------
3702 Chef.set_node({ "platform" => "openvms", "platform_version" => "8.4-2L1" })
3703 let(:out) { StringIO.new }
3704 let(:err) { StringIO.new }
3705 cookbook_version = double(name: "apache2", version: "1.2.3")
3706 expect(out.string).to include("- apache2 (1.2.3")
3707 @now = Time.now
3708 allow(Time).to receive(:now).and_return(@now, @now + 10.0)
3709 allow(Time).to receive(:now).and_return(@now, @now + 610.0)
3710 allow(Time).to receive(:now).and_return(@now, @now + 36610.0)
3711 expect(out.string).to eq("")
3712 expect(out.string).to include(" - Progress: 70%")
3713 expect(out.string).to include(" - Progress: 80%")
3714 let(:formatter) { Chef::Formatters::Base.new(out, err) }
3715 let(:tempname) { windows? ? "chef-new_file" : ".chef-new_file" }
3716 let(:target_file_path) { "/etc/my_app.conf" }
3717 let(:original_target_file_dacl) { [] }
3718 let(:original_target_file_sacl) { [] }
3719 let(:empty_dacl) { double("Windows ACL with no dacl ACEs") }
3720 let(:empty_sacl) { double("Windows ACL with no sacl ACEs") }
3721 .with([])
3722 let(:dacl_inherits?) { false }
3723 let(:sacl_inherits?) { false }
3724 let(:dacl_inherits?) { true }
3725 let(:sacl_inherits?) { true }
3726 let(:target_file_mode) { 0644 }
3727 let(:target_file_uid) { 1001 }
3728 let(:target_file_gid) { 1001 }
3729 let(:target_file_uid) { 0 }
3730 let(:target_file_gid) { 20 }
3731 expect(File).to receive(:open).with(File.join(@file_cache_path, "whiz", "bang"), "w", 416).and_yield(@io)
3732 File.open(File.join(@file_cache_path, "whiz", "bang"), "w") { |f| f.print("borkborkbork") }
3733 expect(File).not_to exist(File.join(@file_cache_path, "whiz", "bang"))
3734 expect(Chef::FileCache.find("snappy/**/*")).to eq(%w{snappy/patter})
3735 load File.join(__dir__, "..", "..", "lib", "chef", "file_access_control.rb")
3736 @resource = Chef::Resource::File.new("/tmp/a_file.txt")
3737 expect(@fac.target_uid).to eq(-2)
3738 let(:num_errors) { 0 }
3739 let(:backtrace) { [] }
3740 let(:num_errors) { 1 }
3741 let(:num_errors) { 2 }
3742 subject.on(:foo_bar) {}
3743 subject.on(:run_failed) { "testhook" }
3744 calls = []
3745 @ivar = [1]
3746 @ivar << 2
3747 run_status = Chef::RunStatus.new({}, {})
3748 @sequence ||= []
3749 Accumulator.sequence << [ :sink_1_event_1, arg ]
3750 Accumulator.sequence << [ :sink_1_event_2, arg ]
3751 Accumulator.sequence << [ :sink_2_event_1, arg ]
3752 Accumulator.sequence << [ :sink_2_event_2, arg ]
3753 [:sink_1_event_1, "two"], # the call to enqueue the event happens here
3754 [:sink_2_event_1, "two"], # event 1 fully finishes
3755 [:sink_1_event_2, "two"],
3756 [:sink_2_event_2, "two"], # then event 2 runs and finishes
3757 expect(@environment.default_attributes({ one: "two" })).to eq({ one: "two" })
3758 expect(@environment.override_attributes({ one: "two" })).to eq({ one: "two" })
3759 @environment.cookbook("apt", "~> 1.2.3")
3760 expect(@environment.cookbook_versions["apt"]).to eq("~> 1.2.3")
3761 @environment.cookbook("apt", ">= 1.2.3")
3762 @environment.cookbook_versions({ "apt" => "= 1.2.3" })
3763 @example.cookbook_versions({ "apt" => "= 2.3.4" })
3764 @environment.cookbook_versions({ apt: "= 1.2.3" })
3765 it "should include '#{t}'" do
3766 expect(@json).to match(/"#{t}":#{Regexp.escape(Chef::JSONCompat.to_json(@environment.send(t.to_sym)))}/)
3767 @data = {
3768 it "should match '#{t}'" do
3769 expect(@environment.update_from_params(name: "@$%^&*()")).to be_falsey
3770 expect(@environment.invalid_fields[:name]).to eq(%q{Property name's value @$%^&*() does not match regular expression /^[\-[:alnum:]_]+$/})
3771 params = { name: "superbowl", cookbook_version: { "0" => "apache2 ~> 1.0.0", "1" => "nginx < 2.0.0" } }
3772 expect(@environment.cookbook_versions).to eq({ "apache2" => "~> 1.0.0", "nginx" => "< 2.0.0" })
3773 params = { cookbook_version: { "0" => "apache2 >>> 1.0.0" } }
3774 expect(@environment.default_attributes).to eq({ "fuuu" => "RAGE" })
3775 e1 = double("Chef::Environment", name: "one")
3776 expect(r["one"]).to eq(e1)
3777 role_dsl = "name \"foo\"
description \"desc\"
"
3778 let(:plaintext_data) { { "foo" => "bar" } }
3779 let(:key) { "passwd" }
3780 let(:plaintext_data) { 5 }
3781 let(:encryption_key) { "passwd" }
3782 let(:json_wrapped_data) { Chef::JSONCompat.to_json({ "json_wrapper" => plaintext_data }) }
3783 let(:bogus_auth_tag) { "bogus_auth_tag" }
3784 let(:decryption_key) { "wrong-passwd" }
3785 ev["cipher"] = "aes-256-foo"
3786 let(:secret) { "abc123SECRET" }
3787 it "doesn't encrypt the 'id' key" do
3788 iv = encoded_data["greeting"]["iv"]
3789 iv = encoded_data["nested"]["iv"]
3790 it "doesn't try to decrypt 'id'" do
3791 let(:secret) { "opensesame" }
3792 expect(tester.encrypted?({ id: "foo" })).to eq(false)
3793 let(:item_name) { "item_name" }
3794 let(:version) { 1 }
3795 let(:version) { 2 }
3796 let(:version) { 3 }
3797 }.each do |m|
3798 it "responds to ##{m}" do
3799 let(:service) { :hashi_vault }
3800 let(:config) { { my_key: "value" } }
3801 dsl.secret(name: "key1", service: :example, config: {})
3802 secret_value = dsl.secret(name: "test1", service: :example, config: { "test1" => "secret value" })
3803 let(:run_context) {
3804 peace secret(name: "test1", service: :example, config: { "test1" => true })
3805 config = { my_config: "value" }
3806 let(:declared_resources) { [] }
3807 r << [dsl_name, name]
3808 it { is_expected.to eq [[:test_resource, "test_name"]] }
3809 it { is_expected.to eq [[:test_resource, nil]] }
3810 hash = {
3811 echo = "foxtrot"
3812 golf = "hotel"
3813 kilo = ["lima", "mike"]
3814 bravo = 10
3815 juliett = "blue"
3816 - lima
3817 - mike
3818 let(:cookbook_name) { "example_cb" }
3819 let(:recipe_name) { "example_recipe" }
3820 recipe = Chef::Recipe.new(nil, nil, Chef::RunContext.new(Chef::Node.new, {}, nil))
3821 @node = node
3822 :openbsd => { default: "free, functional, secure" },
3823 %i{redhat centos fedora scientific} => { default: '"stable"' },
3824 :ubuntu => { "10.04" => "using upstart more", :default => "using init more" },
3825 :default => "bork da bork",
3826 node = { platform: "ubuntu", platform_version: "10.04" }
3827 node = { platform: "ubuntu", platform_version: "9.10" }
3828 bad_hash = { ubuntu: :foo } # should be :ubuntu => {:default => 'foo'}
3829 [:rhel, "fedora"] => "redhatty value",
3830 :gentoo => "gentoo value",
3831 :default => "default value",
3832 cookbook_repo = File.expand_path(File.join(__dir__, "..", "..", "data", "cookbooks"))
3833 ).to be nil
3834 .with("bag_name")
3835 .and_return("item_1" => "http://url_for/item_1", "item_2" => "http://url_for/item_2")
3836 expect( language.data_bag("bag_name").sort ).to eql %w{item_1 item_2}
3837 let(:bag_name) { "bag_name" }
3838 let(:item) do
3839 let(:method_name) { :data_bag_item }
3840 str.split("::").inject(Object) do |mod, class_name|
3841 @a = @r = @w = 1
3842 deprecated_attr :a, "a"
3843 test.a = 10
3844 test.w = 10
3845 expect(test.instance_eval { @w }).to eq 10
3846 let(:message) { "A test message" }
3847 let(:location) { "the location" }
3848 id_map = {}
3849 (id_map[cls.deprecation_id] ||= []) << cls
3850 collisions = id_map.select { |k, v| v.size != 1 }
3851 raise "Found deprecation ID collisions:
#{collisions.map { |k, v| "* #{k} #{v.map(&:name).join(", ")}" }.join("
")}"
3852 it "#is_a?(#{klass}) is true" do
3853 it "#is_a?(Chef::Decorator) is true" do
3854 it "#kind_of?(#{klass}) is true" do
3855 it "#kind_of?(Chef::Decorator) is true" do
3856 it "#instance_of?(#{klass}) is false" do
3857 let(:obj) {}
3858 it "#nil? is false" do
3859 it "!! is true" do
3860 let(:obj) { nil }
3861 it "#nil? is true" do
3862 it "!! is false" do
3863 let(:obj) { {} }
3864 expect(FFI_Yajl::Encoder.encode(decorator, pretty: true)).to eql("{

}
")
3865 let(:obj) { { foo: "bar", baz: "qux" } }
3866 decorator.dup[:baz] << "qux"
3867 decorator.__setobj__([])
3868 @a = 0
3869 Chef::Decorator::Lazy.new { @a += 1 }
3870 expect(@a).to eql(0)
3871 @foo ||= 1
3872 @bar ||= 2
3873 Chef::Decorator::LazyArray.new { [ foo, bar ] }
3874 decorator.each { |i| }
3875 let(:run_list) { node.run_list }
3876 let(:cookbooks) { node.fetch("cookbooks", {}) }
3877 let(:recipe_name) { "atlas" }
3878 let(:node_name) { "spitfire" }
3879 let(:resource_record) { [] }
3880 let(:exception) { nil }
3881 let(:expected_node) { node }
3882 keys ||= {
3883 { "Content-Type" => "application/json" }
3884 keys["message_version"] = "1.1.0"
3885 it "has a end_time" do
3886 it "has a run_id" do
3887 it "has a run_list" do
3888 it "has a source" do
3889 it "has a status" do
3890 let(:total_resource_count) { 0 }
3891 let(:status) { "failure" }
3892 let(:expected_node) { {} } # no node because that failed
3893 let(:expected_run_list) { [] } # no run_list without a node
3894 let(:resource_record) { [] } # and no resources
3895 let(:resource_record) { [ ] }
3896 let(:status) { "success" }
3897 let(:total_resource_count) { 1 }
3898 let(:cookbook_name) { "@recipe_files" }
3899 let(:cookbook_version) { nil }
3900 let(:total_resource_count) { 2 }
3901 rec["conditional"] = "not_if { #code block }" # FIXME: "#code block" is poor, is there some way to fix this?
3902 [ rec ]
3903 rec["conditional"] = 'not_if "true"'
3904 rec["error"] = {
3905 rec = resource_record_for(new_resource, nil, nil, :create, "failed", "1234")
3906 rec["before"] = {}
3907 rec1["error"] = {
3908 [ rec1, rec2 ]
3909 expect(hash["node"]["default"]).to eq({ "secret" => {}, "publicinfo" => { "num_flower_pots" => 18 } })
3910 expect(hash["node"]["default"]).to eq({ "public" => { "entrance" => "is the drawbridge" } })
3911 let(:shift_jis) { "I have no idea what this character is:
#{0x83.chr}#{0x80.chr}.
" }
3912 let(:message) { "message" }
3913 let(:err) do
3914 response = double("Net::HTTP response", code: "404")
3915 Chef::Config[:data_collector][:output_locations] = { files: [ "/always/be/counting/down" ] }
3916 Chef::Config[:data_collector][:output_locations] = { urls: [ "https://esa.local/ariane5" ] }
3917 Chef::Config[:data_collector][:token] = "MTA"
3918 Chef::Config[:data_collector][:output_locations] = { files: ["https://www.esa.local/ariane5"] }
3919 let(:file_path) { "/tmp/client-runs.txt" }
3920 Chef::Config[:data_collector][:output_locations] = { files: [file_path] }
3921 expect(@data_bag.name("clowns")).to eq("clowns")
3922 [ ".", "-", "_", "1"].each do |char|
3923 expect(@data_bag.name("clown#{char}clown")).to eq("clown#{char}clown")
3924 let(:jsonable) { @data_bag }
3925 exception = double("409 error", code: "409")
3926 expect(@rest).to receive(:post).with("data", @data_bag)
3927 expect(@http_client).to receive(:get).with("data/foo").and_return({ "bar" => "https://myserver.example.com/data/foo/bar" })
3928 data_bag = Chef::DataBag.load("foo")
3929 expect(data_bag).to eq({ "bar" => "https://myserver.example.com/data/foo/bar" })
3930 def dir_glob_stub(path, returns = [])
3931 if path == @paths.first
3932 dir_glob_stub(path, [File.join(path, "foo/bar.json"), File.join(path, "foo/baz.json")])
3933 expect(IO).to receive(:read).with(File.join(@paths.first, "foo/bar.json")).and_return('{"id": "bar", "name": "Bob Bar" }')
3934 expect(IO).to receive(:read).with(File.join(@paths.first, "foo/baz.json")).and_return('{"id": "baz", "name": "John Baz" }')
3935 item_with_different_content = "{\"id\": \"bar\", \"name\": \"Bob Bar\", \"path\": \"#{path}\"}"
3936 item_2_with_different_content = '{"id": "bar", "name": "John Baz"}'
3937 dir_glob_stub(path, [File.join(path, "foo/bar.json")])
3938 item_with_same_content = '{"id": "bar", "name": "Bob Bar"}'
3939 test_data_bag = { "bar" => { "id" => "bar", "name" => "Bob Bar" } }
3940 test_item_with_same_content = '{"id": "bar", "name": "Bob Bar"}'
3941 test_uniq_item = "{\"id\": \"baz_#{index}\", \"name\": \"John Baz\", \"path\": \"#{path}\"}"
3942 test_data_bag["baz_#{index}"] = { "id" => "baz_#{index}", "name" => "John Baz", "path" => path }
3943 expect(Dir).to receive(:glob).and_return([File.join(path, "foo"), File.join(path, "bar")])
3944 expect(data_bag_list).to eq({ "bar" => "bar", "foo" => "foo" })
3945 msg = "Data bag path '#{windows? ? "C:/var/chef" : "/var/chef"}/data_bags' not found. Please create this directory."
3946 it_should_behave_like "data bag in solo mode", "#{windows? ? "C:/var/chef" : "/var/chef"}/data_bags"
3947 expect { data_bag_item.raw_data = { "id" => "octahedron" } }.not_to raise_error
3948 expect { data_bag_item.raw_data = { id: "octahedron" } }.not_to raise_error
3949 expect { data_bag_item.raw_data = Mash.new({ "id" => "octahedron" }) }.not_to raise_error
3950 expect { data_bag_item.raw_data = { "monkey" => "pants" } }.to raise_error(ArgumentError)
3951 expect { data_bag_item.raw_data = { "id" => "h1-_" } }.not_to raise_error
3952 expect { data_bag_item.raw_data = { "id" => "foo.bar" } }.not_to raise_error
3953 expect { data_bag_item.raw_data = { "id" => ".bozo" } }.not_to raise_error
3954 expect { data_bag_item.raw_data = { "id" => "!@#" } }.to raise_error(ArgumentError)
3955 data_bag_item.raw_data = { "id" => "highway_of_emptiness" }
3956 expect(data_bag_item.raw_data).to eq({ "id" => "highway_of_emptiness" })
3957 data_bag_item.raw_data = { "id" => "the_beatdown" }
3958 data_bag_item.raw_data = { "id" => "the_beatdown", "name" => "Bruce" }
3959 expect(data_bag_item["name"]).to eq("Bruce")
3960 data_bag_item.raw_data = { "id" => "journey", "trials" => "been through" }
3961 expect(data_bag_item["id"]).to eq("journey")
3962 Chef::DataBagItem.from_hash({ "raw_data" => { "id" => "whoa", "name" => "Bruce", "i_know" => "kung_fu" } })
3963 expect(data_bag_item["id"]).to eq("whoa")
3964 Chef::DataBagItem.from_hash({ "id" => "whoa", "name" => "Bruce", "i_know" => "kung_fu" })
3965 data_bag_item.raw_data = { "id" => "whoa", "name" => "Bruce", "i_know" => "kung_fu" }
3966 let(:to_hash) { data_bag_item.to_hash }
3967 expect(to_hash["id"]).to eq("whoa")
3968 expect(to_hash["name"]).to eq("Bruce")
3969 expect(to_hash["i_know"]).to eq("kung_fu")
3970 expect(to_hash["chef_type"]).to eq("data_bag_item")
3971 expect(to_hash["data_bag"]).to eq("still_lost")
3972 data_bag_item.raw_data = { "id" => "octahedron", "name" => "Bruce", "snooze" => { "finally" => :world_will } }
3973 expect(deserial["name"]).to eq("Bruce")
3974 expect(deserial["snooze"]).to eq({ "finally" => "world_will" })
3975 let(:jsonable) { data_bag_item }
3976 data_bag_item["id"] = "heart of darkness"
3977 raw_data = { "id" => "heart_of_darkness", "author" => "Conrad" }
3978 expect(data_bag_item.inspect).to eq("data_bag_item[\"books\", \"heart_of_darkness\", #{raw_data.inspect}]")
3979 data_bag_item.raw_data = { "id" => "heart_of_darkness", "author" => "Conrad" }
3980 data_bag_item.raw_data = { "id" => "some_id" }
3981 data_bag_item.raw_data = { "id" => "charlie", "shell" => "zsh", "ssh_keys" => %w{key1 key2} }
3982 let(:http_client) { double("Chef::ServerAPI") }
3983 expect(Chef::DataBag).to receive(:load).with("users").and_return({ "charlie" => data_bag_item.to_hash })
3984 mock_struct = # Struct::Passwd.new(nil, nil, 111, 111)
3985 expect(Dir).to receive(:chdir).with("/").and_return(0)
3986 @pw_user = double("Struct::Passwd", uid: 501)
3987 @pw_group = double("Struct::Group", gid: 20)
3988 let(:cookbook_version) { Chef::CookbookVersion.new("mycb", "/tmp/mycb") }
3989 let(:root_files) { [{ name: "root_files/recipe.#{extension}", full_path: "/home/user/repo/cookbooks/test/recipe.#{extension}" } ] }
3990 MD5 = /[0-9a-f]{32}/.freeze
3991 all_files: Dir[File.join(cookbook_root, "**", "**")],
3992 n.normal[:platform] = "ubuntu"
3993 sm = Chef::CookbookVersion.new("foo", "/tmp/blah")
3994 lg = Chef::CookbookVersion.new("foo", "/tmp/blah")
3995 a = Chef::CookbookVersion.new("foo", "/tmp/blah")
3996 b = Chef::CookbookVersion.new("foo", "/tmp/blah")
3997 a.version = "1.2"
3998 b.version = "1.2.0"
3999 expect(a).to eq(b)
4000 apt = Chef::CookbookVersion.new "apt", "/tmp/blah"
4001 apt.version = "1.0"
4002 god = Chef::CookbookVersion.new "god", "/tmp/blah"
4003 god.version = "2.0"
4004 good_versions = %w{1.2 1.2.3 1000.80.50000 0.300.25}
4005 name: "files/afile.rb",
4006 name: "files/bfile.rb",
4007 path: "files/fakeos-2.0.rc.1/bfile.rb",
4008 set[cksum] = nil
4009 let(:policy_mode) { false }
4010 cksum_map[cksum] = { "needs_upload" => true, "url" => url_for(cksum) }
4011 { "checksums" => sandbox_checksums, "uri" => sandbox_commit_uri }
4012 let(:cksums_not_on_remote) { [] }
4013 let(:policy_mode) { true }
4014 COOKBOOK_PATH = File.expand_path(File.join(__dir__, "..", "data", "cookbooks", "openldap"))
4015 @cookbook_repo = File.expand_path(File.join(__dir__, "..", "data", "cookbooks"))
4016 let(:version) { "1.2.3" }
4017 let(:cookbook_root) { "/tmp/blah" }
4018 let(:all_files) { Dir[File.join(cookbook_root, "**", "**")].reject { |f| File.directory? f } }
4019 let(:match_md5) { /[0-9a-f]{32}/ }
4020 parts = relative_path.split("/")
4021 name = if %w{templates files}.include?(parts[0]) && parts.length == 3
4022 File.join(parts[0], parts[2])
4023 }.tap do |fp|
4024 fp["full_path"] = path
4025 files = map_to_file_specs(all_files, full: true).reject { |f| seg = f["name"].split("/")[0]; %w{ files templates }.include?(seg) }
4026 cookbook_loader[cb].files_for(part).inject([]) { |memo, f| memo << f[:full_path]; memo }
4027 cookbook_paths = []
4028 cookbook_paths |= Dir[File.join(repo_path, "*")]
4029 seen = {}
4030 end).not_to eql(nil)
4031 f =~ /\.dotfile$/
4032 end).to match(/\.dotfile$/)
4033 f =~ %r{\.ssh/id_rsa$}
4034 end).to match(%r{\.ssh/id_rsa$})
4035 search_str = "\"openldap\":\""
4036 expect(key_idx).to be > 0
4037 dup_idx = raw[(key_idx + 1)..-1].index(search_str)
4038 spec/spec_helper.rb }.map { |f| File.join(cookbook_path, f) }
4039 @attr_files = %w{default.rb smokey.rb}.map { |f| File.join(cookbook_path, "attributes", f) }
4040 @libr_files = %w{openldap.rb openldap/version.rb}.map { |f| File.join(cookbook_path, "libraries", f) }
4041 @defn_files = %w{client.rb server.rb}.map { |f| File.join(cookbook_path, "definitions", f) }
4042 @recipes = %w{default.rb gigantor.rb one.rb return.rb}.map { |f| File.join(cookbook_path, "recipes", f) }
4043 @spec_files = [ File.join(cookbook_path, "spec", "spec_helper.rb") ]
4044 @ruby_files = @attr_files + @libr_files + @defn_files + @recipes + @spec_files + [File.join(cookbook_path, "metadata.rb")]
4045 @template_files = @basenames.map { |f| File.join(cookbook_path, "templates", "default", f) }
4046 let(:cache_path) { Dir.mktmpdir }
4047 let(:no_lazy_load) { true }
4048 Chef::Config[:file_cache_path] = "/file-cache"
4049 { "valid1" => {}, "valid2" => {} }
4050 expect(synchronizer).to receive(:cookbook_segment).with("valid1", "recipes").at_least(:once).and_return([ { "path" => "recipes/default.rb" }])
4051 let(:root) { windows? ? "C:/file-cache/cookbooks/cookbook_a" : "/file-cache/cookbooks/cookbook_a" }
4052 .with("#{root}/recipes/default.rb")
4053 let(:server_api) { double("Chef::ServerAPI (mock)") }
4054 let(:file_cache) { double("Chef::FileCache (mock)") }
4055 let(:no_lazy_load) { false }
4056 let(:skip_cookbook_sync) { true }
4057 setter = "#{field}="
4058 duck_type.send("#{field_to_change}=".to_sym, :epic_fail)
4059 it "has no name" do
4060 it "is not valid" do
4061 it "is valid" do
4062 metadata.supports("ubuntu", ">= 8.04")
4063 expect(metadata.platforms["ubuntu"]).to eq(">= 8.04")
4064 params = {
4065 license: "Apache v2.0",
4066 version: "0.6.0",
4067 source_url: "http://example.com",
4068 it "should be set-able via #{field}" do
4069 it "should be get-able via #{field}" do
4070 it "should transform an '0.6' version to '0.6.0'" do
4071 expect(metadata.send(:version, "0.6")).to eql("0.6.0")
4072 it "should spit out '0.6.0' after transforming '0.6'" do
4073 metadata.send(:version, "0.6")
4074 dep_types = {
4075 depends: [ :dependencies, "foo::bar", "> 0.2" ],
4076 provides: [ :providing, "foo::bar", "<= 0.2" ],
4077 dep_types.sort_by(&:to_s).each do |dep, dep_args|
4078 it "should be set-able via #{dep}" do
4079 expect(metadata.send(check_with)).to eq({ dep_args[0] => dep_args[1] })
4080 depends: [ :dependencies, "foo::bar", ">0.2", "> 0.2" ],
4081 provides: [ :providing, "foo::bar", "<=0.2", "<= 0.2" ],
4082 depends: [ "foo::bar", "> 0.2", "< 1.0" ],
4083 provides: [ "foo::bar", "> 0.2", "< 1.0" ],
4084 depends: [ "foo::bar", ">> 0.2"],
4085 provides: [ "foo::bar", ">> 0.2"],
4086 it "can be set to a string" do
4087 it "can be set to an array" do
4088 metadata.send(:eager_load_libraries, [ "default.rb", "foo/*/**.rb" ])
4089 expect(metadata.send(:eager_load_libraries)).to eql([ "default.rb", "foo/*/**.rb" ])
4090 ret = []
4091 ret << Gem::Dependency.new("chef", *arg)
4092 expect_chef_version_works(["~> 12"])
4093 expect_chef_version_works([">= 12.0.1", "< 12.5.1"])
4094 expect_chef_version_works(["~> 12.5.1"], ["~> 11.18.10"])
4095 expect_chef_version_works([">= 11.14.2", "< 11.18.10"], [">= 12.2.1", "< 12.5.1"])
4096 expect_chef_version_works(["~> 999.0"])
4097 expect_chef_version_works([">= 999.0", "< 999.9"])
4098 expect_chef_version_works([">= 0.0.1", "< 0.0.9"])
4099 expect_chef_version_works([">= 999.0", "< 999.9"], [">= 0.0.1", "< 0.0.9"])
4100 expect_chef_version_works([">= 999.0", "< 999.9"], ["= #{Chef::VERSION}"])
4101 ret << Gem::Dependency.new("ohai", *arg)
4102 expect_ohai_version_works(["~> 12"])
4103 expect_ohai_version_works([">= 12.0.1", "< 12.5.1"])
4104 expect_ohai_version_works(["~> 12.5.1"], ["~> 11.18.10"])
4105 expect_ohai_version_works([">= 11.14.2", "< 11.18.10"], [">= 12.2.1", "< 12.5.1"])
4106 expect_ohai_version_works(["~> 999.0"])
4107 expect_ohai_version_works([">= 999.0", "< 999.9"])
4108 expect_ohai_version_works([">= 0.0.1", "< 0.0.9"])
4109 expect_ohai_version_works([">= 999.0", "< 999.9"], [">= 0.0.1", "< 0.0.9"])
4110 expect_ohai_version_works([">= 999.0", "< 999.9"], ["= #{Ohai::VERSION}"])
4111 ret << arg
4112 expect_gem_works(["foo", "~> 1.2"])
4113 expect_gem_works(["foo", "~> 1.2"], ["bar", "~> 2.0"])
4114 expect_gem_works(["foo", "~> 1.2"], ["bar", ">= 2.4", "< 4.0"])
4115 c.manifest = { all_files: [
4116 { name: "recipes/default.rb", path: "recipes/default.rb", checksum: "my_only_friend" },
4117 expect(metadata.recipes["test_cookbook"]).to eq("It, um... tests stuff?")
4118 metadata.depends "bobo", "= 1.0"
4119 metadata.depends "bubu", "=1.0"
4120 metadata.gem "foo", "~> 1.2"
4121 metadata.gem "bar", ">= 2.2", "< 4.0"
4122 metadata.chef_version "< 11.18.10", ">= 11.14.2"
4123 metadata.chef_version "< 12.5.1", ">= 12.2.1"
4124 metadata.ohai_version "< 7.5.0", ">= 7.1.0"
4125 metadata.ohai_version "< 8.6.0", ">= 8.0.1"
4126 metadata.eager_load_libraries [ "default.rb", "foo/*/**.rb" ]
4127 @hash[:dependencies.to_s]["foo::bar"] = [ ">= 1.0", "<= 5.2" ]
4128 expect(deserial.send(:dependencies)["foo::bar"]).to eq([])
4129 @hash[:dependencies.to_s]["foo::bar"] = []
4130 @hash[:dependencies.to_s]["foo::bar"] = [ ">= 2.0" ]
4131 expect(deserial.send(:dependencies)["foo::bar"]).to eq(">= 2.0")
4132 json = %q{{ "some_spiffy_new_metadata_field": "stuff its set to" }}
4133 expect(result["version"]).to eq "1.2.3"
4134 source_hash["frozen?"] = true
4135 it "with #{segment}" do
4136 gems: [["httpclient"], ["nokogiri"]]
4137 ),
4138 gems: [["httpclient", ">= 2.0"]]
4139 gems: [["httpclient", ">= 1.0", { "git" => "https://github.com/nahi/httpclient" }]]
4140 gems: [["httpclient", { "path" => "./gems/httpclient" }]]
4141 double(:shell_out, stdout: "")
4142 b = Bundler::Dsl.new
4143 expect(IO).to receive(:read).and_return("")
4144 Chef::Config[:rubygems_url] = [ "https://rubygems.org" ]
4145 expect(Chef::Log).to receive(:info).and_return("")
4146 expect(gem_installer).to receive(:shell_out!).with(["bundle", "install", "--local"], any_args).and_return(shell_out)
4147 let(:http) { double("Chef::ServerAPI") }
4148 let(:chefignore) { nil }
4149 loaded_cookbook.files_for(part).inject([]) { |memo, f| memo << f[:full_path]; memo }
4150 .with(/Ohai::Config\[:#{option}\] is deprecated/)
4151 let(:option) { :log_level }
4152 let(:value) { :debug }
4153 let(:option) { :log_location }
4154 let(:value) { "path/to/log" }
4155 let(:valid_json) { Chef::JSONCompat.to_json({ a: "b" }) }
4156 let(:invalid_json) { %q[{"syntax-error": "missing quote}] }
4157 let(:http) { double("Chef::HTTP::Simple") }
4158 let(:config_location) { "/etc/chef/client.rb" }
4159 let(:config_content) { "# The client.rb content" }
4160 let(:config_location) { "client.rb" }
4161 let(:config_location) { "/etc/chef/first-boot.json" }
4162 expect(fetcher.fetch_json).to eq({ "a" => "b" })
4163 let(:config_location) { "https://example.com/foo.json" }
4164 .with("").and_return(valid_json)
4165 let(:config_location) { nil }
4166 let(:data) { { "ssh-01" => { "expiration_date" => Date.jd(2463810), "justification" => "waived, yo", "run" => false } } }
4167 it "has a path" do
4168 string = <<~EOH
4169 let(:node) { Chef::Node.new(logger: logger) }
4170 r.node = node
4171 r.run_id = "my_run_id"
4172 node.normal["audit"]["profiles"]["ssh"] = { 'compliance': "base/ssh" }
4173 node.normal["audit"]["profiles"] = {}
4174 node.normal["audit"]["profiles"]["linux-baseline"] = {
4175 node.normal["audit"]["profiles"]["ssh"] = {
4176 version: "2.1.0",
4177 name: "ssh",
4178 node.normal["audit"]["profiles"] = [
4179 node.normal["audit"]["owner"] = "my_org"
4180 node.normal["audit"]["inspec_version"] = "90210"
4181 node.normal["audit"]["reporter"] = [ "invalid" ]
4182 node.normal["audit"]["fetcher"] = "invalid"
4183 node.normal["audit"]["attributes"] = {
4184 node.normal["audit"]["inputs"] = {
4185 node.normal["audit"]["reporter"] = [ "chef-automate" ]
4186 expect(inputs["tacos"]).to eq("lunch")
4187 expect(inputs["chef_node"]["audit"]["reporter"]).to eq(nil)
4188 expect(runner.node["audit"]["interval"]["time"]).to be 1440
4189 node.normal["audit"]["interval"]["enabled"] = true
4190 node.normal["audit"]["interval"]["time"] = 9
4191 report = {
4192 { "id": "c1", "results": [{ "status": "passed" }] },
4193 { "id": "c2", "results": [{ "status": "passed" }] },
4194 report = { "profiles": [{ "name": "empty" }] }
4195 report = { "profiles": [{ "controls": [{ "id": "empty" }] }] }
4196 { "id": "c2", "results": [{ "status": "failed" }] },
4197 Chef::Config[:client_key] = File.expand_path("../../../data/ssl/private_key.pem", __dir__)
4198 Chef::Config[:node_name] = "spec-node"
4199 node_info: {
4200 chef_tags: ["mylinux", "my.tag", "some=tag"],
4201 [{ "name": "tmp_compliance_profile",
4202 [{ "title": "A /tmp directory must exist",
4203 { "status": "passed", "code_desc": "File /tmp should be directory", "run_time": 0.002312, "start_time": "2016-10-19 11:09:43 -0400" },
4204 { "title": "/tmp directory is owned by the root user",
4205 { "status": "passed", "code_desc": 'File /tmp should be owned by "root"', "run_time": 1.228845, "start_time": "2016-10-19 11:09:43 -0400" },
4206 { "status": "skipped", "code_desc": 'File /tmp should be owned by "root"', "run_time": 1.228845, "start_time": "2016-10-19 11:09:43 -0400" },
4207 require "json" # For .to_json
4208 run_time_limit: 1.1,
4209 let(:token) { "fake_token" }
4210 ).to_return(
4211 body: {
4212 { "title": "/tmp Compliance Profile", "controls": ["tmp-1.0", "tmp-1.1"], "id": "controls/tmp.rb" },
4213 { "name": "syslog_pkg", "options": { "default": "rsyslog", "description": "syslog package..." } },
4214 body: '{"missing_sha256": []}'
4215 { "status": "passed", "code_desc": "File /tmp should be directory" },
4216 Chef::Config[:data_collector] = { token: "not_nil", server_url: nil }
4217 Chef::Config[:data_collector] = { token: nil, server_url: "not_nil" }
4218 Chef::Config[:data_collector] = { token: "not_nil", server_url: "not_nil" }
4219 [{ "id": "tmp-2.0",
4220 { "status": "passed", "code_desc": "File /etc should be directory", "run_time": 0.002314, "start_time": "2016-10-19 11:09:45 -0400" },
4221 { "status": "passed", "code_desc": "File /opt should be directory", "run_time": 0.002315, "start_time": "2016-10-19 11:09:46 -0400" },
4222 { "status": "skipped", "code_desc": "No-op", "run_time": 0.002316, "start_time": "2016-10-19 11:09:44 -0400", "skip_message": "4 testing" },
4223 { "status": "skipped", "code_desc": "No-op", "run_time": 0.002317, "start_time": "2016-10-19 11:09:44 -0400", "skip_message": "4 testing" },
4224 { "status": "skipped", "code_desc": "No-op", "run_time": 0.002318, "start_time": "2016-10-19 11:09:44 -0400", "skip_message": "4 testing" },
4225 { "status": "failed", "code_desc": "File /etc/passwd should be directory", "run_time": 0.002313, "start_time": "2016-10-19 11:09:44 -0400" },
4226 { "id": "tmp-2.1",
4227 { "status": "passed", "code_desc": 'File /etc should be owned by "root"', "run_time": 1.238845, "start_time": "2016-10-19 11:09:43 -0400" },
4228 statuses = truncated_report[:profiles][0][:controls][0][:results].map { |r| r[:status] }
4229 statuses = truncated_report[:profiles][0][:controls][1][:results].map { |r| r[:status] }
4230 expected = {
4231 other_checks: [],
4232 name: "syslog_pkg",
4233 options: {
4234 id: "tmp-1.0",
4235 results: [
4236 id: "tmp-1.1",
4237 code_desc: 'File /tmp should be owned by "root"',
4238 start_time: "2016-10-19 11:09:43 -0400",
4239 version: "0.1.1",
4240 version: "1.2.1",
4241 name: ssh-baseline#{" "}
4242 title: DevSec SSH Baseline#{" "}
4243 copyright_email: hello@dev-sec.io#{" "}
4244 license: Apache-2.0#{" "}
4245 version: 2.6.4#{" "}
4246 n.default["audit"] = {}
4247 node.default["audit"]["fetcher"] = "chef-server"
4248 version: "1.2.3"
4249 Chef::Config[:data_collector] = {
4250 version: "1.2.3",
4251 hash_including("token" => nil)
4252 allow(ohai).to receive(:[]) do |k|
4253 let(:client_opts) { {} }
4254 Chef::Config[:event_loggers] = []
4255 c.node = node
4256 let(:logger) { instance_double("Mixlib::Log::Child", trace: nil, debug: nil, warn: nil, info: nil, error: nil, fatal: nil) }
4257 let(:stderr) { StringIO.new }
4258 let(:api_client_exists?) { false }
4259 let(:runner) { instance_double("Chef::Runner") }
4260 .with("environments/_default/cookbook_versions", { run_list: [] })
4261 .and_return({})
4262 response = Net::HTTPNotFound.new("1.1", "404", "Not Found")
4263 Chef::Config[:cache_path] = windows? ? 'C:\chef' : "/var/chef"
4264 err.set_backtrace([ "/path/recipe.rb:15", "/path/recipe.rb:12" ])
4265 let(:hostname) { "test" }
4266 let(:my_client) { Chef::Client.new }
4267 let(:cert_name) { "chef-#{hostname}" }
4268 let(:node_name) { "#{hostname}" }
4269 if d.month == 10 || d.month == 11 || d.month == 12
4270 end_date = Time.new(d.year + 1, d.month - 9, d.day, d.hour, d.min, d.sec).utc.iso8601
4271 end_date = Time.new(d.year, d.month + 3, d.day, d.hour, d.min, d.sec).utc.iso8601
4272 Chef::Config[:node_name] = "test"
4273 Chef::Config[:auth_key_registry_type] == "user" ? store = "CurrentUser" : store = "LocalMachine"
4274 it "fails" do
4275 allow(Time).to receive(:now).and_return(Time.new(2021, 5, 1, 5))
4276 it "defaults to 1.1" do
4277 Chef::Config[:fips] = true
4278 it "defaults to 1.3" do
4279 let(:api_client_exists?) { true }
4280 Chef::Client.new(nil, override_runlist: "role[a], role[b]")
4281 let(:client_opts) { { override_runlist: "recipe[override_recipe]" } }
4282 let(:new_runlist) { "recipe[new_run_list_recipe]" }
4283 let(:client_opts) { { runlist: new_runlist } }
4284 let(:run_errors) { [converge_error] }
4285 @run_lock = double("Chef::RunLock", acquire: true)
4286 Chef::Config[:environment] = "A"
4287 test_env = { "name" => "A" }
4288 let(:http_response) { Net::HTTPNotFound.new("1.1", "404", "Not Found") }
4289 let(:fqdn) { nil }
4290 let(:machinename) { nil }
4291 let(:hostname) { nil }
4292 expect(Chef::VERSION).to match(/(\d+)\.(\d+)\.(\d+)/)
4293 expect(Chef::ChefFS::PathUtils.join("a", "b", "c")).to eq("a/b/c")
4294 expect(Chef::ChefFS::PathUtils.join("a/", "/b", "/c/")).to eq("a/b/c")
4295 expect(Chef::ChefFS::PathUtils.join("a/", "/b", "///c/")).to eq("a/b/c")
4296 expect(Chef::ChefFS::PathUtils.join("/a/", "/b", "c/")).to eq("/a/b/c")
4297 expect(Chef::ChefFS::PathUtils.join("///a/", "/b", "c/")).to eq("/a/b/c")
4298 let(:good_path) { __dir__ }
4299 it "handles paths with .. and ." do
4300 expect(Chef::ChefFS::PathUtils.realest_path(good_path + "/*/foo")).to eq(File.expand_path(good_path + "/*/foo"))
4301 expect(Chef::ChefFS::PathUtils.realest_path("C:/")).to eq("C:/")
4302 expect(Chef::ChefFS::PathUtils.realest_path("/")).to eq("/")
4303 expect(Chef::ChefFS::PathUtils.descendant_path("C:/ab/b/c", "C:/AB/B")).to eq("c")
4304 expect(Chef::ChefFS::PathUtils.descendant_path("C:/ab/b/c", "c:/ab/B")).to eq("c")
4305 expect(Chef::ChefFS::PathUtils.descendant_path("/D/E/F", "/A/B/C")).to be_nil
4306 expect(Chef::ChefFS::PathUtils.descendant_path("/A/B/D", "/A/B/C")).to be_nil
4307 expect(Chef::ChefFS::PathUtils.descendant_path("/A/B/D", "/A/B/D")).to eq("")
4308 describe Chef::ChefFS::FileSystem, ruby: ">= 3.0" do
4309 let(:fs) { memory_fs("", {}) }
4310 it "/" do
4311 list_should_yield_paths(fs, "/", "/")
4312 it "/a" do
4313 list_should_yield_paths(fs, "/a", "/a")
4314 it "/a/b" do
4315 list_should_yield_paths(fs, "/a/b", "/a/b")
4316 it "/*" do
4317 list_should_yield_paths(fs, "/*", "/")
4318 expect(Chef::ChefFS::FileSystem.resolve_path(fs, "/").path).to eq("/")
4319 expect(Chef::ChefFS::FileSystem.resolve_path(fs, "/a").path).to eq("/a")
4320 expect(Chef::ChefFS::FileSystem.resolve_path(fs, "/a/b").path).to eq("/a/b")
4321 let(:fs) do
4322 memory_fs("", {
4323 a: {
4324 aa: {
4325 c: "",
4326 zz: "",
4327 ab: {
4328 x: "",
4329 y: {},
4330 it "/**" do
4331 list_should_yield_paths(fs, "/*", "/", "/a", "/x", "/y")
4332 it "/*/*" do
4333 list_should_yield_paths(fs, "/*/*", "/a/aa", "/a/ab")
4334 it "/*/*/*" do
4335 list_should_yield_paths(fs, "/*/*/*", "/a/aa/c", "/a/aa/zz", "/a/ab/c")
4336 it "/*/*/?" do
4337 list_should_yield_paths(fs, "/*/*/?", "/a/aa/c", "/a/ab/c")
4338 it "/a/*/c" do
4339 list_should_yield_paths(fs, "/a/*/c", "/a/aa/c", "/a/ab/c")
4340 it "/**b/c" do
4341 list_should_yield_paths(fs, "/**b/c", "/a/ab/c")
4342 it "/a/ab/c" do
4343 list_should_yield_paths(fs, "/a/ab/c", "/a/ab/c")
4344 list_should_yield_paths(fs, "/a/ab/blah", "/a/ab/blah")
4345 list_should_yield_paths(fs, "/a/ab/blah/bjork", "/a/ab/blah/bjork")
4346 it "resolves /" do
4347 it "resolves /x" do
4348 expect(Chef::ChefFS::FileSystem.resolve_path(fs, "/x").path).to eq("/x")
4349 it "resolves /a" do
4350 it "resolves /a/aa" do
4351 expect(Chef::ChefFS::FileSystem.resolve_path(fs, "/a/aa").path).to eq("/a/aa")
4352 it "resolves /a/aa/zz" do
4353 expect(Chef::ChefFS::FileSystem.resolve_path(fs, "/a/aa/zz").path).to eq("/a/aa/zz")
4354 expect(Chef::ChefFS::FileSystem.resolve_path(fs, "/q/x/w").path).to eq("/q/x/w")
4355 it "is not empty /" do
4356 it "is empty /y" do
4357 !is_dir && File.extname(name) == ".json"
4358 let(:root) do
4359 context "#empty?" do
4360 dir = described_class.new(".test", root, tmp_dir)
4361 let(:file) do
4362 let(:content) { '"name": "canteloup"' }
4363 let(:file_path) { File.join(tmp_dir, "test_file.json") }
4364 let(:error_message) { 'HTTP error writing: 400 "Bad Request"' }
4365 response_body = '{"error":["Invalid key test in request body"]}'
4366 def p(str)
4367 let(:pattern) { Chef::ChefFS::FilePattern.new("") }
4368 it "match?" do
4369 expect(pattern.match?("/")).to be_falsey
4370 let(:pattern) { Chef::ChefFS::FilePattern.new("/") }
4371 expect(pattern.match?("/")).to be_truthy
4372 let(:pattern) { Chef::ChefFS::FilePattern.new("abc") }
4373 let(:pattern) { Chef::ChefFS::FilePattern.new("/abc") }
4374 expect(pattern.exact_child_name_under("/")).to eq("abc")
4375 let(:pattern) { Chef::ChefFS::FilePattern.new("abc/def/ghi") }
4376 let(:pattern) { Chef::ChefFS::FilePattern.new("/abc/def/ghi") }
4377 let(:pattern) { Chef::ChefFS::FilePattern.new('a\*\b') }
4378 context 'with star pattern "/abc/*/ghi"' do
4379 let(:pattern) { Chef::ChefFS::FilePattern.new("/abc/*/ghi") }
4380 let(:pattern) { Chef::ChefFS::FilePattern.new("/abc/d*f/ghi") }
4381 context 'with star pattern "/abc/d??f/ghi"' do
4382 let(:pattern) { Chef::ChefFS::FilePattern.new("/abc/d??f/ghi") }
4383 context 'with star pattern "/abc/d[a-z][0-9]f/ghi"', skip: (ChefUtils.windows?) do
4384 let(:pattern) { Chef::ChefFS::FilePattern.new("/abc/d[a-z][0-9]f/ghi") }
4385 context 'with star pattern "/abc/**/ghi"' do
4386 let(:pattern) { Chef::ChefFS::FilePattern.new("/abc/**/ghi") }
4387 expect(pattern.match?("/abc/d/e/f/ghi")).to be_truthy
4388 context 'with star pattern "/abc**/ghi"' do
4389 let(:pattern) { Chef::ChefFS::FilePattern.new("/abc**/ghi") }
4390 context 'with star pattern "/abc/**ghi"' do
4391 let(:pattern) { Chef::ChefFS::FilePattern.new("/abc/**ghi") }
4392 context 'with star pattern "a**b**c"' do
4393 let(:pattern) { Chef::ChefFS::FilePattern.new("a**b**c") }
4394 expect(pattern.match?("a/x/y/b/z/w/c")).to be_truthy
4395 expect(p("abc/").normalized_pattern).to eq("abc")
4396 expect(p("abc/").exact_path).to eq("abc")
4397 expect(p("abc/").match?("abc")).to be_truthy
4398 expect(p("//").normalized_pattern).to eq("/")
4399 expect(p("//").exact_path).to eq("/")
4400 expect(p("//").match?("/")).to be_truthy
4401 expect(p("/./").normalized_pattern).to eq("/")
4402 expect(p("/./").exact_path).to eq("/")
4403 expect(p("/./").match?("/")).to be_truthy
4404 expect(p("abc//def").exact_path).to eq("abc/def")
4405 expect(p("abc//def").match?("abc/def")).to be_truthy
4406 expect(p("abc//").normalized_pattern).to eq("abc")
4407 expect(p("abc//").exact_path).to eq("abc")
4408 expect(p("abc//").match?("abc")).to be_truthy
4409 expect(p("abc/./def").normalized_pattern).to eq("abc/def")
4410 expect(p("abc/./def").exact_path).to eq("abc/def")
4411 expect(p("abc/./def").match?("abc/def")).to be_truthy
4412 expect(p("./abc/def").normalized_pattern).to eq("abc/def")
4413 expect(p("./abc/def").exact_path).to eq("abc/def")
4414 expect(p("./abc/def").match?("abc/def")).to be_truthy
4415 expect(p("/.").normalized_pattern).to eq("/")
4416 expect(p("/.").exact_path).to eq("/")
4417 expect(p("/.").match?("/")).to be_truthy
4418 expect(p("abc/../def").normalized_pattern).to eq("def")
4419 expect(p("abc/../def").exact_path).to eq("def")
4420 expect(p("abc/../def").match?("def")).to be_truthy
4421 expect(p("abc/def/../..").normalized_pattern).to eq("")
4422 expect(p("abc/def/../..").exact_path).to eq("")
4423 expect(p("abc/def/../..").match?("")).to be_truthy
4424 expect(p("/*/../def").normalized_pattern).to eq("/def")
4425 expect(p("/*/../def").exact_path).to eq("/def")
4426 expect(p("/*/../def").match?("/def")).to be_truthy
4427 expect(p("/*/*/../def").normalized_pattern).to eq("/*/def")
4428 expect(p("/*/*/../def").exact_path).to be_nil
4429 expect(p("/*/*/../def").match?("/abc/def")).to be_truthy
4430 expect(p("/abc/def/../..").normalized_pattern).to eq("/")
4431 expect(p("/abc/def/../..").exact_path).to eq("/")
4432 expect(p("/abc/def/../..").match?("/")).to be_truthy
4433 expect(p("abc/../../def").normalized_pattern).to eq("../def")
4434 expect(p("abc/../../def").exact_path).to eq("../def")
4435 expect(p("abc/../../def").match?("../def")).to be_truthy
4436 expect(p("abc**/def/../ghi").exact_path).to be_nil
4437 expect(p("abc**/def/../ghi").match?("abc/ghi")).to be_truthy
4438 expect(p("abc**/def/../ghi").match?("abc/x/y/z/ghi")).to be_truthy
4439 expect(p("abc**/def/../ghi").match?("ghi")).to be_falsey
4440 expect { Chef::ChefFS::FilePattern.new("abc/**/abc/../../def").exact_path }.to raise_error(ArgumentError)
4441 expect(p("../abc/def").exact_path).to eq("../abc/def")
4442 expect(p("../abc/def").match?("../abc/def")).to be_truthy
4443 expect(p("/../abc/def").exact_path).to eq("/abc/def")
4444 expect(p("/../abc/def").match?("/abc/def")).to be_truthy
4445 expect(p("..").exact_path).to eq("..")
4446 expect(p("..").match?("..")).to be_truthy
4447 expect(p("/..").exact_path).to eq("/")
4448 expect(p("/..").match?("/")).to be_truthy
4449 describe "diff", uses_diff: true, ruby: ">= 3.0" do
4450 diff = diff.gsub(/([+-]{3}.*)\t.*/, '\1 DATE')
4451 let(:a) do
4452 memory_fs("a", {
4453 both_dirs: {
4454 sub_both_dirs: { subsub: nil },
4455 sub_both_dirs_empty: {},
4456 sub_dirs_empty_in_a_filled_in_b: {},
4457 sub_dirs_empty_in_b_filled_in_a: { subsub: nil },
4458 sub_a_only_dir: { subsub: nil },
4459 sub_dir_in_a_file_in_b: {},
4460 sub_file_in_a_dir_in_b: nil,
4461 both_dirs_empty: {},
4462 dirs_empty_in_a_filled_in_b: {},
4463 dirs_empty_in_b_filled_in_a: { subsub: nil },
4464 dirs_in_a_cannot_be_in_b: {},
4465 file_in_a_cannot_be_in_b: nil,
4466 a_only_dir: { subsub: nil },
4467 dir_in_a_file_in_b: {},
4468 file_in_a_dir_in_b: nil,
4469 }, /cannot_be_in_a/)
4470 let(:b) do
4471 memory_fs("b", {
4472 sub_dirs_empty_in_a_filled_in_b: { subsub: nil },
4473 sub_dirs_empty_in_b_filled_in_a: {},
4474 sub_b_only_dir: { subsub: nil },
4475 sub_dir_in_a_file_in_b: nil,
4476 sub_file_in_a_dir_in_b: {},
4477 dirs_empty_in_a_filled_in_b: { subsub: nil },
4478 dirs_empty_in_b_filled_in_a: {},
4479 dirs_in_b_cannot_be_in_a: {},
4480 file_in_b_cannot_be_in_a: nil,
4481 b_only_dir: { subsub: nil },
4482 dir_in_a_file_in_b: nil,
4483 file_in_a_dir_in_b: {},
4484 }, /cannot_be_in_b/)
4485 Chef::ChefFS::CommandLine.diff_print(pattern("/"), a, b, nil, nil) do |diff|
4486 -a
4487 +b
4488 --- a/both_dirs/sub_a_only_file DATE
4489 +++ b/both_dirs/sub_b_only_file DATE
4490 --- a/a_only_file DATE
4491 +++ b/b_only_file DATE
4492 Chef::ChefFS::CommandLine.diff_print(pattern("/both_dirs"), a, b, nil, nil) do |diff|
4493 Chef::ChefFS::CommandLine.diff_print(pattern("/"), a, b, 1, nil) do |diff|
4494 it "Chef::ChefFS::CommandLine.diff_print(/*_*) with depth 0" do
4495 Chef::ChefFS::CommandLine.diff_print(pattern("/*_*"), a, b, 0, nil) do |diff|
4496 Chef::ChefFS::CommandLine.diff_print(pattern("/"), a, b, nil, :name_only) do |diff|
4497 Chef::ChefFS::CommandLine.diff_print(pattern("/"), a, b, nil, :name_status) do |diff|
4498 @name = name
4499 @org = org
4500 { "name" => "worker_bees",
4501 { "actors" =>
4502 { "users" => %w{fizz buzz},
4503 { "name" => "grizzly",
4504 { "family" => "ursidae",
4505 @name = bag_name
4506 @name = "#{item_name}.json"
4507 let(:entry) { TestDataBagItem.new("luggage", "bag") }
4508 { "raw_data" => { "id" => "duffel" } }
4509 { "raw_data" => { "id" => "bag" } }
4510 let(:entry) { TestDataBagItem.new(bag_name.to_s, "bag") }
4511 it "allows the data bag name '#{bag_name}'" do
4512 base_config = {}
4513 ui = double("ui")
4514 Chef::ChefFS::Config.new(base_config, Dir.pwd, {}, ui)
4515 base_config[:chef_server_url] = "http://foo.com/"
4516 Mash.new({
4517 node_path: "/base_path/nodes",
4518 role_path: "/base_path/roles",
4519 user_path: "/base_path/users",
4520 chef_repo_path: "/base_path",
4521 chef_repo_path: %w{ /base_path /second_base_path },
4522 expect(cfg.server_path("/base_path/cookbooks")).to eq("/")
4523 let(:cwd) { "/base_path/cookbooks" }
4524 expect(cfg.server_path("../roles/blah")).to eql("/roles/blah")
4525 expect(Chef::ChefFS::PathUtils).to receive(:realest_path).with("../../readme.txt", cwd).and_return("/readme.txt")
4526 expect(cfg.server_path("../../readme.txt")).to be_nil
4527 expect(Chef::ChefFS::PathUtils).to receive(:realest_path).with("*/*ab*", cwd).and_return("/base_path/cookbooks/*/*ab*")
4528 expect(cfg.server_path("*/*ab*")).to eql("/cookbooks/*/*ab*")
4529 let(:path) { "/roles/foo.json" }
4530 let(:entry) { Entry.new(path) }
4531 expect(cfg.format_path(entry)).to eq(".")
4532 cfg = Chef::ChefFS::Config.new(config, "/base_path")
4533 expect(cfg).to receive(:base_path).and_return("/").at_least(:once)
4534 let(:platform) { "debian" }
4535 x = 1
4536 x = 2
4537 expect(x).to eq(2)
4538 Chef::Config[:silence_deprecation_warnings] = [__LINE__ + 4]
4539 Chef::Config[:silence_deprecation_warnings] = ["chef_class_spec.rb:#{__LINE__ + 4}"]
4540 Chef::Config[:silence_deprecation_warnings] = ["exit_code", "chef_class_spec.rb:#{__LINE__ + 6}"]
4541 expect { Chef.deprecated(:generic, "I'm a little teapot.") }.to raise_error(/I'm a little teapot./)
4542 let(:config_content) { "rspec_ran('true')" }
4543 let(:config_location) { "/etc/chef/default.rb" }
4544 Chef::Config[:log_level] = :auto
4545 expect { app.run_chef_client([]) }.not_to raise_error
4546 let(:tempfile) { Tempfile.new("default.rb").path }
4547 let(:fatal) { false }
4548 allow(app).to receive(:cli_arguments).and_return(["", "test"])
4549 let(:app) { Chef::Application::Solo.new }
4550 Chef::Config[:solo] = true
4551 Chef::Config[:splay] = nil
4552 let(:json_source) { "https://foo.com/foo.json" }
4553 expect(archive).to receive(:extract).with("#{Dir.tmpdir}/chef-solo", { perms: false, ignore: /^\.$/ })
4554 json_attribs = { "a" => "b" }
4555 Chef::Config[:json_attribs] = "https://foo.com/foo.json"
4556 let(:dot_d_config_name) { :solo_d_dir }
4557 let(:root_path) { windows? ? "C:/var/chef" : "/var/chef" }
4558 it "deletes --ez" do
4559 expect(ARGV.include?("--ez")).to be_falsey
4560 run_count = 0
4561 run_count += 1
4562 if run_count > 3
4563 let(:app) do
4564 a.cli_arguments = []
4565 cli_arguments ||= ""
4566 describe "--[no]-fork" do
4567 chef_server_url: "http://example", policy_name: "web"
4568 ARGV.replace(["--config-option", ""])
4569 ARGV.replace(["--config-option", "asdf"])
4570 let(:archive) { double }
4571 let(:config_exists) { false }
4572 ARGV.replace(["--recipe-url=test_url"])
4573 ARGV.replace(["--local-mode", "--recipe-url=test_url"])
4574 ARGV.replace(["--local-mode", "--recipe-url=test_url", "--delete-entire-chef-repo"])
4575 .with("the_path_to_the_repo", secure: true)
4576 it "sets { recipe_url: 'test_url' }" do
4577 .with("the_path_to_the_repo")
4578 .with("test_url", File.join("the_path_to_the_repo", "recipes.tgz"))
4579 .with(File.join("the_path_to_the_repo", "recipes.tgz"))
4580 .with("the_path_to_the_repo", perms: false, ignore: /^\.$/)
4581 let(:config_exists) { true }
4582 File.join("the_path_to_the_repo", ".chef/config.rb")
4583 Chef::Config[:once] = true
4584 let(:daemonize) { true }
4585 let(:wait_secs) { 1 }
4586 let(:daemonize) { wait_secs }
4587 pid = fork do
4588 Chef::Config[:splay] = 60
4589 Chef::Config[:pid_file] = "/path/to/file"
4590 Chef::Config[:lockfile] = "/path/to/file"
4591 let(:dot_d_config_name) { :client_d_dir }
4592 let(:app) { Chef::Application::Client.new }
4593 @pipe = IO.pipe
4594 @pipe[1].puts "started"
4595 expect(@pipe[0].gets).to eq("started
")
4596 expect(IO.select([@pipe[0]], nil, nil, 15)).not_to be_nil
4597 expect(@pipe[0].gets).to eq("finished
")
4598 expect(IO.select([@pipe[0]], nil, nil, 0)).not_to be_nil
4599 Chef::Config[:splay] = 10
4600 let(:validation_path) { "" }
4601 @recipe_file_name = "foo.rb"
4602 @recipe_file = double("Tempfile (mock)", read: @recipe_text)
4603 expect { @app.run }.to raise_error(SystemExit) { |e| expect(e.status).to eq(1) }
4604 @json = @client.to_json
4605 let(:jsonable) { @client }
4606 client = {
4607 Chef::Config[:node_name] = nil
4608 File.open(Chef::Config[:client_key], "r") { |f| f.read.chomp }
4609 name: "some_name",
4610 let(:rest_v0) { @client.chef_rest_v0 }
4611 let(:rest_v1) { @client.chef_rest_v1 }
4612 expect(rest). to receive(:put).with("clients/some_name", { name: "some_name" }).and_return({ name: "some_name" })
4613 let(:rest) { @client.chef_rest_v1 }
4614 let(:rest) { @client.chef_rest_v0 }
4615 expect(@client.chef_rest_v0).to receive(:put).with("clients/#{@client.name}", payload.merge({ private_key: true })).and_return({})
4616 @api_client_with_key = { "name" => "lost-my-key", "private_key" => "the new private key" }
4617 let(:client_name) { "silent-bob" }
4618 File.open(Chef::Config[:validation_key], "r") { |f| f.read.chomp }
4619 let(:http_mock) { double("Chef::ServerAPI mock") }
4620 let(:response_409) { Net::HTTPConflict.new("1.1", "409", "Conflict") }
4621 { "name" => client_name,
4622 { name: client_name, admin: false }
4623 expect(IO.read(key_location)).to eq("--begin rsa key etc--")
4624 @server = nil
4625 def get(path, response_code, data = nil, headers = nil, &block)
4626 def put(path, response_code, data = nil, headers = nil, &block)
4627 debug_info = { message: "no data matches the request for #{env["REQUEST_URI"]}",
4628 [404, { "Content-Type" => "application/json" }, [ Chef::JSONCompat.to_json(debug_info) ]]
4629 @path_spec === uri
4630 HEADERS = { "Content-Type" => "application/json" }.freeze
4631 @block = block_given? ? block : nil
4632 data = @data || @block.call
4633 expect(rest_v1).to receive(:post).with(url, payload.merge({ public_key: "some_public_key" })).and_return({})
4634 expect(rest_v1).to receive(:post).with(url, payload.merge({ create_key: true })).and_return({})
4635 expect(rest_v0).to receive(:post).with(url, payload.merge({ public_key: "some_public_key" })).and_return({})
4636 non_unique: false })
4637 combined_opts = []
4638 combined_opts << option << "hola"
4639 expect(provider.useradd_options).to eq([ "-r", "-m" ])
4640 it "should set -m -d /homedir" do
4641 command = ["useradd",
4642 command.concat([ "-s", "/usr/bin/zsh",
4643 command = ["usermod",
4644 command.concat([ { returns: [0, 12] } ])
4645 @stdout = "root P 09/02/2008 0 99999 7 -1"
4646 .with("passwd", "-S", @new_resource.username, { returns: [0, 1] })
4647 @stdout = "root N"
4648 @stdout = "root L"
4649 ].each do |home_check|
4650 windows? ? normalized_path.tr("\\", "/") : normalized_path
4651 slug = "#{basename}-#{rand(1 << 128)}"
4652 stat_struct = double("::File.stat", mode: 0600, uid: 0, gid: 0, mtime: 10000)
4653 let(:tempfile_name) { "foo-bar-baz" }
4654 t = double("Tempfile", path: "/tmp/#{tempfile_name}", closed?: true)
4655 Chef::Config[:file_cache_path] = "/tmp"
4656 tempfile = double("Tempfile", path: "/tmp/foo-bar-baz")
4657 let(:tempfile_path) { "/tmp/foo-bar-baz" }
4658 let(:diff_for_reporting) { "+++
---
+foo
-bar
" }
4659 diff = double("Diff", for_output: ["+++", "---", "+foo", "-bar"],
4660 @platform_hash = {}
4661 @platform_hash[x] = {
4662 @platform_hash["debian"] = { %w{5 6} => "debian-5/6", "default" => "debian" }
4663 @platform_hash["exact_match"] = { "1.2.3" => "exact", ">= 1.0" => "not exact" }
4664 @platform_hash["multiple_matches"] = { "~> 2.3.4" => "matched ~> 2.3.4", ">= 2.3" => "matched >=2.3" }
4665 @platform_hash["invalid_cookbook_version"] = { ">= 21" => "Matches a single number" }
4666 @platform_hash["successful_matches"] = { "< 3.0" => "matched < 3.0", ">= 3.0" => "matched >= 3.0" }
4667 %i{rhel fedora} => "redhatty value",
4668 node = {}
4669 it "should not require .0 to match >= 21.0" do
4670 @platform_hash = {
4671 @properties = {
4672 stdout: "",
4673 stderr: "",
4674 it "exits 1" do
4675 def memory_fs_value(value, name = "", parent = nil)
4676 if value.is_a?(Hash)
4677 result_paths = []
4678 test_hash = { one: :two }
4679 @resource.cwd("/tmp/")
4680 @resource.environment({ one: :two })
4681 let(:client_d_dir) { nil }
4682 File.join(__dir__, "../../../data/client.d_00")
4683 File.join(__dir__, "../../data/client.d_01")
4684 File.join(__dir__, "../../data/client.d_02")
4685 @config = {
4686 @response = Net::HTTPBadRequest.new("1.1", "400", "(response) bad request")
4687 @response = Net::HTTPNotFound.new("1.1", "404", "(response) not found")
4688 expected = if windows? && ENV[varname].nil?
4689 actual && actual == exp_code
4690 (actual.nil? ? " not called" : "(#{actual}) was called")
4691 if args.length == 1
4692 args = args[0].split(/\s+/)
4693 puts "knife: #{args.join(" ")}" if DEBUG
4694 Chef::Config[:verbosity] = ( DEBUG ? 2 : 0 )
4695 logger.formatter = proc { |severity, datetime, progname, msg| "#{severity}: #{msg}
" }
4696 Chef::Log.level = ( DEBUG ? :debug : :warn )
4697 exit_code = 0
4698 expected = {}
4699 if arg.is_a?(Hash)
4700 expected[:stdout] = expected[:stdout].is_a?(String) ? expected[:stdout].gsub(/[ \t\f\v]+$/, "") : expected[:stdout]
4701 expected[:stderr] = expected[:stderr].is_a?(String) ? expected[:stderr].gsub(/[ \t\f\v]+$/, "") : expected[:stderr]
4702 stderr_actual = stderr_actual.gsub(/[ \t\f\v]+$/, "")
4703 stdout_actual = stdout_actual.gsub(/[ \t\f\v]+$/, "")
4704 stderr_actual = stderr_actual.gsub("\r
", "
")
4705 stdout_actual = stdout_actual.gsub("\r
", "
")
4706 context("when the chef repo #{desc}", *tags) do
4707 FileUtils.mkdir_p(dir) unless dir == "."
4708 File.open(filename, "w") do |file|
4709 @old_cwd = Dir.pwd
4710 expected_architecture == :i386 ? "X86" : "AMD64"
4711 let(:guard_architecture) { :x86_64 }
4712 let(:read_access_denied_command) { "::File.read('#{script_file_path}')" }
4713 let(:modify_access_denied_command) { "::File.write('#{script_file_path}', 'stuff')" }
4714 let(:delete_access_denied_command) { "::File.delete('#{script_file_path}')" }
4715 let(:command_template) { "set BUNDLE_GEMFILE=&#{ruby_interpreter_path} -e \"#{ruby_command_template}\"" }
4716 resource.code("chcp > \"#{script_output_path}\"")
4717 File.read("#{script_output_path}#{suffix}")
4718 if ohai[:platform] == "aix"
4719 let(:expected_user_name) { "guest" }
4720 let(:expected_user_name) { "nobody" }
4721 let(:desired_gid) { 1337 }
4722 let(:expected_gid) { 1337 }
4723 let(:set_mode) { "0740" }
4724 let(:expected_mode) { "0740" }
4725 let(:set_mode) { 00740 }
4726 expect(current_resource.mode).to eq("0#{(0666 & ~File.umask).to_s(8)}")
4727 let(:default_create_mode) { 0666 & ~File.umask }
4728 let(:expected_mode) { "0#{default_create_mode.to_s(8)}" }
4729 let(:set_mode) { 0666 & ~File.umask }
4730 let(:expected_mode) { "0#{set_mode.to_s(8)}" }
4731 let(:expected_user_name) { "Guest" }
4732 let(:expected_user_name) { 'domain\user' }
4733 now = Time.now.to_i
4734 File.utime(now - 9000, now - 9000, path)
4735 File.chown(0, 0, path)
4736 hashes = []
4737 hashes << { mask: ace.mask, type: ace.type, flags: ace.flags }
4738 let(:write_flag) { 3 }
4739 ace.mask == mask &&
4740 ace.type == type &&
4741 @mode_string = "776"
4742 it ":read rights" do
4743 @warn = []
4744 allow(Chef::Log).to receive(:warn) { |msg| @warn << msg }
4745 @api.get("/nyan_cat.png", 200) do
4746 @api.get("/nyan_cat.png.gz", 200, nil, { "Content-Type" => "application/gzip", "Content-Encoding" => "gzip" } ) do
4747 @api.get("/nyan_cat_compressed.png", 200, nil, { "Content-Type" => "application/gzip", "Content-Encoding" => "gzip" } ) do
4748 @api.get("/nyan_cat_content_length.png", 200, nil,
4749 }) do
4750 @api.get("/nyan_cat_truncated.png", 200, nil,
4751 @api.get("/forbidden", 403, "Forbidden",
4752 @api.post("/posty", 200, "Hi!")
4753 @api.get("/bad_request", 400, '{ "error": [ "Your request is just terrible." ] }')
4754 @api.post("/bad_request", 400, '{ "error": [ "Your request is just terrible." ] }')
4755 @server = @api = nil
4756 let(:source) { "http://localhost:9000/nyan_cat.png" }
4757 let(:source) { "http://localhost:9000/nyan_cat.png.gz" }
4758 let(:source) { "http://localhost:9000/forbidden" }
4759 let(:path) do
4760 !symlink?(file_path) && File.file?(file_path)
4761 let(:backup_glob) { File.join(CHEF_SPEC_BACKUP_PATH, test_file_dir.sub(/^([A-Za-z]:)/, ""), "#{file_base}*") }
4762 let(:expect_updated?) { true }
4763 restorecon_test_command = "#{@restorecon_path} -n -v #{path}"
4764 File.open(symlink_target, "wb") { |f| f.print "This is so wrong!!!" }
4765 let(:link1_path) { File.join(CHEF_SPEC_DATA, "points-to-link2") }
4766 let(:link2_path) { File.join(CHEF_SPEC_DATA, "points-to-link1") }
4767 let(:link_path) { File.join(CHEF_SPEC_DATA, "points-to-nothing") }
4768 let(:not_existent_source) { File.join(CHEF_SPEC_DATA, "i-am-not-here") }
4769 let(:not_a_file_path) { File.join(CHEF_SPEC_DATA, "dir-at-end-of-symlink") }
4770 let(:link_path) { File.join(CHEF_SPEC_DATA, "points-to-real-file") }
4771 File.open(path, "wb") { |f| f.write(expected_content) }
4772 File.open(path, "wb") { |f| f.write(wrong_content) }
4773 let(:expect_updated?) { false }
4774 let(:link_to_file_path) { File.join(CHEF_SPEC_DATA, "points-to-real-file") }
4775 let(:link_to_link_path) { File.join(CHEF_SPEC_DATA, "points-to-next-link") }
4776 result = shell_out!("mknod #{path} b 1 2")
4777 result = shell_out!("mknod #{path} c 1 2")
4778 result = shell_out!("mkfifo #{path}")
4779 let(:test_socket_dir) { File.join(Dir.tmpdir, "sockets") }
4780 File.open(path, "wb") { |f| f.print "This is so wrong!!!" }
4781 File.open(path, "wb") { |f| f.print expected_content }
4782 let(:temp_profile_path) { "#{ENV["USERPROFILE"]}\\..\\cheftesttempuser" }
4783 shell_out!("net.exe user /delete #{windows_nonadmin_user}", returns: [0, 2])
4784 let(:windows_alternate_user) { "chef%02d%02d%02d" % [Time.now.year % 100, Time.now.month, Time.now.day] }
4785 shell_out!("icacls \"#{script_output_dir.tr("/", "\\")}\" /grant \"authenticated users:(F)\"")
4786 let(:powershell_equal_to_alternate_user) { "-eq" }
4787 win32 = Object.send(:const_get, "Win32")
4788 libarchive_paths = Dir.glob("{#{Gem.dir},C:/hab}/**/libarchive.dll").map { |f| File.expand_path(f) }
4789 $stderr.puts <<~EOL
4790 !!!!
4791 $stderr.puts "
Found the following libarchive paths:

#{libarchive_paths.map { |f| "- #{f}
" }.join}

"
4792 @node ||= Chef::Node.new.tap do |n|
4793 @run_context ||= Chef::RunContext.new(node, {}, event_dispatch).tap do |rc|
4794 @test_service_file = "#{ENV["TMP"]}/spec_service_file"
4795 File.open(@test_service_file, "wb") do |f|
4796 ::GC.start
4797 end.tap { |l| l.present = present }
4798 (win32_os_version && win32_os_version.start_with?("6.3"))
4799 supports_dsc = !! lcm
4800 windows? && !windows64?
4801 macos? && !!(ohai[:platform_version].to_i >= 11)
4802 RUBY_PLATFORM.include?("freebsd") && !!(ohai[:platform_version].to_f >= 12.3)
4803 !!(ohai[:kernel][:machine] == "x86_64")
4804 !!(ohai[:platform_family] == "rhel")
4805 rhel? && !!(ohai[:platform_version].to_i == 6)
4806 suse? && !!(ohai[:platform_version].to_i >= 15)
4807 rhel? && !!(ohai[:platform_version].to_i == 7)
4808 rhel? && !!(ohai[:platform_version].to_i == 8)
4809 rhel? && !!(ohai[:platform_version].to_i >= 8)
4810 !!(ohai[:platform_family] == "debian")
4811 !((ohai[:virtualization] || {})[:wpar_no].nil?)
4812 !!(ohai[:platform_family] == "suse")
4813 raise "#{__method__}: unrecognized platform '#{platform}', expected one of ':unix' or ':windows'"
4814 def initialize(opts = {})
4815 @warmup = opts[:warmup] || 5
4816 @variance = opts[:variance] || 5000
4817 require File.join(__dir__, "..", "platforms", "prof", "win32")
4818 require File.join(__dir__, "..", "prof", "gc")
4819 @load_order ||= []
4820 @peace = tf
4821 @master = arg
4822 @i_can_count = tf
4823 if [true, false].include?(arg)
4824 @action = "sell"
4825 c = described_class.new([])
4826 let(:params) { [] }
4827 let(:params) { ["charmander"] }
4828 suffix = ""
4829 t = Time.now.strftime("%Y%m%d")
4830 path = "#{prefix}#{t}-#{$$}-#{rand(0x100000000).to_s(36)}"
4831 path << "-#{n}" if n
4832 windows? ? path.tr("/", "\\") : path
4833 File.open(@monkeyfoo, "w") do |file|
4834 file.write("hi")
4835 @path = File.expand_path(File.join(__dir__, "..", "..", "data", "old_home_dir", "my-dot-emacs"))
4836 $LOAD_PATH.unshift File.expand_path("..", __dir__)
4837 $LOAD_PATH.unshift File.expand_path("../chef-config/lib", __dir__)
4838 $LOAD_PATH.unshift File.expand_path("../chef-utils/lib", __dir__)
4839 Dir["spec/support/**/*.rb"]
4840 .grep_v(%r{^spec/support/pedant})
4841 .map { |f| f.gsub(/.rb$/, "") }
4842 .map { |f| f.gsub(%r{spec/}, "") }
4843 .each { |f| require f }
4844 test_node.automatic["os"] = (OHAI_SYSTEM["os"] || "unknown_os").dup.freeze
4845 Chef::Config[:log_level] = :fatal
4846 if Process.euid == 0 && Process.uid == 0
4847 if Process.uid != 0
4848 RSpec.configure { |c| c.fail_fast = true }
4849 if Process.euid != 0
4850 let(:chef_dir) { File.join(__dir__, "..", "..", "..") }
4851 let(:cookbook_x_100_metadata_rb) { cb_metadata("x", "1.0.0") }
4852 let(:cookbook_ancient_100_metadata_rb) { cb_metadata("ancient", "1.0.0") }
4853 let(:nodes_dir) { File.join(@repository_dir, "nodes") }
4854 let(:node_file) { Dir[File.join(nodes_dir, "*.json")][0] }
4855 file "config/solo.rb", <<~EOM
4856 result = shell_out("bundle exec #{ChefUtils::Dist::Solo::EXEC} --minimal-ohai --always-dump-stacktrace -c \"#{path_to("config/solo.rb")}\" -l debug", cwd: chef_dir)
4857 expect(File.stat(nodes_dir).mode.to_s(8)[-3..-1]).to eq("700")
4858 expect(File.stat(node_file).mode.to_s(8)[-4..-1]).to eq("0600")
4859 cookbook_path "#{path_to("cookbooks")}"
4860 file_cache_path "#{path_to("config/cache")}"
4861 result = shell_out("#{chef_solo} -c \"#{path_to("config/solo.rb")}\" -o 'x::default' -l debug", cwd: chef_dir)
4862 file "config/node.json", <<~E
4863 {"run_list":["x::default"]}
4864 result = shell_out("#{chef_solo} -c \"#{path_to("config/solo.rb")}\" -j '#{path_to("config/node.json")}' -l debug", cwd: chef_dir)
4865 file "cookbooks/x/metadata.rb", cb_metadata("x", "1.0.0", "
chef_version '~> 999.0'")
4866 file "cookbooks/x/metadata.rb", cb_metadata("x", "1.0.0", "
ohai_version '~> 999.0'")
4867 file "logs/runs.log", ""
4868 while IO.read(Chef::Config[:log_location][0]) !~ /.* is running, will wait for it to finish and then run./
4869 raise "we ran out of retries" if ( retries -= 1 ) <= 0
4870 chef_dir = File.join(__dir__, "..", "..", "..")
4871 threads = []
4872 s1 = Process.spawn("#{chef_solo} -c \"#{path_to("config/solo.rb")}\" -o 'x::default' -l debug -L #{path_to("logs/runs.log")}", chdir: chef_dir)
4873 s2 = Process.spawn("#{chef_solo} -c \"#{path_to("config/solo.rb")}\" -o 'x::default' -l debug -L #{path_to("logs/runs.log")}", chdir: chef_dir)
4874 run_log = File.read(path_to("logs/runs.log"))
4875 expect(run_log.lines.reject { |l| !l.include? "Run complete in" }.length).to eq(2)
4876 let(:chef_dir) { File.expand_path("../../..", __dir__) }
4877 file "resources/thing.rb", <<-EOM
4878 file "recipes/default.rb", <<~EOM
4879 file "config/client.rb", <<-EOM
4880 result = shell_out("#{chef_client} -c \"#{path_to("config/client.rb")}\" --no-color -F doc -o 'x::default'", cwd: chef_dir)
4881 var = "foo"
4882 puts "
first: \#\{var\}"
4883 var = "bar"
4884 puts "
second: \#\{var\}"
4885 var = "baz"
4886 file "recipes/default.rb", <<-EOM
4887 file "config/client.rb", <<~EOM
4888 result = shell_out("#{chef_client} -c \"#{path_to("config/client.rb")}\" --no-color -F doc -o 'x::default' -l debug", cwd: chef_dir)
4889 puts "
notified: \#\{var\}"
4890 puts "
notifying: \#\{var\}"
4891 edit_resource(:log, "name") do
4892 find_resource(:log, "name") do
4893 before(:all) { Namer.current_index = 1 }
4894 before { Namer.current_index += 1 }
4895 .select { |name, p| p.is_set?(self) }
4896 .map { |name, p| "#{name}=#{p.get(self)}" }
4897 .join(", ")})"
4898 e = self
4899 r = nil
4900 r = public_send(e.resource_name, "blah") do
4901 def index; @index ||= 1; end
4902 let(:converge_recipe) { "#{resource_name} 'blah'" }
4903 def foo(value = nil)
4904 foo "foo!"
4905 ActionJackson.succeeded += " #{bar}" if respond_to?(:bar)
4906 @foo = "#{value}alope" if value
4907 def bar(value = nil)
4908 @bar = "#{value}alope" if value
4909 ActionJackalope.succeeded = "#{foo} #{blarghle} #{bar}"
4910 bar "bar!"
4911 set_or_return(:group, value, {})
4912 new_resource.x = a + c
4913 expect(r.x).to eq(4)
4914 expect(r.x).to eq(8)
4915 let(:chef_dir) { File.join(__dir__, "..", "..", "..", "bin") }
4916 file "aaa", ""
4917 file "zzz/file", ""
4918 file "aaa/file", ""
4919 file "zzz", ""
4920 let!(:dest_dir) { path_to("dest_dir") }
4921 shell_out!("#{chef_client} -c \"#{path_to("config/client.rb")}\" -o 'test::default'", cwd: chef_dir)
4922 path = path_to(path)
4923 (stat.mode & 0777).to_s(8)
4924 expect(mode_of("dest_dir/sub1")).to eq "754"
4925 expect(mode_of("dest_dir/sub1/aaa")).to eq "777"
4926 expect(mode_of("dest_dir/sub1/zzz")).to eq "754"
4927 expect(mode_of("dest_dir/sub1/zzz/file")).to eq "777"
4928 expect(mode_of("dest_dir/sub2")).to eq "754"
4929 expect(mode_of("dest_dir/sub2/aaa")).to eq "754"
4930 expect(mode_of("dest_dir/sub2/aaa/file")).to eq "777"
4931 expect(mode_of("dest_dir/sub2/zzz")).to eq "777"
4932 base_thingy("blah") {}
4933 base_thingy { ; }
4934 bar_thingy("blah") {}
4935 no_name_thingy("blah") {}
4936 another_no_name_thingy("blah") {}
4937 another_thingy_name("blah") {}
4938 another_no_name_thingy_7("blah") {}
4939 my_supplier("blah") {}
4940 hemlock("blah") {}
4941 thingy3("blah") {}
4942 thingy4("blah") {}
4943 thingy5("blah") {}
4944 thingy6("blah") {}
4945 thingy5_2("blah") {}
4946 thingy7("blah") {}
4947 thingy8("blah") {}
4948 thingy12("blah") {}
4949 twizzle("blah") {}
4950 twizzle2("blah") {}
4951 my_super_thingy("blah") {}
4952 context "and a priority array [ Z, B ]" do
4953 context "and priority arrays [ B ] and [ Z ]" do
4954 context "with a priority array [ Z, B ]" do
4955 context "with priority arrays [ B ] and [ Z ]" do
4956 instance_eval("#{temp_two_classes_one_dsl} 'blah' do; end")
4957 let(:my_resource) { :"my_resource#{Namer.current_index}" }
4958 instance_eval("#{dsl_name} 'foo'")
4959 instance_eval("#{temp_my_resource} 'foo'")
4960 before(:all) { Namer.current_index = 0 }
4961 provider_thingy("blah") {}
4962 file "resources/nb_test.rb", <<-EOM
4963 log "bar" do
4964 log "baz" do
4965 log "quux"
4966 expect(result.stdout).to match(/\* notify_group\[foo\] action run\s+\* log\[quux\] action write\s+\* log\[bar\] action write\s+\* log\[baz\] action write/)
4967 log "foo" do
4968 log "baz"
4969 expect(result.stdout).to match(/\* notify_group\[bar\] action run\s+\* log\[baz\] action write\s+\* log\[foo\] action write/)
4970 expect(result.stdout).to match(/\* notify_group\[bar\] action run\s+\* notify_group\[baz\] action run\s+\* log\[foo\] action write/)
4971 expect(result.stdout).not_to match(/\* log\[foo\] action write.*\* log\[foo\] action write/)
4972 expect(result.stdout).to match(/\* notify_group\[bar\] action run\s+\* log\[foo\] action write\s+\* log\[baz\] action write/)
4973 log [ "a", "b" ] do
4974 notifies :write, "log[a, b]"
4975 expect(result.stdout).to match(/\* log\[a, b\] action write/)
4976 file "resources/foo.rb", <<~EOM
4977 file "providers/foo.rb", <<~EOM
4978 l_w_r_p_foo "me"
4979 result = shell_out("#{chef_client} -c \"#{path_to("config/client.rb")}\" --no-color -F doc -o 'l-w-r-p::default'", cwd: chef_dir)
4980 expect(result.stdout).to match(/\* l_w_r_p_foo\[me\] action create \(up to date\)/)
4981 block { r.ran_a "ran a" }
4982 end.to have_updated("ruby_block[run a]", :run)
4983 expect(r.ran_a).to eq "ran a"
4984 ran_a = r.ran_a
4985 block { r.ran_b "ran b: ran_a value was #{ran_a.inspect}" }
4986 .and have_updated("ruby_block[run a]", :run)
4987 .and have_updated("ruby_block[run b]", :run)
4988 expect(r.ran_b).to eq "ran b: ran_a value was \"ran a\""
4989 x_do_nothing 'a'
4990 x_do_nothing 'b'
4991 actual = result.stdout.lines.map(&:chomp).join("
")
4992 expected = <<EOM
4993 (up to date)
4994 expected = expected.lines.map(&:chomp).join("
")
4995 path = t.path
4996 variables[:aliases] ||= {}
4997 recipients [ "out1a", "out1b" ]
4998 recipients [ "out2a", "out2b" ]
4999 recipients [ "out3a", "out3b" ]
5000 file "templates/aliases.erb", <<-EOM.gsub(/^\s+/, "")
5001 <%= pp @aliases %>
5002 variables[:aliases] = {}
5003 r.variables[:aliases][new_resource.address] ||= []
5004 let(:ohai) { "bundle exec ohai" }
5005 shell_out!("#{ohai} hostname")
5006 expect(delta).to be < 4
5007 let(:report_file) { path_to("report_file.json") }
5008 file "inspec.yml", <<~FILE
5009 file "my_control.rb", <<~FILE
5010 result = shell_out!("#{chef_client} --local-mode --json-attributes #{path_to("attributes.json")}", cwd: chef_dir)
5011 expect(profile["name"]).to eq("my-profile")
5012 expect(control["id"]).to eq("my control")
5013 expect(result["status"]).to eq("passed")
5014 default['audit']['reporter'] = "json-file"
5015 default['audit']['json_file'] = {
5016 include_profile ".*::.*"
5017 result = shell_out!("#{chef_client} -c \"#{path_to("config/client.rb")}\" -r 'recipe[x]'", cwd: chef_dir)
5018 let(:chef_zero_opts) { { host: "::1" } }
5019 chef_server_url "http://[::1]:8900"
5020 cache_path '#{cache_path}'
5021 let(:chef_client_cmd) { %Q{bundle exec #{ChefUtils::Dist::Infra::CLIENT} --minimal-ohai -c "#{path_to("config/client.rb")}" -lwarn --always-dump-stacktrace} }
5022 cookbook "noop", "1.0.0", {}, "recipes" => { "default.rb" => "#raise 'foo'" }
5023 result = shell_out("#{chef_client_cmd} -o 'noop::default'", cwd: chef_dir)
5024 Chef::Log.error("!" * 80)
5025 data_bag("expect_bag", { "expect_item" => { "expect_key" => "expect_value" } })
5026 cookbook "api-smoke-test", "1.0.0", {}, "recipes" => { "default.rb" => recipe }
5027 result = shell_out("#{chef_client_cmd} -o 'api-smoke-test::default'", cwd: chef_dir)
5028 shell_out!("#{chef_client} -c \"#{path_to("config/client.rb")}\" -o 'x::default'",
5029 @api.get("/recipes.tgz", 200) do
5030 else {
5031 Try {
5032 if ($response) {return $true}
5033 let(:client_name) { "chef-973334" }
5034 let(:hostname) { "973334" }
5035 shell_out!("#{chef_client} -c \"#{path_to("config/client.rb")}\" -K #{@path} ", cwd: chef_dir)
5036 shell_out!("#{chef_client} -c \"#{path_to("config/client.rb")}\" ", cwd: chef_dir)
5037 before { file "cookbooks/x/recipes/default.rb", "" }
5038 shell_out!("#{chef_client} -c \"#{path_to("config/client.rb")}\" -o 'x::default'", cwd: chef_dir)
5039 result = shell_out("#{chef_client} --no-listen -c \"#{path_to("config/client.rb")}\" -o 'x::default'", cwd: chef_dir)
5040 result = shell_out("#{chef_client} -z -r 'x::default' --disable-config", cwd: path_to(""))
5041 result = shell_out("#{chef_client} -z -o 'x::default' --disable-config", cwd: path_to(""))
5042 result = shell_out("#{chef_client} -z -o 'x::default' --disable-config", cwd: path_to("cookbooks/x"))
5043 result = shell_out("#{chef_client} -z -o 'x::default' --disable-config", cwd: File.expand_path("..", path_to("")))
5044 before { file ".chef/knife.rb", "xxx.xxx" }
5045 result = shell_out("#{chef_client} -z -o 'x::default'", cwd: path_to(""), env: { "PWD" => nil })
5046 result = shell_out("#{chef_client} -c \"#{path_to("config/client.rb")}\" -o 'x::default'", cwd: chef_dir)
5047 file "mykey.pem", <<~EOM
5048 file "arbitrary.rb", <<~EOM
5049 file "arbitrary2.rb", <<~EOM
5050 result = shell_out("#{chef_client} -c \"#{path_to("config/client.rb")}\" #{path_to("arbitrary.rb")} #{path_to("arbitrary2.rb")}", cwd: chef_dir)
5051 expect(IO.read(path_to("tempfile.txt"))).to eq("1")
5052 expect(IO.read(path_to("tempfile2.txt"))).to eq("2")
5053 result = shell_out("#{chef_client} -c \"#{path_to("config/client.rb")}\" arbitrary.rb", cwd: path_to(""))
5054 result = shell_out("#{chef_client} -c \"#{path_to("config/client.rb")}\" -o x::constant_definition arbitrary.rb", cwd: path_to(""))
5055 file "config/dna.json", <<~EOM
5056 result = shell_out("#{chef_client} -c \"#{path_to("config/client.rb")}\" -j \"#{path_to("config/dna.json")}\" arbitrary.rb", cwd: path_to(""))
5057 result = shell_out("#{chef_client} -c \"#{path_to("config/client.rb")}\" -o 'x::default' -z", cwd: chef_dir)
5058 result = shell_out("#{chef_client} -c \"#{path_to("config/client.rb")}\" -o 'x::default' --local-mode", cwd: chef_dir)
5059 result = shell_out("#{chef_client} -c \"#{path_to("config/client.rb")}\" -r 'x::default' -z -l info", cwd: chef_dir)
5060 name 'x'
5061 version '0.0.1'
5062 result = shell_out("#{chef_client} -c \"#{path_to("config/client.rb")}\" -o 'x::default' --no-fork", cwd: chef_dir)
5063 expect(result.stdout).to include('COOKBOOKS: {"x"=>{"version"=>"0.0.1"}}')
5064 chef_version '~> 999.99'
5065 command = shell_out("#{chef_client} -c \"#{path_to("config/client.rb")}\" -o 'x::default' --no-fork", cwd: chef_dir)
5066 result = []
5067 pos = 0
5068 pos = match.end(0) + 1
5069 result = shell_out!("#{chef_client} -c \"#{path_to("config/client.rb")}\" -o 'x::default'", cwd: chef_dir)
5070 [true, false].each do |lazy|
5071 no_lazy_load #{lazy}
5072 result = shell_out("#{chef_client} -l debug -c \"#{path_to("config/client.rb")}\" -o 'x::default' --no-fork", cwd: chef_dir)
5073 english[:version] = "2014"
5074 expect(IO.read(path_to("tempfile.txt"))).to eq("2014")
5075 let(:tmp_dir) { Dir.mktmpdir("recipe-url") }
5076 chef_repo_path "#{tmp_dir}"
5077 result = shell_out("#{chef_client} -c \"#{path_to("config/client.rb")}\" --recipe-url=http://localhost:9000/recipes.tgz -o 'x::default' -z", cwd: tmp_dir)
5078 result = shell_out("#{chef_client} --recipe-url=#{broken_path}", cwd: tmp_dir)
5079 command = shell_out("#{chef_solo} -c \"#{path_to("config/client.rb")}\" -o 'x::default' --no-fork", cwd: chef_dir)
5080 command = shell_out("#{chef_client} -c \"#{path_to("config/client.rb")}\" -o 'x::default' --no-fork | tee #{path_to("chefrun.out")}", cwd: chef_dir)
5081 command = shell_out("#{chef_solo} -c \"#{path_to("config/client.rb")}\" -o 'x::default' --no-fork | tee #{path_to("chefrun.out")}", cwd: chef_dir)
5082 command = shell_out("#{chef_client} -c \"#{path_to("config/client.rb")}\" -o 'x::default'", cwd: chef_dir)
5083 command = shell_out("#{chef_solo} -c \"#{path_to("config/client.rb")}\" -o 'x::default'", cwd: chef_dir)
5084 command = shell_out("#{chef_client} -c \"#{path_to("config/client.rb")}\" -o 'x::default' --fork", cwd: chef_dir)
5085 command = shell_out("#{chef_solo} -c \"#{path_to("config/client.rb")}\" -o 'x::default' --fork", cwd: chef_dir)
5086 eager_load_libraries [ "default.rb", "loadme/**/*.rb" ]
5087 method_name_pattern = /[a-z]+([a-z]|[0-9]|_)*\?{0,1}/
5088 is_win2k8 = os_version_components[0] == "6" && os_version_components[1] == "0"
5089 let(:file_path) { ENV["ComSpec"] }
5090 let(:user) { "security_user" }
5091 let(:password) { "Security@123" }
5092 add_user = Mixlib::ShellOut.new("net user #{user} #{password} /ADD")
5093 let(:user_right) { "SeTest" }
5094 reg["RootType1", Win32::Registry::REG_SZ] = "fibrous"
5095 reg.write("Roots", Win32::Registry::REG_MULTI_SZ, ["strong roots", "healthy tree"])
5096 reg["Strong", Win32::Registry::REG_SZ] = "bird nest"
5097 @run_context = Chef::RunContext.new(@node, {}, events)
5098 expect(@registry.value_exists?("HKCU\\Software\\Root\\Branch\\Flower", { name: "Petals" })).to eq(true)
5099 expect(@registry.value_exists?("HKCU\\Software\\Root\\Branch\\Flower", { name: "petals" })).to eq(true)
5100 expect(@registry.value_exists?("HKCU\\Software\\Root\\Branch\\Flower", { name: "FOOBAR" })).to eq(false)
5101 expect(@registry.value_exists!("HKCU\\Software\\Root\\Branch\\Flower", { name: "Petals" })).to eq(true)
5102 expect(@registry.value_exists!("HKCU\\Software\\Root\\Branch\\Flower", { name: "petals" })).to eq(true)
5103 expect(@registry.data_exists?("HKCU\\Software\\Root\\Branch\\Flower", { name: "Petals", type: :multi_string, data: %w{Pink Delicate} })).to eq(true)
5104 expect(@registry.data_exists?("HKCU\\Software\\Root\\Branch\\Flower", { name: "petals", type: :multi_string, data: %w{Pink Delicate} })).to eq(true)
5105 expect(@registry.data_exists?("HKCU\\Software\\Root\\Branch\\Flower", { name: "slateP", type: :multi_string, data: %w{Pink Delicate} })).to eq(false)
5106 expect(@registry.data_exists?("HKCU\\Software\\Root\\Branch\\Flower", { name: "Petals", type: :string, data: "Pink" })).to eq(false)
5107 expect(@registry.data_exists?("HKCU\\Software\\Root\\Branch\\Flower", { name: "Petals", type: :multi_string, data: %w{Mauve Delicate} })).to eq(false)
5108 expect(@registry.data_exists!("HKCU\\Software\\Root\\Branch\\Flower", { name: "Petals", type: :multi_string, data: %w{Pink Delicate} })).to eq(true)
5109 expect(@registry.data_exists!("HKCU\\Software\\Root\\Branch\\Flower", { name: "petals", type: :multi_string, data: %w{Pink Delicate} })).to eq(true)
5110 expect(values).to eq([{ name: "RootType1", type: :string, data: "fibrous" },
5111 { name: "Roots", type: :multi_string, data: ["strong roots", "healthy tree"] }])
5112 expect(@registry.set_value("HKCU\\Software\\Root\\Branch\\Flower", { name: "Petals", type: :multi_string, data: ["Yellow", "Changed Color"] })).to eq(true)
5113 expect(@registry.data_exists?("HKCU\\Software\\Root\\Branch\\Flower", { name: "Petals", type: :multi_string, data: ["Yellow", "Changed Color"] })).to eq(true)
5114 expect(@registry.set_value("HKCU\\Software\\Root\\Branch\\Flower", { name: "Petals", type: :string, data: "Yellow" })).to eq(true)
5115 expect(@registry.data_exists?("HKCU\\Software\\Root\\Branch\\Flower", { name: "Petals", type: :string, data: "Yellow" })).to eq(true)
5116 expect(@registry.data_exists?("HKCU\\Software\\Root\\Branch\\Flower", { name: "Petals", type: :multi_string, data: ["Yellow", "Changed Color"] })).to eq(false)
5117 expect(@registry.set_value("HKCU\\Software\\Root\\Branch\\Flower", { name: "Stamen", type: :multi_string, data: ["Yellow", "Changed Color"] })).to eq(true)
5118 expect(@registry.data_exists?("HKCU\\Software\\Root\\Branch\\Flower", { name: "Stamen", type: :multi_string, data: ["Yellow", "Changed Color"] })).to eq(true)
5119 expect(@registry.set_value("HKCU\\Software\\Root\\Branch\\Flower", { name: "Stamen", type: :multi_string, data: ["Yellow", "Changed Color"] })).to eq(false)
5120 expect(@registry.set_value("HKCU\\Software\\Root\\Branch\\Flower", { name: "ShouldBe32767", type: :dword, data: "32767" })).to eq(true)
5121 expect(@registry.data_exists?("HKCU\\Software\\Root\\Branch\\Flower", { name: "ShouldBe32767", type: :dword, data: 32767 })).to eq(true)
5122 expect(@registry.data_exists?("HKCU\\Software\\Root\\Branch\\Flower", { name: "ShouldBeZero", type: :dword, data: 0 })).to eq(true)
5123 expect(@registry.set_value("HKCU\\Software\\Root\\Branch\\Flower", { name: "ShouldBePainful", type: :string, data: %w{one two} })).to eq(true)
5124 expect(@registry.data_exists?("HKCU\\Software\\Root\\Branch\\Flower", { name: "ShouldBePainful", type: :string, data: '["one", "two"]' })).to eq(true)
5125 expect(@registry.data_exists?("HKCU\\Software\\Root\\Branch\\Flower", { name: "ShouldBe65535", type: :string, data: "65535" })).to eq(true)
5126 reg["Peter", Win32::Registry::REG_SZ] = "Tiny"
5127 expect(@registry.delete_value("HKCU\\Software\\Root\\Trunk\\Peck\\Woodpecker", { name: "Peter", type: :string, data: "Tiny" })).to eq(true)
5128 expect(@registry.value_exists?("HKCU\\Software\\Root\\Trunk\\Peck\\Woodpecker", { name: "Peter", type: :string, data: "Tiny" })).to eq(false)
5129 reg_subkeys = []
5130 reg.each_key { |name| reg_subkeys << name }
5131 @r = Chef::Win32::Registry.new(@run_context, :i386)
5132 @r = Chef::Win32::Registry.new(@run_context, :x86_64)
5133 reg["Alert", Win32::Registry::REG_SZ] = "Universal"
5134 reg["Status", Win32::Registry::REG_SZ] = "Lost"
5135 expect(@registry.value_exists?("HKLM\\Software\\Root\\Poosh", { name: "Status" })).to eq(true)
5136 expect(@registry.value_exists?("HKLM\\Software\\Root\\Mauve", { name: "Alert" })).to eq(true)
5137 expect(@registry.data_exists?("HKLM\\Software\\Root\\Poosh", { name: "Status", type: :string, data: "Lost" })).to eq(true)
5138 expect(@registry.data_exists?("HKLM\\Software\\Root\\Mauve", { name: "Alert", type: :string, data: "Universal" })).to eq(true)
5139 let(:plaintext) { "p@assword" }
5140 if ($plaintext -ne '#{plaintext}') {
5141 let(:chef_dir) { File.join(__dir__, "..", "..") }
5142 expect(shell_out!("bundle exec #{binary} -v", cwd: chef_dir).stdout.chomp).to match(/.*: #{Chef::VERSION}/)
5143 Dir.mktmpdir("\\silly[dir]") do |dir|
5144 files = ["some.rb", "file.txt", "names.csv"]
5145 File.new(File.join(dir, file), "w").close
5146 @api.get("/blargh", 200, "blargh")
5147 @api.get("/foo/bar", 200, "hello foobar")
5148 expect(response).to eq([200, { "Content-Type" => "application/json" }, [ "hello foobar" ]])
5149 @api.get("/bar/baz", 200) { block_called = true; "hello barbaz" }
5150 expect(response).to eq([200, { "Content-Type" => "application/json" }, [ "hello barbaz" ]])
5151 expect(response[1]).to eq({ "Content-Type" => "application/json" })
5152 expect(response_obj["available_routes"]).to eq({ "GET" => [], "PUT" => [], "POST" => [], "DELETE" => [] })
5153 TinyServer::API.instance.get("/index", 200, "[\"hello\"]")
5154 rest = Chef::HTTP.new("http://localhost:9000")
5155 expect(rest.get("index")).to eq("[\"hello\"]")
5156 buffer = ""
5157 if Time.new - start > 5
5158 reader, writer, pid = PTY.spawn("bundle exec #{ChefUtils::Dist::Infra::SHELL} --no-multiline --no-singleline --no-colorize -c #{config} #{options}")
5159 read_until(reader, "chef (#{Chef::VERSION})>")
5160 writer.puts('"done"')
5161 output = read_until(reader, '=> "done"')
5162 show_log_level_code = %q[puts "===#{Chef::Log.level}==="]
5163 expect(output).to include("===fatal===")
5164 simple_api_get = "api.get('data')"
5165 expect(output).to include("{}")
5166 show_recipes_code = %q[puts "#{node["recipes"].inspect}"]
5167 expect(output).to include(%q{["override::foo", "override::bar"]})
5168 def log_event(message, time = Time.now.strftime("%H:%M:%S.%L"))
5169 events << [ message, time ]
5170 @events ||= []
5171 let!(:p1) { ClientProcess.new(self, "p1") }
5172 let!(:p2) { ClientProcess.new(self, "p2") }
5173 events.each_with_index.sort_by { |(message, time), index| [ time, index ] }.each do |(message, time), index|
5174 print "#{time} #{message}
"
5175 before { p1.run_to("created lock") }
5176 expect(IO.read(lockfile)).to eq("")
5177 before { p2.run_to("acquired lock") }
5178 before { p2.run_to("created lock") }
5179 before { p1.run_to("acquired lock") }
5180 before { p1.run_to("saved pid") }
5181 p1 = fork do
5182 p2 = fork do
5183 event, time = line.split("@")
5184 example.log_event("#{name}.last_event got #{event}")
5185 example.log_event("[#{name}] #{event}", time.strip)
5186 example.log_event("#{name}.run_to(#{to_event.inspect})")
5187 until @last_event == "after #{to_event}"
5188 example.log_event("#{name}.last_event got #{got_event}")
5189 example.log_event("[#{name}] #{got_event}", time.strip)
5190 example.log_event("#{name}.wait_for_exit (pid #{pid})")
5191 example.log_event("#{name}.wait_for_exit finished (pid #{pid})")
5192 example.log_event("#{name}.stop (pid #{pid})")
5193 example.log_event("#{name}.stop finished (stopped pid #{pid})")
5194 example.log_event("#{name}.stop finished (pid #{pid} wasn't running)")
5195 write_to_tests.print("after #{event}@#{Time.now.strftime("%H:%M:%S.%L")}
")
5196 if !@run_to_event || event == @run_to_event
5197 write_to_tests.print("waiting for instructions after #{event}@#{Time.now.strftime("%H:%M:%S.%L")}
")
5198 write_to_tests.print("told to run to #{@run_to_event} after #{event}@#{Time.now.strftime("%H:%M:%S.%L")}
")
5199 write_to_tests.print("continuing until #{@run_to_event} after #{event}@#{Time.now.strftime("%H:%M:%S.%L")}
")
5200 @pid = fork do
5201 exit!(0)
5202 fire_event($!.message.lines.join(" // "))
5203 example.log_event("#{name}.start forked (pid #{pid})")
5204 buffer << fd.read_nonblock(1) while buffer[-1] != "
"
5205 unless buffer == ""
5206 node.automatic[:recipes] = []
5207 expect(node["aliased"]["attr"]).to eq "value"
5208 node.run_list << "simple"
5209 node.run_list << "dup_attr"
5210 node.run_list << "dup_recipe"
5211 File.open("/etc/zypp/repos.d/chef-zypp-localtesting.repo", "w+") do |f|
5212 let(:package_name) { "chef_rpm" }
5213 expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}
' chef_rpm").stdout.chomp).to match("^chef_rpm-1.10-1.#{pkg_arch}$")
5214 preinstall("chef_rpm-1.10-1.#{pkg_arch}.rpm")
5215 preinstall("chef_rpm-1.2-1.#{pkg_arch}.rpm")
5216 expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}
' chef_rpm").stdout.chomp).to match("^chef_rpm-1.2-1.#{pkg_arch}$")
5217 zypper_package.version(["1.2", "1.10"])
5218 expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}
' chef_rpm").stdout.chomp).to match("^package chef_rpm is not installed$")
5219 it "locks an rpm" do
5220 exclude_test = !(%w{rhel fedora amazon}.include?(OHAI_SYSTEM[:platform_family]) && !File.exist?("/usr/bin/dnf"))
5221 expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}
' chef_rpm").stdout.chomp).to match(version)
5222 File.open("/etc/yum.repos.d/chef-yum-localtesting.repo", "w+") do |f|
5223 shell_out!("rpm -qa --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}
' | grep chef_rpm | xargs -r rpm -e")
5224 %w{1.10 1* 1.10-1 1*-1 1.10-* 1*-* 0:1* *:1.10-* *:1*-* 0:1.10 0:1.10-1}.each do |vstring|
5225 %w{1.2 1* 1.2-1 1*-1 1.2-* 1*-* 0:1* *:1.2-* *:1*-* 0:1.2 0:1.2-1}.each do |vstring|
5226 %w{1.2 1.2-1 1.2-* *:1.2-* 0:1.2-1}.each do |vstring|
5227 %w{1* 1*-1 1*-* 0:1* *:1*-*}.each do |vstring|
5228 yum_package "chef_rpm-0:1.2-1.#{pkg_arch}" do
5229 yum_package "chef_rp*-1*" do
5230 version "1*"
5231 version "1.10-1"
5232 version "0:1.10-1"
5233 version "1.10-1*"
5234 version "0:1.10-1*"
5235 version "1.2-1"
5236 yum_package "chef_rpm >= 1.2" do
5237 yum_package "chef_rpm > 1.2" do
5238 yum_package "chef_rpm = 1.10" do
5239 yum_package "chef_rpm = 1.2" do
5240 yum_package "chef_rpm > 2.0"
5241 yum_package "chef_rpm < 1.10" do
5242 version ">= 1.10"
5243 yum_package [ "chef_rpm.#{pkg_arch}", "chef_rpm.i686" ] do
5244 preinstall("chef_rpm-1.10-1.#{pkg_arch}.rpm", "chef_rpm-1.10-1.i686.rpm")
5245 arch [pkg_arch, "i686"]
5246 yum_package "chef_rpm-1.10-1.#{pkg_arch}" do
5247 version "1.2"
5248 expect(shell_out("rpm -q chef_rpm").stdout.chomp).to match("^chef_rpm-1.2-1.#{pkg_arch}")
5249 version("1.2")
5250 let(:principal) { nil }
5251 let(:privilege) { nil }
5252 let(:users) { nil }
5253 let(:sensitive) { true }
5254 node.automatic["os"] = "windows"
5255 let(:principal) { "user_privilege" }
5256 let(:users) { ["Administrators", "#{domain}\\security_user"] }
5257 subject.command "#{ChefUtils::Dist::Infra::CLIENT} -W -L 'C:\\chef\\chef-ad-join.log'"
5258 subject.day "1, 2, 3"
5259 it "creates a scheduled task to run monthly on 1, 2, 3, 4, 8, 20, 21, 15, 28, 31 day of the month" do
5260 subject.day "1, 2, 3, 4, 8, 20, 21, 15, 28, 31"
5261 subject.day "1, 2, 3, 4, 8, 20, 21, 30"
5262 subject.months "Jan, Feb, May, Sep, Dec"
5263 subject.day "1, 2"
5264 context "when wild card (*) set as day" do
5265 subject.day "*"
5266 subject.day "1,2,3"
5267 context "when wild card (*) is set as day" do
5268 it "creates task to activate on '09/10/2018' at '15:00' when start_day = '09/10/2018' and start_time = '15:00' provided" do
5269 let(:task_name) { "\\foo\\chef-client-functional-test" }
5270 let(:task_name) { "\\foo\\bar\\chef-client-functional-test" }
5271 let(:share_name) { "fake_share" }
5272 let(:path) { ENV["temp"] }
5273 let(:concurrent_user_limit) { 7 }
5274 expect(share["Path"]).to eq(path)
5275 expect(get_installed_share_access["AccountName"]).to eq("#{ENV["COMPUTERNAME"]}\\#{full_users[0]}")
5276 let(:secvalue) { "30" }
5277 let(:path) { "test_path" }
5278 before { add_path }
5279 let(:c_path) { "c:\\" }
5280 let(:e_path) { "e:\pagefile.sys" }
5281 let(:pkg_name) { nil }
5282 let(:pkg_path) { nil }
5283 let(:pkg_checksum) { nil }
5284 let(:pkg_version) { nil }
5285 let(:pkg_type) { nil }
5286 let(:pkg_options) { nil }
5287 let(:pkg_type) { :custom }
5288 let(:pkg_options) { "/Q" }
5289 let(:pkg_version) { "8.0.59193" }
5290 before { subject.version("8.0.59193") }
5291 let(:pkg_name) { "Ultra Defragmenter" }
5292 let(:pkg_name) { "Mercurial 3.6.1 (64-bit)" }
5293 let(:pkg_path) { ::File.join(Chef::Config[:file_cache_path], "package", "Mercurial-3.6.1-x64.exe") }
5294 let(:pkg_name) { "7zip" }
5295 let(:pkg_path) { "http://www.7-zip.org/a/7z938-x64.msi" }
5296 path: ::File.join(Chef::Config[:file_cache_path], "7zip.msi"),
5297 let(:new_hostname) { "New-Hostname" }
5298 let(:local_domain_user) { "'mydomain\\Groucho'" }
5299 let(:local_domain_password) { "'P@ssw0rd'" }
5300 let(:hostname) { "Cucumber" }
5301 let(:hostname) { "Gherkin" }
5302 let(:resource_name) { "Playmaker.ttf" }
5303 node.default[:os] = ohai[:os]
5304 let(:rule_name) { "fake_rule" }
5305 let(:remote_port) { "5555" }
5306 let(:enabled) { false }
5307 let(:chef_env_with_delim) { "chef_env_with_delim" }
5308 let(:chef_env_delim) { ";" }
5309 let(:chef_env_test_delim) { "#{value1};#{value2}" }
5310 let(:env_dne_key) { "env_dne_key" }
5311 let(:env_value1) { "value1" }
5312 let(:env_value2) { "value2" }
5313 let(:delim_value) { "#{env_value1};#{env_value2}" }
5314 let(:default_env_user) { "<SYSTEM>" }
5315 let(:env_obj) do
5316 let(:env_value_expandable) { "%SystemRoot%" }
5317 node.default["os"] = "windows"
5318 node.default["platform_version"] = "6.1"
5319 let(:random_name) { Time.now.to_i }
5320 let(:env_val) { "#{env_value_expandable}_#{random_name}" }
5321 let!(:env_path_before) { ENV["PATH"] }
5322 test_resource.value("#{path_before};#{env_val}")
5323 expect(ENV["PATH"]).to include((random_name).to_s)
5324 New-Item -Path Cert:\\#{store_location}\\#{store_name}
5325 let(:password) { "P@ssw0rd!" }
5326 let(:store) { "Chef-Functional-Test" }
5327 let(:store_name) { "MY" }
5328 let(:cert_output_path) { ::File.join(Chef::Config[:file_cache_path], "output.cer") }
5329 let(:pfx_output_path) { ::File.join(Chef::Config[:file_cache_path], "output.pfx") }
5330 let(:key_output_path) { ::File.join(Chef::Config[:file_cache_path], "output.key") }
5331 let(:cer_path) { File.join(CHEF_SPEC_DATA, "windows_certificates", "test.cer") }
5332 let(:pem_path) { File.join(CHEF_SPEC_DATA, "windows_certificates", "test.pem") }
5333 let(:p7b_path) { File.join(CHEF_SPEC_DATA, "windows_certificates", "test.p7b") }
5334 let(:pfx_path) { File.join(CHEF_SPEC_DATA, "windows_certificates", "test.pfx") }
5335 .to receive(:_pv_equal_to)
5336 .with({ store_name: store }, :store_name, anything)
5337 path = File.join(dir, "test.pem")
5338 let(:password) { "DummyP2ssw0rd!" }
5339 shell_out("net user #{u} /delete")
5340 file_content = <<~EOF
5341 windows_template_path = temp_security_template.path.gsub("/") { "\\" }
5342 metadata = {
5343 shell_out!("/usr/bin/dscl . -delete '/Users/#{username}'")
5344 expect(shell_out("/usr/bin/dscl . -read /Users/#{username}").error?).to be(false)
5345 let(:uid) { nil }
5346 let(:gid) { 20 }
5347 let(:home) { nil }
5348 let(:manage_home) { false }
5349 let(:comment) { "Great Chef" }
5350 let(:shell) { "/bin/bash" }
5351 let(:salt) { nil }
5352 let(:iterations) { nil }
5353 r.uid(uid)
5354 r.gid(gid)
5355 let(:iterations) { 25000 }
5356 let(:groups) { %w{staff operator} }
5357 shell_out!("/usr/bin/dscl . -append '/Groups/#{group}' GroupMembership #{username}")
5358 shell_out("/usr/bin/dscl . -delete '/Groups/#{group}' GroupMembership #{username}")
5359 shell_out!("/usr/sbin/userdel #{username}")
5360 expect(shell_out("grep -q #{username} /etc/passwd").error?).to be(false)
5361 expect(shell_out("grep ^#{user}: /etc/shadow | cut -d: -f2 | grep ^#{pass}$").exitstatus).to eq(0)
5362 let(:gid) do
5363 Etc.enum_for(:group).map(&:gid).last
5364 let(:timezone) { "GMT Standard Time" }
5365 let(:timezone) { nil }
5366 let(:file_base) { "template_spec" }
5367 node.normal[:nested][:secret] = "value"
5368 let(:default_mode) { (0666 & ~File.umask).to_s(8) }
5369 %w{all some no}.each do |test_case|
5370 expect(line).to end_with(ChefUtils.windows? ? "\r
" : "
")
5371 resource.variables(secret: [{ "key" => Chef::DelayedEvaluator.new { "nutella" } }])
5372 !::File.exist?("/opt/mytest/mytest.sh")
5373 @pkg_name = "dummy"
5374 @pkg_version = "1-0"
5375 @pkg_path = "#{Dir.tmpdir}/dummy-1-0.aix6.1.noarch.rpm"
5376 @pkg_name = "mytest"
5377 @pkg_version = "1.0-1"
5378 @pkg_path = "#{Dir.tmpdir}/mytest-1.0-1.noarch.rpm"
5379 shell_out("rpm -qa | grep #{@pkg_name}-#{@pkg_version} | xargs rpm -e")
5380 shell_out("rpm -i #{@pkg_path}")
5381 @pkg_version = "2-0"
5382 @pkg_path = "#{Dir.tmpdir}/dummy-2-0.aix6.1.noarch.rpm"
5383 @pkg_version = "2.0-1"
5384 @pkg_path = "#{Dir.tmpdir}/mytest-2.0-1.noarch.rpm"
5385 let(:file_base) { "remote_file_spec" }
5386 @api.get("/seattle_capo.png", 304, "", { "Etag" => "abcdef" } )
5387 let(:source) { "https://localhost:9000/nyan_cat.png" }
5388 let(:smb_file_local_file_name) { "smb_file.txt" }
5389 let(:smb_share_name) { "chef_smb_test" }
5390 let(:smb_remote_path) { File.join("//#{ENV["COMPUTERNAME"]}", smb_share_name, smb_file_local_file_name).tr("/", "\\") }
5391 let(:smb_file_content) { "hellofun" }
5392 let(:remote_domain) { nil }
5393 let(:remote_user) { nil }
5394 let(:remote_password) { nil }
5395 shell_out!("net.exe share #{smb_share_name}=\"#{smb_share_root_directory.tr("/", "\\")}\" /grant:\"authenticated users\",read")
5396 shell_out!("icacls #{smb_file_local_path} /grant:r \"authenticated users:(W)\" /grant \"#{windows_current_user_qualified}:(R)\" /inheritance:r")
5397 let(:invalid_chunk_size) { -1 }
5398 shell_out!("icacls #{smb_file_local_path} /grant:r \"authenticated users:(W)\" /deny \"#{windows_current_user_qualified}:(R)\" /inheritance:r")
5399 let(:remote_domain) { "." }
5400 let(:default_mode) { (0777 & ~File.umask).to_s(8) }
5401 File.join(path, "remotesubdir", ".a_dotfile"),
5402 File.join(path, ".a_dotdir", ".a_dotfile_in_a_dotdir"),
5403 File.open(modified_file, "a") { |f| f.puts "santa is real" }
5404 File.open(modified_subdir_file, "a") { |f| f.puts "so is rudolph" }
5405 FileUtils.mkdir_p(File.join(path, "a", "multiply", "nested", "directory"))
5406 @existing1 = File.join(path, "a", "foo.txt")
5407 @existing2 = File.join(path, "a", "multiply", "bar.txt")
5408 @existing3 = File.join(path, "a", "multiply", "nested", "baz.txt")
5409 @existing4 = File.join(path, "a", "multiply", "nested", "directory", "qux.txt")
5410 @resource.values([{ name: "Color", type: :string, data: "Orange" }])
5411 let(:parent) { "Opscode" }
5412 let(:child) { "Whatever" }
5413 let(:key_parent) { "SOFTWARE\\" + parent }
5414 let(:key_child) { "SOFTWARE\\" + parent + "\\" + child }
5415 let(:reg_parent) { "HKLM\\" + key_parent }
5416 let(:reg_child) { "HKLM\\" + key_child }
5417 [ 0x0100, 0x0200 ].each do |flag|
5418 reg["Color", Win32::Registry::REG_SZ] = "Orange"
5419 allow(@rest_client).to receive(:raw_http_request).and_return({ "result" => "ok" })
5420 allow(@rest_client).to receive(:post_rest).and_return({ "uri" => "https://example.com/reports/nodes/windowsbox/runs/#{@run_id}" })
5421 @new_resource.values([{ name: "Color", type: :string, data: "Orange" }])
5422 expect(@registry.data_exists?(reg_child, { name: "Color", type: :string, data: "Orange" })).to eq(true)
5423 @new_resource.values([{ name: "number", type: :dword, data: "12345" }])
5424 expect(@registry.data_exists?(reg_child, { name: "number", type: :dword, data: 12344 })).to eq(true)
5425 @new_resource.values([{ name: "Mango", type: :string, data: "Yellow" }])
5426 expect(@registry.data_exists?(reg_child, { name: "Mango", type: :string, data: "Yellow" })).to eq(true)
5427 @new_resource.values([{ name: "Color", type: :string, data: "Not just Orange - OpscodeOrange!" }])
5428 expect(@registry.data_exists?(reg_child, { name: "Color", type: :string, data: "Not just Orange - OpscodeOrange!" })).to eq(true)
5429 @new_resource.values([{ name: "Color", type: :multi_string, data: ["Not just Orange - OpscodeOrange!"] }])
5430 expect(@registry.data_exists?(reg_child, { name: "Color", type: :multi_string, data: ["Not just Orange - OpscodeOrange!"] })).to eq(true)
5431 @new_resource.values([{ name: "Chef", type: :multi_string, data: %w{OpscodeOrange Rules} }])
5432 expect(@registry.value_exists?(reg_child + "\\OpscodeTest", { name: "Chef", type: :multi_string, data: %w{OpscodeOrange Rules} })).to eq(true)
5433 @new_resource.values([{ name: "OC", type: :string, data: "MissingData" }])
5434 @new_resource.values([{ name: "OC", data: "my_data" }])
5435 @new_resource.values([{ name: "OC", type: :string }])
5436 @new_resource.values([{ name: "OC" }])
5437 @new_resource.values([{ name: "OC", type: :string, data: "my_data" }])
5438 expect(@registry.value_exists?(reg_child + '\Missing1\Missing2', { name: "OC", type: :string, data: "MissingData" })).to eq(true)
5439 @new_resource.key(reg_child + "\\Atraxi" )
5440 @new_resource.values([{ name: "OC", type: :string, data: "Data" }])
5441 expect(@registry.data_exists?(reg_child + "\\Atraxi", { name: "OC", type: :string, data: "Data" })).to eq(true)
5442 expect(@registry.key_exists?(reg_child + "\\Atraxi")).to eq(false)
5443 @new_resource.key(reg_child + "\\Ood")
5444 @new_resource.values([{ name: "ReportingVal1", type: :string, data: "report1" }, { name: "ReportingVal2", type: :string, data: "report2" }])
5445 expect(@report["action"]).to eq("end")
5446 expect(@report["resources"][0]["type"]).to eq("registry_key")
5447 expect(@report["resources"][0]["name"]).to eq(resource_name)
5448 expect(@report["resources"][0]["id"]).to eq(reg_child + "\\Ood")
5449 expect(@report["resources"][0]["after"][:values]).to eq([{ name: "ReportingVal1", type: :string, data: "report1" },
5450 { name: "ReportingVal2", type: :string, data: "report2" }])
5451 expect(@report["resources"][0]["before"][:values]).to eq([])
5452 expect(@report["resources"][0]["result"]).to eq("create")
5453 expect(@report["status"]).to eq("success")
5454 @new_resource.values([{ name: "BriskWalk", type: :string, data: "is good for health" }])
5455 @new_resource.key(reg_child + "\\Slitheen")
5456 @new_resource.values([{ name: "BriskWalk", data: "my_data" }])
5457 @new_resource.values([{ name: "BriskWalk", type: :string }])
5458 @new_resource.values([{ name: "BriskWalk" }])
5459 @new_resource.values([{ name: "BriskWalk", type: :string, data: "my_data" }])
5460 @new_resource.key(reg_child + "\\Pyrovile")
5461 expect(@registry.value_exists?(reg_child + "\\Pyrovile", { name: "Chef", type: :multi_string, data: %w{OpscodeOrange Rules} })).to eq(true)
5462 expect(@registry.value_exists?(reg_child + "\\Sontaran\\Sontar", { name: "OC", type: :string, data: "MissingData" })).to eq(true)
5463 @new_resource.key(reg_child + "\\Adipose")
5464 @new_resource.key(reg_child + "\\Judoon")
5465 @new_resource.values([{ name: "ReportingVal3", type: :string, data: "report3" }])
5466 expect(@report["resources"][0]["id"]).to eq(reg_child + "\\Judoon")
5467 expect(@report["resources"][0]["after"][:values]).to eq([{ name: "ReportingVal3", type: :string, data: "report3" }])
5468 expect(@report["resources"][0]["result"]).to eq("create_if_missing")
5469 @new_resource.key(reg_child + "\\Zygons\\Zygor")
5470 expect(@registry.key_exists?(reg_child + "\\Zygons")).to eq(false)
5471 expect(@registry.key_exists?(reg_child + "\\Zygons\\Zygor")).to eq(false)
5472 @new_resource.key(reg_child + "\\Zygons")
5473 @new_resource.key(reg_parent + "\\Osirian")
5474 expect(@registry.data_exists?(reg_parent + "\\Opscode", { name: "Color", type: :string, data: "Orange" })).to eq(true)
5475 @new_resource.key(reg_parent + "\\Opscode")
5476 @new_resource.values([{ name: "Opscode", type: :multi_string, data: %w{Seattle Washington} }, { name: "AKA", type: :string, data: "OC" }])
5477 expect(@registry.value_exists?(reg_parent + "\\Opscode", { name: "AKA", type: :string, data: "OC" })).to eq(false)
5478 expect(@registry.value_exists?(reg_parent + "\\Opscode", { name: "Opscode", type: :multi_string, data: %w{Seattle Washington} })).to eq(false)
5479 @new_resource.values([{ name: "Color", type: :multi_string, data: %w{Black Orange} }])
5480 expect(@registry.value_exists?(reg_parent + "\\Opscode", { name: "Color", type: :string, data: "Orange" })).to eq(false)
5481 @new_resource.values([{ name: "ReportVal4", type: :string, data: "report4" }, { name: "ReportVal5", type: :string, data: "report5" }])
5482 expect(@report["resources"][0]["id"]).to eq(reg_parent + "\\ReportKey")
5483 expect(@report["resources"][0]["before"][:values]).to eq([{ name: "ReportVal4", type: :string, data: "report4" },
5484 { name: "ReportVal5", type: :string, data: "report5" }])
5485 expect(@report["resources"][0]["result"]).to eq("delete")
5486 expect(@report["resources"][0]["result"]).to eq("delete_key")
5487 let(:output_command) { " | out-file -encoding ASCII " }
5488 let(:cmdlet_exit_code_success_content) { "get-item ." }
5489 file = Tempfile.new(["foo", ".ps1"])
5490 resource.code(". \"#{file.path}\"")
5491 let(:negative_exit_status) { -27 }
5492 let(:unsigned_exit_status) { (-negative_exit_status ^ 65535) + 1 }
5493 resource.code("if({)")
5494 resource.not_if "cd ."
5495 resource.only_if "cd ."
5496 custom_cwd = "#{ENV["SystemRoot"]}\\system32\\drivers\\etc"
5497 resource.not_if "exit ! [int32]($pwd.path -eq '#{custom_cwd}')", cwd: custom_cwd
5498 resource.only_if "exit ! [int32]($pwd.path -eq '#{custom_cwd}')", cwd: custom_cwd
5499 resource.only_if "exit ! [int32]($pwd.path -eq '#{custom_cwd}')"
5500 resource.not_if "exit ! [int32]($pwd.path -eq '#{custom_cwd}')"
5501 let(:source_name) { "fake" }
5502 let(:source_location) { "https://www.nuget.org/api/v2" }
5503 let(:trusted) { true }
5504 let(:provider_name) { "NuGet" }
5505 expect(shell_out!("/usr/libexec/PlistBuddy -c 'Print :\"AppleFirstWeekday\":gregorian' \"#{global_prefs}\"").stdout.to_i).to eq(4)
5506 when "aix"
5507 device = "/"
5508 when "debian", "rhel", "amazon"
5509 device = "/dev/ram1"
5510 shell_out("mknod -m 660 #{device} b 1 0")
5511 shell_out("ls -1 /dev/ram*").stdout.each_line do |d|
5512 if shell_out("mount | grep #{d}").exitstatus == "1"
5513 device = d
5514 fstype = "tmpfs"
5515 shell_out!("mkfs -q #{device} 512")
5516 device = "swap"
5517 validation_cmd = "mount | grep #{mount_point} | grep #{device} "
5518 validation_cmd << " | grep #{fstype} " unless fstype.nil?
5519 validation_cmd << " | grep #{options.join(",")} " unless options.nil? || options.empty?
5520 expect(shell_out("cat #{unix_mount_config_file} | grep \"#{mount_point}:\" ").exitstatus).to eq(0)
5521 expect(shell_out("cat #{unix_mount_config_file} | grep \"#{mount_point}\" | grep \"#{device}\" ").exitstatus).to eq(0)
5522 @device = "/" if test.metadata[:skip_before]
5523 line.split(" ").each do |section|
5524 describe "when device is '/'" do
5525 skip_remount = include_flag || (ohai[:platform] == "solaris2")
5526 new_resource.options "rw" if ohai[:platform] == "aix"
5527 resource.value [ { "User": "/Library/Managed Installs/way_fake.log" } ]
5528 resource.lc_env({ "LC_TIME" => "en_IN" })
5529 let(:file_base) { "file_spec" }
5530 let(:to) do
5531 puts "Could not remove a file: #{$!}"
5532 system "rmdir '#{path}'"
5533 def link(a, b)
5534 File.link(a, b)
5535 let(:test_user) { windows? ? nil : ENV["USER"] }
5536 @info = []
5537 allow(logger).to receive(:info) { |msg| @info << msg }
5538 File.open(to, "w") { |file| file.write("wowzers") }
5539 File.open(to, "w") do |file|
5540 let(:test_user) { "test-link-user" }
5541 File.open(@other_target, "w") { |file| file.write("eek") }
5542 File.open(target_file, "w") { |file| file.write("eek") }
5543 elsif macos? || solaris? || freebsd? || aix?
5544 let(:path) { target_file }
5545 }.each do |prefix, desc|
5546 let(:to) { "#{prefix}#{File.basename(absolute_to)}" }
5547 let(:absolute_to) { File.join(test_file_dir, make_tmpname("to_spec")) }
5548 File.open(target_file, "w") { |file| file.write("tomfoolery") }
5549 resource.owner(windows? ? "Guest" : "nobody")
5550 expect(shell_out!("launchctl list io.chef.testing.fake").stdout).to match('"PID" = \d+')
5551 !Dir.glob("/etc/rc*/**/S*#{service_name}").empty?
5552 Dir.glob("/etc/rc*/**/S*#{service_name}").empty?
5553 expect(File.exist?("#{Dir.tmpdir}/#{file_name}")).to be_truthy
5554 expect(File.exist?("#{Dir.tmpdir}/#{file_name}")).to be_falsey
5555 files = Dir.glob("#{Dir.tmpdir}/init[a-z_]*.txt")
5556 FileUtils.cp((File.join(__dir__, "/../assets/inittest")).to_s, "/etc/init.d/inittest")
5557 include_flag = !(%w{amazon debian aix}.include?(ohai[:platform_family]) || (ohai[:platform_family] == "rhel" && ohai[:platform_version].to_i < 7))
5558 shell_out("ip link list |grep UP|grep -vi loop|head -1|cut -d':' -f 2 |cut -d'@' -f 1").stdout.strip
5559 interface + ":10"
5560 expect(shell_out("ifconfig #{@interface} | grep 10.10.0.1").exitstatus).to eq(0)
5561 expect(shell_out("ifconfig #{@interface} | grep 10.10.0.1").exitstatus).to eq(1)
5562 expect(shell_out("lsattr -E -l #{@interface} | grep 10.10.0.1").exitstatus).to eq(0)
5563 expect(shell_out("lsattr -E -l #{@interface} | grep 10.10.0.1").exitstatus).to eq(1)
5564 expect(current_resource.inet_addr).to match(/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/)
5565 exclude_test = ohai[:platform] != "ubuntu"
5566 when "mac_os_x"
5567 sid = nil
5568 sid.nil? ? nil : sid[1].to_s
5569 domain, user = user_name.split("\\")
5570 if user && domain != "."
5571 let(:excluded_members) { [] }
5572 high_uid += 1
5573 let(:included_members) { [] }
5574 let!(:group_name) do
5575 it "should be no-op" do
5576 let(:included_members) { [spec_members[0], spec_members[1]] }
5577 let(:excluded_members) { [spec_members[2]] }
5578 let(:tested_action) { :modify }
5579 let(:computer_domain) { ohai[:kernel]["cs_info"]["domain"].split(".")[0] }
5580 let(:spec_members) { ["#{computer_domain}\\Domain Admins", "#{computer_domain}\\Domain Users", "#{computer_domain}\\Domain Computers"] }
5581 let(:tested_action) { :manage }
5582 let(:base_dir_path) { Dir.mktmpdir }
5583 let(:origin_repo) { "#{origin_repo_dir}/example" }
5584 shell_out!("git", "clone", git_bundle_repo, "example", cwd: origin_repo_dir)
5585 File.open("#{origin_repo}/.git/config", "a+") do |f|
5586 [user]
5587 let(:path_with_spaces) { "#{origin_repo_dir}/path with spaces" }
5588 expect_revision_to_be("v1.0.0", v1_tag)
5589 shell_out!("git", "reset", "--hard", rev_foo, cwd: deploy_directory)
5590 let(:expected_content) { "Don't fear the ruby." }
5591 def create_resource(opts = {})
5592 File.open(path, "w") { |f| f.print expected_content }
5593 let(:guard) { "ruby -e 'exit 0'" }
5594 let(:guard) { %{ruby -e 'exit 1 unless File.exists?("./nested.json")'} }
5595 resource.only_if %{ruby -e 'exit 1 if ENV["SAWS_SECRET"] != "supersecret"'}
5596 resource.only_if %{ruby -e 'exit 1 if ENV["SAWS_SECRET"] == "supersecret"'}
5597 resource.only_if %{ruby -e 'exit 1 if ENV["SGCE_SECRET"] != "regularsecret"'}, {
5598 environment: { "SGCE_SECRET" => "regularsecret" },
5599 resource.only_if %{ruby -e 'exit 1 if ENV["SGCE_SECRET"] == "regularsecret"'}, {
5600 resource.only_if %{ruby -e 'exit 1 if ENV["SAWS_SECRET"] != "regularsecret"'}, {
5601 environment: { "SAWS_SECRET" => "regularsecret" },
5602 resource.only_if %{ruby -e 'exit 1 if ENV["SAWS_SECRET"] == "regularsecret"'}, {
5603 winrm_code = <<-CODE
5604 ::FileUtils.rm_rf(@temp_dir) if ::Dir.exist?(@temp_dir)
5605 script_code = data ? code : "Configuration '#{configuration_name}'
{
\t#{code}
}
"
5606 data_suffix = data ? "_config_data" : ""
5607 extension = data ? "psd1" : "ps1"
5608 ::File.open(script_path, "wt") do |script|
5609 shell_out!("net user #{target_user}")
5610 shell_out!("net user #{target_user} /delete")
5611 let(:dsc_env_variable) { "chefenvtest" }
5612 let(:dsc_env_value1) { "value1" }
5613 let(:test_registry_data1) { "LL927" }
5614 let(:test_registry_data2) { "LL928" }
5615 let(:registry_embedded_parameters) { "$#{reg_key_name_param_name} = '#{test_registry_key}';$#{reg_key_value_param_name} = '#{test_registry_value}'" }
5616 Key = $#{reg_key_name_param_name}
5617 let(:dsc_code) { dsc_reg_code }
5618 let(:dsc_user_prefix) { "dsc" }
5619 let(:dsc_user_suffix) { "chefx" }
5620 let(:dsc_user) { "#{dsc_user_prefix}_usr_#{dsc_user_suffix}" }
5621 let(:dsc_user_prefix_env_var_name) { "dsc_user_env_prefix" }
5622 let(:dsc_user_suffix_env_var_name) { "dsc_user_env_suffix" }
5623 let(:dsc_user_prefix_env_code) { "$env:#{dsc_user_prefix_env_var_name}" }
5624 let(:dsc_user_suffix_env_code) { "$env:#{dsc_user_suffix_env_var_name}" }
5625 let(:dsc_user_prefix_param_code) { "$#{dsc_user_prefix_param_name}" }
5626 let(:dsc_user_suffix_param_code) { "$#{dsc_user_suffix_param_name}" }
5627 let(:dsc_user_env_code) { "\"$(#{dsc_user_prefix_env_code})_usr_$(#{dsc_user_suffix_env_code})\"" }
5628 let(:dsc_user_param_code) { "\"$(#{dsc_user_prefix_param_code})_usr_$(#{dsc_user_suffix_param_code})\"" }
5629 let(:config_flags) { nil }
5630 (
5631 let(:config_param_section) { "" }
5632 let(:dsc_user_code) { "'#{dsc_user}'" }
5633 $testuser = #{dsc_user_code}
5634 @{
5635 AllNodes = @(
5636 let(:dsc_environment_env_var_name) { "dsc_test_cwd" }
5637 if (($pwd.path -eq '#{dsc_environment_fail_etc_directory}') -and (test-path('#{dsc_environment_fail_etc_directory}')))
5638 Name = '#{dsc_environment_env_var_name}'
5639 let(:dsc_code) { dsc_reg_script }
5640 let(:dsc_user_code) { dsc_user_param_code }
5641 let(:config_flags) { { "#{dsc_user_prefix_param_name}": (dsc_user_prefix).to_s, "#{dsc_user_suffix_param_name}": (dsc_user_suffix).to_s } }
5642 let(:dsc_user_code) { dsc_user_env_code }
5643 cd c:\\
5644 $cert = ls Cert:\\LocalMachine\\My\\ |
5645 Where-Object {$_.Subject -match "ChefTest"} |
5646 if($cert -eq $null) {
5647 $pfxpath = '#{self_signed_cert_path}'
5648 $password = ''
5649 UserName = '#{dsc_user}'
5650 let(:tmp_file_name) { Dir::Tmpname.create("tmpfile") {} }
5651 let(:test_text) { "'\"!@#$%^&*)(}{][\u2713~n" }
5652 contents = File.open(tmp_file_name, "rb:bom|UTF-16LE") do |f|
5653 f.read.encode("UTF-8")
5654 let(:test1_0) { File.join(apt_data, "chef-integration-test_1.0-1_amd64.deb") }
5655 let(:test1_1) { File.join(apt_data, "chef-integration-test_1.1-1_amd64.deb") }
5656 let(:test2_0) { File.join(apt_data, "chef-integration-test2_1.0-1_amd64.deb") }
5657 status = shell_out("dpkg -s #{package}")
5658 if action.nil? || action == :purge
5659 shell_out!("dpkg -i #{test1_0}")
5660 shell_out!("dpkg -i #{test1_0} #{test2_0}")
5661 shell_out!("dpkg -i #{test2_0}")
5662 shell_out!("dpkg -i #{test1_1}")
5663 let(:action) { :purge }
5664 exclude_test = !(%w{rhel amazon fedora}.include?(OHAI_SYSTEM[:platform_family]) && File.exist?("/usr/bin/dnf"))
5665 File.open("/etc/yum.repos.d/chef-dnf-localtesting.repo", "w+") do |f|
5666 %w{1.10 1* 1.10-1 1*-1 1.10-* 1*-* 0:1.10 0:1* 0:1.10-1 0:1*-1 *:1.10-* *:1*-*}.each do |vstring|
5667 %w{1.2 1* 1.2-1 1*-1 1.2-* 1*-* 0:1.2 0:1* 0:1.2-1 0:1*-1 *:1.2-* *:1*-*}.each do |vstring|
5668 %w{1.2 1.2-1 1.2-* 0:1.2 0:1.2-1 *:1.2-*}.each do |vstring|
5669 %w{1* 1*-1 1*-* 0:1* 0:1*-1 *:1*-*}.each do |vstring|
5670 dnf_package "chef_rpm-0:1.2-1.#{pkg_arch}" do
5671 dnf_package "chef_rp*-1*" do
5672 it "matches with a vr glob", :rhel_gte_8 do
5673 dnf_package "chef_rpm >= 1.2" do
5674 dnf_package "chef_rpm > 1.2" do
5675 dnf_package "chef_rpm = 1.10" do
5676 dnf_package "chef_rpm = 1.2" do
5677 dnf_package "chef_rpm > 2.0"
5678 dnf_package "chef_rpm < 1.10" do
5679 dnf_package [ "chef_rpm.#{pkg_arch}", "chef_rpm.i686" ] do
5680 dnf_package "chef_rpm-1.10-1.#{pkg_arch}" do
5681 when "aix", "solaris2", "omnios"
5682 expect(shell_out("crontab -l #{new_resource.user} | grep \"#{cron_name}\"").exitstatus).to eq(0)
5683 expect(shell_out("crontab -l #{new_resource.user} | grep \"#{cron_name}\"").stdout.lines.to_a.size).to eq(1)
5684 expect(shell_out("crontab -l #{new_resource.user} | grep \"#{command}\"").exitstatus).to eq(0)
5685 expect(shell_out("crontab -l #{new_resource.user} | grep \"#{command}\"").stdout.lines.to_a.size).to eq(1)
5686 expect(shell_out("crontab -l -u #{new_resource.user} | grep \"#{cron_name}\"").exitstatus).to eq(0)
5687 expect(shell_out("crontab -l #{new_resource.user} | grep \"#{cron_name}\"").stdout.lines.to_a.size).to eq(0)
5688 expect(shell_out("crontab -l -u #{new_resource.user} | grep \"#{command}\"").exitstatus).to eq(0)
5689 expect(shell_out("crontab -l #{new_resource.user} | grep \"#{command}\"").stdout.lines.to_a.size).to eq(0)
5690 expect(shell_out("crontab -l #{new_resource.user} | grep \"#{cron_name}\"").exitstatus).to eq(1)
5691 expect(shell_out("crontab -l #{new_resource.user} | grep \"#{new_resource.command}\"").stdout.lines.to_a.size).to eq(0)
5692 expect(shell_out("crontab -l -u #{new_resource.user} | grep \"#{cron_name}\"").exitstatus).to eq(1)
5693 expect(shell_out("crontab -l -u #{new_resource.user} | grep \"#{new_resource.command}\"").stdout.lines.to_a.size).to eq(0)
5694 weekdays = { Mon: 1, tuesday: 2, '3': 3, 'thursday': 4, 'Fri': 5, 6 => 6 }
5695 expect(shell_out("crontab -l -u #{new_resource.user} | grep '#{attribute.upcase}=\"#{value}\"'").exitstatus).to eq(0)
5696 %i{ home mailto path shell }.each do |attr|
5697 let(:file_base) { "cookbook_file_spec" }
5698 let(:source) { "java.response" }
5699 let(:cookbook_name) { "java" }
5700 let(:package_name) { "test-A" }
5701 let(:package_list) { proc { shell_out!("choco list -lo -r #{Array(package_name).join(" ")}").stdout.chomp } }
5702 let(:package_name) { %w{test-A test-B} }
5703 expect(package_list.call).to eq("test-A|2.0\r
test-B|1.0")
5704 expect(provider.send(:cmd_args)).to eq(["--force", "--confirm"])
5705 subject.options [ "--force", "--confirm" ]
5706 ::File.exist?("/usr/PkgA/bin/acommand")
5707 !::File.exist?("/usr/PkgA/bin/acommand")
5708 @pkg_name = "PkgA.rte"
5709 @pkg_path = "#{Dir.tmpdir}/PkgA.1.0.0.0.bff"
5710 shell_out("installp -u #{@pkg_name}")
5711 shell_out("installp -aYF -d #{@pkg_path} #{@pkg_name}")
5712 @pkg_path = "#{Dir.tmpdir}/PkgA.2.0.0.0.bff"
5713 let(:output_command) { " > " }
5714 let(:code) { "echo hello" }
5715 let(:command) { "wizard racket" }
5716 let(:code) { nil }
5717 let(:tmp_path) { Dir.mktmpdir }
5718 let(:extract_destination) { "#{tmp_path}/extract_here" }
5719 expect(Dir.glob("#{extract_destination}/**/*").length).to eq(4)
5720 expect(Dir.glob("#{extract_destination}/**/*").length).to eq(3)
5721 expect(Dir.glob("#{extract_destination}/**/*").length).to eq(1)
5722 File.open("/etc/apt/sources.list.d/chef-integration-test.list", "w+") do |f|
5723 shell_out!("apt-get update " +
5724 metadata = { unix_only: true,
5725 r.options("--force-yes")
5726 r.version("2.0")
5727 shell_out!("dpkg -i #{v_1_1_package}")
5728 pkg_check = shell_out!("dpkg -l chef-integration-test", returns: [0, 1])
5729 shell_out!("dpkg -i #{v_1_0_package}")
5730 dpkg_l = shell_out!("dpkg -l chef-integration-test", returns: [0])
5731 r.version("1.1-1")
5732 directory = []
5733 directory << "/etc/rc.d/rc#{level}.d/#{(o[0] == :start ? "S" : "K")}#{o[1]}#{new_resource.service_name}"
5734 directory << "/etc/rc.d/rc#{run_level}.d/#{status}#{priority}#{new_resource.service_name}"
5735 files = Dir.glob("#{Dir.tmpdir}/chefinit[a-z_]*.txt")
5736 FileUtils.cp((File.join(__dir__, "/../assets/chefinittest")).to_s, "/etc/rc.d/init.d/chefinittest")
5737 valid_symlinks(["/etc/rc.d/rc2.d/Schefinittest"], 2, "S")
5738 valid_symlinks(["/etc/rc.d/rc2.d/S75chefinittest"], 2, "S", 75)
5739 valid_symlinks(["/etc/rc.d/rc2.d/Kchefinittest"], 2, "K")
5740 valid_symlinks(["/etc/rc.d/rc2.d/K25chefinittest"], 2, "K", 25)
5741 @priority = { 2 => [:stop, 20], 3 => [:start, 10] }
5742 valid_symlinks(["/etc/rc.d/rc2.d/K80chefinittest"], 2, "K", 80)
5743 expect(shell_out!("lssrc -a | grep #{new_resource.service_name}").stdout.split(" ").last).to eq("active")
5744 expect(shell_out!("lssrc -a | grep #{new_resource.service_name}").stdout.split(" ").last).to eq("inoperative")
5745 args = shell_out!("lssrc -a | grep #{new_resource.service_name}").stdout.split(" ")
5746 if args.length == 3
5747 shell_out("id -u #{ENV["USER"]}").stdout.chomp
5748 script_dir = File.join(__dir__, "/../assets/")
5749 shell_out!("mkssys -s ctestsys -p #{script_dir}/testchefsubsys -u #{get_user_id} -S -n 15 -f 9 -R -Q")
5750 shell_out!("mkssys -s ctestsys -p #{script_dir}/testchefsubsys -u #{get_user_id} -S -n 15 -f 9 -R -Q -G ctestgrp")
5751 windows: "#{ENV["SYSTEMROOT"]}/System32/shutdown.exe /r /t 300 /c \"rebooter spec test\"",
5752 linux: 'shutdown -r +5 "rebooter spec test" &',
5753 solaris: 'shutdown -i6 -g5 -y "rebooter spec test" &',
5754 let(:uri) { URI.parse("http://www.bing.com/robots.txt") }
5755 let(:mtime) { "Thu, 01 Aug 2013 08:16:32 GMT" }
5756 URI.parse("http://www.bing.com/" + ("0" * 1024))
5757 n.override[:os] = "darwin"
5758 let(:recipe) { Chef::Recipe.new("notif", "test", run_context) }
5759 actions = []
5760 actions[-1][:why_run] = Chef::Config[:why_run] if Chef::Config[:why_run]
5761 r = recipe
5762 t = self
5763 if succeeded == 0 || last_error != 0
5764 let(:test_user) { "chefuserctx3" }
5765 let(:test_password) { "j823jfxK3;2Xe1" }
5766 let(:domain_to_impersonate) { "." }
5767 shell_out("echo %LC_ALL%", default_env: false)
5768 shell_out("echo %LC_ALL%", environment: { "LC_ALL" => "POSIX" }, default_env: false)
5769 shell_out("echo $LC_ALL", environment: { "LC_ALL" => "POSIX" }, default_env: false)
5770 def a(a = nil)
5771 @a = a if a
5772 @a
5773 @debug_log = ""
5774 allow(Chef::Log).to receive(:trace) { |str| @debug_log << str }
5775 let(:source) { "http://localhost:9000" }
5776 ( mode_int & 07777).to_s(8)
5777 File.open(path, "w+", 0600) { |f| f.print(staging_file_content) }
5778 random.rand(1 << 32).to_s
5779 let(:elapsed_time) { rand }
5780 let(:mock_exception) { double("Exception", { message: rand, backtrace: [rand, rand] }) }
5781 e.source == ChefUtils::Dist::Infra::SHORT && e.event_id == 10000 &&
5782 e.source == ChefUtils::Dist::Infra::SHORT && e.event_id == 10001 &&
5783 e.source == ChefUtils::Dist::Infra::SHORT && e.event_id == 10002 &&
5784 e.string_inserts[0].include?(run_id) &&
5785 e.source == ChefUtils::Dist::Infra::SHORT && e.event_id == 10003 &&
5786 e.string_inserts[0].include?("UNKNOWN") &&
5787 e.string_inserts[1].include?("UNKNOWN") &&
5788 expect(values.include?({ name: "RootType1", type: :string, data: "fibrous" })).to eq(true)
5789 expect(@resource.registry_value_exists?("HKCU\\Software\\Root", { name: "RootType1", type: :string, data: "fibrous" })).to eq(true)
5790 expect(@resource.registry_data_exists?("HKCU\\Software\\Root", { name: "RootType1", type: :string, data: "fibrous" })).to eq(true)
5791 let(:reg_key) { nil }
5792 let(:original_set) { false }
5793 { name: "PendingFileRenameOperations", type: :multi_string, data: ['\??\C:\foo.txt|\??\C:\bar.txt'] })
5794 Chef::Config[:ftp_proxy] = nil
5795 Chef::Config[:no_proxy] = nil
5796 so = if windows?
5797 shell_out("echo %http_proxy%")
5798 ohai[:disabled_plugins] << "darwin::system_profiler" << "darwin::kernel" << "darwin::ssh_host_key" << "network_listeners"
5799 ohai[:disabled_plugins] << "darwin::uptime" << "darwin::filesystem" << "dmi" << "languages" << "perl" << "python" << "java"
5800 ohai[:disabled_plugins] << "linux::block_device" << "linux::kernel" << "linux::ssh_host_key" << "linux::virtualization"
5801 ohai[:disabled_plugins] << "linux::cpu" << "linux::memory" << "ec2" << "rackspace" << "eucalyptus" << "ip_scopes"
5802 ohai[:disabled_plugins] << "solaris2::cpu" << "solaris2::dmi" << "solaris2::filesystem" << "solaris2::kernel"
5803 ohai[:disabled_plugins] << "c" << "php" << "mono" << "groovy" << "lua" << "erlang"
5804 ohai[:disabled_plugins] << "kernel" << "linux::filesystem" << "ruby"
5805 chef_repo_path __dir__
5806 run_list "test", "test::one", "test::two"
5807 define :new_cat, :is_pretty => true do
5808 cat "#{params[:name]}" do
5809 define :new_dog, :is_cute => true do
5810 dog "#{params[:name]}" do
5811 badger "#{params[:name]}"
5812 normal_unless[:attr_load_order] = []
5813 @resources ||= []
5814 block { }
5815 version "1.0.0"
5816 default["aliased"]["attr"] = "value"
5817 default["aliased"]["attr"] = "other"
5818 version "0.0.1"
5819 default[:sunshine] = "in"
5820 normal[:sunshine] = "in"
5821 a :foo
5822 c :bar
5823 }.each do |os|
5824 @monkey_name = "my monkey's name is '#{new_resource.monkey}'"
5825 block {}
5826 option :scro, :short => '-s SCRO', :long => '--scro SCRO', :description => 'a configurable setting'
5827 @ran = true
5828 define :rico_suave, :rich => "smooth" do
5829 something "#{params[:rich]}"
5830 version '0.1.0'
5831 supports 'centos', '>= 6'
5832 supports 'freebsd', '> 10.1-fake-p12'
5833 chef_env ||= nil
5834 (*&(*&(*&(*&(*^%$%^%#^^&(*)(*{}}}}}}}}+++++===))))))
5835 (*&(*&(*&(*&(*^%$%^%#^^&(*)(*{}}}}}}}}+++++===)))))
5836 echo "grant all on *.* to root@'$i' identified by 'a_password'; flush privileges;" | mysql -u root -h 127.0.0.1
5837 1 / 0
5838 Dir["#{gem_home}/bundler/gems/*"].each do |gempath|
5839 matches = File.basename(gempath).match(/.*-[A-Fa-f0-9]{12}/)
5840 gem_name = File.basename(Dir["#{gempath}/*.gemspec"].first, ".gemspec")
5841 puts "re-installing #{gem_name}..."
5842 (base_dirs.length - 1).downto(0) do |i|
5843 candidate_ca_bundle = File.join(base_dirs[0..i] + [ "ssl/certs/cacert.pem" ])
5844 source path: "#{project.files_path}/#{name}"
5845 Dir.glob("#{install_dir}/embedded/lib/ruby/gems/*/gems/*/bin/{console,setup}").each do |f|
5846 puts "Deleting #{f}"
5847 Dir.glob("#{install_dir}/**/{.gitkeep,.keep}").each do |f|
5848 target_dir = "#{install_dir}/embedded/lib/ruby/gems/*/gems".tr("\\", "/")
5849 files = %w{
5850 Dir.glob("#{target_dir}/*/{#{files.join(",")}}").each do |f|
5851 next if File.basename(File.expand_path("..", f)).start_with?("chef-")
5852 next if File.basename(File.expand_path("..", f)).start_with?("ruby-prof-")
5853 Dir.glob("#{install_dir}/embedded/lib/ruby/gems/*/gems/*/VERSION".tr("\\", "/")).each do |f|
5854 next if File.basename(File.expand_path("..", f)).start_with?("aws", "jmespath")
5855 next if Dir.exist?(File.join(File.dirname(f), "bin")) && !Dir.empty?(File.join(File.dirname(f), "bin"))
5856 Dir.glob("#{install_dir}/embedded/lib/ruby/gems/*/gems/*/spec".tr("\\", "/")).each do |f|
5857 }.each do |f|
5858 file_path = "#{install_dir}/embedded/bin/#{f}"
5859 source path: "#{project.files_path}/../..",
5860 options: { exclude: [ "omnibus/vendor" ] }
5861 ruby_version = "3.1.2"
5862 ruby_version = ruby_version.split(".")[0..1].join(".")
5863 ruby_mmv = "#{ruby_version}.0"
5864 ruby_dir = "#{install_dir}/embedded/lib/ruby/#{ruby_mmv}"
5865 gem_dir = "#{install_dir}/embedded/lib/ruby/gems/#{ruby_mmv}"
5866 bin_dirs bin_dirs.concat ["#{gem_dir}/gems/*/bin/**"]
5867 bundle "install --without #{bundle_excludes.join(" ")}", env: env
5868 gem "build #{gemspec_name}", env: env
5869 copy "chef*.gem", "pkg"
5870 %w{rubyzip}.each do |gem|
5871 sync "#{project_dir}", "#{install_dir}"
5872 current_file ||= __FILE__
5873 version_file = File.expand_path("../../../../VERSION", current_file)
5874 install_dir "#{default_root}/#{name}"
5875 current_file = __FILE__
5876 chef_project_contents = IO.read(File.expand_path("chef.rb", __dir__))
5877 marketing_names = []
5878 (@major_version == v[:major]) &&
5879 (@minor_version == v[:minor]) &&
5880 (v[:callable] ? v[:callable].call(@product_type, @suite_mask, @build_number) : true)
5881 break mn[0] if send(mn[1])
5882 define_method("#{m}?") do
5883 (self.class.const_get(c) == @sku) &&
5884 (c.to_s =~ /#{m}/i )
5885 windows_10? && build_number >= 15063
5886 os_version.split(".").collect(&:to_i)
5887 length = 0
5888 while last_char != "\000\000"
5889 length += 1
5890 last_char = get_bytes(0, length * 2)[-2..]
5891 wide_to_utf8(get_bytes(0, num_wchars * 2))
5892 offset = 0
5893 offset += 2 while get_bytes(offset, 2) != "\x00\x00"
5894 def ==(other)
5895 (!domain.nil? && domain.length > 0) ? "#{domain}\\#{name}" : name
5896 SID.from_string_sid("S-1-0")
5897 SID.from_string_sid("S-1-0-0")
5898 SID.from_string_sid("S-1-1")
5899 SID.from_string_sid("S-1-1-0")
5900 SID.from_string_sid("S-1-2")
5901 SID.from_string_sid("S-1-3")
5902 SID.from_string_sid("S-1-3-0")
5903 SID.from_string_sid("S-1-3-1")
5904 SID.from_string_sid("S-1-3-2")
5905 SID.from_string_sid("S-1-3-3")
5906 SID.from_string_sid("S-1-4")
5907 SID.from_string_sid("S-1-5")
5908 SID.from_string_sid("S-1-5-1")
5909 SID.from_string_sid("S-1-5-2")
5910 SID.from_string_sid("S-1-5-3")
5911 SID.from_string_sid("S-1-5-4")
5912 SID.from_string_sid("S-1-5-6")
5913 SID.from_string_sid("S-1-5-7")
5914 SID.from_string_sid("S-1-5-8")
5915 SID.from_string_sid("S-1-5-9")
5916 SID.from_string_sid("S-1-5-10")
5917 SID.from_string_sid("S-1-5-11")
5918 SID.from_string_sid("S-1-5-12")
5919 SID.from_string_sid("S-1-5-13")
5920 SID.from_string_sid("S-1-5-18")
5921 SID.from_string_sid("S-1-5-19")
5922 SID.from_string_sid("S-1-5-20")
5923 SID.from_string_sid("S-1-5-32-544")
5924 SID.from_string_sid("S-1-5-32-545")
5925 SID.from_string_sid("S-1-5-32-546")
5926 SID.from_string_sid("S-1-5-32-547")
5927 SID.from_string_sid("S-1-5-32-548")
5928 SID.from_string_sid("S-1-5-32-549")
5929 SID.from_string_sid("S-1-5-32-550")
5930 SID.from_string_sid("S-1-5-32-551")
5931 SID.from_string_sid("S-1-5-32-552")
5932 if user_info[:usri3_user_id] == 500 && user_info[:usri3_priv] == 2 # USER_PRIV_ADMIN (2) - Administrator
5933 @path = path
5934 @type = type
5935 aces_size = aces.inject(0) { |sum, ace| sum + ace.size }
5936 0.upto(length - 1) do |i|
5937 return false if self[i] != other[i]
5938 def [](index)
5939 0.upto(length - 1) { |i| yield self[i] }
5940 aces.reverse_each { |ace| add_ace(self, ace, index) }
5941 (size + 4 - 1) & 0xfffffffc
5942 type == other.type && flags == other.flags && mask == other.mask && sid == other.sid
5943 struct[:Mask] = val
5944 struct[:Mask] = mask
5945 privileges = []
5946 accounts = []
5947 if result == 0
5948 account_name = (!domain.nil? && domain.length > 0) ? "#{domain}\\#{name}" : name
5949 Chef::ReservedNames::Win32::Error.raise!("get_named_security_info(#{path}, #{type}, #{info})", hr)
5950 [ present.read_char != 0, acl.null? ? nil : ACL.new(acl, security_descriptor), defaulted.read_char != 0 ]
5951 [ sid, defaulted ]
5952 IsValidAcl(acl) != 0
5953 IsValidSid(sid) != 0
5954 use = FFI::Buffer.new(:long).write_long(0)
5955 owner = args[:owner]
5956 group = args[:group]
5957 dacl = args[:dacl]
5958 sacl = args[:sacl]
5959 access = 0
5960 if win32_error != 0
5961 reg.map { |name, type, data| { name: name, type: get_name_from_type(type), data: data } }
5962 data = value[:data]
5963 data = data.to_s if value[:type] == :string
5964 Chef::Log.trace("Updating value #{value[:name]} in registry key #{key_path} with type #{value[:type]} and data #{data}")
5965 Chef::Log.trace("Value #{value[:name]} in registry key #{key_path} updated")
5966 Chef::Log.trace("Value #{value[:name]} in registry key #{key_path} created")
5967 key_parent = key_parts.join("\\")
5968 rescue ::Win32::Registry::Error => e
5969 reg.each_key { |key| return true }
5970 subkeys = []
5971 reg.each_key { |current_key| subkeys << current_key }
5972 ( applied_arch == :x86_64 ) ? 0x0100 : 0x0200
5973 val_type == get_type_from_name(value[:type]) &&
5974 val_data == value[:data]
5975 if val_name == value[:name]
5976 if val_type == type_new
5977 missing_key_arr = key_path.split("\\")
5978 key = missing_key_arr.join("\\")
5979 ::RbConfig::CONFIG["target_cpu"] == "x64" ? :x86_64 : :i386
5980 reg_path = path.split("\\")
5981 key = reg_path.join("\\")
5982 hive = {
5983 }[hive_name]
5984 [hive, key]
5985 @_name_type_map ||= _type_name_map.invert
5986 }[val_type]
5987 existing_key_path = existing_key_path << "\\" << intermediate_key
5988 (call_succeeded != 0) && (is_64_bit_process_result.get_int(0) != 0)
5989 { usri3_name: nil,
5990 }.each do |(k, v)|
5991 s.set(k, v)
5992 group_members = []
5993 server_name, group_name, 0, buf, -1,
5994 args.each do |k, v|
5995 buf.set(k, v)
5996 info.each do |k, v|
5997 ui2_hash.each do |(k, v)|
5998 rc = NetUseAdd(server_name, 2, buf, nil)
5999 if @handle == 0
6000 }.each do |method|
6001 to_hex(trans[:w_lang]) + to_hex(trans[:w_code_page])
6002 integer.to_s(16).rjust(4, "0")
6003 raise Errno::ENOENT, "(#{old_name}, #{new_name})" unless ::File.exist?(old_name) || ::File.symlink?(old_name)
6004 if ::File.exist?(file_name) || ::File.symlink?(file_name)
6005 if /^\\\?\?\\/.match?(link_dest)
6006 link_dest = link_dest[4..]
6007 if size == 0
6008 result = FFI::MemoryPointer.new :char, (size + 1) * 2
6009 def self.format_message(message_id = 0, args = {})
6010 source = args[:source] || 0
6011 language_id = args[:language_id] || 0
6012 varargs = args[:varargs] || [:int, 0]
6013 if num_chars == 0
6014 formatted_message << "---- Begin Win32 API output ----
"
6015 formatted_message << "---- End Win32 API output ----
"
6016 :sz_csd_version, [:BYTE, 256],
6017 :w_suite_mask, :WORD,
6018 :w_product_type, :BYTE,
6019 :Sbzl, :uchar,
6020 :Mask, :uint32,
6021 ].include?(ace_type)
6022 val = if val.is_a? String
6023 self[key] = val
6024 val = self[key]
6025 members.inject({}) do |memo, key|
6026 memo[key] = get(key)
6027 if !val.nil? && !val.null?
6028 ffi_lib "msi"
6029 if status != 234
6030 if status != 0
6031 (device_type << 16) | (access << 14) | (function << 2) | method
6032 layout :w_lang, :WORD,
6033 :n_file_size_high, :DWORD,
6034 :n_file_size_low, :DWORD,
6035 :c_alternate_file_name, [:BYTE, 14]
6036 :Flags, :uint32,
6037 path = ::File.expand_path(path) if path.start_with? "/"
6038 if success == 0
6039 if file_size == 0
6040 layout :cbData, :DWORD, # Count, in bytes, of data
6041 arguments_list = []
6042 offset = offset + argument.length * 2 + 2
6043 ((low & 0xff) | (high & 0xff)) << 8
6044 ((low & 0xffff) | (high & 0xffff)) << 16
6045 l & 0xffff
6046 l >> 16
6047 w & 0xff
6048 w >> 8
6049 status >> 31 == 1
6050 sev << 31 | fac << 16 | code
6051 (hr >> 16) & 0x1fff
6052 if x <= 0
6053 (x & 0x0000FFFF) | (7 << 16) | 0x80000000
6054 (hr >> 31) & 0x1
6055 status < 0
6056 status >= 0
6057 low + (high * (2**32))
6058 OPS = %w{< > = <= >= ~>}.freeze
6059 PATTERN = /^(#{OPS.join('|')}) *([0-9].*)$/.freeze
6060 other.class == self.class && @op == other.op && @version == other.version
6061 alias_method :==, :eql?
6062 elsif @op == "="
6063 elsif @op == "~>"
6064 raise "bad op #{@op}"
6065 msg << "['#{constraint_spec.join(", ")}']"
6066 if str.index(" ").nil? && str =~ /^[0-9]/
6067 @op = "="
6068 @op = $1
6069 @raw_version = $2
6070 if @raw_version.split(".").size <= 2
6071 def initialize(str = "")
6072 def <=>(other)
6073 ans = (version <=> other.send(method))
6074 other.is_a?(Version) && self == other
6075 def parse(str = "")
6076 @major, @minor, @patch =
6077 when /^(\d+)\.(\d+)\.(\d+)$/
6078 [ $1.to_i, $2.to_i, $3.to_i ]
6079 when /^(\d+)\.(\d+)$/
6080 [ $1.to_i, $2.to_i, 0 ]
6081 msg = "'#{str}' does not match 'x.y.z' or 'x.y'"
6082 when /^(\d+)$/
6083 [ $1.to_i, 0, 0 ]
6084 when /^(\d+).(\d+)-[a-z]+\d?(-p(\d+))?$/i # Match FreeBSD
6085 [ $1.to_i, $2.to_i, ($4 ? $4.to_i : 0)]
6086 msg = "'#{str}' does not match 'x.y.z', 'x.y' or 'x'"
6087 require_relative "../../win32/api/file"
6088 name += "\\" unless /\\$/.match?(name) # trailing slash required
6089 require_relative "../../win32/net"
6090 args.inject({}) do |memo, (k, v)|
6091 usri3.inject({}) do |memo, (k, v)|
6092 memo[t[k]] = v
6093 if /System Error Code: 1326/.match?(e.to_s)
6094 user[:last_logon] = user[:units_per_week] = 0 # ignored as per USER_INFO_3 doc
6095 user[:logon_hours] = nil # PBYTE field; \0 == no changes
6096 args.each do |key, val|
6097 user[key] = val
6098 use_info.inject({}) do |memo, (k, v)|
6099 memo["ui2_#{k}".to_sym] = v
6100 args = {}
6101 args[:local] ||= use_name
6102 ui2_hash.inject({}) do |memo, (k, v)|
6103 memo[k.to_s.sub("ui2_", "").to_sym] = v
6104 @token = nil
6105 def <<(job)
6106 @queue << job
6107 fn = @queue.pop
6108 fn.arity == 1 ? fn.call(@lock) : fn.call
6109 workers.each { |worker| self << Thread.method(:exit) }
6110 restorecon_flags = [ "-R" ]
6111 @changes = (editor.replace_lines(regex, newline) > 0) || @changes
6112 @changes = (editor.replace(regex, replace) > 0) || @changes
6113 @changes = (editor.remove_lines(regex) > 0) || @changes
6114 @changes = (editor.append_line_after(regex, newline) > 0) || @changes
6115 !!@changes
6116 lines = []
6117 lines << line
6118 (lines.length - @lines.length).tap { @lines = lines }
6119 count = 0
6120 count = 1
6121 @lines.map! do |line|
6122 count += 1
6123 if found.length == 0
6124 r["ResourceType"].casecmp(new_r["ResourceType"]) == 0
6125 if count == 0
6126 rs.each do |r|
6127 found = rs.find_all do |r|
6128 name_matches = r["Name"].casecmp(name) == 0
6129 module_name.nil? || (r["Module"] && r["Module"]["Name"].casecmp(module_name) == 0)
6130 []
6131 [ret_val]
6132 @sets = sets
6133 @change_log = change_log || []
6134 ps4_base_command + " -whatif; if (! $?) { exit 1 }"
6135 !! (dsc_exception_output.gsub(/
+/, "").gsub(/\s+/, " ") =~ /A parameter cannot be found that matches parameter name 'Whatif'/i)
6136 !! (command_output =~ /\sCimException/ &&
6137 Chef::Log.warn("Could not parse LCM output: #{e}")
6138 require_relative "../../log"
6139 lcm_output = String(lcm_output).split("
")
6140 resources = []
6141 op_action , op_value = line.strip.split(":")
6142 current_resource[:skipped] = op_value.strip == "True" ? true : false
6143 current_resource = { name: info }
6144 Chef::Log.trace("Ignoring op_action #{op_action}: Read line #{line}")
6145 if match = line.match(/^.*?:.*?:\s*LCM:\s*\[(.*?)\](.*)/)
6146 op_action, op_type = operation.strip.split(" ").map { |m| m.downcase.to_sym }
6147 op_action = op_type = :info
6148 if match = line.match(/^.*?:.*?: \s+(.*)/)
6149 [op_action, op_type, info]
6150 Chef::Util::DSC::ResourceInfo.new(r[:name], !r[:skipped], r[:logs])
6151 Chef::Log.trace("DSC: DSC code:
'#{code}'")
6152 unless switch_parameter_name.match?(/\A[A-Za-z]+[_a-zA-Z0-9]*\Z/)
6153 parameter_value.gsub(/(`|'|"|#)/, '`\1')
6154 switch_argument = ""
6155 switch_present ? ["-#{switch_name.to_s.downcase}", switch_argument].join(" ").strip : ""
6156 if !!(configuration_name =~ /\A[A-Za-z]+[_a-zA-Z0-9]*\Z/) == false
6157 if resources.length == 0 || resources.include?("*")
6158 document_file_name = ::Dir.entries(document_directory).find { |path| path =~ /.*.mof/ }
6159 @diff.nil? ? [ @error ] : @diff
6160 @diff.join("\
")
6161 @error = do_diff(old_file, new_file)
6162 diff_str = ""
6163 diff_data = ::Diff::LCS.diff(old_data, new_data)
6164 ft = File.stat(old_file).mtime.localtime.strftime("%Y-%m-%d %H:%M:%S.%N %z")
6165 diff_str << "--- #{old_file}\t#{ft}
"
6166 ft = File.stat(new_file).mtime.localtime.strftime("%Y-%m-%d %H:%M:%S.%N %z")
6167 diff_str << "+++ #{new_file}\t#{ft}
"
6168 old_hunk = hunk = nil
6169 diff_str << old_hunk.diff(:unified) << "
"
6170 Chef::Log.trace("Running: diff -u #{old_file} #{new_file}")
6171 @diff = diff_str.split("
")
6172 buff = "" if buff.nil?
6173 return buff !~ /\A[\s[:print:]]*\z/m
6174 diff_str.encode!("UTF-8", invalid: :replace, undef: :replace, replace: "?")
6175 @path = path.nil? ? new_resource.path : path
6176 if @new_resource.backup != false && @new_resource.backup > 0 && ::File.exist?(path)
6177 nanoseconds = sprintf("%6f", time.to_f).split(".")[1]
6178 savetime = time.strftime("%Y%m%d%H%M%S.#{nanoseconds}")
6179 backup_filename = "#{path}.chef-#{savetime}"
6180 backup_filename = backup_filename.sub(/^([A-Za-z]:)/, "") # strip drive letter on Windows
6181 @prefix ||= Chef::Config[:file_backup_path].to_s
6182 Chef::Log.info("#{@new_resource} backed up to #{backup_path}")
6183 !!(f =~ /\A#{fn}.chef-[0-9.]*\B/)
6184 end.map { |f| ::File.join(::File.dirname(backup_path), f) }
6185 unsorted_backup_files.sort.reverse # faster than sort { |a, b| b <=> a }
6186 @last_name = nil
6187 @email = nil
6188 @chef_root_rest_v0 ||= Chef::ServerAPI.new(Chef::Config[:chef_server_root], { api_version: "0" })
6189 @chef_root_rest_v1 ||= Chef::ServerAPI.new(Chef::Config[:chef_server_root], { api_version: "1" })
6190 regex: /^[a-z0-9\-_]+$/)
6191 def email(arg = nil)
6192 result["email"] = @email unless @email.nil?
6193 payload = {
6194 if new_user["chef_key"]
6195 if new_user["chef_key"]["private_key"]
6196 new_user["private_key"] = new_user["chef_key"]["private_key"]
6197 new_user["public_key"] = new_user["chef_key"]["public_key"]
6198 if e.response.code == "400"
6199 if e.response.code == "409"
6200 payload = to_h.merge({ "private_key" => true })
6201 if e.response.code == "406" && e.response["x-ops-server-api-version"]
6202 users.inject({}) do |user_map, (name, _url)|
6203 new_response = {}
6204 name = u["user"]["username"]
6205 new_response[name] = Chef::Config[:chef_server_url] + "/users/#{name}"
6206 @name = ""
6207 @chef_rest_v0 ||= Chef::ServerAPI.new(Chef::Config[:chef_server_url], { api_version: "0" })
6208 def name(arg = nil)
6209 def admin(arg = nil)
6210 chef_rest_v0.delete("users/#{@name}")
6211 payload = { name: name, admin: admin }
6212 reregistered_self = chef_rest_v0.put("users/#{name}", { name: name, admin: admin, private_key: true })
6213 response = Chef::ServerAPI.new(Chef::Config[:chef_server_url], { api_version: "0" }).get("users")
6214 response = Chef::ServerAPI.new(Chef::Config[:chef_server_url], { api_version: "0" }).get("users/#{name}")
6215 !!@node_built
6216 print "."
6217 msg = success ? "done.

" : "epic fail!

"
6218 Chef::Log.info("Run List is [#{@node.run_list}]")
6219 Chef::Log.info("Run List expands to [#{@expanded_run_list_with_versions.join(", ")}]")
6220 puts "#{e.class.name}: #{e.message}"
6221 puts "* " * 40
6222 return all if query.to_s == "all"
6223 objects = @model_class.method(:list).arity == 0 ? @model_class.list : @model_class.list(true)
6224 objects.map { |obj| Array(obj).find { |o| o.is_a?(@model_class) } }
6225 query.map { |key, value| "#{key}:#{value}" }.join(" AND ")
6226 all_items = []
6227 @jobs.select { |job| block.call(job[1].context.main) }
6228 banner = []
6229 banner << ""
6230 banner << "".ljust(80, "=")
6231 banner << "| " + "Command".ljust(25) + "| " + "Description"
6232 banner << "| " + help_text.cmd.ljust(25) + "| " + help_text.desc
6233 banner << "
"
6234 banner.join("
")
6235 help = all_help_descriptions.find { |h| h.cmd.to_s == method_name.to_s }
6236 puts ""
6237 puts "Command: #{method_name}"
6238 puts "".ljust(80, "=")
6239 :on
6240 @help_descriptions ||= []
6241 @desc, @explain = nil, nil
6242 help_descriptions << Help.new("#{mname}.#{subcommand}", text.to_s, nil)
6243 @subcommand_help = {}
6244 when "on"
6245 when "off"
6246 explain(<<~E)
6247 puts "echo is #{conf.echo.to_on_off_str}"
6248 def ohai(key = nil)
6249 filename = "#{ChefUtils::Dist::Infra::SHELL}-edit-#{object.class.name}-"
6250 edited_data = Tempfile.open([filename, ".js"]) do |tempfile|
6251 system("#{Shell.editor} #{tempfile.path}")
6252 clients.all #=> [<Chef::ApiClient...>, ...]
6253 clients.search("KEY:VALUE") { |c| c.name }
6254 clients.transform("*:*") do |client|
6255 if client.name =~ /borat/i
6256 nodes.all #=> [<Chef::Node...>, <Chef::Node...>, ...]
6257 nodes.find(:name => "app*") #=> [<Chef::Node @name="app1.example.com" ...>, ...]
6258 nodes.find(:name => "app#") { |node| node.ec2 }
6259 if node.fqdn =~ /.*\\.preprod\\.example\\.com/
6260 show: "load a node by name",
6261 show: "load a role by name",
6262 show: "load a data bag item by id",
6263 @named_databags_wrappers ||= {}
6264 ::IRB.setup(nil)
6265 Chef::Config[:log_level] ||= :warn
6266 Chef::Config[:log_level] = :warn if Chef::Config[:log_level] == :auto
6267 Chef::Log.level = Chef::Config[:log_level] || :warn
6268 @irb_conf || IRB.conf
6269 irb_conf[:IRB_RC] = lambda do |conf|
6270 m = conf.main
6271 env_string = Shell.env ? " (#{Shell.env})" : ""
6272 puts "run `help' for help, `exit' or ^D to quit."
6273 long: "--[no-]multiline",
6274 long: "--[no-]singleline",
6275 long: "--[no-]colorize",
6276 short: "-h",
6277 long: "--help",
6278 on: :tail,
6279 proc: proc { print_help }
6280 short: "-a",
6281 long: "--standalone",
6282 short: "-s",
6283 long: "--solo",
6284 proc: proc { Chef::Config[:solo] = true }
6285 short: "-z",
6286 long: "--client",
6287 long: "--solo-legacy-mode",
6288 proc: proc { Chef::Config[:solo_legacy_mode] = true }
6289 short: "-v",
6290 long: "--version",
6291 proc: lambda { |items| items.split(",").map { |item| Chef::RunList::RunListItem.new(item) } }
6292 long: "--[no-]skip-cookbook-sync",
6293 unversioned? ? 0 : nil
6294 def initialize(url = Chef::Config[:chef_server_url], options = {})
6295 options[:client_name] ||= Chef::Config[:node_name]
6296 def raw_request(method, path, headers = {}, data = false)
6297 secret_uri = URI.parse("https://#{vault}.vault.azure.net/secrets/#{name}/#{version}?api-version=7.2")
6298 response = http.get(secret_uri, { "Authorization" => "Bearer #{token}",
6299 raise Chef::Exceptions::Secret::FetchFailed.new("#{result["error"]["code"]}: #{result["error"]["message"]}")
6300 if name.include?("/")
6301 name.split("/", 2)
6302 [config[:vault], name]
6303 @token_query ||= begin
6304 p = {}
6305 p["api-version"] = api_version
6306 p["client_id"] = client_id if client_id
6307 p["mi_res_id"] = mi_res_id if mi_res_id
6308 response = http.get(token_uri, { "Metadata" => "true" })
6309 config[:region] = config[:region] || Aws.config[:region] || run_context.node.dig("ec2", "region")
6310 config[:token] = "#{config[:access_id]}..#{config[:access_key]}"
6311 when nil, ""
6312 autoload :URI, "uri"
6313 @url = url
6314 @rest ||= Chef::ServerAPI.new(@url || @config[:chef_server_url])
6315 def search(type, query = "*:*", *args, &block)
6316 if args_h[:fuzz]
6317 if type.to_sym == :node
6318 args_h = args_h.reject { |k, v| k == :fuzz }
6319 args_h[:rows] ||= 1000
6320 response["rows"].each { |row| yield(row) if row }
6321 next_start = response["start"] + args_h[:rows]
6322 [ response["rows"], response["start"], response["total"] ]
6323 if !/:/.match?(query)
6324 unless t.is_a?(String) || t.is_a?(Symbol)
6325 msg = "Invalid search object type #{t.inspect} (#{t.class}), must be a String or Symbol." +
6326 args_h = {}
6327 args_h[:start] = args[0] if args[0]
6328 args_h[:rows] = args[1]
6329 args_h[:filter_result] = args[2]
6330 query_param_value = Addressable::URI::CharacterClasses::QUERY + "\\&\\;"
6331 qstr = "search/#{type}?q=#{escape_value(query)}"
6332 qstr += "&start=#{escape_value(start)}" if start
6333 qstr += "&rows=#{escape_value(rows)}" if rows
6334 def call_rest_service(type, query: "*:*", rows: nil, start: 0, filter_result: nil)
6335 response["rows"].map! { |row| row["data"] }
6336 response["rows"].map! do |row|
6337 saved = Chef::Config[:why_run]
6338 Chef::Config[:why_run] = saved
6339 @end_time = Time.now
6340 if @start_time && @end_time
6341 @end_time - @start_time
6342 { node: node,
6343 run_id: run_id }
6344 @exception && "#{@exception.class.name}: #{@exception.message}"
6345 @mutex = nil
6346 @runpid = nil
6347 if time_to_wait > 0.0
6348 @runlock = File.open(runlock_file, "a+")
6349 @mutex = Chef::ReservedNames::Win32::Mutex.new("Global\\#{runlock_file.tr("\\", "/").downcase}")
6350 release # Just to be on the safe side...
6351 @versions = {}
6352 map { |recipe_name| { name: recipe_name, version: @versions[recipe_name] } }
6353 [ recipe_name.sub(/::default$/, ""), recipe_name ]
6354 elsif recipe_name.include?("::")
6355 [ recipe_name, "#{recipe_name}::default" ]
6356 @type = (item["type"] || item[:type]).to_sym
6357 @name = item["name"] || item[:name]
6358 if item.key?("version") || item.key?(:version)
6359 @version = item["version"] || item[:version]
6360 @type = :recipe
6361 @name = match[1]
6362 @version = match[3] if match[3]
6363 @type = :role
6364 name = match[1]
6365 raise ArgumentError, "Unable to create #{self.class} from #{item.class}:#{item.inspect}: must be recipe[#{name}] or role[#{name}]"
6366 @name = item
6367 @type == :role
6368 @type == :recipe
6369 to_s == other.to_s
6370 other.respond_to?(:type) && other.respond_to?(:name) && other.respond_to?(:version) && other.type == @type && other.name == @name && other.version == @version
6371 unless (item.key?("type") || item.key?(:type)) && (item.key?("name") || item.key?(:name))
6372 @applied_roles = {}
6373 @run_list_trace = Hash.new { |h, key| h[key] = [] }
6374 @better_run_list_trace = Hash.new { |h, key| h[key] = [] }
6375 @all_missing_roles = {}
6376 @role_errors = {}
6377 seen_items = { recipe: {}, role: {} }
6378 { type: "recipe", name: item.name, version: item.version, skipped: !!skipped }
6379 { type: :role, name: item.name, children: (missing || error || skipped) ? [] : convert_run_list_trace(item.to_s, seen_items),
6380 @rest ||= (source || Chef::ServerAPI.new(Chef::Config[:chef_server_url]))
6381 Chef::Role.from_hash(rest.get("roles/#{name}"))
6382 if e.message == '404 "Not Found"'
6383 @role_errors[name] = e.to_s
6384 @run_list_items = run_list_items.map { |i| coerce_to_run_list_item(i) }
6385 @run_list_items.inject([]) { |memo, run_list_item| memo << run_list_item.name if run_list_item.role?; memo }
6386 @run_list_items.inject([]) { |memo, run_list_item| memo << run_list_item.name if run_list_item.recipe?; memo }
6387 def <<(run_list_item)
6388 alias :push :<<
6389 alias :add :<<
6390 @run_list_items.join(", ")
6391 to_a.map(&:to_s)
6392 @run_list_items.length == 0 ? true : false
6393 def [](pos)
6394 def []=(pos, item)
6395 @run_list_items.each { |i| yield(i) }
6396 @run_list_items.each_index { |i| yield(i) }
6397 item.each { |r| self << r }
6398 self << item
6399 @run_list_items.delete_if { |i| i == item }
6400 autoload :Set, "set"
6401 seen_cookbooks = {}
6402 default_file = list_of_attr_files.find { |path| File.basename(path) == "default.rb" }
6403 each_file_in_cookbook_by_segment(cookbook_name, :compliance, [ "waivers/**/*.{yml,yaml}" ]) do |filename|
6404 each_file_in_cookbook_by_segment(cookbook_name, :compliance, [ "inputs/**/*.{yml,yaml}" ]) do |filename|
6405 target = record[:path].delete_prefix("#{segment}/")
6406 rc = self
6407 @logger = logger || Chef::Log.with_child
6408 @definitions = {}
6409 @loaded_recipes_hash = {}
6410 @reboot_info = {}
6411 @before_notification_collection = Hash.new { |h, k| h[k] = [] }
6412 @immediate_notification_collection = Hash.new { |h, k| h[k] = [] }
6413 @delayed_notification_collection = Hash.new { |h, k| h[k] = [] }
6414 @delayed_actions = []
6415 v.select do |n|
6416 (n.resource.is_a?(String) && n.resource == resource.declared_key) ||
6417 result_recipes = []
6418 loaded_recipes_hash.key?("#{cookbook}::#{recipe}")
6419 loaded_recipes_hash["#{cookbook}::#{recipe}"] = true
6420 }.map(&:to_sym)
6421 @description = ""
6422 @env_run_lists = { "_default" => Chef::RunList.new }
6423 :name,
6424 regex: /^[\-[:alnum:]_]+$/
6425 @env_run_lists["_default"].reset!(args)
6426 @env_run_lists["_default"]
6427 msg << "(env_run_lists: #{env_run_lists.inspect})"
6428 env_run_lists.each { |k, v| @env_run_lists[k] = Chef::RunList.new(*Array(v)) }
6429 accumulator[k] = v.map(&:to_s)
6430 role = new
6431 role.name(o["name"])
6432 env_run_list_hash = { "_default" => (o.key?("run_list") ? o["run_list"] : o["recipes"]) }
6433 if o["env_run_lists"]
6434 response = {}
6435 chef_server_rest.put("roles/#{@name}", self)
6436 roles_files = Dir.glob(File.join(Chef::Util::PathHelper.escape_glob_dir(path), "**", "**"))
6437 js_files = roles_files.select { |file| file.match(%r{/#{name}\.json$}) }
6438 rb_files = roles_files.select { |file| file.match(%r{/#{name}\.rb$}) }
6439 if js_files.count > 1 || rb_files.count > 1
6440 if js_path && File.exist?(js_path)
6441 as_hash = {}
6442 as_hash["duration"] = ( action_record.elapsed_time * 1000 ).to_i.to_s
6443 @status = "success"
6444 @expanded_run_list = {}
6445 if !e.response || (code != "404" && code != "406")
6446 exception = "Exception: #{code} "
6447 reason = "Received #{code}. "
6448 if code == "406"
6449 @status = "failure"
6450 run_data = {}
6451 run_data["action"] = "end"
6452 run_data["status"] = @status
6453 run_data["data"] = {}
6454 run_data["start_time"] = start_time.to_s
6455 run_data["end_time"] = end_time.to_s
6456 exception_data = {}
6457 Zlib::GzipWriter.wrap(StringIO.new(out)) { |gz| gz << data }
6458 data[:actions] = {}
6459 resource.properties.reject { |_, k| k.options[:declared_in] == Chef::Resource || k.options[:skip_docs] }
6460 resource.properties.reject { |_, k| k.options[:skip_docs] }
6461 data[:properties] = properties.each_with_object([]) do |(n, k), acc|
6462 acc << { name: n, description: opts[:description],
6463 equal_to: sort_equal_to(opts[:equal_to]) }
6464 resources.each_with_object({}) do |r, res|
6465 pth = r["full_path"]
6466 extract_cookbook(arg, complete).each { |k, v| acc[k] = v }
6467 @defines = {}
6468 @name = nil
6469 @params = {}
6470 @recipe = nil
6471 @params[symbol] = args.length == 1 ? args[0] : args
6472 (name).to_s
6473 @position = 0
6474 @position += 1
6475 step while @position < size && !paused?
6476 @resources_by_key = {}
6477 key = key.to_s
6478 msg = "arguments to #{self.class.name}#find should be of the form :resource => 'name' or 'resource[name]'"
6479 rl = o["instance_vars"]["@resources_by_key"]
6480 resources = rl.merge(rl) { |k, r| Chef::Resource.from_hash(r) }
6481 instance_names = name_list.is_a?(Array) ? name_list : [ name_list ]
6482 name = $2
6483 arg =~ /^.+\[(.+)\]$/
6484 name = ""
6485 @resources = []
6486 ret = @resources.reject! { |r| r.to_s == key }
6487 def []=(index, resource)
6488 resources = o["instance_vars"]["@resources"].map { |r| Chef::Resource.from_hash(r) }
6489 instance_vars = {}
6490 o["instance_vars"].each do |k, v|
6491 def insert(resource, opts = {})
6492 if !(resource_type.nil? && instance_name.nil?)
6493 Chef::Log.warn("`[]=` is deprecated, use `insert` (which only inserts at the end)")
6494 Chef::Log.warn("`push` is deprecated, use `insert`")
6495 alias_method :<<, :insert
6496 { "@resource_list" => "ResourceList", "@resource_set" => "ResourceSet" }.each_pair do |name, klass|
6497 type 'rpm-md'
6498 regex: [%r{^[^/]+$}],
6499 coerce: proc { |v| Array(v) },
6500 default: []
6501 coerce: proc { |x| x.is_a?(String) ? x.shellsplit : x },
6502 default: "/etc/yum.repos.d/",
6503 property :cost, String, regex: /^\d+$/,
6504 property :metadata_expire, String, regex: [/^\d+$/, /^\d+[mhd]$/, /never/],
6505 property :mirror_expire, String, regex: [/^\d+$/, /^\d+[mhd]$/],
6506 property :mirrorlist_expire, String, regex: [/^\d+$/, /^\d+[mhd]$/],
6507 property :priority, String, regex: /^(\d?[1-9]|[0-9][0-9])$/,
6508 property :repositoryid, String, regex: [%r{^[^/]+$}],
6509 property :timeout, String, regex: /^\d+$/,
6510 yum_package 'netpbm >= 10.35.58-8.el8'
6511 yum_package 'netpbm >= 10'
6512 or:
6513 flush_cache [ :before ]
6514 identity: true, coerce: proc { |x| x.is_a?(Array) ? x.to_a : x }
6515 coerce: proc { |x| x.is_a?(Array) ? x.to_a : x }
6516 property :arch, [ String, Array ],
6517 default: { before: false, after: false },
6518 coerce: proc { |v|
6519 if v.is_a?(Hash)
6520 elsif v.is_a?(Array)
6521 v.each_with_object({}) { |arg, obj| obj[arg] = true }
6522 elsif v.is_a?(TrueClass) || v.is_a?(FalseClass)
6523 { before: v, after: v }
6524 elsif v == :before
6525 { before: true, after: false }
6526 elsif v == :after
6527 { after: true, before: false }
6528 regex: /^\S*$/, # no spaces
6529 coerce: proc { |x| clarify_reboot(x) },
6530 cmd = ""
6531 cmd << " -Force"
6532 coerce: proc { |v| Array(v) }
6533 users = []
6534 (users - accounts).each do |user|
6535 notify: 2,
6536 p >= 0 && p <= 22
6537 p > 0 && p < 25
6538 values [{
6539 type: :dword,
6540 values [{ name: "EnableLUA", type: :dword, data: bool_to_reg(new_resource.enable_uac) },
6541 bool ? 1 : 0
6542 day 'Mon, Thu'
6543 day 'Mon, Fri'
6544 property :task_name, String, regex: [%r{\A[^/\:\*\?\<\>\|]+\z}],
6545 description: "The Months of the year on which the task runs, such as: `JAN, FEB` or `*`. Multiple months should be comma delimited. e.g. `Jan, Feb, Mar, Dec`."
6546 default: 7, callbacks: { "should be in range of 0 to 10" => proc { |v| v >= 0 && v <= 10 } }
6547 introduced: "14.7",
6548 introduced: "17.0", default: 5,
6549 if start_day.nil? && day.nil?
6550 if (frequency_modifier.to_i.between?(2, 12)) && !(months.nil?)
6551 if start_day && frequency == :none
6552 raise ArgumentError, "`start_time` property must be in the HH:mm format (e.g. 6:20pm -> 18:20)." unless /^[0-2][0-9]:[0-5][0-9]$/.match?(start_time)
6553 @password_required ||= (!user.nil? && !Chef::ReservedNames::Win32::Security::SID.system_user?(user))
6554 if (%i{on_logon onstart on_idle none}.include?(frequency)) && ( frequency_modifier != 1)
6555 min = 1
6556 raise ArgumentError, "day wild card (*) is only valid with frequency :weekly" if frequency == :monthly && day == "*"
6557 if day.is_a?(String) && day.to_i.to_s != day
6558 days = day.split(",")
6559 days.map! { |day| day.to_s.strip.downcase }
6560 months = months.split(",")
6561 if !idle_time.nil? && frequency != :on_idle
6562 if idle_time.nil? && frequency == :on_idle
6563 unless idle_time.nil? || idle_time > 0 && idle_time <= 999
6564 task = ::Win32::TaskScheduler.new(new_resource.task_name, nil, "\\", false)
6565 pathed_task_name = new_resource.task_name.start_with?("\\") ? new_resource.task_name : "\\#{new_resource.task_name}"
6566 trigger_hash = {
6567 day = day.to_s.split(",")
6568 day.map! { |value| value.strip.upcase }
6569 flag = (task.author != new_resource.user ||
6570 task.principals[:run_level] != run_level ||
6571 task.author.to_s.casecmp(new_resource.user.to_s) != 0 ||
6572 ( new_resource.start_day && (current_task_trigger[:start_year].to_i != new_task_trigger[:start_year] ||
6573 ( new_resource.start_time && ( current_task_trigger[:start_hour].to_i != new_task_trigger[:start_hour] ||
6574 { once: nil }
6575 { months: months_of_year.to_i, days: days_of_month.to_i }
6576 weeks_of_month = []
6577 weeks.map! { |week| week.to_s.strip.upcase }
6578 days_of_month = []
6579 days = new_resource.day.to_s.split(",")
6580 days.map! { |day| day.to_s.strip.upcase }
6581 if days - (1..31).to_a
6582 days_of_month = days_of_month.size > 1 ? days_of_month.inject(:|) : days_of_month[0]
6583 new_resource.day = "mon, tue, wed, thu, fri, sat, sun" if new_resource.day == "*" && new_resource.frequency == :weekly
6584 months_of_year = []
6585 new_resource.months = "jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec" if new_resource.months == "*" && new_resource.frequency == :monthly
6586 data = []
6587 data.size > 1 ? data.inject(:|) : data[0]
6588 settings = {
6589 settings = {}
6590 validate = []
6591 cmd = "schtasks /#{task_action} /TN \"#{new_resource.task_name}\" "
6592 unless option == "TR"
6593 cmd += "/#{option} "
6594 cmd += "\"#{options[option].to_s.gsub('"', "\\\"")}\" " unless options[option] == ""
6595 if options["TR"]
6596 cmd += "/TR \"#{options["TR"]} \" " unless task_action == "DELETE"
6597 shell_out!(cmd, returns: [0])
6598 Date.strptime(date, "%m/%d/%Y").strftime("%a").upcase
6599 path 'C:\\foo'
6600 coerce: proc { |p| p.tr("/", "\\") || p }
6601 default: ""
6602 default: [], coerce: proc { |u| u.sort }
6603 default: "*"
6604 f_users = []
6605 c_users = []
6606 r_users = []
6607 when 2 then r_users << stripped_account(perm["AccountName"]) # 2 == read
6608 [f_users, c_users, r_users]
6609 name.slice!("#{node["hostname"]}\\")
6610 grant_command = "Grant-SmbShareAccess -Name '#{new_resource.share_name}' -AccountName \"#{new_resource.send("#{perm_type}_users").join('","')}\" -Force -AccessRight #{perm_type}"
6611 property_name = "#{type}_users"
6612 revoke_command = "Revoke-SmbShareAccess -Name '#{new_resource.share_name}' -AccountName \"#{users.join('","')}\" -Force"
6613 bool ? "$true" : "$false"
6614 property :display_name, String, regex: /^.{1,256}$/,
6615 coerce: proc { |x|
6616 if x.is_a?(Integer)
6617 introduced: "14.0",
6618 default: false, coerce: proc { |x|
6619 x == 0 ? false : true
6620 coerce: proc { |x| x.downcase }
6621 file = Tempfile.new(["#{security_option}", ".inf"])
6622 policy_line = "#{security_option} = \"#{security_value}\""
6623 file_path = file.path.tr("/", "\\")
6624 policy_line = "#{security_option} = #{security_value}"
6625 $security_options_data = (Get-Content $env:TEMP\\secopts_export.inf | Select-String -Pattern "^[CEFLMNPR].* =.*$" | Out-String)
6626 proc { |v| v.match(Resolv::IPv4::Regex) },
6627 default: lazy { |x| "IP_#{x.ipv4_address}" },
6628 description: "The printer port protocol: 1 (RAW) or 2 (LPR).",
6629 default: 1, equal_to: [1, 2]
6630 $_.Put()
6631 introduced: "17.3",
6632 windows_path 'C:\\7-Zip' do
6633 env "path" do
6634 value path.tr("/", "\\")
6635 path 'C'
6636 path 'E:\'
6637 path 'f:\'
6638 coerce: proc { |x| x.tr("/", "\\") },
6639 when /^[a-zA-Z]/
6640 new_resource.path[0] + ":\\pagefile.sys"
6641 when /^[a-zA-Z]:.*.sys/
6642 if ::Dir.exist?(pagefile[0] + ":\\") == false
6643 @exists ||= begin
6644 $page_file_name = '#{pagefile}';
6645 if ([string]::IsNullOrEmpty($pagefile)) { return $false } else { return $true }
6646 $page_file = '#{pagefile}';
6647 $driveLetter = $page_file.split(':')[0];
6648 { return $true }
6649 { return $false }
6650 $page_file = "#{pagefile}"
6651 $driveLetter = $page_file.split(':')[0]
6652 converge_by("set #{pagefile} to InitialSize=#{min} & MaximumSize=#{max}") do
6653 source 'C:\\7z920.msi'
6654 :path => 'C:\\7zip.msi',
6655 options '/Q'
6656 property :returns, [ String, Integer, Array ], default: [ 0, 3010 ],
6657 coerce: (proc do |s|
6658 end),
6659 desired_state: false, coerce: (proc { |c| c.downcase }),
6660 coerce: proc { |x| /^.:.*/.match?(x) ? x.tr("\\", "/").gsub("//", "/") : x }
6661 fonts_dir = Chef::Util::PathHelper.join(ENV["windir"], "fonts")
6662 icmp_type '8'
6663 default: lazy { rule_name },
6664 coerce: proc { |d| d.is_a?(String) ? d.split(/\s*,\s*/).sort : Array(d).sort.map(&:to_s) },
6665 coerce: proc { |d| d.is_a?(String) ? d.downcase.to_sym : d }
6666 default: "TCP",
6667 default: "Any",
6668 coerce: proc { |f| f.is_a?(String) ? f.downcase.to_sym : f }
6669 coerce: proc { |p| Array(p).map(&:downcase).map(&:to_sym).sort },
6670 p.all? { |e| %i{public private domain any notapplicable}.include?(e) }
6671 coerce: proc { |i| i.is_a?(String) ? i.downcase.to_sym : i }
6672 current_profiles = state["profile"].split(", ").map(&:to_sym)
6673 cmd << " -Group '#{new_resource.group}'" if new_resource.group && cmdlet_type == "New"
6674 cmd << " -LocalPort '#{new_resource.local_port.join("', '")}'" if new_resource.local_port
6675 cmd << " -RemoteAddress '#{new_resource.remote_address.join("', '")}'" if new_resource.remote_address
6676 cmd << " -RemotePort '#{new_resource.remote_port.join("', '")}'" if new_resource.remote_port
6677 cmd << " -IcmpType '#{new_resource.icmp_type}'"
6678 cmd << " -Profile '#{new_resource.profile.join("', '")}'" if new_resource.profile
6679 cmd << " -Enabled '#{new_resource.enabled}'"
6680 new_resource.icmp_type.split(":").all? { |type| (0..255).cover?(type.to_i) }
6681 if obj.to_s.downcase == "true"
6682 if ($#{profile_name}.Enabled) {
6683 } else {return $false}
6684 coerce: proc { |x| to_formatted_array(x) },
6685 x = x.split(/\s*,\s*/) if x.is_a?(String) # split multiple forms of a comma separated list
6686 converge_by("remove Windows feature#{"s" if features_to_remove.count > 1} #{features_to_remove.join(",")}") do
6687 @remove ||= begin
6688 raw_list_of_features || []
6689 raise "The Windows feature#{"s" if removed.count > 1} #{removed.join(",")} #{removed.count > 1 ? "are" : "is"} removed from the host and cannot be installed." unless removed.empty?
6690 install_command = "dism.exe /online /enable-feature #{features_to_install.map { |f| "/featurename:#{f}" }.join(" ")} /norestart"
6691 message = "remove Windows feature#{"s" if features_to_remove.count > 1} #{features_to_remove.join(",")}"
6692 shell_out!("dism.exe /online /disable-feature #{features_to_remove.map { |f| "/featurename:#{f}" }.join(" ")} /norestart", returns: [0, 42, 127, 3010], timeout: new_resource.timeout)
6693 @install ||= begin
6694 node.override["dism_features_cache"]["enabled"] = []
6695 node.override["dism_features_cache"]["disabled"] = []
6696 node.override["dism_features_cache"]["removed"] = []
6697 feature_details = feature_string.strip.split(/\s+[|]\s+/).first
6698 source 'd:\\sources\\sxs'
6699 property :delim, [ String, nil, false ],
6700 @key_exists ||= !!env_value(new_resource.key_name)
6701 needs_delete = new_values.any? { |v| current_values.include?(v) }
6702 obj = env_obj(key_name)
6703 @env_obj = nil
6704 if ( ENV[new_resource.key_name] || key_exists? ) && !delete_element
6705 description: "",
6706 only_if "return ((Get-DfsnRoot -Path '\\\\#{ENV["COMPUTERNAME"]}\\#{new_resource.namespace_name}') -ne $null)"
6707 if (!($needs_creating))
6708 only_if "return ((Get-DfsnFolder -Path '\\\\#{ENV["COMPUTERNAME"]}\\#{new_resource.namespace_name}\\#{new_resource.folder_path}' ) -ne $null)"
6709 paths 'c:\\foo\\bar, d:\\bar\\baz'
6710 property :paths, [String, Array], default: [],
6711 coerce: proc { |x| to_consistent_path_array(x) },
6712 fixed = x.dup || []
6713 fixed = fixed.split(/\s*,\s*/) if fixed.is_a?(String)
6714 fixed.map! { |v| v.gsub(%r{/}, "\\") }
6715 values.transform_values! { |x| Array(x) }
6716 cmd << " -#{flag} #{to_add.join(",")}" unless to_add.empty?
6717 property :lock_ui, [true, false],
6718 cmd << " -UILockdown #{type_coercion(new_resource.lock_ui)}"
6719 cmd << " -#{flag} #{type_coercion(!new_resource.send(prop))}"
6720 private_key_acl ["acme\\fred", "pc\\jane"]
6721 default: lazy { pfx_password ? true : false }, skip_docs: true
6722 hash = "\"#{new_resource.source.gsub(/\s/, "")}\""
6723 code_script = ""
6724 guard_script = ""
6725 if ::File.extname(new_resource.output_path) == ".pfx"
6726 if cert_obj != false && cert_obj != "Certificate Not Found"
6727 if !!out == out
6728 @local_pfx_path = ""
6729 pfx_file = file_name + ".pfx"
6730 f = ::File.open(new_resource.output_path, "w")
6731 ::File.file?(source)
6732 string.match?(/[0-9A-Fa-f]/) && string.length == 40
6733 result == ( "Certificate Not Found" || "Certificate Has Expired" ) ? false : true
6734 $cert = Get-ChildItem -path cert:\\#{store_location}\\#{store_name} -Recurse | Where { $_.Thumbprint -eq "#{thumbprint.upcase}" }
6735 cert_script << " \"#{file}\""
6736 if ::File.extname(file.downcase) == ".pfx"
6737 cert_script << ", \"#{new_resource.pfx_password}\""
6738 cert_script << "
"
6739 $hash = #{hash}
6740 Test-Path "Cert:\\#{ps_cert_location}\\#{new_resource.store_name}\\$hash"
6741 set_acl_script = <<-EOH
6742 if ($storeCert -eq $null) { throw 'no key exists.' }
6743 if ($keyname -eq $null) { throw 'no private key exists.' }
6744 set_acl_script << "$uname='#{name}'; icacls $fullpath /grant $uname`:RX
"
6745 state = uri.is_a?(URI::HTTP) && !uri.host.nil? ? true : false
6746 ::File.open(local_path, "wb") do |file|
6747 when ".pfx"
6748 when ".p7b"
6749 out_file = ::File.new(output_path, "w+")
6750 when ".pem"
6751 when ".der"
6752 when ".cer"
6753 when ".crt"
6754 temp = result == ( "Certificate Not Found" || "Certificate Has Expired" ) ? false : true
6755 if temp == true
6756 when ".key"
6757 Chef::Log.info("Supported certificate format .pem, .der, .cer, .crt, and .p7b")
6758 coerce: proc { |x| x.tr("/", "\\") }, # make sure we have windows paths for the registry
6759 data = "\"#{new_resource.path}\""
6760 data << " #{new_resource.args}" if new_resource.args
6761 data: "",
6762 { machine: "HKLM", user: "HKCU" }[new_resource.root] + \
6763 coerce: proc { |p| Array(p) },
6764 s_val = new_resource.success ? "enable" : "disable"
6765 f_val = new_resource.failure ? "enable" : "disable"
6766 converge_by "Update Audit Policy for \"#{subcategory}\" to Success:#{s_val} and Failure:#{f_val}" do
6767 cmd = "auditpol /set "
6768 cmd += "/user:\"#{new_resource.include_user}\" /include " if new_resource.include_user
6769 cmd += "/user:\"#{new_resource.exclude_user}\" /exclude " if new_resource.exclude_user
6770 cmd += "/subcategory:\"#{subcategory}\" /success:#{s_val} /failure:#{f_val}"
6771 if ($auditpol_config | Select-String "#{setting}") { return $true } else { return $false }
6772 setting = option_setting ? "Enabled$" : "Disabled$"
6773 regex: /.\../, # anything.anything
6774 cmd << " -OUPath \"#{new_resource.ou_path}\"" if new_resource.ou_path
6775 cmd << " -NewName \"#{new_resource.new_hostname}\"" if new_resource.new_hostname
6776 coerce: proc { |m| m.end_with?(".conf") ? m : m + ".conf" },
6777 default: lazy { |r| r.username == "*" ? "00_all_limits.conf" : "#{r.username}_limits.conf" }
6778 source ::File.expand_path("support/ulimit.erb", __dir__)
6779 coerce: proc { |n| n && Integer(n) rescue n }
6780 if salt && password !~ /^[[:xdigit:]]{256}$/
6781 (salt.nil? && password) ? password : nil
6782 provides :user, os: "aix"
6783 introduced: "18.0",
6784 /Time Zone: (.*)/.match(tz_shellout.stdout)[1]
6785 tz_shellout = shell_out("tzutil /g")
6786 tz_shellout = shell_out(["/usr/bin/timedatectl", "status"])
6787 /Time zone: (.*) \(.*/.match(tz_shellout.stdout)[1]
6788 /ZONE="(.*)"/.match(::File.read("/etc/sysconfig/clock"))[1]
6789 when "rhel", "amazon"
6790 shell_out!(["tzutil", "/s", new_resource.timezone])
6791 else # linux / macos
6792 package suse? ? "timezone" : "tzdata"
6793 only_if { ::File.executable?("/usr/sbin/tzdata-update") }
6794 not_if { ::File.executable?("/usr/sbin/tzdata-update") }
6795 @source = "#{::File.basename(name)}.erb"
6796 @inline_helper_blocks = {}
6797 @helper_modules = []
6798 kind_of: [ String, Array ]
6799 default: {}
6800 if block_given? && !module_name.nil?
6801 [ helper_mod ]
6802 content({ Unit: {
6803 Documentation: ['https://coreos.com/etcd', 'man:etcd(1)'],
6804 Service: {
6805 Type: 'notify',
6806 Install: {
6807 } })
6808 [Unit]
6809 :mask, :unmask,
6810 :start, :stop,
6811 doc.section(sect, { option_sep: "=" }) do |section|
6812 [val].flatten.each do |v|
6813 provides(:sysctl) { true }
6814 coerce: proc { |v| coerce_value(v) },
6815 default: [],
6816 v.join(" ")
6817 v.to_s
6818 file "#{new_resource.conf_dir}/99-chef-#{new_resource.key.tr("/", ".")}.conf" do
6819 command "sysctl #{"-e " if new_resource.ignore_error}-p"
6820 if ::File.exist?("#{new_resource.conf_dir}/99-chef-#{new_resource.key.tr("/", ".")}.conf")
6821 converge_by "removing sysctl config at #{new_resource.conf_dir}/99-chef-#{new_resource.key.tr("/", ".")}.conf" do
6822 shell_out!("sysctl #{"-e " if new_resource.ignore_error}-w \"#{key}=#{value}\"")
6823 sysctl_lines = Array(new_resource.comment).map { |c| "# #{c.strip}" }
6824 sysctl_lines << "#{new_resource.key} = #{new_resource.value}"
6825 sysctl_lines.join("
") + "
"
6826 val = shell_out!("sysctl -n -e #{key}").stdout.tr("\t", " ").strip
6827 raise unless ::File.exist?("/etc/sysctl.d/99-chef-#{key.tr("/", ".")}.conf")
6828 k, v = ::File.read("/etc/sysctl.d/99-chef-#{key.tr("/", ".")}.conf").match(/(.*) = (.*)/).captures
6829 provides(:swap_file) { true }
6830 shell_out!("mkswap -f #{new_resource.path}")
6831 swapfile_regex = Regexp.new("^#{new_resource.path}[\\s\\t\
\\f]+")
6832 Chef::Log.debug("#{new_resource} fallocate size is #{size}")
6833 command = "fallocate -l #{size} #{new_resource.path}"
6834 command = "dd if=/dev/zero of=#{new_resource.path} bs=#{block_size} count=#{new_resource.size}"
6835 Chef::Log.debug("#{new_resource} dd command is '#{command}'")
6836 command = "df -PT #{parent_directory} | awk 'NR==2 {print $2}'"
6837 fstab = "/etc/fstab"
6838 if contents.any? { |line| line.strip == addition }
6839 Chef::Log.info("#{new_resource} adding entry to #{fstab} for #{new_resource.path}")
6840 contents << "#{addition}
"
6841 ::File.open(fstab, "w") { |f| f.write(contents.join("")) }
6842 provides(:sudo) { true }
6843 coerce: proc { |x| x.gsub(/[\.~]/, "__") }
6844 coerce: proc { |x| x.is_a?(Array) ? x : x.split(/\s*,\s*/) }
6845 coerce: proc { |x| coerce_groups(x) }
6846 default: ["ALL"]
6847 groups = x.is_a?(Array) ? x : x.split(/\s*,\s*/)
6848 groups.map { |g| g[0] == "%" ? g : "%#{g}" }
6849 source ::File.expand_path("support/sudoer.erb", __dir__)
6850 if ::File.exist?(path)
6851 key 'node.example.com ssh-rsa ...'
6852 default: lazy { node["root_group"] },
6853 key =
6854 hoststr = (new_resource.port != 22) ? "[#{new_resource.host}]:#{new_resource.port}" : new_resource.host
6855 keyscan_cmd = ["ssh-keyscan", "-t#{new_resource.key_type}", "-p #{new_resource.port}"]
6856 key.sub!(/^#{new_resource.host}/, "[#{new_resource.host}]:#{new_resource.port}") if new_resource.port != 22
6857 comment = key.split("
").first || ""
6858 keys.any? do |line|
6859 type_map = {
6860 type_map[key_type] || key_type
6861 coerce: proc { |x| x.is_a?(Array) ? x.each_with_object({}) { |i, m| m[i] = true } : x }
6862 coerce: proc { |x| x.respond_to?(:split) ? x.shellsplit : x }
6863 level 's0'
6864 range 's0'
6865 coerce: proc { |r| Array(r).sort }
6866 users = shell_out!("semanage user -l").stdout.split("
")
6867 current_user = users.grep(/^#{Regexp.escape(new_resource.user)}\s+/) do |u|
6868 args = ""
6869 args += " -L #{new_resource.level}" if new_resource.level
6870 args += " -r #{new_resource.range}" if new_resource.range
6871 args += " -R '#{new_resource.roles.join(" ")}'" unless new_resource.roles.to_a.empty?
6872 source debian? ? ::File.expand_path("selinux/selinux_debian.erb", __dir__) : ::File.expand_path("selinux/selinux_default.erb", __dir__)
6873 when "rhel", "fedora", "amazon"
6874 regex: /^\d+$/,
6875 equal_to: %w{tcp udp},
6876 seinfo --portcon=#{new_resource.port} | grep 'portcon #{new_resource.protocol}' | \
6877 awk -F: '$(NF-1) !~ /reserved_port_t$/ && $(NF-3) !~ /[0-9]*-[0-9]*/ {print $(NF-1)}'
6878 shell_out!("semanage port -a -t '#{new_resource.secontext}' -p #{new_resource.protocol} #{new_resource.port}")
6879 shell_out!("semanage port -m -t '#{new_resource.secontext}' -p #{new_resource.protocol} #{new_resource.port}")
6880 path.concat(".#{type}") if type
6881 shell_out!("semodule --list-modules").stdout.split("
").map { |x| x.split(/\s/).first }
6882 %w{fc if pp te}.each do |type|
6883 shell_out!("semodule", "--install", selinux_module_filepath("pp"))
6884 user 'test_u'
6885 logins = shell_out!("semanage login -l").stdout.split("
")
6886 current_login = logins.grep(/^#{Regexp.escape(new_resource.login)}\s+/) do |l|
6887 l.match(/^(?<login>[^\s]+)\s+(?<user>[^\s]+)\s+(?<range>[^\s]+)/)
6888 args += " -s #{new_resource.user}" if new_resource.user
6889 if node["platform"] == "ubuntu"
6890 if node["platform_version"].to_f == 18.04
6891 selinux_fcontext '/var/www/moodle(/.*)?' do
6892 file_type 'l'
6893 default: "a",
6894 equal_to: %w{a f d c b s l p},
6895 file_hash = {
6896 c.match(/.+ (?<user>.+):(?<role>.+):(?<type>.+):(?<level>.+)$/)[:type]
6897 index = spec.size.times { |i| break i if spec[i] != escaped[i] }
6898 ::File.dirname spec[0...index]
6899 common = "/" if common[0] != "/"
6900 value 'on'
6901 equal_to: %w{on off},
6902 coerce: proc { |p| selinux_bool(p) },
6903 cmd += " -P" if new_resource.persistent
6904 cmd += " #{new_resource.boolean} #{new_resource.value}"
6905 if ["on", "true", "1", true, 1].include?(bool)
6906 elsif ["off", "false", "0", false, 0].include?(bool)
6907 (selinux_disabled? && %i{enforcing permissive}.include?(action)) || ((selinux_enforcing? || selinux_permissive?) && action == :disabled)
6908 use "scm"
6909 coerce: proc { |v| v == false ? nil : v }, # coerce false to nil
6910 default: "--no-auth-cache"
6911 require_relative "../../resource"
6912 git "#{Chef::Config[:file_cache_path]}/ruby-build" do
6913 cwd "#{Chef::Config[:file_cache_path]}/ruby-build"
6914 environment 'PREFIX' => '/usr/local'
6915 git "#{Chef::Config[:file_cache_path]}/my_app" do
6916 description: "A Hash of environment variables in the form of ({'ENV_VARIABLE' => 'VALUE'}).",
6917 examples <<~'DOC'
6918 FileUtils.cp "#{node['mysql']['client']['lib_dir']}\\libmysql.dll",
6919 node['mysql']['client']['ruby_dir']
6920 not_if { ::File.exist?("#{node['mysql']['client']['ruby_dir']}\\libmysql.dll") }
6921 f = File.open(node['bittorrent']['torrent'],'rb')
6922 data = {
6923 rc = Chef::Util::FileEdit.new('/etc/hosts')
6924 rc.search_file_replace_line(/^127\.0\.0\.1 localhost$/,
6925 ENV['PATH'] = "#{node[:rbenv][:root]}/bin:#{node[:ruby_build][:bin_path]}:#{ENV['PATH']}"
6926 cmd = Mixlib::ShellOut.new("subscription-manager list --consumed | grep #{subscription}", env: { LANG: "en_US" })
6927 !cmd.stdout.match(/Pool ID:\s+#{subscription}$/).nil?
6928 serials = {}
6929 pool = nil
6930 cmd = Mixlib::ShellOut.new("subscription-manager list --consumed", env: { LANG: "en_US" })
6931 key, value = line.split(/:\s+/, 2)
6932 next unless ["Pool ID", "Serial"].include?(key)
6933 if key == "Pool ID"
6934 elsif key == "Serial"
6935 provides(:rhsm_repo) { true }
6936 cmd = Mixlib::ShellOut.new("subscription-manager repos --list-enabled", env: { LANG: "en_US" })
6937 repo == "*" || !cmd.stdout.match(/Repo ID:\s+#{repo}$/).nil?
6938 coerce: proc { |x| Array(x) },
6939 [Float, String],
6940 node["platform_version"].to_i >= 8 ? :dnf_package : :yum_package
6941 coerce: proc { |x| x.downcase },
6942 node["platform_version"].to_i >= 8 ? "dnf" : "yum"
6943 nethttp: {
6944 @source = []
6945 { callbacks: {
6946 elsif args[0].is_a?(Chef::DelayedEvaluator) && args.count == 1
6947 description: <<~'DOCS'
6948 headers({ "Cookie" => "user=some_user; pass=p@ssw0rd!" })
6949 headers({ "Referer" => "#{header}" })
6950 headers( "Authorization"=>"Basic #{ Base64.encode64("#{username}:#{password}").gsub("
", "") }" )
6951 introduced: "16.2",
6952 introduced: "13.4",
6953 introduced: "17.5",
6954 if specified_user && ((specified_user.include? "\\") || (specified_user.include? "@")) && specified_domain
6955 domain_and_user = user.split("\\")
6956 domain_and_user = user.split("@")
6957 if ( password || domain ) && user.nil?
6958 { domain: domain, user: user }
6959 regex: /^\d{3,4}$/, default: lazy { 0644 unless Chef::Platform.windows? }
6960 :name => "test",
6961 :type => :binary,
6962 :data => [0, 1, 2].map(&:chr).join
6963 values [{name: 'ProxyEnable', type: :reg_dword, data: 1},
6964 {name: 'ProxyServer', data: "#{proxy.host}:#{proxy.port}"},
6965 {name: 'ProxyOverride', type: :reg_string, data: <local>},
6966 {name: '', type: :string, data: 'test'},
6967 data: ''
6968 [ Mash.new(v).symbolize_keys ]
6969 v.all? do |value|
6970 @unscrubbed_values ||= []
6971 scrubbed = []
6972 command '...'
6973 not_if 'test -e ~/data/nodes.bak'
6974 introduced: "17.6",
6975 if output == "PSRepository" || output == "PackageSource"
6976 if output == "PackageSource" || output == "PSRepository"
6977 logger.warn("*****************************************")
6978 cmd << "#{cmdlet_type}-PSRepository -Name '#{new_resource.source_name}'"
6979 cmd << " -InstallationPolicy '#{install_policy}'"
6980 cmd << " | Out-Null"
6981 cmd << "#{cmdlet_type}-PackageSource -Name '#{new_resource.source_name}'"
6982 cmd << " -NewName '#{new_resource.new_name}'" if new_resource.new_name
6983 (Get-PSRepository -Name '#{source_name}') | Select @{n='source_name';e={$_.Name}}, @{n='source_location';e={$_.SourceLocation}},
6984 @{n='trusted';e={$_.Trusted}}, @{n='provider_name';e={$_.PackageManagementProvider}}, @{n='publish_location';e={$_.PublishLocation}},
6985 @{n='provider_name';e={$_.ProviderName}}, @{n='trusted';e={$_.IsTrusted}}, @{n='publish_location';e={$_.PublishLocation}}
6986 coerce: proc { |x| [x].flatten }
6987 file_type_cmd = shell_out "/usr/bin/file", "--brief", "--mime-encoding", "--preserve-date", new_resource.path
6988 file_owner_cmd = shell_out("/usr/bin/stat", "-f", "%Su", new_resource.path)
6989 file_group_cmd = shell_out("/usr/bin/stat", "-f", "%Sg", new_resource.path)
6990 content({}.to_plist)
6991 converge_by "add entry \"#{new_resource.entry}\" to #{plist_file_name}" do
6992 value.to_i == 1
6993 sep = " "
6994 when "add"
6995 sep = ":"
6996 value.map { |k, v| "#{k} #{type_to_commandline_string(v)}" }
6997 when "set"
6998 value.map { |k, v| "#{k} #{v}" }
6999 entry_with_arg = ["\"#{entry}\"", arg].join(sep).strip
7000 plutil_output = shell_out(PLUTIL_EXECUTABLE, "-extract", entry, "xml1", "-o", "-", path).stdout.chomp
7001 coerce: proc { |x| x.is_a?(String) ? x.shellsplit : x }
7002 profile_hash = {
7003 property :profile, [ String, Hash ],
7004 def path(path = nil)
7005 @path ||= path
7006 name_or_identifier.end_with?(".mobileconfig") || !/^\w+(?:(\.| )\w+)+$/.match(name_or_identifier)
7007 if action == :remove
7008 if mac? && node["platform_version"] =~ ">= 11.0"
7009 ::File.join(
7010 path = ::File.join( get_cache_dir, "#{cookbook_file}.remote")
7011 ).to_s
7012 cmd = [ "/usr/bin/profiles", "-I", "-F", profile_path ]
7013 logger.trace("cmd: #{cmd.join(" ")}")
7014 shell_out!(*cmd)
7015 cmd = [ "/usr/bin/profiles", "-R", "-p", new_profile_identifier ]
7016 so = shell_out( "/usr/bin/profiles", "-P", "-o", "stdout-xml" )
7017 equal_to: %w{rsa ec}, default: "ec",
7018 equal_to: [1024, 2048, 4096, 8192], default: 2048,
7019 @key_file ||=
7020 path + "/" + filename + ".key"
7021 crl_info = {}
7022 revoke_info = {}
7023 org 'Foo Bar'
7024 description: "Hash of X509 Extensions entries, in format `{ 'keyUsage' => { 'values' => %w( keyEncipherment digitalSignature), 'critical' => true } }`.",
7025 equal_to: %w{rsa ec},
7026 equal_to: [1024, 2048, 4096, 8192],
7027 ca_info = {}
7028 default: lazy { "des3" },
7029 proc { |v| OpenSSL::Cipher.ciphers.include?(v) },
7030 equal_to: [2, 5],
7031 provides(:ohai_hint) { true }
7032 path << ".json" unless path.end_with?(".json")
7033 return "" if content.nil? || content.empty?
7034 home '/dev/null'
7035 puts node['etc']['passwd']['daemon_user']['uid']
7036 puts node['etc']['passwd']['daemon_user']['gid']
7037 ohai = ::Ohai::System.new
7038 action [ :enable, :start ]
7039 default: lazy { { remount: false } },
7040 coerce: proc { |arg| arg.is_a?(String) ? arg.to_sym : arg },
7041 equal_to: RUBY_PLATFORM.match?(/solaris/i) ? %i{ device } : %i{ device label uuid }
7042 default: "-"
7043 @fstype = nil
7044 (options.is_a?(String) ? options.split(",") : options).collect(&:strip)
7045 mdadm --create /dev/md0 --level=0 --raid-devices=10 /dev/s01.../dev/s10
7046 mdadm '/dev/md0' do
7047 devices [ '/dev/s01', ... '/dev/s10' ]
7048 (again, where /dev/s01 .. /dev/s10 represents devices /dev/s01, /dev/s02, /dev/s03, and so on).
7049 devices [ '/dev/sda', '/dev/sdb' ]
7050 action [ :create, :assemble ]
7051 mdadm '/dev/sd0' do
7052 devices [ '/dev/s1', '/dev/s2', '/dev/s3', '/dev/s4' ]
7053 default: "0.90",
7054 description: "The RAID5 parity algorithm. Possible values: `left-asymmetric` (or `la`), `left-symmetric` (or ls), `right-asymmetric` (or `ra`), or `right-symmetric` (or `rs`)."
7055 mdadm = shell_out!("mdadm", "--detail", "--test", new_resource.raid_device, returns: [0, device_not_found])
7056 exists = (mdadm.status == 0)
7057 command << " --chunk=#{new_resource.chunk}" unless new_resource.level == 1
7058 command << " --metadata=#{new_resource.metadata}"
7059 command << " --raid-devices #{new_resource.devices.length} #{new_resource.devices.join(" ")}"
7060 command = "yes | mdadm --assemble #{new_resource.raid_device} #{new_resource.devices.join(" ")}"
7061 command = "yes | mdadm --stop #{new_resource.raid_device}"
7062 @loaded_lwrps ||= {}
7063 default: {},
7064 coerce: proc { |h|
7065 if h.respond_to?(:keys)
7066 def lc_all(arg = nil)
7067 locale_values = Hash[old_content.split("
").map { |v| v.split("=") }]
7068 a.assertion { which("locale-gen") }
7069 shell_out!("locale-gen #{unavailable_locales.join(" ")}", timeout: 1800)
7070 available = shell_out!("locale -a").stdout.split("
")
7071 @new_content ||= begin
7072 content = {}
7073 content.sort.map { |t| t.join("=") }.join("
") + "
"
7074 introduced: "12.19",
7075 coerce: proc { |type|
7076 array = if type.is_a?(Array)
7077 [type]
7078 failed_keys = entry.keys.reject { |k| allowed_keys.include?(k) }.join(", ")
7079 failed_values = entry.values.reject { |val| val.is_a?(Integer) }.join(", ")
7080 if array.size == 1
7081 default: "daemon", coerce: proc { |type|
7082 type = type ? type.downcase : "daemon"
7083 introduced: "12.14",
7084 introduced: "15.1",
7085 callbacks: { "should be a Integer between -20 and 19" => proc { |v| v >= -20 && v <= 19 } }
7086 @interpreter = "ksh"
7087 /^#{new_resource.modname}/.match?(::File.read("/proc/modules"))
7088 re = Regexp.new("\\d{4}-\\d{2}-\\d{2}$").freeze
7089 if re.match?(e)
7090 Date.valid_date?(*e.split("-").map(&:to_i))
7091 e.nil?
7092 control_hash = {}
7093 if %r{(/|C:\\).*(.yaml|.yml)}i.match?(file_name)
7094 if hash == false || hash.nil? || hash == ""
7095 inspec_waiver 'openssh::.*' do
7096 my_hash = { "ssh-01" => {
7097 inspec_input 'openssh::.*' do
7098 source( { ssh_custom_path: '/whatever2' })
7099 property :name, [ Hash, String ]
7100 property :input, [ Hash, String ],
7101 property :source, [ Hash, String ],
7102 introduced: "14.4",
7103 introduced: "16.7",
7104 allowed_actions :get, :patch, :put, :post, :delete, :head, :options
7105 property :aliases, [ Array, nil ],
7106 text = IO.read(path).split("
")
7107 text.reject! { |s| s =~ regex }
7108 text += [ string ]
7109 content text.join("
") + "
"
7110 not_if { IO.read(path).split("
").include?(string) }
7111 REXML::XPath.each(config, "//Plugin/State[../Name/text() = 'Ec2SetComputerName']") do |element|
7112 return ""
7113 newline << " #{new_resource.hostname}"
7114 newline << " #{new_resource.aliases.join(" ")}" if new_resource.aliases && !new_resource.aliases.empty?
7115 newline << " #{new_resource.hostname[/[^\.]*/]}"
7116 shortname = new_resource.hostname[/[^\.]*/]
7117 when ::File.exist?("/usr/bin/hostnamectl") && !docker?
7118 not_if { shell_out!("hostnamectl status", returns: [0, 1]).stdout =~ /Static hostname:\s*#{new_resource.hostname}\s*$/ }
7119 when ::File.exist?("/etc/hostname")
7120 when ::File.exist?("/etc/conf.d/hostname")
7121 when ::File.exist?("/etc/rc.conf")
7122 when ::File.exist?("/usr/sbin/svccfg") # solaris 5.11
7123 raise "Do not know how to set hostname on os #{node["os"]}, platform #{node["platform"]},"\
7124 regex: %r{^[\w-]+(?:\/[\w-]+)+$},
7125 shell_out!("#{new_resource.homebrew_path} tap #{new_resource.tap_name} #{new_resource.url || ""}",
7126 tap_dir = name.gsub("/", "/homebrew-")
7127 regex: %r{^[\w/\-@]+$},
7128 return true if spec == "*"
7129 return spec >= min && spec <= max
7130 spec.split(%r{\/|-|,}).each do |x|
7131 next if x == "*"
7132 return false unless /^\d+$/.match?(x)
7133 x = x.to_i
7134 return false unless x >= min && x <= max
7135 spec = spec.to_s
7136 spec == "*" ||
7137 validate_numeric(spec, 0, 7) ||
7138 http: {
7139 property :config, Mash, required: true, coerce: proc { |m| m.is_a?(Hash) ? Mash.new(m) : m },
7140 @wmi = ::WIN32OLE.connect("winmgmts://")
7141 property :topology, [Symbol, String], equal_to: [:standalone, "standalone", :leader, "leader"], default: :standalone, coerce: proc { |s| s.is_a?(String) ? s.to_sym : s },
7142 property :channel, [Symbol, String], default: :stable, coerce: proc { |s| s.is_a?(String) ? s.to_sym : s },
7143 property :bind, [String, Array], coerce: proc { |b| b.is_a?(String) ? [b] : b }, default: [],
7144 property :binding_mode, [Symbol, String], equal_to: [:strict, "strict", :relaxed, "relaxed"], default: :strict, coerce: proc { |s| s.is_a?(String) ? s.to_sym : s },
7145 Chef::Log.debug("service #{service_name} binds: #{bind}")
7146 http_uri = "http://#{remote_sup_http}"
7147 headers = {}
7148 origin, name, _version, _release = svc_name.split("/")
7149 svcs.find do |s|
7150 s["pkg"]["origin"] == origin && s["pkg"]["name"] == name
7151 service_details["process"]["state"] == "up"
7152 options << "--force"
7153 command "hab svc load #{new_resource.service_name} #{options.join(" ")}"
7154 execute "hab svc stop #{new_resource.service_name} #{svc_options.join(" ")}"
7155 opts = []
7156 opts.push(*new_resource.bind.map { |b| "--bind #{b}" }) if new_resource.bind
7157 opts << "--binding-mode #{new_resource.binding_mode}"
7158 opts << "--url #{new_resource.bldr_url}" if new_resource.bldr_url
7159 hab_version '1.5.50'
7160 if ::File.exist?(hab_path)
7161 cmd = shell_out!([hab_path, "--version"].flatten.compact.join(" "))
7162 version = %r{hab (\d*\.\d*\.\d[^\/]*)}.match(cmd.stdout)[1]
7163 habfile = "#{Chef::Config[:file_cache_path]}/#{package_name}.zip"
7164 not_if { ::Dir.exist?("c:\\habitat") }
7165 user "hab" do
7166 gid "hab"
7167 }.each_with_object({}) do |(var, property), env|
7168 cmd = "bash #{Chef::Config[:file_cache_path]}/hab-install.sh"
7169 cmd << " -v #{new_resource.hab_version} " if new_resource.hab_version
7170 cmd << " -t x86_64-linux-kernel2" if node["kernel"]["release"].to_i < 3
7171 sc = {}
7172 opts << ["--user", new_resource.user] if new_resource.user
7173 tempfile = Tempfile.new(["habitat_config", ".toml"])
7174 not_if { ::Win32::Service.exists?("Habitat") }
7175 not_if { node["chef_packages"]["chef"]["chef_root"].include?("/pkgs/chef/chef-infra-client") }
7176 ExecStop: "/bin/hab sup term",
7177 }.compact,
7178 listen_http '0.0.0.0:9999'
7179 sup_version '1.5.50'
7180 sup_version '1.5.86'
7181 property :peer, [String, Array], coerce: proc { |b| b.is_a?(String) ? [b] : b },
7182 property :health_check_interval, [String, Integer], coerce: proc { |h| h.is_a?(String) ? h : h.to_s },
7183 not_if { ::File.exist?("/bin/hab") }
7184 not_if { ::File.exist?("/usr/bin/hab") }
7185 not_if { ::File.exist?("c:/habitat/hab.exe") }
7186 not_if { ::File.exist?("c:/ProgramData/Habitat/hab.exe") }
7187 only_if { ::Dir.exist?("C:/hab") }
7188 source ::File.expand_path("../support/sup.toml.erb", __dir__)
7189 only_if { ::Dir.exist?("C:/hab/sup/default/config") }
7190 only_if { ::Dir.exist?("/hab") }
7191 only_if { ::Dir.exist?("/hab/sup/default/config") }
7192 peer_list = []
7193 peer_list << if !/.*:.*/.match?(p)
7194 p + ":9632"
7195 opts << "--org #{new_resource.org}" unless new_resource.org == "default"
7196 opts.push(*new_resource.peer.map { |b| "--peer #{b}" }) if new_resource.peer
7197 opts << "--ring #{new_resource.ring}" if new_resource.ring
7198 opts.join(" ")
7199 version '3.2.3'
7200 (["hab"] + command).flatten.compact.join(" ")
7201 (["hab"] + command)
7202 members ['domain\\foo']
7203 property :gid, [ String, Integer ],
7204 property :members, [String, Array], default: [],
7205 coerce: proc { |arg| arg.is_a?(String) ? arg.split(/\s*,\s*/) : arg },
7206 introduced: "14.9",
7207 source '/tmp/loofah-2.7.0.gem'
7208 property :source, [ String, Array ],
7209 property :options, [ String, Hash, Array, nil ],
7210 @provider = if /^ports$/i.match?(source.to_s)
7211 def verify(path, opts = {})
7212 require_relative "../../../mixin/which"
7213 temp = "#{dir}/#{::File.basename(@parent_resource.path)}"
7214 @systemd_analyze_cmd ||= "#{systemd_analyze_path} verify %{path}"
7215 c = descendants.find { |d| d.provides?(name) }
7216 if c.nil?
7217 if @command.include?("%{file}")
7218 command = @command % { path: path }
7219 property :checksum, [ String, nil ],
7220 regex: /^\h{64}$/,
7221 coerce: lambda { |s| s.is_a?(String) ? s.downcase : s },
7222 def verify(command = nil, opts = {}, &block)
7223 environment ({'HOME' => '/home/my_home'})
7224 the recipe: `execute 'foo'`, `template 'baz'`, `execute [restart_baz]`,
7225 command 'echo > /proc/.../ipv4/ip_forward'
7226 --source \#{node[:name_of_node][:ipsec][:local][:subnet]}
7227 -j test_rule"
7228 if (node.attribute?('ec2') && !FileTest.directory?(node['mysql']['ec2_path']))
7229 command "mv \#{node['mysql']['data_dir']} \#{node['mysql']['ec2_path']}"
7230 not_if { ::File.directory?(node['mysql']['ec2_path']) }
7231 [node['mysql']['ec2_path'], node['mysql']['data_dir']].each do |dir|
7232 mount node['mysql']['data_dir'] do
7233 device node['mysql']['ec2_path']
7234 pip_binary = '/usr/bin/pip'
7235 pip_binary = '/usr/local/bin/pip'
7236 not_if { ::File.exist?(pip_binary) }
7237 \#{node['python']['binary']} distribute_setup.py \#{::File.dirname(pip_binary)}/easy_install pip
7238 </div>
7239 search("users", "*:*") do |u|
7240 execute "generate-openvpn-\#{u['id']}" do
7241 command "./pkitool \#{u['id']}"
7242 %w{ conf ovpn }.each do |ext|
7243 template "\#{node['openvpn']['key_dir']}/\#{u['id']}.\#{ext}" do
7244 variables :username => u['id']
7245 (**bash**, **csh**, **perl**, **python**, or **ruby**). For example:
7246 bash 'foo' do
7247 environment ({'HOME' => '/home/vagrant', 'USER' => 'vagrant'})
7248 input File.read(__FILE__)
7249 introduced: "14.2",
7250 property :returns, [ Integer, Array ], default: 0,
7251 property :user, [ String, Integer ],
7252 introduced: "12.21",
7253 introduced: "17.0",
7254 if specified_user.is_a?(String) && ((specified_user.include? "\\") || (specified_user.include? "@")) && specified_domain
7255 :cwd,
7256 :user,
7257 @imports = {}
7258 def code(arg = nil)
7259 :code,
7260 kind_of: [ String ]
7261 if arg && code
7262 @imports[module_name] ||= []
7263 if args.length == 0
7264 @imports[module_name] << "*"
7265 obj_text = if obj.respond_to?(:to_text)
7266 @properties.reduce({}) do |memo, (k, v)|
7267 memo[k] = value_of(v)
7268 introduced: "12.6",
7269 property :source, [ String, Array, nil ],
7270 which("dnf")
7271 equal_to: %w{app pkg mpkg},
7272 attach_cmd = new_resource.accept_eula ? "yes | " : ""
7273 shell_out!(attach_cmd, env: { "PAGER" => "true" })
7274 when "app"
7275 when "mpkg", "pkg"
7276 @dmg_file ||= if new_resource.file.nil?
7277 /image-path.*#{dmg_file}/.match?(shell_out!("/usr/bin/hdiutil info #{passphrase_cmd}").stdout)
7278 @interpreter = "csh"
7279 variables["users"] ||= []
7280 cron_d 'noop' do
7281 hour '5'
7282 minute '0'
7283 --thread-max'"
7284 only_if { ::File.exist?('/home/jboss') }
7285 hour '8'
7286 hour '20'
7287 day '*'
7288 month '11'
7289 weekday '1-5'
7290 file "/etc/cron.d/#{sanitized_name}" do
7291 new_resource.cron_name.tr(".", "-")
7292 new_resource.cron_name =~ /^[a-zA-Z0-9_-]+$/
7293 source ::File.expand_path("../support/cron.d.erb", __dir__)
7294 -v '/usr/local/bin/tomcat-stat --thread-max'"
7295 hour '0'
7296 }.join(' ')
7297 state_attrs :minute, :hour, :day, :month, :weekday, :user
7298 sunday: "0", monday: "1", tuesday: "2", wednesday: "3", thursday: "4", friday: "5", saturday: "6",
7299 sun: "0", mon: "1", tue: "2", wed: "3", thu: "4", fri: "5", sat: "6"
7300 description: "The minute at which the cron entry should run (`0 - 59`).",
7301 default: "*", callbacks: {
7302 description: "The hour at which the cron entry is to run (`0 - 23`).",
7303 description: "The day of month at which the cron entry should run (`1 - 31`).",
7304 description: "The month in the year on which a cron entry is to run (`1 - 12`, `jan-dec`, or `*`).",
7305 description: "The day of the week on which this entry is to run (`0-7`, `mon-sun`, `monday-sunday`, or `*`), where Sunday is both `0` and `7`.",
7306 default: "*", coerce: proc { |day| weekday_in_crontab(day) },
7307 description: "A Hash of timeouts in the form of `({'OPTION' => 'VALUE'})`. Accepted valid options are:
7308 - `preserve-status` (BOOL, default: 'false'),
7309 - `foreground` (BOOL, default: 'false'),
7310 - `kill-after` (in seconds),
7311 - `signal` (a name like 'HUP' or a number)",
7312 introduced: "15.7",
7313 if h.is_a?(Hash)
7314 elsif h.is_a?(Integer) || h.is_a?(String)
7315 { "duration" => h }
7316 default: lazy { ::File.basename(name) }
7317 @block = nil
7318 Chef::Log.warn "Command '#{@command}' timed out"
7319 @block.call.tap do |rv|
7320 if rv.is_a?(String) && !rv.empty?
7321 (@parent_resource.sensitive ? "" : " If so use '#{@positivity} #{sanitized_rv}' in your code."))
7322 cmd_or_block = @command ? "command `#{@command}`" : "ruby block"
7323 data = REXML::XPath.first(config_contents, "//sources/source[@id=\"#{id}\"]")
7324 shell_out!(choco_cmd("add"))
7325 cmd = "#{ENV["ALLUSERSPROFILE"]}\\chocolatey\\bin\\choco source #{action} -n \"#{new_resource.source_name}\""
7326 if action == "add"
7327 cmd << " --source=\"#{new_resource.source}\" --priority=#{new_resource.priority}"
7328 cmd << " --user=\"#{new_resource.username}\"" if new_resource.username
7329 cmd << " --password=\"#{new_resource.password}\"" if new_resource.password
7330 cmd << " --cert=\"#{new_resource.cert}\"" if new_resource.cert
7331 introduced: "15.3",
7332 default: [ 0, 2 ], desired_state: false,
7333 data = REXML::XPath.first(contents, "//features/feature[@name=\"#{name}\"]")
7334 value 'C:\\temp\\choco'
7335 data = REXML::XPath.first(contents, "//config/add[@key=\"#{id}\"]")
7336 shell_out!(choco_cmd("set"))
7337 shell_out!(choco_cmd("unset"))
7338 cmd = "#{ENV["ALLUSERSPROFILE"]}\\chocolatey\\bin\\choco config #{action} --name #{new_resource.config_key}"
7339 cmd << " --value #{new_resource.value}" if action == "set"
7340 raw_data({ 'auth' => 'baz' })
7341 search '*:*'
7342 property :search, String, default: "*:*", desired_state: false,
7343 property :raw_data, [Hash, Mash], default: {},
7344 Chef::Log.debug("#{new_resource.id} search query: '#{new_resource.search}'")
7345 Chef::Log.debug("#{new_resource.id} clients: '#{new_resource.clients}'")
7346 Chef::Log.debug("#{new_resource.id} admins (users): '#{new_resource.admins}'")
7347 chef_data_bag_item [new_resource.id, "keys"].join("_") do
7348 coerce: proc { |s| Integer(s) },
7349 Chef::Log.info('Cookbooks and versions run: #{cookbooks.map {|x| x.name.to_s + ' ' + x.version }}')
7350 irb(main):002:0> require 'json' => true
7351 irb(main):003:0> require 'chef' => true
7352 irb(main):005:0> r.keys => ['end_time', 'node', 'updated_resources', 'exception', 'all_resources', 'success', 'elapsed_time', 'start_time', 'backtrace']
7353 irb(main):006:0> r['elapsed_time'] => 0.00246
7354 _, klass = get_class(class_name)
7355 ancestors = class_full_name.split("::")
7356 default: "#{RbConfig::CONFIG["bindir"]}/gem",
7357 proc { |v| v == "#{RbConfig::CONFIG["bindir"]}/gem" },
7358 path << ".pem" unless path.end_with?(".pem")
7359 introduced: "16.5",
7360 coerce: proc { |x| Integer(x) },
7361 callbacks: { "should be a positive Integer" => proc { |v| v > 0 } }
7362 cmd << " -c #{::File.join(new_resource.config_directory, "client.rb")}"
7363 unit = {
7364 unit["Service"]["Environment"] = new_resource.environment.collect { |k, v| "\"#{k}=#{v}\"" } unless new_resource.environment.empty?
7365 callbacks: { "should be a positive number" => proc { |v| v > 0 } },
7366 default: lazy { frequency == "minute" ? 30 : 1 },
7367 regex: [%r{^[0-1][0-9]\/[0-3][0-9]\/\d{4}$}]
7368 regex: [/^\d{2}:\d{2}$/]
7369 callbacks: { "should be a positive number" => proc { |v| v >= 0 } },
7370 default: lazy { |r| "#{r.config_directory}/log" },
7371 seed = node["shard_seed"] || Digest::MD5.hexdigest(node.name).to_s.hex
7372 cmd << " -L #{::File.join(new_resource.log_directory, new_resource.log_file_name)}"
7373 cmd << " #{new_resource.daemon_options.join(" ")}" if new_resource.daemon_options.any?
7374 default: "/var/root"
7375 callbacks: { "should be an Integer between -20 and 19" => proc { |v| v >= -20 && v <= 19 } }
7376 program_arguments ["/bin/bash", "-c", client_command]
7377 cmd << "/bin/sleep #{splay_sleep_time(new_resource.splay)};"
7378 cmd << " #{new_resource.chef_binary_path}"
7379 hour '0,12'
7380 description: "The minute at which #{ChefUtils::Dist::Infra::PRODUCT} is to run (0 - 59) or a cron pattern such as '0,30'.",
7381 default: "0,30", callbacks: {
7382 description: "The hour at which #{ChefUtils::Dist::Infra::PRODUCT} is to run (0 - 23) or a cron pattern such as '0,12'.",
7383 description: "The day of month at which #{ChefUtils::Dist::Infra::PRODUCT} is to run (1 - 31) or a cron pattern such as '1,7,14,21,28'.",
7384 description: "The month in the year on which #{ChefUtils::Dist::Infra::PRODUCT} is to run (1 - 12, jan-dec, or *).",
7385 description: "The day of the week on which #{ChefUtils::Dist::Infra::PRODUCT} is to run (0-7, mon-sun, or *), where Sunday is both 0 and 7.",
7386 default: lazy { platform?("mac_os_x") ? "/Library/Logs/#{ChefUtils::Dist::Infra::DIR_SUFFIX.capitalize}" : "/var/log/#{ChefUtils::Dist::Infra::DIR_SUFFIX}" },
7387 cmd << "/bin/sleep #{splay_sleep_time(new_resource.splay)}; "
7388 cmd << "#{which("nice")} -n #{new_resource.nice} " if new_resource.nice
7389 cmd << "#{new_resource.chef_binary_path} "
7390 cmd << "-c #{::File.join(new_resource.config_directory, "client.rb")} "
7391 cmd << " || echo \"#{ChefUtils::Dist::Infra::PRODUCT} execution failed\"" if new_resource.mailto
7392 linux? ? :cron_d : :cron
7393 if prop_val.is_a?(String) && prop_val.start_with?(":")
7394 prop_val[1..-1].to_sym
7395 default_description: "`/etc/chef/` on *nix-like systems and `C:\\chef\\` on Windows"
7396 default: lazy { node.name },
7397 coerce: proc { |x| string_to_symbol(x) },
7398 p.is_a?(Symbol) ? %i{win_evt syslog}.include?(p) : true
7399 coerce: proc { |x| x.is_a?(Array) ? x.join(",") : x },
7400 coerce: proc { |x| x.map { |v| string_to_symbol(v).capitalize } },
7401 mode dir_path == ::File.dirname(new_resource.log_location.to_s) ? "0755" : "0750"
7402 source ::File.expand_path("support/client.erb", __dir__)
7403 handler_data = []
7404 handler_data << "#{handler["class"]}.new(#{handler["arguments"].join(",")})"
7405 introduced: "15.5",
7406 !shell_out("xcode-select", "-p").error?
7407 available_updates.stdout[/^\s*\* (?:Label: )?(Command Line Tools.*)/, 1]
7408 yum_key node['yum']['elrepo']['key'] do
7409 key node['yum']['elrepo']['key']
7410 mirrorlist node['yum']['elrepo']['url']
7411 exclude node['yum']['elrepo']['exclude']
7412 breakpoint "before yum_key node['yum']['repo_name']['key']" do
7413 yum_key node['yum']['repo_name']['key'] do
7414 breakpoint "after yum_key node['yum']['repo_name']['key']" do
7415 key node['yum']['repo_name']['key']
7416 mirrorlist node['yum']['repo_name']['url']
7417 exclude node['yum']['repo_name']['exclude']
7418 cwd '/tmp'
7419 find ./ -name "*.tar.Z" -mtime +180 -exec rm -f {} \\;
7420 src_filename = "foo123-nginx-module-v#{node['nginx']['foo123']['version']}.tar.gz"
7421 src_filepath = "#{Chef::Config['file_cache_path']}/#{src_filename}"
7422 extract_path = "#{Chef::Config['file_cache_path']}/nginx_foo123_module/#{node['nginx']['foo123']['checksum']}"
7423 source node['nginx']['foo123']['url']
7424 tar xzf #{src_filename} -C #{extract_path}
7425 mv #{extract_path}/*/* #{extract_path}/
7426 not_if { ::File.exist?(extract_path) }
7427 default['python']['version'] = '2.7.1'
7428 if python['install_method'] == 'package'
7429 default['python']['prefix_dir'] = '/usr'
7430 default['python']['prefix_dir'] = '/usr/local'
7431 default['python']['url'] = 'http://www.python.org/ftp/python'
7432 default['python']['checksum'] = '80e387...85fd61'
7433 version = node['python']['version']
7434 install_path = "#{node['python']['prefix_dir']}/lib/python#{version.split(/(^\d+\.\d+)/)[1]}"
7435 source "#{node['python']['url']}/#{version}/Python-#{version}.tar.bz2"
7436 not_if { ::File.exist?(install_path) }
7437 (cd Python-#{version} && ./configure #{configure_options})
7438 (cd Python-#{version} && make && make install)
7439 mode '700'
7440 coerce: proc { |f| ::File.expand_path(f) },
7441 default: lazy { [:time] }
7442 Chef::Log.trace("#{pathname} mtime is #{::File.mtime(pathname)} and archive is #{e.mtime}")
7443 def extract(src, dest, options = [])
7444 converge_by("extract #{src} to #{dest}") do
7445 provides(:apt_update) { true }
7446 ::File.exist?("#{STAMP_DIR}/update-success-stamp") &&
7447 content "APT::Update::Post-Invoke-Success {\"touch #{STAMP_DIR}/update-success-stamp 2>/dev/null || true\";};
"
7448 command [ "apt-get", "-q", "update" ]
7449 default: [], coerce: proc { |x| x ? Array(x) : x }
7450 def is_key_id?(id)
7451 id = id[2..] if id.start_with?("0x")
7452 id =~ /^\h+$/ && [8, 16, 40].include?(id.length)
7453 so = shell_out(*cmd)
7454 so.stdout.split(/
/).map do |t|
7455 if z = t.match(/^fpr:+([0-9A-F]+):/)
7456 if t.match(/^pub:/)
7457 f = t.split(":")
7458 f.slice(0, 6).join(":")
7459 valid = shell_out("apt-key", "list").stdout.each_line.none?(%r{^\/#{key}.*\[expired: .*\]$})
7460 logger.debug "key #{key} #{valid ? "is valid" : "is not valid"}"
7461 if uri.start_with?("http")
7462 key_name = key.gsub(/[^0-9A-Za-z\-]/, "_")
7463 tmp_dir = Dir.mktmpdir(".gpg")
7464 verify "gpg --homedir #{tmp_dir} %{path}"
7465 command [ "apt-key", "add", cached_keyfile ]
7466 not_if { no_new_keys?(cached_keyfile) }
7467 cmd = "apt-key adv --no-tty --recv"
7468 cmd << " --keyserver "
7469 cmd << if keyserver.start_with?("hkp://")
7470 cmd << " #{key}"
7471 url = "https://launchpad.net/api/1.0/~#{owner}/+archive/#{repo}"
7472 key_id = Chef::HTTP::Simple.new(url).get("signing_key_fingerprint").delete('"')
7473 def is_ppa_url?(url)
7474 url.start_with?("ppa:")
7475 owner, repo = ppa[4..-1].split("/")
7476 repo ||= "ppa"
7477 uri = make_ppa_url(uri) if is_ppa_url?(uri)
7478 options = []
7479 options << "arch=#{arch}" if arch
7480 if is_key_id?(k) && !has_cookbook_file?(k)
7481 regex: [/^([a-z]|[A-Z]|[0-9]|_|-|\.|\*|\+)+$/],
7482 required: [:add]
7483 name.tr(".", "_").gsub("*", "wildcard")
7484 default: lazy { |n| "/usr/bin/#{n.link_name}" },
7485 coerce: proc { |n| n.to_i },
7486 escaped_path = Regexp.new(Regexp.escape("#{new_resource.path} - priority ") + "(.*)")
7487 match.nil? ? nil : match[1].to_i
7488 map = {}
7489 send(function, resource_data) || {}
7490 function = "#{property}_to_json".to_sym
7491 identity_map = {}
7492 hsh.each do |_, v|
7493 deep_compact!(v) if v.is_a? Hash
7494 end.reject! { |_, v| v.nil? || (v.respond_to?(:empty?) && v.empty?) }
7495 hsh1.merge!(hsh2) { |_, v1, v2| deep_merge!(v1, v2) }
7496 arr = path.split(".")
7497 ret = {}
7498 if arr.count == 1
7499 partial_path = arr[0..-2].join(".")
7500 property :name, String, coerce: proc { |v| v.is_a?(Array) ? v.join(", ") : v.to_s }, desired_state: false, required: true
7501 @before = nil
7502 @not_if = []
7503 @only_if = []
7504 arg = Array(arg).map(&:to_sym)
7505 { action: action },
7506 { action: { kind_of: Symbol, equal_to: allowed_actions } }
7507 @action = arg
7508 def only_if(command = nil, opts = {}, &block)
7509 def not_if(command = nil, opts = {}, &block)
7510 state = {}
7511 result = {}
7512 unless iv == :@source_line || iv == :@action || iv == :@not_if || iv == :@only_if
7513 logger.info("Processing #{self} action #{action} (#{defined_at})")
7514 @elapsed_time = 0 if @elapsed_time < 0
7515 text = "# Declared in #{@source_line}

"
7516 text << "#{resource_name}(\"#{name}\") do
"
7517 all_props = {}
7518 all_props[p.name.to_s] = p.sensitive? ? '"*sensitive value suppressed*"' : value_to_text(p.get(self))
7519 iv = ivar.to_s.sub(/^@/, "")
7520 elsif (value = instance_variable_get(ivar)) && !(value.respond_to?(:empty?) && value.empty?)
7521 text << "end
"
7522 ivars.inject("<#{self}") do |str, ivar|
7523 str << " #{ivar}: #{instance_variable_get(ivar).inspect}"
7524 end << ">"
7525 def as_json(*a)
7526 instance_vars[iv.to_s.sub(/^@/, "")] = instance_variable_get(iv)
7527 result[p.name] = p.get(self)
7528 key = iv.to_s.sub(/^@/, "").to_sym
7529 resource = new(o["instance_vars"]["@name"])
7530 resource.instance_variable_set("@#{k}".to_sym, v)
7531 klass = if arg.is_a?(String) || arg.is_a?(Symbol)
7532 set_or_return(:provider, klass, kind_of: [ Class ])
7533 @updated ||= true_or_false
7534 @allowed_actions ||=
7535 [ :nothing ]
7536 [:nothing]
7537 @action_class ||=
7538 source_line.match(/(.*):(\d+):?.*$/).to_a[1]
7539 source_line.match(/(.*):(\d+):?.*$/).to_a[2]
7540 if partial =~ /^core::(.*)/
7541 partial = $1
7542 basename = ::File.basename(partial, ".rb")
7543 basename = basename[1..] if basename.start_with?("_")
7544 class_eval IO.read(::File.expand_path("resource/#{dirname}/_#{basename}.rb", __dir__))
7545 when /(.+?)::(.+)/
7546 [ $1.to_sym, $2 ]
7547 when /^::(.+)/
7548 [ current_cookbook.to_sym, $1 ]
7549 [ recipe_name.to_sym, "default" ]
7550 unless res.is_a?(Hash) && res.key?("resources")
7551 @dll = Pwsh.dll
7552 @dll ||= Dir.glob("#{RbConfig::CONFIG["bindir"]}/**/Chef.PowerShell.Wrapper.Core.dll").last
7553 so = shell_out!("gpg --version")
7554 version = /gpg \(GnuPG\)\s*(.*)/.match(so.stdout)[1]
7555 so = shell_out("/bin/rpm -qa gpg-pubkey*")
7556 logger.trace("GPG key at #{key_path} is known by rpm? #{status ? "true" : "false"}")
7557 if gpg_version >= Gem::Version.new("2.2") # SLES 15+
7558 so = shell_out!("gpg --import-options import-show --dry-run --import --with-colons #{key_path}")
7559 short_key_id = /fpr:*\h*(\h{8}):/.match(so.stdout)[1].downcase
7560 so = shell_out!("gpg --with-fingerprint #{key_path}")
7561 short_key_id = %r{pub\s*\S*/(\S*)}.match(so.stdout)[1].downcase
7562 logger.trace("GPG short key ID of key at #{key_path} is #{short_key_id}")
7563 cached_keyfile = ::File.join(Chef::Config[:file_cache_path], uri.split("/")[-1])
7564 source ::File.expand_path("support/yum_repo.erb", __dir__)
7565 only_if "yum repolist all | grep -P '^#{new_resource.repositoryid}([ \t]|$)'"
7566 raise Chef::Exceptions::Override, "You must override #{__method__} in #{self}"
7567 logger.trace("#{new_resource} does not exist (#{e.message})")
7568 @change_desc = []
7569 if !new_val.nil? && new_val != cur_val
7570 @change_desc << "change #{user_attrib} from #{cur_val} to #{new_val}"
7571 field_list.sort_by { |a| a[0] }.each do |field, option|
7572 user = IO.read(PASSWORD_FILE).match(/^#{Regexp.escape(new_resource.username)}:([^:]*):/)
7573 @locked = user[1].start_with?("*LK*")
7574 shell_out!("passwd", "-l", new_resource.username)
7575 shell_out!("passwd", "-u", new_resource.username)
7576 opts << "-c" << new_resource.comment if should_set?(:comment)
7577 opts << "-g" << new_resource.gid if should_set?(:gid)
7578 opts << "-s" << new_resource.shell if should_set?(:shell)
7579 opts << "-u" << new_resource.uid if should_set?(:uid)
7580 opts << "-d" << new_resource.home if updating_home?
7581 opts << "-o" if new_resource.non_unique
7582 opts << "-m"
7583 opts += [ "-u", new_resource.uid ] if new_resource.non_unique
7584 opts << "-r" if new_resource.manage_home
7585 opts << "-f" if new_resource.force
7586 opts << "-m" if new_resource.manage_home
7587 buffer = Tempfile.new("shadow", "/etc")
7588 user = entry.split(":").first
7589 mode = s.mode & 0o7777
7590 fields = entry.split(":")
7591 fields.join(":")
7592 (Time.now.to_i / 86400).floor
7593 shell_out!("pw", "useradd", set_options)
7594 shell_out!("pw", "usermod", set_options)
7595 command = [ "pw", "userdel", new_resource.username ]
7596 require_relative "../../mixin/shell_out"
7597 require_relative "../../mixin/which"
7598 admin_group_xml = run_dscl("read", "/Groups/admin")
7599 user_xml = run_dscl("read", "/Users/#{new_resource.username}")
7600 return nil if user_xml.nil? || user_xml == ""
7601 shadow_binary_plist = [shadow_hash_hex.delete(" ")].pack("H*")
7602 shadow_xml_plist = shell_out("plutil", "-convert", "xml1", "-o", "-", "-", input: shadow_binary_plist).stdout
7603 cmd = [-"-addUser", new_resource.username]
7604 cmd += ["-fullName", new_resource.comment] if prop_is_set?(:comment)
7605 cmd += ["-UID", prop_is_set?(:uid) ? new_resource.uid : get_free_uid]
7606 cmd += ["-shell", new_resource.shell]
7607 cmd += ["-home", new_resource.home]
7608 cmd += ["-admin"] if new_resource.admin
7609 if prop_is_set?(:gid)
7610 desc = "Update #{attr}"
7611 desc << " from #{current_resource.send(attr)} to #{new_resource.send(attr)}"
7612 @change_desc << desc
7613 %i{uid home}.each do |prop|
7614 admins << user_plist[:guid][0]
7615 admins.reject! { |m| m == user_plist[:guid][0] }
7616 cmd << new_resource.manage_home ? "-secure" : "-keepHome"
7617 if %i{admin_username admin_password}.all? { |p| prop_is_set?(p) }
7618 auth_string = user_plist[:auth_authority].reject! { |tag| tag == ";DisabledUser;" }.join.strip
7619 uid = nil
7620 users_uids = run_dscl("list", "/Users", "uid")
7621 if users_uids&.match?(Regexp.new("#{Regexp.escape(next_uid_guess.to_s)}
"))
7622 next_uid_guess += 1
7623 [g.name, g.gid.to_s, :modify]
7624 [g.username, nil, :create]
7625 (current_resource.hidden ? 1 : 0) != hidden_value.to_i
7626 if prop_is_set?(:salt)
7627 return true if %i{salt iterations}.any? { |prop| diverged?(prop) }
7628 ).unpack("H*")[0] != current_resource.password
7629 string.unpack("a2" * (string.size / 2)).collect { |i| i.hex.chr }.join
7630 shadow_hash = user_plist[:shadow_hash] ? user_plist[:shadow_hash][0] : {}
7631 shell_out("plutil", "-convert", "binary1", "-o", "-", "-",
7632 ::File.open(import_file, "w+", 0600) do |f|
7633 run_dscl("create", "/Users/#{new_resource.username}", "Password", "********")
7634 timeout = Time.now + 5
7635 result = shell_out("dscl", "-plist", ".", "-#{args[0]}", args[1..])
7636 return "" if ( args.first =~ /^delete/ ) && ( result.exitstatus != 0 )
7637 result = shell_out("plutil", "-#{args[0]}", args[1..])
7638 !v.nil? && v != ""
7639 alias_method :[], :get
7640 plist_hash[property_map[key]] = [ value ]
7641 alias_method :[]=, :set
7642 @change_desc ||= []
7643 if !new_val.nil? && new_val.to_s != cur_val.to_s
7644 if manage_u.exitstatus == 12 && manage_u.stderr !~ /exists/
7645 shell_out!("usermod", "-L", new_resource.username)
7646 shell_out!("usermod", "-U", new_resource.username)
7647 opts << "-e" << new_resource.expire_date if prop_is_set?(:expire_date)
7648 opts << "-f" << new_resource.inactive if prop_is_set?(:inactive)
7649 opts << "-p" << new_resource.password if should_set?(:password)
7650 opts << "-r" if new_resource.system
7651 passwd_s = shell_out("passwd", "-S", new_resource.username, returns: [ 0, 1 ])
7652 @locked = nil
7653 status_line = passwd_s.stdout.split(" ")
7654 @locked = false if /^[PN]/.match?(status_line[1])
7655 @locked = true if /^L/.match?(status_line[1])
7656 provides :user, os: "darwin", platform_version: "<= 10.13"
7657 a.assertion { ::File.exist?("/usr/bin/dscl") }
7658 a.assertion { ::File.exist?("/usr/bin/plutil") }
7659 if new_resource.password && dscl_get(user_info, :password) == "********"
7660 run_dscl("create", "/Users/#{new_resource.username}")
7661 users_uids = run_dscl("list", "/Users", "uid").split("
")
7662 uid_map = users_uids.each_with_object({}) do |tuid, tmap|
7663 tmap[x[1]] = x[0]
7664 if uid_map[uid.to_s]
7665 elsif !new_resource.gid.to_s.match(/^\d+$/)
7666 possible_gid = run_dscl("read", "/Groups/#{new_resource.gid}", "PrimaryGroupID").split(" ").last
7667 unless %r{^/}.match?(new_resource.home)
7668 shell_out!("/usr/sbin/createhomedir", "-c", "-u", (new_resource.username).to_s)
7669 files = ::Dir.glob("#{Chef::Util::PathHelper.escape_glob_dir(src)}/*", ::File::FNM_DOTMATCH) - ["#{src}/.", "#{src}/.."]
7670 run_dscl("create", "/Users/#{new_resource.username}", "UserShell", "/usr/bin/false")
7671 shadow_info = {}
7672 salt = nil
7673 pbkdf_info = {}
7674 run_dscl("list", "/Groups").each_line do |group|
7675 run_dscl("delete", "/Users/#{new_resource.username}")
7676 diverged?(:password) || diverged?(:salt) || diverged?(:iterations)
7677 membership_info = ""
7678 membership_info = run_dscl("read", "/Groups/#{group_name}")
7679 uid: "uid",
7680 gid: "gid",
7681 home: "home",
7682 shell: "shell",
7683 user_plist_info = run_plutil("convert", "xml1", "-o", "-", user_plist_file)
7684 result = shell_out("dscl", ".", "-#{args[0]}", args[1..])
7685 result.stdout.encode("utf-8", "binary", undef: :replace, invalid: :replace, replace: "?")
7686 shell_out("plutil", "-convert", "xml1", "-o", "-", "-", input: binary_plist_string).stdout
7687 !!(string =~ /^[[:xdigit:]]{136}$/)
7688 !!(string =~ /^[[:xdigit:]]{256}$/)
7689 opts << "-g" << "system" if new_resource.system
7690 lock_info = shell_out!("lsuser", "-a", "account_locked", new_resource.username)
7691 status = /\S+\s+account_locked=(\S+)/.match(lock_info.stdout)
7692 @locked =
7693 if status && status[1] == "true"
7694 command = "echo '#{new_resource.username}:#{new_resource.password}' | chpasswd -c -e"
7695 if new_resource.gid.is_a?(String) && new_resource.gid.to_i == 0
7696 Time.at(@shadow_info.sp_expire * 60 * 60 * 24).strftime("%Y-%m-%d")
7697 a.assertion { !supports_ruby_shadow? || @shadow_lib_ok }
7698 a.assertion { (!new_resource.expire_date && !new_resource.inactive) || linux? }
7699 logger.info("#{new_resource} altered, #{change_desc.join(", ")}")
7700 logger.info("#{new_resource} managed: #{change_desc.join(", ")}")
7701 logger.info("#{new_resource} modified: #{change_desc.join(", ")}")
7702 obj.map { |value| visitor.call(value) }
7703 s = shell_out(*systemctl_cmd, "show", "-p", "UnitFileState", "-p", "ActiveState", new_resource.unit_name, **systemctl_opts)
7704 status = {}
7705 k, v = line.strip.split("=")
7706 status[k] = v
7707 @systemctl_args ||= new_resource.user ? "--user" : "--system"
7708 @systemctl_opts ||=
7709 if ::File.exist?(::File.join(new_resource.destination, ".svn"))
7710 args = ["--force"]
7711 c = scm :export, *args
7712 @revision_int ||= if /^\d+$/.match?(new_resource.revision)
7713 svn_info = shell_out!(command, **run_options(cwd: cwd, returns: [0, 1])).stdout
7714 command = scm(:info)
7715 def run_options(run_opts = {})
7716 repo_attrs = svn_info.lines.inject({}) do |attrs, line|
7717 property, value = $1, $2
7718 rev = (repo_attrs["Last Changed Rev"] || repo_attrs["Revision"])
7719 result << "--password #{new_resource.svn_password} "
7720 binary = "\"#{binary}\"" if /\s/.match?(binary)
7721 [binary, *args].compact.join(" ")
7722 !::File.exist?(new_resource.destination) || Dir.entries(new_resource.destination).sort == [".", ".."]
7723 (ChefUtils.windows? ? "svn.exe" : "svn")
7724 require_relative "../../win32/error"
7725 new_config = {
7726 }.reject { |k, v| v.nil? || v.length == 0 }
7727 username.gsub(%r{[/\\. ]+}, "_")
7728 username.sub(/^\.?\\+/, "")
7729 config = {}
7730 when "all"
7731 require_relative "../../util/file_edit"
7732 @job << " #{key}=#{value}"
7733 @upstart_job_dir = "/etc/init"
7734 @upstart_conf_suffix = ".conf"
7735 if ::File.exist?("#{@upstart_job_dir}/#{@new_resource.service_name}#{@upstart_conf_suffix}")
7736 ::File.open("#{@upstart_job_dir}/#{@new_resource.service_name}#{@upstart_conf_suffix}", "r") do |file|
7737 when /^start on/
7738 logger.trace("#{@new_resource} enabled: #{line.chomp}")
7739 when /^#start on/
7740 logger.trace("#{@new_resource} disabled: #{line.chomp}")
7741 shell_out!("/sbin/start #{@job}", default_env: false)
7742 shell_out!("/sbin/stop #{@job}", default_env: false)
7743 shell_out!("/sbin/reload #{@job}", default_env: false)
7744 conf.search_file_replace(/^#start on/, "start on")
7745 conf.search_file_replace(/^start on/, "#start on")
7746 command = "/sbin/status #{@job}"
7747 s = shell_out!(systemctl_path, args, "show", "-p", "UnitFileState", "-p", "ActiveState", new_resource.service_name, **options)
7748 options = {
7749 args = "--user"
7750 args = "--system"
7751 @status_command = "/bin/svcs"
7752 cmd = shell_out!(@status_command, "-l", @current_resource.service_name, returns: [0, 1])
7753 key, value = line.strip.split(/\s+/, 2)
7754 (!ps_cmd.nil? && !ps_cmd.empty?)
7755 @run_context.node[:command] && @run_context.node[:command][:ps]
7756 @current_run_levels = []
7757 if ::File.exist?("/sbin/chkconfig")
7758 chkconfig.stdout.split(/\s+/)[1..].each do |level|
7759 index = level.split(":").first
7760 status = level.split(":").last
7761 (run_levels.nil? || run_levels.empty?) ? "" : "--level #{run_levels.join("")} "
7762 @init_command = ::File.exist?(rcd_script_path) ? rcd_script_path : nil
7763 update_rcl rc_conf_local + "
" + "#{builtin_service_enable_variable_name}=\"\"
"
7764 old_services_list = rc_conf_local.match(/^pkg_scripts="(.*)"/)
7765 old_services_list = old_services_list ? old_services_list[1].split(" ") : []
7766 if /^pkg_scripts="(.*)"/.match?(rc_conf_local)
7767 new_rcl = rc_conf_local.sub(/^pkg_scripts="(.*)"/, "pkg_scripts=\"#{new_services_list.join(" ")}\"")
7768 new_rcl = rc_conf_local + "
" + "pkg_scripts=\"#{new_services_list.join(" ")}\"
"
7769 update_rcl rc_conf_local + "
" + "#{builtin_service_enable_variable_name}=\"NO\"
"
7770 old_list = rc_conf_local.match(/^pkg_scripts="(.*)"/)
7771 old_list = old_list ? old_list[1].split(" ") : []
7772 update_rcl rc_conf_local.sub(/^pkg_scripts="(.*)"/, pkg_scripts = (new_list.join(" ")).to_s)
7773 @bsevn ||= begin
7774 if m = rcscript.read.match(/^# \$OpenBSD: (\w+)[(.rc),]?/)
7775 result = m[1] + "_flags"
7776 if /^#{Regexp.escape(var_name)}=(.*)/.match?(rc_conf)
7777 if m = rc_conf.match(/^#{Regexp.escape(var_name)}=(.*)/)
7778 unless /"?[Nn][Oo]"?/.match?(m[1])
7779 if m = rc_conf_local.match(/^#{Regexp.escape(var_name)}=(.*)/)
7780 unless /"?[Nn][Oo]"?/.match?(m[1]) # e.g. looking for httpd_flags=NO
7781 if m = rc_conf_local.match(/^pkg_scripts="(.*)"/)
7782 if m[1].include?(var_name) # e.g. looking for 'gdm' in pkg_scripts="gdm unbound"
7783 Chef::Util::PathHelper.home("Library", "LaunchAgents") { |p| locations << p }
7784 @plist_size = 0
7785 logger.trace("#{new_resource} console_user: '#{@console_user}'")
7786 @base_user_cmd = "su -l #{@console_user} -c"
7787 logger.trace("#{new_resource} base_user_cmd: '#{@base_user_cmd}'")
7788 logger.trace("#{new_resource} Plist: '#{@plist}' service_label: '#{@service_label}'")
7789 a.assertion { @plist_size < 2 }
7790 a.assertion { ::File.exist?(@plist.to_s) }
7791 a.assertion { !@service_label.to_s.empty? }
7792 a.assertion { @plist_size > 0 }
7793 session = @session_type ? "-S #{@session_type} " : ""
7794 cmd = "/bin/launchctl load -w " + session + @plist
7795 cmd = "/bin/launchctl unload -w " + @plist
7796 shell_out("#{@base_user_cmd} '#{cmd}'", default_env: false)
7797 cmd = "/bin/launchctl list #{@service_label}"
7798 when /\s+\"pid\"\s+=\s+(\d+).*/
7799 pid = $1
7800 logger.trace("Current PID for #{@service_label} is #{pid}")
7801 plist_xml = shell_out!(
7802 plists = PLIST_DIRS.inject([]) do |results, dir|
7803 edir = ::File.expand_path(dir)
7804 if Dir.glob("/etc/rc*/**/S*#{service_name}").empty?
7805 shell_out!("/sbin/insserv -r -f #{new_resource.service_name}")
7806 shell_out!("/sbin/insserv -d -f #{new_resource.service_name}")
7807 @init_command = "/etc/init.d/#{@new_resource.service_name}"
7808 logger.trace "#{@new_resource} exists: #{exists}, readable: #{readable}"
7809 a.assertion { ::File.exist?("/sbin/rc-update") }
7810 if ::File.exist?("/etc/rc.d/#{new_resource.service_name}")
7811 @init_command = "/etc/rc.d/#{new_resource.service_name}"
7812 ::File.open("/etc/rc.conf", "r", &:readlines)
7813 ::File.open("/etc/rc.conf", "w") do |file|
7814 lines.each { |line| file.puts(line) }
7815 if line =~ /^name="?(\w+)"?/
7816 return $1 + "_enable"
7817 shell_out!("#{init_command} rcvar").stdout[/(\w+_enable)=/, 1]
7818 if ::File.exist?("/etc/rc.conf") && var_name
7819 when /^#{Regexp.escape(var_name)}="(\w+)"/
7820 if $1.casecmp?("yes")
7821 elsif $1.casecmp?("no") || $1.casecmp?("none")
7822 lines.delete_if { |line| line =~ /^\#?\s*#{Regexp.escape(service_enable_variable_name)}=/ }
7823 lines << "#{service_enable_variable_name}=\"#{value}\""
7824 update_rcd = "/usr/sbin/update-rc.d"
7825 a.assertion { ::File.exist? update_rcd }
7826 a.assertion { @got_priority == true }
7827 temp_priorities = { "6" => [:stop, "20"],
7828 return [] unless ::File.exist?(path)
7829 ::File.readlines(path).each_with_object([]) do |line, acc|
7830 if line =~ /Default-(Start|Stop):\s+(\d.*)/
7831 acc << $2.split(" ")
7832 priority = {}
7833 rc_files = []
7834 rc_files.push Dir.glob("/etc/rc#{level}.d/[SK][0-9][0-9]#{current_resource.service_name}")
7835 priority[$1] = [($2 == "S" ? :start : :stop), $3]
7836 if priority[2] && [2..5].all? { |runlevel| priority[runlevel] == priority[2] }
7837 disable_or_enable = (action == :start ? "enable" : "disable")
7838 @init_command = "/etc/rc.d/#{@new_resource.service_name}"
7839 raise Chef::Exceptions::Service, "No DAEMONS found in /etc/rc.conf" unless /DAEMONS=\((.*)\)/m.match?(::File.read("/etc/rc.conf"))
7840 if ::File.read("/etc/rc.conf") =~ /DAEMONS=\((.*)\)/m
7841 entries += $1.gsub(/\\?[\r
]/, " ").gsub(/# *[^ ]+/, " ").split(" ") if $1.length > 0
7842 content = ::File.read("/etc/rc.conf").gsub(/DAEMONS=\((.*)\)/m, "DAEMONS=(#{entries.join(" ")})")
7843 ::File.open("/etc/rc.conf", "w") do |f|
7844 new_daemons = []
7845 if daemon == "!#{new_resource.service_name}"
7846 new_daemons << "!#{new_resource.service_name}"
7847 @init_command = "/etc/rc.d/init.d/#{@new_resource.service_name}"
7848 create_symlink(level, (o[0] == :start ? "S" : "K"), o[1])
7849 create_symlink(2, "S", "")
7850 create_symlink(level, "K", 100 - o[1]) if o[0] == :stop
7851 create_symlink(2, "K", "")
7852 ::File.symlink("/etc/rc.d/init.d/#{@new_resource.service_name}", "/etc/rc.d/rc#{run_level}.d/#{status}#{priority}#{@new_resource.service_name}")
7853 files = Dir.glob(["/etc/rc.d/rc2.d/[SK][0-9][0-9]#{@new_resource.service_name}", "/etc/rc.d/rc2.d/[SK]#{@new_resource.service_name}"])
7854 priority[2] = [($1 == "S" ? :start : :stop), ($2.empty? ? "" : $2.to_i)]
7855 if $1 == "S"
7856 if is_enabled && files.length == 1
7857 if service.split(" ").last == "active"
7858 so = shell_out("lssrc -g #{@new_resource.service_name}")
7859 method_name = "#{action}_command".to_sym
7860 MASK = { "0.0.0.0" => "0",
7861 hex_ip = hex_data.to_s.downcase.gsub(/[^0-9a-f]/, "")
7862 return nil if hex_ip.length != hex_data.length || hex_ip.length != 8
7863 octets = hex_ip.scan(/../).reverse.collect { |octet| [octet].pack("H2").unpack("C").first }
7864 ip = octets.join(".")
7865 logger.trace("Invalid IP address data: hex=#{hex_ip}, ip=#{ip}")
7866 route_file = ::File.open("/proc/net/route", "r")
7867 _, destination, gateway, _, _, _, _, mask = line.split
7868 running_ip = IPAddr.new("#{destination}/#{mask}")
7869 converge_by("run #{command.join(" ")} to add route") do
7870 converge_by("run #{command.join(" ")} to delete route ") do
7871 if platform_family?("rhel", "amazon", "fedora")
7872 conf = {}
7873 dev = resource.device || "eth0"
7874 conf[dev] = "" if conf[dev].nil?
7875 conf.each_key do |k|
7876 network_file = ::File.new(network_file_name, "w")
7877 converge_by("write route route.#{k}
#{conf[k]} to #{network_file_name}") do
7878 logger.trace("#{new_resource} writing route.#{k}
#{conf[k]}")
7879 command = [ "ip", "route", "replace", target ]
7880 command = [ "ip", "route", "delete", target ]
7881 content = ""
7882 content << "# #{options[:comment]}
" if options[:comment]
7883 content << (options[:target]).to_s
7884 content << "/#{MASK[options[:netmask].to_s]}" if options[:netmask]
7885 content << " via #{options[:gateway]}" if options[:gateway]
7886 content << " dev #{options[:device]}" if options[:device]
7887 content << " metric #{options[:metric]}" if options[:metric]
7888 content << "
"
7889 attr_accessor :event_data # e.g., a diff.
7890 autoload :CGI, "cgi"
7891 @uri = uri
7892 host = port ? "#{hostname}:#{port}" : hostname
7893 @sftp ||= Net::SFTP.start(host, user, password: pass)
7894 path = uri.path.sub(%r{\A/}, "%2F") # re-encode the beginning slash because uri library decodes it.
7895 directories = path.split(%r{/}, -1)
7896 d.gsub!(/%([0-9A-Fa-f][0-9A-Fa-f])/) { [$1].pack("H2") }
7897 if filename.length == 0 || filename.end_with?( "/" )
7898 Chef::Log.trace("#{new_resource} staging #{@source} to #{tempfile.path}")
7899 ::File.open(@source, "rb") do |remote_file|
7900 path.gsub(%r{^/([a-zA-Z]:)}, '\1')
7901 @source_path ||= begin
7902 require_relative "../../http/simple"
7903 require_relative "../../digester"
7904 opts = {}
7905 if /gz$/.match?(uri.to_s)
7906 @ftp ||= Net::FTP.new
7907 if typecode && /\A[ai]\z/ !~ typecode
7908 ftp.voidcmd("CWD #{cwd}")
7909 when "http", "https"
7910 when "ftp"
7911 !!(/\A\\\\[A-Za-z0-9+\-\.]+/ =~ source)
7912 require_relative "../../mixin/uris"
7913 logger.warn("#{@new_resource} cannot be downloaded from #{source}: #{e}")
7914 require_relative "../../file_cache"
7915 require_relative "../../json_compat"
7916 uri = uri.dup
7917 @uri = uri.to_s
7918 @etag, @mtime = nil, nil
7919 @etag = previous_cc_data["etag"]
7920 uri.gsub(/\W/, "_")[0..63]
7921 @managed_files ||= Set.new
7922 Dir.glob(::File.join(Chef::Util::PathHelper.escape_glob_dir(path), "**", "*"), ::File::FNM_DOTMATCH).sort!.reverse!.each do |file|
7923 next if [".", ".."].include?(Pathname.new(file).basename.to_s)
7924 if dir == path
7925 @name_hash = Hash[values.map { |val| [val[:name].downcase, val] }]
7926 @name_hash = {}
7927 value[:data] = value[:data].to_i if WORD_TYPES.include?(value[:type])
7928 unless current_value[:type] == value[:type] && current_value[:data] == value[:data]
7929 %Q{"#{interpreter_path}"},
7930 %Q{-File "#{script_file_path}"},
7931 ].join(" ")
7932 %Q{-Command ". '#{user_script_file.path}'"},
7933 $global:lastcmdlet = $?
7934 other.version == version && other.arch == arch
7935 name == other.name && version == other.version && arch == other.arch
7936 alias eql? ==
7937 resolved_source_array.all? { |s| s && ::File.exist?(s) }
7938 resolved_source_array.select { |s| s.nil? || !::File.exist?(s) }
7939 shell_out!("rpm -qp --queryformat '%{NAME} %{EPOCH} %{VERSION} %{RELEASE} %{ARCH}
' #{new_resource.source}").stdout.each_line do |line|
7940 when /^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)$/
7941 return Version.new($1, "#{$2 == "(none)" ? "0" : $2}:#{$3}-#{$4}", $5)
7942 status = shell_out!("zypper", "--non-interactive", "info", package_name)
7943 when /^Version *: (.+) *$/
7944 when /^Installed *: Yes.*$/ # http://rubular.com/r/9StcAMjOn6
7945 when /^Status *: out-of-date \(version (.+) installed\) *$/
7946 search_string = new_version.nil? ? package_name : "#{package_name}=#{new_version}"
7947 so = shell_out!("zypper", "--non-interactive", "search", "-s", "--provides", "--match-exact", "--type=package", search_string)
7948 (status, name, type, version, arch, repo) = [ md[1], md[2], md[3], md[4], md[5], md[6] ]
7949 next unless version == new_version || version.start_with?("#{new_version}-")
7950 @available_version ||= []
7951 @installed_version ||= []
7952 names.zip(versions).map do |n, v|
7953 (v.nil? || v.empty?) ? n : "#{n}=#{v}"
7954 @zypper_version ||=
7955 shell_out!("zypper", global_options, gpg_checks, command, *options, "-y", names)
7956 names.all? { |n| locked_packages.include? n }
7957 names.all? { |n| !locked_packages.include? n }
7958 @locked_packages ||=
7959 locked = shell_out!("zypper", "locks")
7960 line.split("|").shift(2).last.strip
7961 require_relative "../../package"
7962 lead = 0
7963 epoch = $1.to_i
7964 lead = $1.length + 1
7965 elsif evr[0].ord == ":".ord
7966 epoch = 0
7967 lead = 1
7968 if /:?.*-(.*)$/.match(evr) # rubocop:disable Performance/RedundantMatch
7969 release = $1
7970 tail = evr.length - release.length - lead - 1
7971 isalpha(x) || isdigit(x)
7972 v = x.ord
7973 (v >= 65 && v <= 90) || (v >= 97 && v <= 122)
7974 v >= 48 && v <= 57
7975 return 0 if x == y
7976 if x.nil?
7977 x = ""
7978 if y.nil?
7979 y = ""
7980 y_pos = 0
7981 y_seg_pos = 0
7982 y_pos_max = y.length - 1
7983 y_comp = nil
7984 while x_pos <= x_pos_max && y_pos <= y_pos_max
7985 while (x_pos <= x_pos_max) && (isalnum(x[x_pos]) == false)
7986 x_pos += 1 # +1 over pos_max if end of string
7987 y_pos += 1 while (y_pos <= y_pos_max) && (isalnum(y[y_pos]) == false)
7988 if (x_pos == x_pos_max + 1) || (y_pos == y_pos_max + 1)
7989 x_seg_pos = x_pos
7990 y_seg_pos = y_pos
7991 x_seg_is_num = true
7992 x_seg_pos += 1
7993 x_seg_pos += 1 while (x_seg_pos <= x_pos_max) && isdigit(x[x_seg_pos])
7994 x_comp = x[x_pos, x_seg_pos - x_pos]
7995 y_seg_pos += 1 while (y_seg_pos <= y_pos_max) && isdigit(y[y_seg_pos])
7996 y_comp = y[y_pos, y_seg_pos - y_pos]
7997 x_seg_is_num = false
7998 x_seg_pos += 1 while (x_seg_pos <= x_pos_max) && isalpha(x[x_seg_pos])
7999 y_seg_pos += 1 while (y_seg_pos <= y_pos_max) && isalpha(y[y_seg_pos])
8000 if y_pos == y_seg_pos
8001 return x_seg_is_num ? 1 : -1
8002 x_pos += x_comp.length # +1 over pos_max if end of string
8003 y_pos += y_comp.length
8004 x_comp = x_comp.to_i
8005 y_comp = y_comp.to_i
8006 if x_comp > y_comp
8007 if (x_pos == x_pos_max + 1) && (y_pos == y_pos_max + 1)
8008 if (x_pos_max - x_pos) > (y_pos_max - y_pos)
8009 -1
8010 end # self
8011 if args.size == 1
8012 @e, @v, @r = RPMUtils.version_parse(args[0])
8013 elsif args.size == 3
8014 @e = args[0].to_i
8015 @v = args[1]
8016 @r = args[2]
8017 attr_reader :e, :v, :r
8018 new(*args)
8019 if @r.nil?
8020 @v
8021 x = self
8022 if (x.e.nil? == false && x.e > 0) && y.e.nil?
8023 elsif x.e.nil? && (y.e.nil? == false && y.e > 0)
8024 elsif x.e.nil? == false && y.e.nil? == false
8025 if x.e < y.e
8026 elsif x.e > y.e
8027 if partial && (x.v.nil? || y.v.nil?)
8028 elsif x.v.nil? == false && y.v.nil?
8029 elsif x.v.nil? && y.v.nil? == false
8030 elsif x.v.nil? == false && y.v.nil? == false
8031 return cmp if cmp != 0
8032 if partial && (x.r.nil? || y.r.nil?)
8033 elsif x.r.nil? == false && y.r.nil?
8034 elsif x.r.nil? && y.r.nil? == false
8035 elsif x.r.nil? == false && y.r.nil? == false
8036 if args.size == 4
8037 @n = args[0]
8038 @a = args[2]
8039 @provides = args[3]
8040 elsif args.size == 6
8041 e = args[1].to_i
8042 v = args[2]
8043 r = args[3]
8044 @version = RPMVersion.new(e, v, r)
8045 @a = args[4]
8046 @provides = args[5]
8047 @provides = [ RPMProvide.new(@n, @version.evr, :==) ]
8048 attr_reader :n, :a, :version, :provides
8049 return 0 if x.nevra == y.nevra
8050 if x.n.nil? == false && y.n.nil?
8051 elsif x.n.nil? && y.n.nil? == false
8052 elsif x.n.nil? == false && y.n.nil? == false
8053 if x.n < y.n
8054 elsif x.n > y.n
8055 if x.a.nil? == false && y.a.nil?
8056 elsif x.a.nil? && y.a.nil? == false
8057 elsif x.a.nil? == false && y.a.nil? == false
8058 if x.a < y.a
8059 elsif x.a > y.a
8060 if args.size == 3
8061 @name = args[0]
8062 @flag = args[2] || :==
8063 elsif args.size == 5
8064 @flag = args[4] || :==
8065 if /^(\S+)\s+(>|>=|=|==|<=|<)\s+(\S+)$/.match(string) # rubocop:disable Performance/RedundantMatch
8066 name = $1
8067 flag = if $2 == "="
8068 :==
8069 :"#{$2}"
8070 version = $3
8071 new(name, nil, nil)
8072 if x.name != y.name
8073 if (sense < 0) && ((x.flag == :> || x.flag == :>=) || (y.flag == :<= || y.flag == :<))
8074 elsif (sense > 0) && ((x.flag == :< || x.flag == :<=) || (y.flag == :>= || y.flag == :>))
8075 elsif sense == 0 && (
8076 (x.flag == :< && y.flag == :<) ||
8077 (x.flag == :> && y.flag == :>)
8078 @rpms = {}
8079 @index = {}
8080 @provides = {}
8081 def [](package_name)
8082 @rpms[new_rpm.n] ||= []
8083 @rpms[new_rpm.n] << new_rpm
8084 @provides[provide.name] ||= []
8085 def <<(*args)
8086 what = []
8087 what << pkg
8088 require_relative "../../../mixin/shell_out"
8089 YUM_HELPER = ::File.expand_path(::File.join(::File.dirname(__FILE__), "yum_helper.py")).freeze
8090 @yum_command ||= begin
8091 cmd = which("platform-python", "python", "python2", "python2.7", extra_path: "/usr/libexec") do |f|
8092 shell_out("#{f} -c 'import yum'").exitstatus == 0
8093 @stdin = @stdout = @stderr = @inpipe = @outpipe = @wait_thr = nil
8094 query("close_rpmdb", {})
8095 query("versioncompare", { "versions" => [version1, version2] }).to_i
8096 query_output = query("installonlypkgs", { "package" => name })
8097 if query_output == "False"
8098 options.each_with_object({}) do |opt, h|
8099 if opt =~ /--enablerepo=(.+)/
8100 $1.split(",").each do |repo|
8101 h["repos"] ||= []
8102 h["repos"].push( { "enable" => repo } )
8103 if opt =~ /--disablerepo=(.+)/
8104 h["repos"].push( { "disable" => repo } )
8105 raise "provides must have an epoch in the version to deconstruct" unless provides =~ /^(\S+)-(\d+):(\S+)/
8106 epoch = $2
8107 other = $3
8108 ret = { "provides" => name, "epoch" => epoch }
8109 arch = if is_arch?(maybe_arch)
8110 other.delete_suffix!(".#{maybe_arch}")
8111 ret.merge!({ "arch" => arch }) if arch
8112 (version, _, release) = other.rpartition("-")
8113 ret.merge!({ "version" => release }) # yeah, rpartition is just weird
8114 ret.merge!({ "version" => version, "release" => release })
8115 version = if !version.nil? && !version.empty?
8116 arch = if !arch.nil? && !arch.empty?
8117 if version =~ /^[><=]/
8118 return { "provides" => "#{provides}.#{arch} #{version}" }
8119 return { "provides" => "#{provides} #{version}" }
8120 provides.delete_suffix!(".#{arch}")
8121 provides = "#{provides}-#{version}" if version
8122 provides = "#{provides}.#{arch}" if arch
8123 if provides =~ /-\d+:/ && provides !~ /[\*\?]/
8124 { "provides" => provides }
8125 repo_opts = options_params(options || {})
8126 hash = { "action" => action }
8127 array = output.split.map { |x| x == "nil" ? nil : x }
8128 array.each_slice(3).map { |x| Version.new(*x) }.first
8129 output = ""
8130 fds, = IO.select([stderr, stdout, inpipe], nil, nil, 0)
8131 fds.each do |fd|
8132 output += fd.sysread(4096) rescue ""
8133 max_retries ||= 5
8134 ret = nil
8135 @current_version = []
8136 methods = []
8137 yum(options, "-y", "remove", resolved_names)
8138 yum("-d0", "-e0", "-y", options, "versionlock", "add", resolved_package_lock_names(names))
8139 yum("-d0", "-e0", "-y", options, "versionlock", "delete", resolved_package_lock_names(names).map { |n| "*:#{n}-*" })
8140 locked = yum("versionlock", "list")
8141 line.sub(/-[^-]*-[^-]*$/, "").split(":").last.strip
8142 def version_gt?(v1, v2)
8143 return false if v1.nil? || v2.nil?
8144 @magical_version ||= []
8145 @current_version ||= []
8146 @yum_binary ||=
8147 yum_binary ||= ::File.exist?("/usr/bin/yum-deprecated") ? "yum-deprecated" : "yum"
8148 ].each do |hkey|
8149 desired = hkey.length > 1 ? hkey[1] : ::Win32::Registry::Constants::KEY_READ
8150 reg.each_key do |key, _wtime|
8151 logger.trace("Registry error opening key '#{key}' on node #{desired}: #{ex}")
8152 logger.trace("Registry error opening hive '#{hkey[0]}' :: #{desired}: #{ex}")
8153 @hive = hive
8154 @key = key
8155 options ? " #{options}" : ""
8156 uninstall_string = "msiexec /x #{uninstall_string.match(/{.*}/)}"
8157 ].join
8158 %{start "" /wait #{uninstall_string} & exit %%%%ERRORLEVEL%%%%}
8159 a.assertion { new_resource.source || msi? }
8160 ::Kernel.open(::File.expand_path(source_location), "rb") do |io|
8161 if basename == "setup.exe"
8162 if v1 == "latest" || v2 == "latest"
8163 gem_v1 = Gem::Version.new(v1)
8164 gem_v2 = Gem::Version.new(v2)
8165 gem_v1 <=> gem_v2
8166 return :inno if entry.key.end_with?("_is1")
8167 send(k.to_sym, v)
8168 ::File.exist?(new_source) ? new_source : nil
8169 ::File.extname(source_location).casecmp(".msi") == 0
8170 status = shell_out("pkginfo", "-l", "-d", new_resource.source, new_resource.package_name)
8171 [ "pkgadd", "-n", "-d", new_resource.source, new_resource.package_name ]
8172 [ "pkgadd", "-n", "-d", new_resource.source, "all" ]
8173 [ "pkgadd", "-n", options, "-d", new_resource.source, new_resource.package_name ]
8174 [ "pkgadd", "-n", options, "-d", new_resource.source, "all" ]
8175 shell_out!( "pkgrm", "-n", name )
8176 shell_out!( "pkgrm", "-n", options, name )
8177 request = "#{method} #{uri} HTTP/1.0\r
" +
8178 request.concat("\r
")
8179 body = ""
8180 body << c
8181 next unless ["}", "]"].include?(c)
8182 call_snap_api("GET", "/v2/changes/#{id}")
8183 if response["type"] == "error"
8184 raise "status: #{response["status"]}, kind: #{response["result"]["kind"]}, message: #{response["result"]["message"]}"
8185 n = 0
8186 when "Do", "Doing", "Undoing", "Undo"
8187 when "Abort", "Hold", "Error"
8188 n += 1
8189 shell_out!("snap", *args)
8190 body = {
8191 }.to_json
8192 response = snapctl(["info", path])
8193 stdout.match(/version: (\S+)/)[1]
8194 snap_options = options.map do |k, v|
8195 --#{snap_name}
8196 request = {
8197 call_snap_api("POST", "/v2/snaps", json)
8198 call_snap_api("POST", "/v2/snaps/#{snap_name}", json)
8199 json = call_snap_api("GET", "/v2/find?name=#{name}")
8200 if json["status-code"] != 200
8201 unless json["result"][0]["channels"]["latest/#{channel}"]
8202 json["result"][0]["channels"]["latest/#{channel}"]["version"]
8203 json = call_snap_api("GET", "/v2/snaps")
8204 if result["status-code"] == 404
8205 json = call_snap_api("GET", "/v2/snaps/#{name}")
8206 json = call_snap_api("GET", "/v2/snaps/#{name}/conf")
8207 response = call_snap_api("PUT", "/v2/snaps/#{name}/conf", value)
8208 info = shell_out!("/opt/local/sbin/pkg_info", "-E", "#{name}*", env: nil, returns: [0, 1])
8209 version = info.stdout[/^#{new_resource.package_name}-(.+)/, 1]
8210 name = nil
8211 pkg = shell_out!("/opt/local/bin/pkgin", "se", new_resource.package_name, env: nil, returns: [0, 1])
8212 name, version = line.split(/[; ]/)[0].split(/-([^-]+)$/)
8213 package = "#{name}-#{version}"
8214 out = shell_out!("/opt/local/bin/pkgin", "-y", "install", package, env: nil)
8215 out = shell_out!("/opt/local/bin/pkgin", "-y", "remove", package, env: nil)
8216 if rubygems_version >= Gem::Version.new("3.1")
8217 if defined?(Gem::Format) && Gem::Package.respond_to?(:open)
8218 rs.specs.find { |s| s.name == gem_dependency.name }
8219 source_list = sources.compact.empty? ? "[#{Gem.sources.to_a.join(", ")}]" : "[#{sources.join(", ")}]"
8220 def uninstall(gem_name, gem_version = nil, opts = {})
8221 gem_version ? opts[:version] = gem_version : opts[:all] = true
8222 JRUBY_PLATFORM = /(:?universal|x86_64|x86)\-java\-[0-9\.]+/.freeze
8223 @gempath_cache ||= {}
8224 @platform_cache ||= {}
8225 @source_index ||= Gem::SourceIndex.from_gems_in(*gem_paths.map { |p| p + "/specifications" })
8226 ["ruby", Gem::Platform.new(jruby)]
8227 msg << "in #{new_resource} from #{new_resource.source_line}"
8228 msg = [
8229 logger.trace("#{new_resource} using gem '#{gem_location}'")
8230 scheme = nil if /^[a-z]$/.match?(scheme)
8231 srcs = [ new_resource.source ]
8232 src = []
8233 if new_resource.source.is_a?(String) && new_resource.source =~ /\.gem$/i
8234 src << "--clear-sources" if clear_sources?
8235 src += gem_sources.map { |s| "--source=#{s}" }
8236 src_str = src.empty? ? "" : " #{src.join(" ")}"
8237 if !version.nil? && !version.empty?
8238 shell_out!("#{gem_binary_path} install #{name} -q #{rdoc_string} -v \"#{version}\"#{src_str}#{opts}", env: nil)
8239 shell_out!("#{gem_binary_path} install \"#{name}\" -q #{rdoc_string} #{src_str}#{opts}", env: nil)
8240 shell_out!("#{gem_binary_path} uninstall #{name} -q -x -I -v \"#{version}\"#{opts}", env: nil)
8241 shell_out!("#{gem_binary_path} uninstall #{name} -q -x -I -a#{opts}", env: nil)
8242 a.assertion { !@rpm_status.nil? && (@rpm_status.exitstatus == 0 || @rpm_status.exitstatus == 1) }
8243 shell_out!("rpm", "-qp", "--queryformat", "%{NAME} %{VERSION}-%{RELEASE}
", new_resource.source).stdout.each_line do |line|
8244 when /^(\S+)\s(\S+)$/
8245 @rpm_status = shell_out("rpm", "-q", "--queryformat", "%{NAME} %{VERSION}-%{RELEASE}
", current_resource.package_name)
8246 logger.trace("#{new_resource} current version is #{$2}")
8247 shell_out!("rpm", options, "-U", "--oldpackage", new_resource.source)
8248 shell_out!("rpm", options, "-U", new_resource.source)
8249 shell_out!("rpm", options, "-i", new_resource.source)
8250 shell_out!("rpm", options, "-e", "#{name}-#{version}")
8251 shell_out!("rpm", options, "-e", name)
8252 version = "0"
8253 versions = []
8254 version_list = []
8255 command.unshift("(")
8256 command.join(" ")
8257 possibilities = Dir["/var/db/pkg/#{globsafe_category || "*"}/#{globsafe_pkg}-*"].map { |d| d.sub(%r{/var/db/pkg/}, "") }
8258 if entry =~ %r{[^/]+/#{Regexp.escape(pkg)}\-(\d[\.\d]*[a-z]?((_(alpha|beta|pre|rc|p)\d*)*)?(-r\d+)?)}
8259 [$&, $1]
8260 categories = atoms.map { |v| v.split("/")[0] }.uniq
8261 logger.trace("#{new_resource} current version #{$1}")
8262 if /-r\d+$/.match?(pkginfo.stdout)
8263 @candidate_version = pkginfo.stdout.split(/(?<=-)/).last(2).join
8264 pkg = "=#{name}-#{version}"
8265 if version =~ /^\~(.+)/
8266 pkg = "~#{name}-#{$1}"
8267 shell_out!( "emerge", "-g", "--color", "n", "--nospinner", "--quiet", options, pkg )
8268 shell_out!( "emerge", "--unmerge", "--color", "n", "--nospinner", "--quiet", options, pkg )
8269 re = Regexp.new("(.*)[[:blank:]](.*)[[:blank:]](.*)$")
8270 res = re.match(line)
8271 shell_out!("cave", "-L", "warning", "resolve", "-x", options, pkg)
8272 shell_out!("cave", "-L", "warning", "uninstall", "-x", options, pkg)
8273 if ::File.exist?("/etc/pacman.conf")
8274 pacman = ::File.read("/etc/pacman.conf")
8275 repos = pacman.scan(/\[(.+)\]/).flatten
8276 status = shell_out("pacman", "-Sl")
8277 @candidate_version = []
8278 shell_out!("pacman", "--sync", "--noconfirm", "--noprogressbar", options, *name)
8279 shell_out!("pacman", "--remove", "--noconfirm", "--noprogressbar", options, *name)
8280 if /^(.+?)--(.+)/.match?(new_resource.package_name)
8281 if parts = name.match(/^(.+?)--(.+)/) # use double-dash for stems with flavors, see man page for pkg_add
8282 name = parts[1]
8283 shell_out!("pkg_add", "-r", package_string(name, version), env: { "PKG_PATH" => pkg_path }).status
8284 if parts = name.match(/^(.+?)--(.+)/)
8285 name = if parts = new_resource.package_name.match(/^(.+?)--(.+)/)
8286 pkg_info = shell_out!("pkg_info", "-e", "#{name}->0", env: nil, returns: [0, 1])
8287 result = pkg_info.stdout[/^inst:#{Regexp.escape(name)}-(.+?)\s/, 1]
8288 results << if parts = new_resource.package_name.match(/^(.+?)--(.+)/)
8289 line[/^#{Regexp.escape(parts[1])}-(.+?)\s/, 1]
8290 line[/^#{Regexp.escape(new_resource.package_name)}-(.+?)\s/, 1]
8291 ENV["PKG_PATH"] || "http://ftp.OpenBSD.org/pub/#{node["kernel"]["name"]}/#{node["kernel"]["release"]}/packages/#{node["kernel"]["machine"]}/"
8292 shell_out!("#{ENV["SYSTEMROOT"]}\\system32\\expand.exe -f:* #{msu_file} #{destination}")
8293 xml_files = Dir.glob("#{msu_dir}/*.xml")
8294 cab_files = []
8295 doc = ::File.open(xml_files.first.to_s) { |f| REXML::Document.new f }
8296 cab_files << msu_dir + "/" + loc.attribute("location").value.split("\\")[1]
8297 command = [ "port", "installed", new_resource.package_name ]
8298 match = line.match(/^.+ @([^\s]+) \(active\)$/)
8299 command = [ "port", "info", "--version", new_resource.package_name ]
8300 match = output.match(/^version: (.+)$/)
8301 match ? match[1] : nil
8302 command = [ "port", options, "install", name ]
8303 command << "@#{version}" if version && !version.empty?
8304 command = [ "port", options, "uninstall", name ]
8305 command = [ "port", options, "deactivate", name ]
8306 shell_out!( "port", options, "upgrade", name, "@#{version}" )
8307 return $1.split[0] if line =~ /^\s+Version: (.*)/
8308 shell_out!("pkg", "info", "-r", new_resource.package_name).stdout.each_line do |line|
8309 return $1.split[0] if line =~ /Version: (.*)/
8310 command = [ "pkg", options, "install", "-q" ]
8311 command << "#{name}@#{version}"
8312 package_name = "#{name}@#{version}"
8313 shell_out!( "pkg", options, "uninstall", "-q", package_name )
8314 @brew_info ||= begin
8315 command_array = ["info", "--json=v1"].concat package_name_array
8316 hsh[package_name] = {}
8317 hsh[json["name"]] = json
8318 Hash[Chef::JSONCompat.from_json(cmd_output).collect { |pkg| [pkg["name"], pkg] }]
8319 return p if p["full_name"] == package_name || p["aliases"].include?(package_name)
8320 if p_data["keg_only"]
8321 p_data["linked_keg"]
8322 p_data["versions"]["stable"]
8323 logger.trace "Executing 'brew #{command.join(" ")}' as user '#{homebrew_user.name}'"
8324 shell_out_cmd = options[:allow_failure] ? :shell_out : :shell_out!
8325 output = send(shell_out_cmd, "brew", *command, timeout: 1800, user: homebrew_uid, environment: { "HOME" => homebrew_user.dir, "RUBYOPT" => nil, "TMPDIR" => nil })
8326 opts = ["pkg", "install", "--channel", new_resource.channel, "--url", new_resource.bldr_url]
8327 opts += ["#{strip_version(n)}/#{v}", new_resource.options]
8328 opts += ["--binlink"] if new_resource.binlink
8329 opts += ["--force"] if new_resource.binlink.eql? :force
8330 opts += ["#{strip_version(n).chomp("/")}#{v}", new_resource.options]
8331 opts += ["--exclude"] if new_resource.exclude
8332 opts += ["--no-deps"] if new_resource.no_deps
8333 n = name.squeeze("/").chomp("/").sub(%r{^\/}, "")
8334 n = n[0..(n.rindex("/") - 1)] while n.count("/") >= 2
8335 elsif node["kernel"]["release"].to_i < 3
8336 @depot_package ||= {}
8337 @depot_package[name] ||=
8338 origin, pkg_name = name.split("/")
8339 name_version = [pkg_name, version].compact.join("/").squeeze("/").chomp("/").sub(%r{^\/}, "")
8340 url = if new_resource.bldr_url.include?("/v1/")
8341 url << "/latest" unless name_version.count("/") >= 2
8342 @http ||= Chef::HTTP::Simple.new(new_resource.bldr_url.to_s)
8343 hab("pkg", "path", ident).stdout.chomp.split(windows? ? "\\" : "/")[-2..-1].join("/")
8344 nv_parts = new_version.squeeze("/").split("/")
8345 current_version.squeeze("/").split("/")[0] == new_version.squeeze("/")
8346 hab_v1 = Mixlib::Versioning.parse(v1.tr("/", "+"))
8347 hab_v2 = Mixlib::Versioning.parse(v2.tr("/", "+"))
8348 hab_v1 <=> hab_v2
8349 shell_out!("make", "-DBATCH", "install", "clean", timeout: 1800, env: nil, cwd: port_dir).status
8350 shell_out!("make", "deinstall", timeout: 300, env: nil, cwd: port_dir).status
8351 pkg_info = shell_out!("pkg", "info", new_resource.package_name, env: nil, returns: [0, 70])
8352 pkg_info.stdout[/^#{Regexp.escape(new_resource.package_name)}-(.+)/, 1]
8353 when %r{^(http|ftp|/)}
8354 shell_out!("pkg", "add", options, new_resource.source, env: { "LC_ALL" => nil }).status
8355 shell_out!("pkg", "install", "-y", options, name, env: { "LC_ALL" => nil }).status
8356 options_dup = options && options.map { |str| str.sub(repo_regex, "") }.reject!(&:empty?)
8357 shell_out!("pkg", "delete", "-y", options_dup, "#{name}#{version ? "-" + version : ""}", env: nil).status
8358 pkg_info = shell_out!("pkg", "info", new_resource.package_name, env: nil, returns: [0, 1, 70])
8359 pkg_info.stdout[/^Version +: (.+)$/, 1]
8360 new_resource.source[/#{Regexp.escape(new_resource.package_name)}-(.+)\.txz/, 1]
8361 if options && options.join(" ").match(repo_regex)
8362 options = $1.split(" ")
8363 pkg_query = shell_out!("pkg", "rquery", options, "%v", new_resource.package_name, env: nil)
8364 pkg_query.exitstatus == 0 ? pkg_query.stdout.strip.split('
').last : nil
8365 /(-r\s?\S+)\b/
8366 require_relative "../../../resource/package"
8367 ::File.exist?("/usr/ports/Makefile")
8368 when %r{^/}
8369 when %r{/}
8370 whereis = shell_out!("whereis", "-s", port, env: nil)
8371 unless path = whereis.stdout[/^#{Regexp.escape(port)}:\s+(.+)$/, 1]
8372 options = dir ? { cwd: dir } : {}
8373 options[:env] = nil
8374 options[:returns] = [0, 1]
8375 make_v = shell_out!("make", "-V", variable, **options)
8376 sources = name.map { |n| name_sources[n] }
8377 logger.info("#{new_resource} installing package(s): #{name.join(" ")}")
8378 run_noninteractive("dpkg", "-i", *options, *sources)
8379 logger.info("#{new_resource} removing package(s): #{name.join(" ")}")
8380 run_noninteractive("dpkg", "-r", *options, *name)
8381 logger.info("#{new_resource} purging packages(s): #{name.join(" ")}")
8382 run_noninteractive("dpkg", "-P", *options, *name)
8383 if !shell_out("dpkg", "--compare-versions", v1.to_s, "gt", v2.to_s).error?
8384 elsif !shell_out("dpkg", "--compare-versions", v1.to_s, "eq", v2.to_s).error?
8385 status = shell_out!("dpkg", "-s", package_name, returns: [0, 1])
8386 logger.trace("#{new_resource} current version is #{$1}")
8387 @name_pkginfo ||=
8388 status = shell_out!("dpkg-deb", "-W", src)
8389 @name_candidate_version ||= name_pkginfo.transform_values { |v| v ? v.split("\t")[1]&.strip : nil }
8390 @name_package_name ||= name_pkginfo.transform_values { |v| v ? v.split("\t")[0] : nil }
8391 DNF_HELPER = ::File.expand_path(::File.join(::File.dirname(__FILE__), "dnf_helper.py")).freeze
8392 @dnf_command ||= begin
8393 cmd = which("platform-python", "python", "python3", "python2", "python2.7", extra_path: "/usr/libexec") do |f|
8394 shell_out("#{f} -c 'import dnf'").exitstatus == 0
8395 parameters = { "provides" => provides, "version" => version, "arch" => arch }
8396 if version =~ /(\S+):(\S+)/
8397 epoch = $1
8398 version = $2
8399 if version =~ /(\S+)-(\S+)/
8400 version = $1
8401 release = $2
8402 dnf(options, "-y", "install", new_resource.source)
8403 dnf(options, "-y", "install", resolved_names)
8404 dnf(options, "-y", "remove", resolved_names)
8405 dnf("-d0", "-e0", "-y", options, "versionlock", "add", resolved_package_lock_names(names))
8406 dnf("-d0", "-e0", "-y", options, "versionlock", "delete", resolved_package_lock_names(names).map { |n| "*:#{n}-*" })
8407 locked = dnf("versionlock", "list")
8408 shell_out!("dnf", *args)
8409 cache_seed_to = "#{file_cache_dir}/#{name}-#{version}.seed"
8410 name_nil_versions = name_versions_to_install.select { |n, v| v.nil? }
8411 choco_command("install", "-y", "--version", version, cmd_args, name)
8412 choco_command("install", "-y", cmd_args, *cmd_names)
8413 choco_command("upgrade", "-y", "--version", version, cmd_args, name)
8414 choco_command("upgrade", "-y", cmd_args, *cmd_names)
8415 @choco_exe ||= begin
8416 exe_path = ::File.join(choco_install_path, "bin", "choco.exe")
8417 result = "" if result.empty?
8418 cmd = [ "list", "-r", pkg ]
8419 @installed_packages ||= Hash[*parse_list_output("list", "-l", "-r").flatten]
8420 hash = {}
8421 name, version = line.split("|")
8422 args = []
8423 args.push( [ "--user", new_resource.user ] ) if new_resource.user
8424 packages = []
8425 key, value = line.split(":") if line.start_with?("Package Identity")
8426 next if key.nil? || value.nil?
8427 package = {}
8428 package[key.downcase.strip.tr(" ", "_")] = value.strip.chomp
8429 package_data = {}
8430 errors = []
8431 if line =~ /Error: (.*)/
8432 errors << $1.strip
8433 elsif section_headers.any? { |header| line =~ /^(#{header})/ }
8434 in_section = $1.downcase.tr(" ", "_")
8435 elsif line =~ /(.*) ?: (.*)/
8436 k = $1.downcase.strip.tr(" ", "_")
8437 package_data[k] = v
8438 data["name"], data["publisher"], data["arch"], data["resource_id"], data["version"] = identity.split("~")
8439 @packages ||= begin
8440 ret = shell_out("installp", "-L", "-d", new_resource.source)
8441 fields = line.split(":")
8442 unless ret.exitstatus == 0 || ret.exitstatus == 1
8443 when /\w:#{Regexp.escape(new_resource.package_name)}:(.*)/
8444 shell_out!("installp", "-u", name)
8445 shell_out!("installp", "-u", options, name)
8446 @package_data ||= Hash.new do |hash, key|
8447 locked = shell_out!("apt-mark", "showhold")
8448 package_name = name.zip(version).map do |n, v|
8449 package_data[n][:virtual] ? n : "#{n}=#{v}"
8450 package_name = name.map do |n|
8451 run_noninteractive("apt-get", "-q", "-y", options, "remove", package_name)
8452 run_noninteractive("apt-get", "-q", "-y", options, "purge", package_name)
8453 @apt_version ||= shell_out("apt-get --version").stdout.match(/^apt (\S+)/)[1]
8454 @supports_allow_downgrade = ( version_compare(apt_version, "1.1.0") >= 0 )
8455 [ "-o", "APT::Default-Release=#{new_resource.default_release}" ]
8456 return if Array(options).any? { |opt| opt.include?("--force-conf") }
8457 [ "-o", "Dpkg::Options::=--force-confnew" ]
8458 [ "-o", "Dpkg::Options::=--force-confdef", "-o", "Dpkg::Options::=--force-confold" ]
8459 all_versions = []
8460 when /^\s{2}Installed: (.+)$/
8461 current_version = ( $1 != "(none)" ) ? $1 : nil
8462 logger.trace("#{new_resource} installed version for #{pkg} is #{$1}")
8463 when /^\s{2}Candidate: (.+)$/
8464 candidate_version = ( $1 != "(none)" ) ? $1 : nil
8465 logger.trace("#{new_resource} candidate version for #{pkg} is #{$1}")
8466 when /\s+(?:\*\*\* )?(\S+) \d+/
8467 all_versions << $1
8468 return nil if partitions[0] == "" && partitions[1] == "" # not found in output
8469 if set.size > 1
8470 f = []
8471 f << (item == current_version_array[index])
8472 f.any?
8473 v1 == v2
8474 missing = []
8475 @new_version_array ||= [ new_resource.version ].flatten.map { |v| v.to_s.empty? ? nil : v }
8476 @source_array ||=
8477 if use_package_name_for_source? && source.nil? && package_name.match(/#{::File::SEPARATOR}/) && ::File.exist?(package_name)
8478 method_sym.to_s.start_with?("action_") || super
8479 if /^action_/.match?(method_sym.to_s)
8480 /^\\\\\?\\Volume\{[\w-]+\}\\$/.match?(name) ? true : false
8481 @mount = nil
8482 a.assertion { !device_should_exist? || ::File.exist?(device) }
8483 unless fsck_device == "-"
8484 a.assertion { ::File.exist?(fsck_device) }
8485 a.assertion { ::File.exist?(mount_point) }
8486 command = [ "mount", "-F", fstype ]
8487 command << "-o"
8488 command << actual_options.join(",")
8489 command << [ device, mount_point ]
8490 mount_options = actual_options.empty? ? "" : ",#{actual_options.join(",")}"
8491 shell_out!("mount", "-o", "remount#{mount_options}", mount_point)
8492 shell_out!("mount", "-v").stdout.each_line do |line|
8493 when /^#{device_regex}\s+on\s+#{Regexp.escape(mount_point)}\s+/
8494 when %r{^([/\w]+)\son\s#{Regexp.escape(mount_point)}\s+}
8495 when /^[#\s]/
8496 when %r{^#{device_regex}\s+[-/\w]+\s+#{Regexp.escape(mount_point)}\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)}
8497 if Regexp.last_match[3] == "no"
8498 options += ",noauto"
8499 pass = (Regexp.last_match[2] == "-") ? 0 : Regexp.last_match[2].to_i
8500 logger.trace("Found mount #{device} to #{mount_point} in #{VFSTAB}")
8501 when %r{^[-/\w]+\s+[-/\w]+\s+#{Regexp.escape(mount_point)}\s+}
8502 options.nil? || !options.include?("noauto")
8503 f.write(contents.join(""))
8504 autostr = mount_at_boot? ? "yes" : "no"
8505 passstr = pass == 0 ? "-" : pass
8506 optstr = (actual_options.nil? || actual_options.empty?) ? "-" : actual_options.join(",")
8507 contents = []
8508 if !found && line =~ /^#{device_regex}\s+\S+\s+#{Regexp.escape(mount_point)}/
8509 ["-"]
8510 new_options = []
8511 new_options += temp_options.nil? ? [] : temp_options.dup
8512 unless ::File.exist?("/etc/fstab")
8513 ::File.foreach("/etc/fstab") do |line|
8514 when /^(#{device_fstab_regex})\s+#{Regexp.escape(@new_resource.mount_point)}\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)/
8515 when /^#{device_mount_regex}\s+on\s+#{Regexp.escape(real_mount_point)}\s/
8516 when %r{^([/\w])+\son\s#{Regexp.escape(real_mount_point)}\s+}
8517 logger.trace("Special device #{$~[1]} mounted as #{real_mount_point}")
8518 command = [ "mount", "-t", @new_resource.fstype ]
8519 command << @new_resource.options.join(",")
8520 [ "-L", @new_resource.device ]
8521 [ "-U", @new_resource.device ]
8522 [ "mount", "-o", "remount,#{@new_resource.options.join(",")}", @new_resource.mount_point ]
8523 linux? ? "defaults" : "rw"
8524 ::File.open("/etc/fstab", "a") do |fstab|
8525 @new_resource.device.include?(":") || @new_resource.device.include?("//")
8526 ( @new_resource.device != "none" ) &&
8527 ( not network_device? ) &&
8528 @real_device = ""
8529 (@real_device == "/" || @real_device.match?(":/$")) ? @real_device : @real_device.chomp("/")
8530 device_mount_regex.gsub(" ", "\\x20")
8531 Regexp.escape(device_real) + "/?"
8532 if !found && line =~ /^#{device_fstab_regex}\s+#{Regexp.escape(@new_resource.mount_point)}\s/
8533 ::File.open("/etc/fstab", "w") do |fstab|
8534 @loop_mount_points ||= shell_out!("losetup -a").stdout
8535 @loop_mount_points = ""
8536 when %r{\A#{Regexp.escape(real_mount_point)}\s+\/dev\/loop+[0-9]+\s}
8537 when %r{\A#{Regexp.escape(real_mount_point)}\s+([/\w])+\s}
8538 when %r{\A#{Regexp.escape(real_mount_point)}\s+([/\w])+\[#{device_mount_regex}\]\s}
8539 when /\A#{Regexp.escape(real_mount_point)}\s+#{device_mount_regex}\[/
8540 if @new_resource.fstype == "auto"
8541 if regex_arr.size == 2
8542 when /^#\s/
8543 when /^#{Regexp.escape(@new_resource.mount_point)}:#{devicename}:(\S+):#{nodename}:(\S+)?:(\S+):(\S+):(\S+):(\S+)/
8544 when /^#{Regexp.escape(@new_resource.mount_point)}:#{nodename}:(\S+)::(\S+)?:(\S+):(\S+):(\S+):(\S+)/
8545 when /^#{Regexp.escape(@new_resource.mount_point)}:(\S+)?:(\S+):#{devicename}:(\S+)?:(\S+):(\S+):(\S+):(\S+)/
8546 if $3.split("=")[0] == "LABEL" || $1.split("=")[0] == "LABEL"
8547 elsif $3.split("=")[0] == "UUID" || $1.split("=")[0] == "UUID"
8548 when %r{^[/\w]+\s+#{Regexp.escape(@new_resource.mount_point)}\s+}
8549 command = [ "mount", "-v", @new_resource.fstype ]
8550 [ "mount", "-o", "remount,#{@new_resource.options.join(",")}", @new_resource.device, @new_resource.mount_point ]
8551 [ "mount", "-o", "remount", @new_resource.device, @new_resource.mount_point ]
8552 ::File.open("/etc/filesystems", "a") do |fstab|
8553 fstab.puts("

#{@new_resource.mount_point}:")
8554 fstab.puts("\tdev\t\t= #{device_details[1]}")
8555 fstab.puts("\tnodename\t\t= #{device_details[0]}")
8556 fstab.puts("\tdev\t\t= #{device_fstab}")
8557 fstab.puts("\tvfs\t\t= #{@new_resource.fstype}")
8558 fstab.puts("\tmount\t\t= false")
8559 current_resource_options = @current_resource.options.delete_if { |x| x == "rw" }
8560 ::File.open("/etc/filesystems", "r").each_line do |line|
8561 when %r{^/.+:\s*$}
8562 if /#{Regexp.escape(@new_resource.mount_point)}+:/.match?(line)
8563 ::File.open("/etc/filesystems", "w") do |fstab|
8564 if (tries -= 1) < 0
8565 if @new_resource.device == "/" || @new_resource.device.match?(":/$")
8566 if ::File.exist?(new_resource.to) &&
8567 (current_resource.link_type == :symbolic || current_resource.to != "")
8568 types = {
8569 if ::File.exists?(path)
8570 only_if { manage_agent?(action) }
8571 root = console_user == "root"
8572 agent = type == "agent"
8573 lltstype = ""
8574 if root && agent && invalid_action && invalid_type
8575 ) do |a|
8576 a.assertion { %w{daemon agent}.include?(type.to_s) }
8577 }.each_with_object({}) do |(key, val), memo|
8578 @path ||= new_resource.path || gen_path_from_type
8579 @config_template = %{
8580 <% if new_resource.device -%>
8581 DEVICE=<%= new_resource.device %>
8582 <% end -%>
8583 <% if new_resource.onboot == "yes" -%>
8584 ONBOOT=<%= new_resource.onboot %>
8585 <% if new_resource.bootproto -%>
8586 <% if new_resource.target -%>
8587 IPADDR=<%= new_resource.target %>
8588 <% if new_resource.mask -%>
8589 <% if new_resource.network -%>
8590 <% if new_resource.bcast -%>
8591 <% if new_resource.onparent -%>
8592 <% if new_resource.hwaddr -%>
8593 HWADDR=<%= new_resource.hwaddr %>
8594 <% if new_resource.metric -%>
8595 METRIC=<%= new_resource.metric %>
8596 <% if new_resource.mtu -%>
8597 MTU=<%= new_resource.mtu %>
8598 <% if new_resource.ethtool_opts -%>
8599 <% if new_resource.bonding_opts -%>
8600 <% if new_resource.master -%>
8601 MASTER=<%= new_resource.master %>
8602 <% if new_resource.slave -%>
8603 SLAVE=<%= new_resource.slave %>
8604 <% if new_resource.vlan -%>
8605 VLAN=<%= new_resource.vlan %>
8606 <% if new_resource.gateway -%>
8607 <% if new_resource.bridge -%>
8608 BRIDGE=<%= new_resource.bridge %>
8609 auto <%= new_resource.device %>
8610 when "dhcp" -%>
8611 iface <%= new_resource.device %> <%= new_resource.family %> dhcp
8612 <% when "bootp" -%>
8613 iface <%= new_resource.device %> <%= new_resource.family %> bootp
8614 <% else -%>
8615 iface <%= new_resource.device %> <%= new_resource.family %> static
8616 netmask <%= new_resource.mask %>
8617 metric <%= new_resource.metric %>
8618 mtu <%= new_resource.mtu %>
8619 interfaces_dot_d_for_regexp = INTERFACES_DOT_D_DIR.gsub(/\./, "\\.") # escape dots for the regexp
8620 regexp = %r{^\s*source\s+#{interfaces_dot_d_for_regexp}/\*\s*$}
8621 interface = {}
8622 @status = shell_out("ifconfig", "-a")
8623 if line =~ /^(\S+):\sflags=(\S+)/
8624 elsif line =~ /^(\S+):\sflags=(\S+)/
8625 current_resource.inet_addr(Regexp.last_match(1)) if line =~ /inet\s(\S+)\s/
8626 command = [ "chdev", "-l", new_resource.device, "-a", "netaddr=#{new_resource.name}" ]
8627 command += [ "-a", "netmask=#{new_resource.mask}" ] if new_resource.mask
8628 command += [ "-a", "mtu=#{new_resource.mtu}" ] if new_resource.mtu
8629 [ "chdev", "-l", new_resource.device, "-a", "state=down" ]
8630 dec = netmask[2..3].to_i(16).to_s(10)
8631 [4, 6, 8].each { |n| dec = dec + "." + netmask[n..n + 1].to_i(16).to_s(10) }
8632 autoload :ERB, "erb"
8633 @interfaces = {}
8634 @net_tools_version = shell_out("ifconfig", "--version")
8635 if /^net-tools (\d+\.\d+)/.match?(line)
8636 @ifconfig_version = line.match(/^net-tools (\d+\.\d+)/)[1]
8637 if !line[0..9].strip.empty?
8638 @int_name = line[0..9].strip
8639 @interfaces[@int_name] = { "hwaddr" => (line =~ /(HWaddr)/ ? ($') : "nil").strip.chomp }
8640 @interfaces[@int_name]["inet_addr"] = (line =~ /inet addr:(\S+)/ ? Regexp.last_match(1) : "nil") if /inet addr:/.match?(line)
8641 @interfaces[@int_name]["bcast"] = (line =~ /Bcast:(\S+)/ ? Regexp.last_match(1) : "nil") if /Bcast:/.match?(line)
8642 @interfaces[@int_name]["mask"] = (line =~ /Mask:(\S+)/ ? Regexp.last_match(1) : "nil") if /Mask:/.match?(line)
8643 @interfaces[@int_name]["mtu"] = (line =~ /MTU:(\S+)/ ? Regexp.last_match(1) : "nil") if /MTU:/.match?(line)
8644 @interfaces[@int_name]["metric"] = (line =~ /Metric:(\S+)/ ? Regexp.last_match(1) : "nil") if /Metric:/.match?(line)
8645 addr_regex = /^((\w|-)+):?(\d*):?\ .+$/
8646 @int_name = "nil"
8647 elsif line.match(addr_regex)[3] == ""
8648 @interfaces[@int_name] = {}
8649 @interfaces[@int_name]["mtu"] = (line =~ /mtu (\S+)/ ? Regexp.last_match(1) : "nil") if line.include?("mtu") && @interfaces[@int_name]["mtu"].nil?
8650 @int_name = "#{line.match(addr_regex)[1]}:#{line.match(addr_regex)[3]}"
8651 @interfaces[@int_name]["bcast"] = (line =~ /broadcast (\S+)/ ? Regexp.last_match(1) : "nil") if line.include?("broadcast") && @interfaces[@int_name]["bcast"].nil?
8652 @interfaces[@int_name]["mask"] = (line =~ /netmask (\S+)/ ? Regexp.last_match(1) : "nil") if line.include?("netmask") && @interfaces[@int_name]["mask"].nil?
8653 @interfaces[@int_name]["hwaddr"] = (line =~ /ether (\S+)/ ? Regexp.last_match(1) : "nil") if line.include?("ether") && @interfaces[@int_name]["hwaddr"].nil?
8654 a.assertion { @status.exitstatus == 0 }
8655 converge_by("run #{command.join(" ")} to add #{new_resource}") do
8656 converge_by("run #{command.join(" ")} to enable #{new_resource}") do
8657 converge_by("run #{command.join(" ")} to delete #{new_resource}") do
8658 converge_by("run #{command.join(" ")} to disable #{new_resource}") do
8659 !@config_template.nil? && !@config_path.nil?
8660 template = ::ERB.new(@config_template, nil, "-")
8661 command += [ "mtu", new_resource.mtu ] if new_resource.mtu
8662 [ "ifconfig", new_resource.device, "down" ]
8663 @http ||= Chef::HTTP::Simple.new(new_resource.url)
8664 converge_by("#{new_resource} GET to #{new_resource.url}") do
8665 body = http.get(
8666 converge_by("#{new_resource} PUT to #{new_resource.url}") do
8667 body = http.put(
8668 members_to_be_added = [ ]
8669 members_to_be_removed = [ ]
8670 account_name.include?("\\") ? account_name : "#{ENV["COMPUTERNAME"]}\\#{account_name}"
8671 a.assertion { ::File.exist?("/usr/sbin/usermod") }
8672 a.assertion { ::File.exist?("/usr/sbin/usermod") && ::File.exist?("/usr/sbin/groupmod") }
8673 shell_out!("groupmod", "-U", members.join(","), new_resource.group_name)
8674 shell_out!("usermod", "-G", "+#{new_resource.group_name}", member)
8675 shell_out!("usermod", "-G", "-#{new_resource.group_name}", member)
8676 a.assertion { ::File.exist?("/usr/sbin/pw") }
8677 command = [ "pw", "groupadd", set_options ]
8678 command += [ "-M", new_resource.members.join(",") ]
8679 shell_out!("pw", "groupmod", set_options)
8680 shell_out!("pw", "groupmod", set_options, option)
8681 opts << "-g"
8682 opts = [ ]
8683 logger.debug("#{new_resource} adding group members: #{members_to_be_added.join(",")}")
8684 opts << [ "-m", members_to_be_added.join(",") ]
8685 opts << [ "-d", members_to_be_removed.join(",") ]
8686 shell_out!("group", "add", set_options)
8687 shell_out!("user", "mod", "-G", new_resource.group_name, user)
8688 shell_out!("group", "mod", "-n", "#{new_resource.group_name}_bak", new_resource.group_name)
8689 shell_out!("group", "add", set_options(overwrite_gid: true))
8690 shell_out!("group", "del", "#{new_resource.group_name}_bak")
8691 opts << "-o"
8692 [ "/usr/sbin/groupadd",
8693 { gid: "-g" }.sort_by { |a| a[0] }.each do |field, option|
8694 logger.trace("#{new_resource} set #{field} to #{new_resource.send(field)}")
8695 opts << "-r" if new_resource.system && !node.platform?("solaris2")
8696 a.assertion { ::File.exist?("/usr/bin/gpasswd") }
8697 shell_out!("gpasswd", "-M", "", new_resource.group_name)
8698 shell_out!("gpasswd", "-M", members.join(","), new_resource.group_name)
8699 shell_out!("gpasswd", "-a", member, new_resource.group_name)
8700 shell_out!("gpasswd", "-d", member, new_resource.group_name)
8701 shellcmd = [ "dscl", ".", "-#{cmd}", argdup ]
8702 stdout_result = ""
8703 stderr_result = ""
8704 result = dscl(*args)
8705 return "" if ( args.first =~ /^delete/ ) && ( result[1].exitstatus != 0 )
8706 raise(Chef::Exceptions::Group, "dscl error: #{result.inspect}") if /No such key: /.match?(result[2])
8707 group_info = safe_dscl("read", "/Groups/#{new_resource.group_name}")
8708 key, val = line.split(": ")
8709 gid = nil; next_gid_guess = 200
8710 groups_gids = safe_dscl("list", "/Groups", "gid")
8711 next_gid_guess += 1
8712 search_gids = safe_dscl("search", "/Groups", "PrimaryGroupID", gid.to_s)
8713 !!(search_gids =~ /\b#{gid}\b/)
8714 safe_dscl("create", "/Groups/#{new_resource.group_name}", "GroupMembers", "") # clear guid list
8715 safe_dscl("create", "/Groups/#{new_resource.group_name}", "GroupMembership", "") # clear user list
8716 safe_dscl("create", "/Groups/#{new_resource.group_name}", "Password", "*")
8717 [ "/usr/bin/mkgroup",
8718 shell_out!("chgrpmem", "-m", "+", member, new_resource.group_name)
8719 shell_out!("chgrpmem", "-m", "=", members.join(","), new_resource.group_name)
8720 shell_out!("chgrpmem", "-m", "-", member, new_resource.group_name)
8721 { gid: "id" }.sort_by { |a| a[0] }.each do |field, option|
8722 opts << "#{option}=#{new_resource.send(field)}"
8723 @change_desc = [ ]
8724 missing_members = []
8725 @change_desc << "add missing member(s): #{missing_members.join(", ")}"
8726 members_to_be_removed = []
8727 @change_desc << "remove existing member(s): #{members_to_be_removed.join(", ")}"
8728 logger.info("#{new_resource} altered: #{change_desc.join(", ")}")
8729 a.assertion { !(new_resource.revision =~ %r{^origin/}) }
8730 FileUtils.rm_rf(::File.join(cwd, ".git"))
8731 @git_has_single_branch_option ||= !git_gem_version.nil? && git_gem_version >= Gem::Version.new("1.7.10")
8732 output = git("--version").stdout
8733 ::File.exist?(::File.join(cwd, ".git"))
8734 !::File.exist?(cwd) || Dir.entries(cwd).sort == [".", ".."]
8735 if ::File.exist?(::File.join(cwd, ".git"))
8736 result = git("rev-parse", "HEAD", cwd: cwd, returns: [0, 128]).stdout.strip
8737 sha_hash?(result) ? result : nil
8738 current_branch = git("rev-parse", "--abbrev-ref", "HEAD", cwd: cwd, returns: [0, 128]).stdout.strip
8739 converge_by("clone from #{repo_url} into #{cwd}") do
8740 clone_cmd = ["clone"]
8741 clone_cmd << "-o #{remote}" unless remote == "origin"
8742 clone_cmd << "\"#{new_resource.repository}\""
8743 clone_cmd << "\"#{cwd}\""
8744 logger.info "#{new_resource} cloning repo #{repo_url} to #{cwd}"
8745 git("reset", "--hard", target_revision, cwd: cwd)
8746 git("branch", "-u", "#{new_resource.remote}/#{new_resource.revision}", cwd: cwd)
8747 git("submodule", "sync", cwd: cwd)
8748 git("submodule", "update", "--init", "--recursive", cwd: cwd)
8749 git("fetch", "--prune", new_resource.remote, cwd: cwd)
8750 git("fetch", new_resource.remote, "--tags", cwd: cwd)
8751 check_remote_command = ["config", "--get", "remote.#{remote_name}.url"]
8752 remote_status = git(check_remote_command, cwd: cwd, returns: [0, 1, 2])
8753 when 0, 2
8754 git("config", "--replace-all", "remote.#{remote_name}.url", %{"#{remote_url}"}, cwd: cwd)
8755 git("remote", "add", remote_name, remote_url, cwd: cwd)
8756 @target_revision ||=
8757 refs = @resolved_reference.split("
").map { |line| line.split("\t") }
8758 found = refs_search(refs, "HEAD")
8759 found.size == 1 ? found.first[0] : nil
8760 @is_tag = true
8761 if ["", "HEAD"].include? new_resource.revision
8762 git("ls-remote", "\"#{new_resource.repository}\"", "\"#{rev_pattern}\"").stdout
8763 refs.find_all { |m| m[1] == pattern }
8764 !!@is_branch
8765 !!@is_tag
8766 def git(*args, **run_opts)
8767 git_command = ["git", args].compact.join(" ")
8768 string =~ /^[0-9a-f]{40}$/
8769 a.assertion { error.nil? }
8770 if !l_exist?(path)
8771 [nil, nil, nil]
8772 @content ||= begin
8773 when ::File.pipe?(path)
8774 !file_class.symlink?(path) && ::File.file?(path)
8775 ::File.exist?(path) || file_class.symlink?(path)
8776 @diff ||= Chef::Util::Diff.new
8777 if creates && creates_relative? && !cwd
8778 if (logger.info? || live_stream?) && !sensitive?
8779 ( cwd && creates_relative? ) ? ::File.join(cwd, creates) : creates
8780 @operations = {
8781 end }
8782 err = [
8783 cwd = @dsc_resource.cwd || Dir.pwd
8784 cleaned_messages = resource.change_log[0..-2].map { |c| c.sub(/^#{Regexp.escape(resource.name)}/, "").strip }
8785 !(!@module_name && @module_version)
8786 @module_name ||= begin
8787 if found[0]["Module"].nil?
8788 found[0]["Module"]["Name"]
8789 @converge_description << "

"
8790 @module_version.nil? ? module_name : "@{ModuleName='#{module_name}';ModuleVersion='#{@module_version}'}"
8791 switches = "-Method #{method} -Name #{new_resource.resource}"\
8792 ).tap do |r|
8793 if ::File.exist?(base_dir)
8794 require_relative "../../provider"
8795 crontab = shell_out(%w{/usr/bin/crontab -l}, user: @new_resource.user)
8796 if status > 1
8797 crontab.stdout.chomp << "
"
8798 error_message = ""
8799 provides :cron, os: "aix"
8800 newcron = "# Chef Name: #{new_resource.name}
"
8801 newcron << "#{@new_resource.minute} #{@new_resource.hour} #{@new_resource.day} #{@new_resource.month} #{@new_resource.weekday}"
8802 newcron << " #{@new_resource.command}
"
8803 @new_resource.environment.length > 0 || !@new_resource.mailto.nil? || !@new_resource.path.nil? || !@new_resource.shell.nil? || !@new_resource.home.nil?
8804 provides :cron, os: ["!aix", "!solaris2"]
8805 crontab_lines = []
8806 when "# Chef Name: #{new_resource.name}"
8807 crontab = ""
8808 newcron = ""
8809 current_resource.send(attr_name.downcase.to_sym, attr_value.gsub(/^"|"$/, ""))
8810 so = shell_out!("crontab -l -u #{new_resource.user}", returns: [0, 1])
8811 so = shell_out!("crontab -u #{new_resource.user} -", input: crontab)
8812 str = []
8813 str << "#{v.to_s.upcase}=\"#{new_resource.send(v)}\"" if new_resource.send(v)
8814 new_resource.send(name.downcase.to_sym, value.gsub(/^"|"$/, ""))
8815 str << "#{name.to_s.upcase}=\"#{value}\""
8816 str << "#{name}=#{value}"
8817 str.join("
")
8818 str = " timeout"
8819 str << " --preserve-status" if new_resource.time_out["preserve-status"].to_s.casecmp("true") == 0
8820 str << " --foreground" if new_resource.time_out["foreground"].to_s.casecmp("true") == 0
8821 str << " --kill-after #{new_resource.time_out["kill-after"]}" if new_resource.time_out["kill-after"]
8822 str << " --signal #{new_resource.time_out["signal"]}" if new_resource.time_out["signal"]
8823 str << " #{new_resource.time_out["duration"]};"
8824 newcron = []
8825 newcron << "# Chef Name: #{new_resource.name}"
8826 newcron.join("
")
8827 @action_descriptions ||= {}
8828 send("action_#{@action}")
8829 end.join(", ")
8830 modified.map! do |p|
8831 property_size = properties.map(&:name).map(&:to_sym).map(&:size).max
8832 def self.provides(short_name, opts = {}, &block)
8833 resource.class.properties.keys.map { |k| "#{k}=".to_sym } -
8834 def #{from}=(value)
8835 options = options.inject({}) { |memo, (key, value)| memo[key.to_sym] = value; memo }
8836 options = Hash[options.map { |k, v| k == :name_attribute ? [ :name_property, v ] : [ k, v ] }]
8837 obj.each { |value| visitor.call(value) }
8838 :"@#{name}"
8839 if !action.nil? && options[:required].is_a?(Array)
8840 if !value.frozen? && !value.nil?
8841 if !value.nil? || has_default?
8842 resource.validate({ name => value }, { name => validation_options })
8843 def #{name}=(value)
8844 options.key?(:coerce) ||
8845 (options.key?(:is) && Chef::Mixin::ParamsValidate.send(:_pv_is, { name => nil }, name, options[:is]))
8846 obj.each { |k, v| obj[k] = visitor.call(v) }
8847 obj.each_with_index { |v, i| obj[i] = visitor.call(v) }
8848 timeout = -1 if timeout == 0 || timeout.nil?
8849 { type: "recipe", name: r, skipped: false, version: nil }
8850 to_h.to_json(*opts)
8851 @node = nil
8852 Chef::Log.info("Run List is [#{run_list}]")
8853 Chef::Log.info("Run List expands to [#{run_list_with_versions_for_display(run_list).join(", ")}]")
8854 node.automatic_attrs[:roles] = []
8855 display = "#{cookbook}::#{recipe}@#{lock_data["version"]} (#{lock_data["identifier"][0...7]})"
8856 rmatch = recipe_spec.to_s.match(/recipe\[([^:]+)::([^:]+)\]/)
8857 rmatch = recipe_spec.to_s.match(/recipe\[([^:]+)\]/)
8858 [rmatch[1], "default"]
8859 [rmatch[1], rmatch[2]]
8860 (policy["named_run_lists"] || {}).keys
8861 rel_url = "cookbooks/#{cookbook_name}/#{xyz_version}"
8862 message = "Error loading cookbook #{cookbook_name} at version #{xyz_version} from #{rel_url}: #{e.class} - #{e.message}"
8863 Chef::Log.warn "Overridden Run List: [#{node.run_list}]"
8864 Chef::Log.info("Run List is [#{node.run_list}]")
8865 node.expand!("disk")
8866 cookbook_hash = cookbook_hash.inject({}) do |memo, (key, value)|
8867 @node =
8868 providers = []
8869 configs = []
8870 cmd = case
8871 when node["os"] == "solaris2"
8872 node[:languages] && node[:languages][:powershell] &&
8873 node[:languages][:powershell][:version].to_i >= 4
8874 supports_dsc?(node) &&
8875 platform = node[:os]
8876 @full_name = ""
8877 @guid = nil
8878 def guid(arg = nil)
8879 result["guid"] = @guid if @guid
8880 payload = { name: name, full_name: full_name }
8881 request_body = { user: username }
8882 association_id = response["uri"].split("/").last
8883 org = Chef::Org.new(org_hash["name"])
8884 org.guid org_hash["guid"] if org_hash.key?("guid")
8885 orgs.inject({}) do |org_map, (name, _url)|
8886 org_map[name] = Chef::Org.load(name)
8887 def <<(message); end
8888 new_matcher = { klass: klass }
8889 new_matcher[:os] = os if os
8890 map[key] ||= []
8891 if cmp && cmp <= 0
8892 map[key] << new_matcher
8893 return [] unless map.key?(key)
8894 end.map { |matcher| matcher[:klass] }
8895 deleted = {}
8896 if matcher[:klass].to_s == klass.to_s
8897 method = "#{m}?".to_sym
8898 blocklist, allowlist = filter_values.partition { |v| v.is_a?(String) && v.start_with?("!") }
8899 return false if blocklist.any? { |v| v[1..] == value || platform_family_query_helper?(node, v[1..]) }
8900 allowlist.empty? || allowlist.any? { |v| v == :all || v == value || platform_family_query_helper?(node, v) }
8901 return false if blocklist.any? { |v| v[1..] == value }
8902 allowlist.empty? || allowlist.any? { |v| v == :all || v == value }
8903 return 1 if !a && b
8904 return -1 if !b && a
8905 return 0 if !a && !b
8906 a_negated = Array(a).any? { |f| f.is_a?(String) && f.start_with?("!") }
8907 b_negated = Array(b).any? { |f| f.is_a?(String) && f.start_with?("!") }
8908 return -1 if b_negated && !a_negated
8909 a <=> b
8910 @map ||= {}
8911 attr_reader :__path__
8912 attr_reader :__root__
8913 attr_reader :__node__
8914 def initialize(data = nil, root = self, node = nil, precedence = nil)
8915 data.nil? ? super() : super(data)
8916 @__path__ = []
8917 @__root__ = root
8918 @__node__ = node
8919 def [](*args)
8920 next_path = [ __path__, convert_key(key) ].flatten.compact
8921 def []=(*args)
8922 def __path__=(path)
8923 @__path__ = path
8924 def __root__=(root)
8925 def __node__=(node)
8926 if __node__ && __node__.run_context && __node__.run_context.events
8927 def send_reset_cache(path = nil, key = nil)
8928 __root__.reset_cache(next_path.first) if !__root__.nil? && __root__.respond_to?(:reset_cache) && !next_path.nil?
8929 ret.__path__ = next_path
8930 ret.__root__ = __root__
8931 ret.__node__ = __node__
8932 ret.__precedence__ = __precedence__
8933 def <<(obj)
8934 def []=(*keys, value)
8935 objs = objs.map { |obj| convert_value(obj) }
8936 map! { |x| convert_value(x) }
8937 def map!(&block)
8938 super { |x| convert_value(x) }
8939 def fill(*args, &block)
8940 <
8941 <=
8942 >
8943 >=
8944 &
8945 +
8946 -
8947 |
8948 def [](key)
8949 ret = if deep_merge_cache.key?(key.to_s)
8950 ImmutableMash.new(value, __root__, __node__, __precedence__)
8951 ImmutableArray.new(value, __root__, __node__, __precedence__)
8952 Array.new(map { |e| safe_dup(e) })
8953 Array.new(map do |v|
8954 v.to_a
8955 v.to_h
8956 to_a.to_yaml(*opts)
8957 def initialize(mash_data = {})
8958 h = Mash.new
8959 each_pair do |k, v|
8960 h[k] = safe_dup(v)
8961 h = {}
8962 h[k] =
8963 to_h.to_yaml(*opts)
8964 obj.is_a?(Hash) || (obj.is_a?(Array) && key.is_a?(Integer))
8965 value = block_given? ? yield : args.pop
8966 prev_memo = prev_key = nil
8967 chain = args.inject(self) do |memo, key|
8968 prev_memo[prev_key] = {}
8969 def write!(*args, &block)
8970 obj = args.inject(self) do |memo, key|
8971 if memo.is_a?(Hash)
8972 read!(*path)
8973 def read!(*path)
8974 hash = path.empty? ? self : read(*path)
8975 return nil unless hash.is_a?(Hash) || hash.is_a?(Array)
8976 ret = super(*args, &block)
8977 send_reset_cache(__path__, key)
8978 def initialize(data = [])
8979 map! { |e| convert_value(e) }
8980 VividMash.new(value, __root__, __node__, __precedence__)
8981 AttrArray.new(value, __root__, __node__, __precedence__)
8982 super(*args, &block)
8983 def initialize(data = {})
8984 if !key?(key)
8985 value = self.class.new({}, __root__)
8986 def []=(key, value)
8987 [component.to_s.sub(/^@/, ""), value]
8988 @default = VividMash.new(new_data, self, __node__, :default)
8989 @role_default = VividMash.new(new_data, self, __node__, :role_default)
8990 @env_default = VividMash.new(new_data, self, __node__, :env_default)
8991 @normal = VividMash.new(new_data, self, __node__, :normal)
8992 @override = VividMash.new(new_data, self, __node__, :override)
8993 @env_override = VividMash.new(new_data, self, __node__, :env_override)
8994 def rm(*args)
8995 hash = obj.read(*path)
8996 ret = hash[last]
8997 ret == NIL ? nil : ret
8998 write(:normal, *args) if normal.read(*args[0...-1]).nil?
8999 write(:default, *args) if default.read(*args[0...-1]).nil?
9000 write(:override, *args) if override.read(*args[0...-1]).nil?
9001 if path[0].nil?
9002 def write!(level, *args, &block)
9003 send(level).write!(*args, &block)
9004 alias :key? :has_key?
9005 end.join(", ") << ">"
9006 path ||= []
9007 if val.respond_to?(:[])
9008 if !val.respond_to?(:has_key?)
9009 key.is_a?(Symbol) ? key.to_s : key
9010 if merge_onto.is_a?(Hash) && merge_with.is_a?(Hash)
9011 elsif merge_onto.is_a?(Array) && merge_with.is_a?(Array)
9012 def_delegators :attributes, :keys, :each_key, :each_value, :key?, :has_key?
9013 def_delegators :attributes, :read, :read!, :write, :write!, :unlink, :unlink!
9014 @logger = logger || Chef::Log.with_child(subsystem: "node")
9015 @attributes = Chef::Node::Attribute.new({}, {}, {}, {}, self)
9016 @run_state = {}
9017 if !arg.nil?
9018 { name: arg },
9019 { name: { kind_of: String,
9020 regex: /^[\-[:alnum:]_:.]+$/ },
9021 @name = arg
9022 { regex: /^[\-[:alnum:]_]+$/, kind_of: String }
9023 validate({ policy_name: arg }, { policy_name: { kind_of: [ String, NilClass ], regex: /^[\-:.[:alnum:]_]+$/ } })
9024 validate({ policy_group: arg }, { policy_group: { kind_of: [ String, NilClass ], regex: /^[\-:.[:alnum:]_]+$/ } })
9025 def [](attrib)
9026 fully_qualified_recipe = "#{cookbook}::#{recipe}"
9027 args.length > 0 ? rl.reset!(args) : rl
9028 rl = list
9029 run_list.detect { |r| r == item } ? true : false
9030 automatic[:chef_guid] = Chef::Config[:chef_guid] || ( Chef::Config[:chef_guid] = node_uuid )
9031 normal[:tags] = Array(normal[:tags])
9032 attrs = attrs ? attrs.dup : {}
9033 if new_run_list = attrs.delete("recipes") || attrs.delete("run_list")
9034 if attrs.key?("recipes") || attrs.key?("run_list")
9035 Chef::Environment.new.tap { |e| e.name("_default") }
9036 index_hash["chef_type"] = "node"
9037 index_hash["name"] = name
9038 display = {}
9039 return o if o.is_a? Chef::Node
9040 node = new
9041 node.name(o["name"])
9042 node.policy_name = o["policy_name"] if o.key?("policy_name")
9043 node.policy_group = o["policy_group"] if o.key?("policy_group")
9044 if o.key?("attributes")
9045 node.normal_attrs = Mash.new(o["normal"]) if o.key?("normal")
9046 node.default_attrs = Mash.new(o["default"]) if o.key?("default")
9047 if o.key?("run_list")
9048 node.run_list.reset!(o["run_list"])
9049 elsif o.key?("recipes")
9050 o["recipes"].each { |r| node.recipes << r }
9051 Chef::Search::Query.new.search(:node, "chef_environment:#{environment}") { |n| response[n.name] = n unless n.nil? }
9052 n = Chef::Node.from_hash(n)
9053 if e.response.code == "404"
9054 name <=> other.name
9055 sockets = []
9056 res.each do |ai|
9057 logger.debug("TCPServer.new(#{ai[3]}, #{port})") if logger
9058 sock = TCPServer.new(ai[3], port)
9059 port = sock.addr[1] if port == 0
9060 rescue => ex
9061 CP1252 = {
9062 128 => 8364, # euro sign
9063 134 => 8224, # dagger
9064 135 => 8225, # double dagger
9065 137 => 8240, # per mille sign
9066 149 => 8226, # bullet
9067 150 => 8211, # en dash
9068 151 => 8212, # em dash
9069 152 => 732, # small tilde
9070 153 => 8482, # trade mark sign
9071 38 => "&amp;", # ampersand
9072 62 => "&gt;", # right angle bracket
9073 unescaped_str.unpack("U*").map { |char| xml_escape_char!(char) }.join
9074 unescaped_str.unpack("C*").map { |char| xml_escape_char!(char) }.join
9075 char = CP1252[char] || char
9076 char = PREDEFINED[char] || (char < 128 ? char.chr : "&##{char};")
9077 ).address, flags, 5000, nil) == 0
9078 buf = 0.chr * 32 * 1024
9079 node ||= begin
9080 {}.tap do |n|
9081 n[:kernel] = {}
9082 n[:kernel][:machine] = os_arch == "AMD64" ? :x86_64 : :i386
9083 ( node_windows_architecture(node) == :x86_64 ) || ( desired_architecture == :i386 )
9084 ( architecture == :x86_64 ) || ( architecture == :i386 )
9085 if ( node_windows_architecture(node) == :x86_64) && ::ChefUtils.windows?
9086 if str.nil? || str.encoding == Encoding::UTF_16LE
9087 ustring = (ustring + "").force_encoding("UTF-8")
9088 ustring += "\000\000" if ustring.length == 0 || ustring[-1].chr != "\000"
9089 @actions = []
9090 @assertions = Hash.new { |h, k| h[k] = [] }
9091 @blocked_actions = []
9092 @versioned_interfaces ||= []
9093 .max_by { |a| a.send(:minimum_api_version) }
9094 line_no = __LINE__; str = %{
9095 def self.#{method}(*args, &block)
9096 versioned_api_class.__send__(:#{method}, *args, &block)
9097 module_eval(str, __FILE__, line_no)
9098 !!(%r{\A[A-Za-z][A-Za-z0-9+\-\.]*://} =~ source)
9099 data = message.match(/(\[.+?\] )?(\w+):(.*)$/)
9100 @_extension_modules = []
9101 output = output.gsub(/\r?
/, "\r
")
9102 $1.to_i if original_exception.backtrace.find { |line| line =~ /#{Regexp.escape(options[:filename])}:(\d+)/ }
9103 $1.to_i if original_exception.backtrace.find { |line| line =~ /\(erubis\):(\d+)/ }
9104 lines = @template.split(/
/)
9105 output = []
9106 line_number = (index + beginning_line + 1).to_s.rjust(3)
9107 output << "#{line_number}: #{line}"
9108 output.join("
")
9109 instance_variable_set(:"@#{sym}", true)
9110 !!instance_variable_get(:"@#{sym}")
9111 define_method :"#{sym}?" do
9112 self.class.send(:"#{sym}?")
9113 def owner(arg = nil)
9114 def group(arg = nil)
9115 def mode(arg = nil)
9116 :mode,
9117 if m.is_a?(String)
9118 m =~ /^0/ || m = "0#{m}"
9119 Integer(m) <= 0777 && Integer(m) >= 0
9120 Integer(m) <= 07777 && Integer(m) >= 0
9121 rights = instance_variable_get("@#{name}".to_sym)
9122 input = {
9123 principals: { required: true, kind_of: [String, Array] },
9124 applies_to_children: { equal_to: [ true, false, :containers_only, :objects_only ] },
9125 applies_to_self: { kind_of: [ TrueClass, FalseClass ] },
9126 one_level_deep: { kind_of: [ TrueClass, FalseClass ] },
9127 if permission < 0 || permission > 1 << 32
9128 if input[:one_level_deep] == true
9129 rights ||= []
9130 proxy = ENV["https_proxy"] || ENV["http_proxy"] || false
9131 if proxy && !fuzzy_hostname_match_any?(host, ENV["no_proxy"])
9132 def provides(short_name, opts = {})
9133 @properties ||= {}
9134 elsif type.is_a?(Property) || (type.is_a?(Class) && type <= Property)
9135 options[:is] = ([ type ] + [ options[:is] ]).flatten(1)
9136 options[:is] = type
9137 names = names.map(&:to_sym).uniq
9138 names = names.map(&:to_sym)
9139 result = name_property ? [ properties[name_property] ] : [ properties[:name] ]
9140 p = properties.find { |n, p| p.name_property? }
9141 p ? p.first : nil
9142 translated = x.inject([]) do |memo, (k, v)|
9143 memo << "#{k}=#{translate_type(v)}"
9144 translated = x.map do |v|
9145 ["'", "#", "`", '"'].any? do |x|
9146 if unsafe?(s)
9147 options ||= {}
9148 flags = [
9149 @validation_message ||= {}
9150 unless key.is_a?(Symbol) || key.is_a?(String)
9151 check_method = "_pv_#{check}"
9152 if opts.key?(key.to_s)
9153 return true if opts.key?(key.to_s) && (explicitly_allows_nil || !opts[key.to_s].nil?)
9154 return true if opts.key?(key.to_sym) && (explicitly_allows_nil || !opts[key.to_sym].nil?)
9155 def _pv_equal_to(opts, key, to_be)
9156 to_be = Array(to_be)
9157 to_be.each do |tb|
9158 def _pv_kind_of(opts, key, to_be)
9159 predicate_method = :"#{method_name}?"
9160 opts[key] = instance_variable_get(:"@name")
9161 def _pv_is(opts, key, to_be)
9162 return true if !opts.key?(key.to_s) && !opts.key?(key.to_sym)
9163 to_be = [ to_be ].flatten(1)
9164 passed = to_be.any? do |tb|
9165 raise if to_be.size == 1
9166 errors << $!
9167 tb === value
9168 message << " Errors:
#{errors.map { |m| "- #{m}" }.join("
")}"
9169 cert_file_path + ::File::SEPARATOR + cert_filename + ".key"
9170 number >= 1024 && ( number & (number - 1) == 0 )
9171 key_content = ::File.exist?(key_file) ? File.read(key_file) : key_file
9172 ::OpenSSL::X509::CRL.new ::File.read(crl_file)
9173 key_content = ::File.exist?(priv_key) ? File.read(priv_key) : priv_key
9174 ::OpenSSL::PKey::EC.send(:alias_method, :private?, :private_key?)
9175 exts = []
9176 cert.not_after = cert.not_before + info["validity"] * 24 * 60 * 60
9177 if info["issuer"].nil?
9178 crl.next_update = Time.now + 3600 * 24 * info["validity"]
9179 crlnum = 1
9180 crlnum = e.value if e.oid == "crlNumber"
9181 crlnum.to_i + 1
9182 revoke_info["serial"].to_i(16)
9183 crl.next_update = crl.last_update + 3600 * 24 * info["validity"]
9184 Dir[File.join(RbConfig::CONFIG["prefix"], "**", "openssl.cnf")].first
9185 @descendants ||= []
9186 ::File
9187 @@direct_descendants = {}
9188 @@direct_descendants[klass] || []
9189 arr = []
9190 descendants(klass).first { |c| c.name == name }
9191 (@@direct_descendants[klass] ||= []) << descendant
9192 @deprecated_constants ||= {}
9193 Chef::Log.warn("Called from:
#{caller[0...3].map { |l| "\t#{l}" }.join("
")}")
9194 KEEPERS = %w{__id__ __send__ instance_eval == equal? initialize object_id}.freeze
9195 @level ||= :warn
9196 called_from.each { |l| log(l) }
9197 instance_variable_get("@#{name}")
9198 define_method("#{name}=") do |value|
9199 instance_variable_set("@#{name}", value)
9200 env["PATH"] = default_paths(env)
9201 if dest.is_a?(Hash)
9202 dest[src_key] = deep_merge!(src_value, dest[src_key])
9203 if dest.is_a?(Array)
9204 unless file_path.is_a?(String) || file_path.is_a?(Array)
9205 file_path.shift if file_path[0] == ""
9206 file_path[0] = "#{File::SEPARATOR}#{file_path[0]}"
9207 create_path = File.join(file_path[0, i + 1])
9208 regexp = /^(.+?)(_(.+))?$/
9209 while mn && mn[3]
9210 mn = mn[3].match(regexp)
9211 str = str.dup
9212 str.sub!(/^#{namespace}(\:\:)?/, "") if namespace
9213 str.gsub!(/[A-Z]/) { |s| "_" + s }
9214 str.sub!(/^\_/, "")
9215 str.gsub!(/[^A-Za-z0-9_]/, "_")
9216 str.gsub!(/^(_+)?/, "")
9217 with_namespace.split("::").last.sub(/^_/, "")
9218 str = base.to_s + (file_base == "default" ? "" : "_#{file_base}")
9219 def __log
9220 data: [msg]
9221 chef_gem_path = File.expand_path("..", __dir__)
9222 caller(0..20).find { |c| !c.start_with?(chef_gem_path) } || caller(0..1)[0]
9223 server_options = {}
9224 parts = port.split(",")
9225 if parts.size == 1
9226 a, b = parts[0].split("-", 2)
9227 a.to_i.upto(b.to_i)
9228 [ a.to_i ]
9229 array += parse_port(part).to_a
9230 @rest ||= if @actor_field_name == "user"
9231 @api_base ||= if @actor_field_name == "user"
9232 def actor(arg = nil)
9233 regex: /^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z|infinity)$/)
9234 @actor_field_name => @actor,
9235 result["name"] = @name if @name
9236 if @public_key.nil? && !@create_key
9237 if @name.nil?
9238 payload = { "name" => @name }
9239 result = chef_rest.post("#{api_base}/#{@actor}/keys", payload)
9240 new_key = to_h
9241 if @name.nil? && put_name.nil?
9242 put_name = @name if put_name.nil?
9243 new_key = chef_rest.put("#{api_base}/#{@actor}/keys/#{put_name}", to_h)
9244 chef_rest.delete("#{api_base}/#{@actor}/keys/#{@name}")
9245 if key_hash.key?("user")
9246 key = Chef::Key.new(key_hash["user"], "user")
9247 key = Chef::Key.new(key_hash["client"], "client")
9248 key.name key_hash["name"] if key_hash.key?("name")
9249 Chef::Key.from_hash(response.merge({ "user" => actor }))
9250 Chef::Key.from_hash(response.merge({ "client" => actor }))
9251 OpenSSL::Digest.hexdigest("SHA1", data_string.to_der).scan(/../).join(":")
9252 keys.inject({}) do |key_map, result|
9253 name = result["name"]
9254 def parse(source, opts = {})
9255 def from_json(source, opts = {})
9256 unless obj.is_a?(Hash) || obj.is_a?(Array)
9257 def to_json(obj, opts = nil)
9258 options_map = { pretty: true }
9259 options_map[:indent] = opts[:indent] if opts.respond_to?(:key?) && opts.key?(:indent)
9260 def initialize(opts = {}); end
9261 def handle_request(method, url, headers = {}, data = false)
9262 def read_body(dest = nil, &block)
9263 100 => "Continue",
9264 200 => "OK",
9265 201 => "Created",
9266 202 => "Accepted",
9267 204 => "No Content",
9268 205 => "Reset Content",
9269 206 => "Partial Content",
9270 207 => "Multi-Status",
9271 300 => "Multiple Choices",
9272 302 => "Found",
9273 303 => "See Other",
9274 304 => "Not Modified",
9275 305 => "Use Proxy",
9276 400 => "Bad Request",
9277 401 => "Unauthorized",
9278 402 => "Payment Required",
9279 403 => "Forbidden",
9280 404 => "Not Found",
9281 405 => "Method Not Allowed",
9282 406 => "Not Acceptable",
9283 408 => "Request Timeout",
9284 409 => "Conflict",
9285 410 => "Gone",
9286 411 => "Length Required",
9287 414 => "Request-URI Too Large",
9288 423 => "Locked",
9289 426 => "Upgrade Required",
9290 429 => "Too Many Requests",
9291 501 => "Not Implemented",
9292 502 => "Bad Gateway",
9293 504 => "Gateway Timeout",
9294 @url = base_url
9295 net_http_response = to_net_http(res[0], res[1], res[2])
9296 body_str = body || ""
9297 body = chunked_body.join("")
9298 value.each { |v| response.add_field(name, v) }
9299 options.reject { |name, _| KNOWN_OPTIONS.include?(name) }.map do |name, value|
9300 [name.to_s.split("_").map(&:capitalize).join("-"), value]
9301 headers["Accept"] ||= "application/json"
9302 Chef::Log.trace("Response body contains:
#{http_response.body.length < 256 ? http_response.body : http_response.body[0..256] + " [...truncated...]"}")
9303 @opts = opts
9304 headers.delete_if { |key, _value| key.casecmp("content-type") == 0 }
9305 json_opts = {}
9306 requested_content_type = headers.find { |k, v| k.casecmp("content-type") == 0 }
9307 @user_agent = ua
9308 @method, @url = method, url
9309 @url.path.empty? ? SLASH : @url.path
9310 if /#{Regexp.escape(%q{undefined method `closed?' for nil:NilClass})}/.match?(e.to_s)
9311 Chef::Log.trace("#{e.class.name}: #{e}")
9312 Chef::Log.trace(e.backtrace.join("
"))
9313 @headers["Host"] = host_header unless @headers.keys.any? { |k| k.downcase.to_s == HOST_LOWER }
9314 req_path << "?#{query}" if query
9315 @host, @port = url.host, url.port
9316 if @cookies.key?("#{@host}:#{@port}")
9317 headers["Cookie"] = @cookies["#{@host}:#{@port}"]
9318 @cookies["#{@host}:#{@port}"] = http_response["set-cookie"]
9319 def request(method, url, req_body, base_headers = {})
9320 Chef::Log.trace("Initiating #{method} to #{url}")
9321 Chef::Log.trace("---- HTTP Request Header Data: ----")
9322 Chef::Log.trace("#{name}: #{value}")
9323 Chef::Log.trace("---- End HTTP Request Header Data ----")
9324 Chef::Log.trace("---- HTTP Status and Header Data: ----")
9325 Chef::Log.trace("#{header}: #{value}")
9326 Chef::Log.trace("---- End HTTP Status/Header Data ----")
9327 if !response.code || !response.code.start_with?("2")
9328 Chef::Log.trace("---- HTTP Response Body ----")
9329 Chef::Log.trace("---- End HTTP Response Body -----")
9330 Chef::Log.trace("---- HTTP Request Body ----")
9331 Chef::Log.trace("---- End HTTP Request Body ----")
9332 opts["read_timeout"] ||= config[:rest_timeout]
9333 opts["open_timeout"] ||= config[:rest_timeout]
9334 http_client.send(:"#{key}=", value)
9335 Chef::Log.trace("Using #{proxy_uri.host}:#{proxy_uri.port} for proxy")
9336 @raw_key = nil
9337 elsif key_file == nil? && raw_key == nil?
9338 Chef::Log.warn "Failed to read the private key #{key_file}: #{e.inspect}"
9339 key = raw_data[1]
9340 $aes.Key = $KeyBytes
9341 password = ""
9342 if secret[:name] == "PfxPass"
9343 corrected_store = (store == "CurrentUser" ? "HKCU" : "HKLM")
9344 size = 14
9345 values = [
9346 { name: "PfxPass", type: :string, data: encrypted_password },
9347 { name: "PfxKey", type: :string, data: key },
9348 { name: "PfxIV", type: :string, data: vector },
9349 file_path = ps_blob["PSPath"].split("::")[1]
9350 future.mjd - today.mjd <= 7
9351 $cert = Get-ChildItem -path cert:\\#{store}\\My -Recurse | Where-Object { $_.Subject -match "chef-#{client_name}$" } -ErrorAction Stop;
9352 $tempfile = [System.IO.Path]::GetTempPath() + "export_pfx.pfx";
9353 Get-ChildItem -path cert:\\#{store}\\My -Recurse | Where-Object { $_.Subject -match "chef-#{client_name}$" } | Remove-Item -ErrorAction Stop;
9354 host: "#{url.host}:#{url.port}",
9355 request_params[:body] ||= ""
9356 !!key
9357 signed = sign_obj.sign(key, use_ssh_agent: @use_ssh_agent).merge({ host: host })
9358 signed.inject({}) { |memo, kv| memo[(kv[0].to_s.upcase).to_s] = kv[1]; memo }
9359 def initialize(options = {}); end
9360 if http_response.code == "406"
9361 @stream_handlers = []
9362 @middlewares ||= []
9363 def initialize(url, options = {})
9364 @default_headers = options[:headers] || {}
9365 @nethttp_opts = options[:nethttp] || {}
9366 @middlewares = []
9367 def head(path, headers = {})
9368 def get(path, headers = {})
9369 def put(path, json, headers = {})
9370 def post(path, json, headers = {})
9371 def delete(path, headers = {})
9372 def request(method, path, headers = {}, data = false)
9373 http_attempts ||= 0
9374 data = nil
9375 base_url ||= url
9376 @http_client ||= {}
9377 @http_client[base_url.host] ||= {}
9378 if %r{^(http|https|chefzero)://}i.match?(path)
9379 elsif path.nil? || path.empty?
9380 URI.parse(@url.gsub(%r{/+$}, "") + "/" + path.gsub(%r{^/+}, ""))
9381 return_value ||= {}
9382 error_message << (return_value["error"].respond_to?(:join) ? return_value["error"].join(", ") : return_value["error"].to_s)
9383 sleep_time = 1 + (2**http_attempts) + rand(2**http_attempts)
9384 def build_headers(method, url, headers = {}, json_body = false)
9385 if tf.nil?
9386 @amount ||= 10
9387 puts "
Top #{count} slowest #{count == 1 ? "resource" : "resources"}:

"
9388 puts "
"
9389 num > amount ? amount : num
9390 resource.source_line&.gsub(%r{.*/cookbooks/}, "")&.gsub(%r{.*/chef-[0-9\.]+/}, "")
9391 @config[:path] ||= "/var/chef/reports"
9392 savetime = Time.now.strftime("%Y%m%d%H%M%S")
9393 File.open(File.join(config[:path], "chef-run-report-#{savetime}.json"), "w") do |file|
9394 run_data[:start_time] = run_data[:start_time].to_s
9395 run_data[:end_time] = run_data[:end_time].to_s
9396 Chef::Config[:start_handlers] ||= []
9397 Chef::Config[:start_handlers] |= [self]
9398 Chef::Config[:report_handlers] ||= []
9399 Chef::Config[:report_handlers] |= [self]
9400 Chef::Config[:exception_handlers] ||= []
9401 Array(e.backtrace).each { |line| Chef::Log.error(line) }
9402 @output = "STDOUT: #{result.stdout}
STDERR: #{result.stderr}
"
9403 @group ||= {}
9404 body_hash = {
9405 groupname: "#{groupname}",
9406 actors: {
9407 admins["actors"].length <= 2
9408 admins["actors"].length <= 1
9409 @updated_resources = []
9410 @updates_by_resource = Hash.new { |h, k| h[k] = [] }
9411 puts "done."
9412 puts "* #{resource}"
9413 print "S"
9414 print "U"
9415 @out, @err = out, err
9416 @indent = 0
9417 @pastel ||= begin
9418 if colors.size == 1 && colors[0].is_a?(Hash)
9419 print_line("", options)
9420 if line[-1..] == "
"
9421 if Chef::Config[:color] && options[:colors]
9422 @out.puts ""
9423 @out.print "#{(" " * indent)}[#{options[:name]}] "
9424 @out.print " " * (indent + 3 + options[:name].size)
9425 @out.print " " * indent
9426 headline = "Recipe Compile Error" + ( path ? " in #{path}" : "" )
9427 original_run_list = node.run_list.map { |item| "* #{item}" }.join("
")
9428 end.join("
")
9429 @snippet ||= if (file = parse_source) && (line = parse_line(file))
9430 relevant_lines = ["# In #{file}

"]
9431 current_line = line - 1
9432 nesting += 1 if /\s+do\s*/.match?(lines[current_line])
9433 nesting -= 1 if /end\s*$/.match?(lines[current_line])
9434 break if current_line >= (line + 50)
9435 filters = Array(Chef::Config.cookbook_path).map { |p| /^#{Regexp.escape(p)}/ }
9436 exception.backtrace.select { |line| filters.any? { |filter| line =~ filter } }
9437 line_nr_string = (line_nr + 1).to_s.rjust(3) + ": "
9438 resource.source_line[/^((\w:)?[^:]+):(\d+)/, 1]
9439 resource.source_line[/^#{Regexp.escape(source)}:(\d+)/, 1].to_i
9440 explanation = ""
9441 explanation << "* #{cookbook}
"
9442 explanation << "
"
9443 explanation << <<~EOM
9444 @expanded_run_list.map { |i| "* #{i}" }.join("
")
9445 error_description.section("Additional information:", msg.gsub(/^ {6}/, ""))
9446 context_lines = []
9447 context_lines << "#{culprit_file}:

"
9448 line_nr = (i + 1).to_s.rjust(3)
9449 context_lines << "#{line_nr}#{indicator}#{file_lines[i]}"
9450 lower = (culprit_line - 8)
9451 lower = 0 if lower < 0
9452 upper = (culprit_line + 8)
9453 @culprit_line ||= begin
9454 line_number = culprit_backtrace_entry[/^(?:.\:)?[^:]+:(\d+)/, 1].to_i
9455 @culprit_file ||= culprit_backtrace_entry[/^((?:.\:)?[^:]+):(\d+)/, 1]
9456 filters = Array(Chef::Config.cookbook_path).map { |p| /^#{Regexp.escape(p)}/i }
9457 r = exception.backtrace.select { |line| filters.any? { |filter| line =~ filter } }
9458 Chef::Log.trace("Filtered backtrace of compile error: #{r.join(",")}")
9459 @sections = []
9460 @sections << { heading => (text || "") }
9461 out.puts "=" * 80
9462 out.puts "
"
9463 out.puts "-" * heading.size
9464 context_info[:executable] = File.realpath(caller.last[/^(.*):\d+:in /, 1])
9465 context_info.map { |k, v| "#{k}=#{v}" }.join("
")
9466 @end_time = @start_time
9467 @progress = {}
9468 if time < 60
9469 puts_line ""
9470 puts_line "#{prefix}#{line}"
9471 puts_line "Using Policyfile '#{policy["name"]}' at revision '#{policy["revision_id"]}'"
9472 puts_line "- #{cookbook.name} (#{cookbook.version})"
9473 puts_line "- Installing #{gem} #{version}", :green
9474 puts_line "- Using #{gem} #{version}"
9475 @progress[resource] ||= -1
9476 percent_complete = (current.to_f / total.to_f * 100).to_i unless total.to_f == 0.0
9477 start_line " - Progress: #{percent_complete}%", :green
9478 @up_to_date_resources += 1
9479 prefix = Chef::Config[:why_run] ? "Would " : ""
9480 start_line "- #{prefix}#{line}", :green
9481 puts_line "- #{handler.class.name}"
9482 start_line("* #{line}", :yellow)
9483 color = Chef::Config[:why_run] ? :yellow : :red
9484 start_line("* #{line}", color)
9485 indent_by(-2)
9486 @deprecations ||= {}
9487 @formatters_by_name ||= {}
9488 puts("")
9489 tf = nil
9490 errors = [ ]
9491 i = b.index(".")
9492 i.nil? ? "" : b[i..].scrub
9493 [ Dir.tmpdir ]
9494 [ ::File.dirname(@new_resource.path), Dir.tmpdir ]
9495 [ ::File.dirname(@new_resource.path) ]
9496 apply_dacl = ACL.create(dst_sd.dacl.select { |ace| !ace.inherited? })
9497 apply_sacl = ACL.create(dst_sd.sacl.select { |ace| !ace.inherited? })
9498 stat = ::File.stat(dst)
9499 Chef::Log.trace("Applying mode = #{mode.to_s(8)}, uid = #{uid}, gid = #{gid} to #{src}")
9500 ::File.chown(uid, nil, src)
9501 Chef::Log.warn("Could not set uid = #{uid} on #{src}, file modes not preserved")
9502 ::File.chown(nil, gid, src)
9503 Chef::Log.warn("Could not set gid = #{gid} on #{src}, file modes not preserved")
9504 ::File.chmod(mode, src)
9505 path: { kind_of: String },
9506 contents: { kind_of: String },
9507 File.open(File.join(cache_path, file_name), "w", perm) do |io|
9508 file: { kind_of: String },
9509 raise "Cannot move #{file} to #{path}!"
9510 find("**#{File::Separator}*")
9511 keys = []
9512 if File.file?(f)
9513 keys << f[/^#{Regexp.escape(Dir[Chef::Util::PathHelper.escape_glob_dir(file_cache_path)].first) + File::Separator}(.+)/, 1]
9514 alias_method :has_key?, :key?
9515 changes = []
9516 actual_acl = actual_acl.select { |ace| !ace.inherited? }
9517 new_target_acl = []
9518 return true unless ::File.exist?(file) || ::File.symlink?(file)
9519 ( ! inherits.nil? && inherits != existing_descriptor.dacl_inherits? ) || ( dacl && !acls_equal(dacl, existing_dacl) )
9520 if dacl.nil? && !existing_dacl.nil?
9521 Chef::Log.info("#{log_string} group changed to #{group}")
9522 Chef::Log.info("#{log_string} owner changed to #{owner}")
9523 mask = 0
9524 return [] if mask == 0
9525 [ ACE.access_allowed(sid, mask) ]
9526 flags = 0
9527 acls = nil
9528 acls = [] if acls.nil?
9529 acls += mode_ace(owner, (mode & 0700) >> 6)
9530 elsif mode & 0700 != 0
9531 acls += mode_ace(group, (mode & 070) >> 3)
9532 elsif mode & 070 != 0
9533 acls += mode_ace(SID.Everyone, (mode & 07))
9534 changes << "change mode from '#{mode_to_s(current_mode)}' to '#{mode_to_s(target_mode)}'" if should_update_mode?
9535 Chef::Log.info("#{log_string} owner changed to #{target_uid}")
9536 Chef::Log.info("#{log_string} group changed to #{target_gid}")
9537 return nil if res.nil? || res.mode.nil?
9538 (res.mode.respond_to?(:oct) ? res.mode.oct : res.mode.to_i) & 007777
9539 mode.nil? ? "" : "0#{mode.to_s(8)}"
9540 Chef::Log.info("#{log_string} mode changed to #{target_mode.to_s(8)}")
9541 @stat ||= File.lstat(file)
9542 @stat ||= File.stat(file)
9543 target_mode & 04000 > 0
9544 @resource || @file
9545 %q{To set an attribute use code like `node.default["key"] = "value"'}
9546 @all_failures = []
9547 message << "* #{error.class} occurred in #{location}: #{error.message}
"
9548 @all_failures << [ "#{ChefUtils::Dist::Infra::PRODUCT} run", exception ]
9549 if @all_failures.size == 1
9550 @all_failures[0][1]
9551 super "Checksum on resource (#{res_cksum}...) does not match checksum on content (#{cont_cksum}...)"
9552 backtrace = []
9553 backtrace << "" unless i == wrapped_errors.length - 1
9554 constraint_str = constraints.map { |c| c.requirement.as_list.to_s }.join(", ")
9555 if r["Module"].nil?
9556 super "Found multiple resources matching #{matches_info[0]["Module"]["Name"]}:
#{(matches_info.map { |f| f["Module"]["Version"] }).uniq.join("
")}"
9557 data =
9558 [@run_status.run_id,
9559 data: data + [e.class.name,
9560 e.backtrace.join("
")]
9561 @event_loggers_by_name ||= {}
9562 def <<(str)
9563 Thread.current[:chef_client_event_list] ||= []
9564 subscribers.reject! { |x| x == subscriber }
9565 event_list << [ method_name, *args ]
9566 def #{method_name}(*args)
9567 subscribers.any? { |s| s.respond_to?(:is_formatter?) && s.is_formatter? }
9568 @in_call = true
9569 if mth.arity < args.size && mth.arity >= 0
9570 @in_call = false
9571 @cookbook_versions = {}
9572 }, {
9573 version: {
9574 if md.nil? || md[2].nil?
9575 cookbook_versions[md[1]] = md[2]
9576 invalid_fields[:cookbook_version] ||= {}
9577 @invalid_fields ||= {}
9578 if name.nil? || name.size == 0
9579 js_file = File.join(Chef::Config[:environment_path], "#{name}.json")
9580 rb_file = File.join(Chef::Config[:environment_path], "#{name}.rb")
9581 @iv = iv && Base64.decode64(iv)
9582 @iv
9583 @hmac ||= begin
9584 super + %w{ hmac }
9585 @auth_tag = nil
9586 super + %w{ auth_tag }
9587 @decrypted_data ||=
9588 d.iv = iv
9589 expected_bytes.zip(candidate_hmac_bytes) { |x, y| valid |= x ^ y.to_i }
9590 valid == 0
9591 d = super
9592 d.auth_data = ""
9593 data = raw_data.reject { |k, _| k == "id" } # Remove the "id" key.
9594 data.empty? ? false : data.reject { |_, v| !looks_like_encrypted?(v) } == data
9595 return false unless data.is_a?(Hash) && data.key?("version")
9596 @enc_hash = enc_hash
9597 value = @enc_hash[key]
9598 if key == "id" || value.nil?
9599 @enc_hash.keys.inject({}) { |hash, key| hash[key] = self[key]; hash }
9600 plain_hash.inject({}) do |h, (key, val)|
9601 h[key] = if key != "id"
9602 when %r{^\w+://}
9603 raise Errno::ENOENT, "file not found '#{path}'"
9604 @toml_str = ""
9605 visit(hash, [])
9606 if prefix.any? && (simple_pairs.any? || hash.empty?)
9607 nested_pairs = []
9608 simple_pairs = []
9609 table_array_pairs = []
9610 val = hash[key]
9611 element = [key, val]
9612 elsif val.is_a?(Array) && val.first.is_a?(Hash)
9613 @toml_str << "#{key} = #{to_toml(val)}
"
9614 visit val, prefix + [key], false
9615 aux_prefix = prefix + [key]
9616 new_prefix = prefix.join(".")
9617 new_prefix = "[#{new_prefix}]" if array
9618 @toml_str += "[#{new_prefix}]
"
9619 if obj.is_a?(Time) || obj.is_a?(DateTime)
9620 obj.strftime("%Y-%m-%dT%H:%M:%SZ")
9621 obj.strftime("%Y-%m-%d")
9622 obj.inspect.gsub(/\\(#[$@{])/, '\1')
9623 !!key.to_s.match(/^[a-zA-Z0-9_-]*$/)
9624 rest_property_map = rest_property_map.to_h { |k| [k.to_sym, k] } if rest_property_map.is_a? Array
9625 @rest_post_only_properties || []
9626 def #{dsl_name}(args = nil, &block)
9627 JSON.pretty_generate(hash) + "
"
9628 yaml_content.gsub!(" :", " ")
9629 when ".toml"
9630 when ".yaml", ".yml"
9631 when ".json"
9632 @values = {}
9633 key_matches = []
9634 keys.each do |k|
9635 key_matches << k
9636 if platforms.to_s == "default"
9637 @values["default"] = value
9638 hash.inject({}) do |h, key_value|
9639 h[key.to_s] = value
9640 msg << "you gave a value #{value.inspect} for platform(s) #{platforms}"
9641 @values["default"] = nil
9642 if match = file_spec.match(/(.+?)::(.+)/)
9643 [match[1], match[2]]
9644 [file_spec, "default"]
9645 def #{dsl_name}(*args, &block)
9646 created_at ||= caller[0]
9647 Chef.autoload :DataBag, File.expand_path("../data_bag", __dir__)
9648 Chef.autoload :DataBagItem, File.expand_path("../data_bag_item", __dir__)
9649 if Kernel.block_given? || args.length >= 4
9650 results << o
9651 }.each do |method_name|
9652 def #{method_name}(*args, &block)
9653 self.#{method_name}(*args, &block)
9654 if ::ChefVault::Item.vault?(bag, id)
9655 data_bag(bag).each_with_object([]) do |id, acc|
9656 File.open(file, "rb") { |f| checksum_io(f, digest) }
9657 while chunk = io.read(1024 * 8)
9658 message = "Method '#{name}' of '#{self.class}' is deprecated. It will be removed in #{ChefUtils::Dist::Infra::PRODUCT} #{Chef::VERSION.to_i.next}."
9659 return true if location =~ /^(.*?):(\d+):in/ && begin
9660 line_no = $2.to_i
9661 location_file = ::File.open($1)
9662 relevant_line.match?(/#.*chef:silence_deprecation($|[^:]|:#{self.class.deprecation_key})/)
9663 def target(id, page = nil)
9664 @doc_page = page || deprecation_key.to_s
9665 attr_accessor :__path__
9666 __path__.push(key)
9667 @delegate_sd_obj.public_send(__method__, *__path__, value)
9668 def [](idx)
9669 Lazy.new { block.call[idx] }
9670 def __getobj__
9671 @__defined_methods__ = []
9672 __getobj__.nil?
9673 def is_a?(klass)
9674 __getobj__.is_a?(klass) || super
9675 def __setobj__(obj)
9676 r = true
9677 target = __getobj__ { r = false }
9678 if r && target.respond_to?(m)
9679 target.__send__(m, *args, &block)
9680 @__defined_methods__.push(m)
9681 super(m, *args, &block)
9682 @__defined_methods__.each do |m|
9683 message = {
9684 message["error"] = {
9685 hash["after"] = {}
9686 hash["error"] = {
9687 action = "up-to-date" if action == "up_to_date"
9688 Chef::Config[:chef_server_url].match(%r{/+organizations/+([^\s/]+)}).nil? ? "unknown_organization" : $1
9689 @error_description ||= {}
9690 running_mode = ( Chef::Config[:solo_legacy_mode] || Chef::Config[:local_mode] ) ? :solo : :client
9691 when (want_mode != :both) && running_mode != want_mode
9692 when running_mode == :solo && !Chef::Config[:data_collector][:token]
9693 hash.is_a?(Hash) && keys.any? { |k| hash.key?(k) }
9694 code = e&.response&.code.to_s
9695 msg = "Error while reporting run start to Data Collector. URL: #{Chef::Config[:data_collector][:server_url]} Exception: #{code} -- #{e.message} "
9696 if code == "404"
9697 msg << " (This is normal if you do not have #{ChefUtils::Dist::Automate::PRODUCT})"
9698 File.open(File.expand_path(file_name), "a") do |fh|
9699 headers = { "Content-Type" => "application/json" }
9700 VALID_ID = /^[\.\-[:alnum:]_]+$/.freeze
9701 if id_str.nil? || ( id_str !~ VALID_ID )
9702 @data_bag = nil
9703 @raw_data = Mash.new
9704 unless new_data.respond_to?(:[]) && new_data.respond_to?(:keys)
9705 validate_id!(new_data["id"])
9706 @raw_data = new_data
9707 def data_bag(arg = nil)
9708 :data_bag,
9709 id = raw_data["id"]
9710 result["chef_type"] = "data_bag_item"
9711 result["data_bag"] = data_bag.to_s
9712 item = new
9713 item.data_bag(h.delete("data_bag")) if h.key?("data_bag")
9714 if h.key?("raw_data")
9715 item.raw_data = h["raw_data"]
9716 item = bag[name]
9717 item = Chef::ServerAPI.new(Chef::Config[:chef_server_url]).get("data/#{data_bag}/#{name}")
9718 def save(item_id = @raw_data["id"])
9719 r.put("data/#{data_bag}/#{item_id}", self)
9720 r.post("data/#{data_bag}", self)
9721 other.respond_to?(:to_h) &&
9722 other.respond_to?(:data_bag) &&
9723 (other.to_h == to_h) &&
9724 (other.data_bag.to_s == data_bag.to_s)
9725 pretty_printer.pp({ "data_bag_item('#{data_bag}', '#{id}')" => to_hash })
9726 @raw_data["id"]
9727 bag = new
9728 bag.name(o["name"])
9729 names = []
9730 )).map { |f| File.basename(f) }.sort
9731 names.inject({}) { |h, n| h[n] = n; h }
9732 list(false).inject({}) do |response, bag_and_uri|
9733 data_bag = {}
9734 Dir.glob(File.join(Chef::Util::PathHelper.escape_glob_dir(path, name.to_s), "*.json")).inject({}) do |bag, f|
9735 if data_bag.key?(item["id"]) && data_bag[item["id"]] != item
9736 data_bag[item["id"]] = item
9737 chef_server_rest.delete("data/#{@name}")
9738 Chef::Log.info("Forked, in #{Process.pid}. Privileges: #{Process.euid} #{Process.egid}")
9739 $stdin.reopen("/dev/null")
9740 $stdout.reopen("/dev/null", "a")
9741 Chef::Config[:pid_file] || "/tmp/#{@name}.pid"
9742 Dir.chdir("/")
9743 if Chef::Config[:user] && Chef::Config[:group]
9744 Chef::Log.info("About to change privilege to #{Chef::Config[:user]}:#{Chef::Config[:group]}")
9745 if (uid != target_uid) || (gid != target_gid)
9746 Chef::Application.fatal!("Permission denied when trying to change #{uid}:#{gid} to #{target_uid}:#{target_gid}. #{e.message}")
9747 @all_files = []
9748 record[:name] == "root_files/recipe.yml" ||
9749 files_for("recipes").inject([]) do |memo, recipe|
9750 rname = recipe[:name].split("/")[1]
9751 rname = File.basename(rname, ".rb")
9752 memo << "#{name}::#{rname}"
9753 files_for(segment).map { |f| f["full_path"] || File.join(root_dir, f["path"]) }
9754 path[root_dir.length + 1..-1]
9755 error_message << "

This cookbook _does_ contain: ['#{pretty_existing_files.join("','")}']"
9756 filenames_by_pref = {}
9757 preferences.each { |pref| filenames_by_pref[pref] = [] }
9758 if manifest_record_path =~ %r{(#{Regexp.escape(segment.to_s)}/[^/]*/?#{Regexp.escape(dirname)})/.+$}
9759 non_specific_path = manifest_record_path[%r{#{Regexp.escape(segment.to_s)}/[^/]*/?#{Regexp.escape(dirname)}/(.+)$}, 1]
9760 records_by_pref = {}
9761 preferences.each { |pref| records_by_pref[pref] = [] }
9762 if manifest_record_path =~ %r{(#{Regexp.escape(segment.to_s)}/[^/]+/#{Regexp.escape(dirname)})/.+$}
9763 if segment.to_sym == :files || segment.to_sym == :templates
9764 fqdn = node[:fqdn]
9765 search_versions = []
9766 parts = version.to_s.split(".")
9767 search_versions << parts.join(".")
9768 search_path = [ File.join("host-#{fqdn}", path) ]
9769 search_path << File.join("#{platform}-#{v}", path)
9770 [path]
9771 output["name"] = full_name
9772 cookbook_version = new(o["cookbook_name"] || o["name"])
9773 def self.load(name, version = "_latest")
9774 version = "_latest" if version == "latest"
9775 cb["version"]
9776 if /^404/.match?(e.to_s)
9777 json_file = "#{path}/metadata.json"
9778 rb_file = "#{path}/metadata.rb"
9779 f = File.open(json_file, "w")
9780 records.select { |record| record[:name] =~ /\.rb$/ }.inject({}) { |memo, record| memo[File.basename(record[:name], ".rb")] = record[:path]; memo }
9781 records.select { |record| record[:name] =~ /\.rb$/ }.inject({}) { |memo, record| memo[File.basename(record[:name], ".rb")] = record[:full_path]; memo }
9782 yml_files = records.select { |record| record[:name] =~ /\.(y[a]?ml)$/ }
9783 result = yml_files.inject({}) do |acc, record|
9784 if /#{(File.extname(filename) == ".yml") ? "#{base_dup_name}.yaml" : "#{base_dup_name}.yml"}$/.match?(other[:name])
9785 @policy_mode = opts[:policy_mode] || false
9786 checksum_files = {}
9787 Chef::Log.info("Saving #{cb.name}")
9788 checksums = checksum_files.inject({}) { |memo, elt| memo[elt.first] = nil; memo }
9789 if info["needs_upload"] == true
9790 Chef::Log.info("Uploading #{checksum_files[checksum]} (checksum hex = #{checksum}) to #{info["url"]}")
9791 if e.message =~ /^400/ && (retries += 1) <= 5
9792 when "409"
9793 headers = { "content-type" => "application/x-binary", "content-md5" => checksum64, "accept" => "application/json" }
9794 error_message = "Failed to upload #{file} (#{checksum}) to #{url} : #{e.message}"
9795 error_message << "
#{e.response.body}" if e.respond_to?(:response)
9796 result = to_h
9797 seg = file[:name].split("/")[0]
9798 part.to_s == seg
9799 manifest[:all_files].inject({}) do |memo, file|
9800 parts = file[:name].split("/")
9801 parent = if parts.length == 1
9802 memo[parent] ||= []
9803 memo[parent] << file
9804 segment, name = file[:name].split("/")
9805 name.nil? || segment == "root_files"
9806 all_files: [],
9807 @checksums = {}
9808 if !root_paths || root_paths.size == 0
9809 rs = Mash.new({
9810 manifest[:all_files] << rs
9811 next if parts[0] == ".."
9812 return [ "root_files/#{pathname}", pathname.to_s, "default" ] if parts.length == 1
9813 return [ name, pathname.to_s, "root_default" ]
9814 return [ name, pathname.to_s, parts[1] ]
9815 return [ name, pathname.to_s, "default" ]
9816 @metadata ||= Mash.new
9817 def [](cookbook)
9818 alias :fetch :[]
9819 @chefignores ||= {}
9820 @all_files_in_repo_paths ||=
9821 files = Dir[File.join(path, "**", "*.rb")]
9822 Chef::Log.trace("Testing #{ruby_file} for syntax errors...")
9823 file_relative_path = erb_file[/^#{Regexp.escape(cookbook_path + File::Separator)}(.*)/, 1]
9824 error_message.each_line { |l| Chef::Log.fatal(l.chomp) }
9825 @valid_cache_entries = {}
9826 cache.find(File.join(%w{cookbooks ** {*,.*}})).each do |cache_filename|
9827 @cookbook_full_file_paths = {}
9828 @lazy_files = {}
9829 @files ||= cookbooks.inject([]) do |memo, cookbook|
9830 part = manifest_record[:name].split("/")[0]
9831 @lazy_files[cookbook] ||= []
9832 Chef::Log.info("Loading cookbooks [#{cookbooks.map { |ckbk| ckbk.name + "@" + ckbk.version }.join(", ")}]")
9833 queue << lambda do |lock|
9834 cache.find(File.join(%w{cookbooks ** {*,.*}})).each do |cache_file|
9835 cache_file =~ %r{^cookbooks/([^/]+)/}
9836 md = cache_file.match(%r{^cookbooks/([^/]+)/([^/]+)/(.*)})
9837 ( cookbook_name, segment, file ) = md[1..3]
9838 if manifest_segment.select { |manifest_record| manifest_record["path"] == "#{segment}/#{file}" }.empty?
9839 @rest = rest
9840 if filename =~ %r{([^/]+)/(.+)$}
9841 segment = $1
9842 @long_description = ""
9843 @maintainer = ""
9844 @maintainer_email = ""
9845 @version = Version.new("0.0.0")
9846 @source_url = ""
9847 @issues_url = ""
9848 @chef_versions = []
9849 @ohai_versions = []
9850 @gems = []
9851 @errors = []
9852 equal_so_far && other.respond_to?(field) && (other.send(field) == send(field))
9853 if /::default$/.match?(recipe_name)
9854 @recipes[unqualified_name] ||= ""
9855 cm = new
9856 acc[cb] = (constraints.empty? || constraints.size > 1) ? [] : constraints.first
9857 deps.any? { |dep| dep.match?(what, version) }
9858 Called by: #{caller_name} '#{dep_name}', #{version_constraints.map(&:inspect).join(", ")}
9859 longer use "<<" and ">>" for 'less than' and 'greater than'; use '<' and
9860 Called by: #{caller_name} '#{dep_name}', '#{constraint_str}'
9861 if arry.is_a?(Array)
9862 validate( { choice: choice }, { choice: { kind_of: String } } )
9863 if opts[:choice].is_a?(Array)
9864 validator = [ String ]
9865 validator = [ Array ]
9866 validator = [ Hash ]
9867 validator = [ Symbol ]
9868 validator = [ Numeric ]
9869 validate( { choice: choice }, { choice: { kind_of: validator } } )
9870 calculated_conflict = ((options[:default].is_a?(Array) && !options[:default].empty?) ||
9871 (options[:default].is_a?(String) && !options[:default] != "")) &&
9872 if options[:default].is_a?(String) && options[:default] != ""
9873 if options[:default].is_a?(Array) && !options[:default].empty?
9874 result["all_files"].map! { |file| file.delete("full_path"); file }
9875 file["name"] = "#{segment}/#{file["name"]}"
9876 memo << file
9877 file["name"] = file["name"].split("/")[1]
9878 result[segment] ||= []
9879 result.merge({ "frozen?" => manifest.frozen_version?, "chef_type" => "cookbook_version" })
9880 cookbook_gems = Hash.new { |h, k| h[k] = [] }
9881 args << {} unless args.last.is_a?(Hash)
9882 cookbook_gems[args.first] += args[1..]
9883 File.open("#{dir}/Gemfile", "w+") do |tf|
9884 Array(Chef::Config[:rubygems_url] || "https://rubygems.org").each do |s|
9885 tf.puts "source '#{s}'"
9886 tf.puts "gem(*#{([gem_name] + args).inspect})"
9887 cmd = [ "bundle", "install", Chef::Config[:gem_installer_bundler_options] ]
9888 env = {
9889 so = shell_out!(cmd, cwd: dir, env: env)
9890 @relative_path = %r{#{Regexp.escape(cookbook_path)}/(.+)$}
9891 all_files: {},
9892 when /\.rb$/
9893 when /\.json$/
9894 if !empty? && !metadata.valid?
9895 next if File.directory?(top_path) && top_filename.start_with?(".")
9896 @frozen = data["frozen?"]
9897 super() do |hash, key|
9898 @ignores.any? { |glob| File.fnmatch?(glob, file_name) }
9899 ignore_globs = []
9900 File.exist?(path) && File.readable?(path) &&
9901 (File.file?(path) || File.symlink?(path))
9902 http.get("")
9903 !!(config_location =~ %r{^(http|https)://})
9904 evt_loggers = []
9905 evt_loggers << :win_evt
9906 select(&:enabled?).each_with_object({}) { |waiver, hash| hash.merge!(waiver.inspec_data) }
9907 (cookbook_name, waiver_name) = arg.split("::")
9908 waivers = select { |waiver| /^#{cookbook_name}$/.match?(waiver.cookbook_name) && /^#{waiver_name}$/.match?(waiver.pathname) }
9909 @data = data
9910 !!@enabled
9911 logger.debug("#{self.class}##{__method__}: #{Inspec::Dist::PRODUCT_NAME} profiles? #{inspec_profiles.any?}")
9912 logger.debug("#{self.class}##{__method__}: audit cookbook? #{audit_cookbook_present}")
9913 logger.debug("#{self.class}##{__method__}: compliance phase attr? #{node["audit"]["compliance_phase"]}")
9914 logger.debug("#{self.class}##{__method__}: enabling Compliance Phase")
9915 values = deprecated_config_values.sort.map { |v| "'#{v}'" }.join(", ")
9916 if !node["audit"]["inputs"].empty?
9917 node["audit"]["inputs"].to_h
9918 node["audit"]["attributes"].to_h
9919 inputs["chef_node"] = node.to_h
9920 output: node["audit"]["quiet"] ? ::File::NULL : STDOUT,
9921 Array(node["audit"]["waiver_file"])
9922 profiles = node["audit"]["profiles"]
9923 unless profiles.respond_to?(:map) && profiles.all? { |_, p| p.respond_to?(:transform_keys) && p.respond_to?(:update) }
9924 end || []
9925 case node["audit"]["fetcher"]
9926 runlist_roles = node.run_list.select { |item| item.type == :role }.map(&:name)
9927 runlist_recipes = node.run_list.select { |item| item.type == :recipe }.map(&:name)
9928 os: {
9929 policy_name: node.policy_name || "",
9930 policy_group: node.policy_group || "",
9931 organization_name: chef_server_uri.path.split("/").last || "",
9932 source_fqdn: chef_server_uri.host || "",
9933 fqdn: node["fqdn"],
9934 insecure: node["audit"]["insecure"],
9935 run_id: run_id,
9936 run_time_limit: node["audit"]["run_time_limit"],
9937 path = node.dig("audit", "json_file", "location")
9938 when "cli"
9939 url = if node["audit"]["server"]
9940 URI(node["audit"]["server"])
9941 URI(Chef::Config[:chef_server_url]).tap do |u|
9942 u.path = ""
9943 org = Chef::Config[:chef_server_url].split("/").last
9944 @reporters = {}
9945 unless (fetcher = node["audit"]["fetcher"]).nil?
9946 if !node["audit"]["attributes"].empty? && !node["audit"]["inputs"].empty?
9947 (Array(node["audit"]["reporter"]) + ["cli"]).uniq
9948 @interval_time ||= node.read("audit", "interval", "time")
9949 @interval_enabled ||= node.read("audit", "interval", "enabled")
9950 @path = opts.fetch(:file)
9951 if @path.nil? || @path.class != String || @path.empty?
9952 output = ["
Compliance report:"]
9953 output << " * #{profile[:title]}"
9954 output << "#{" " * 6}#{control[:title]}"
9955 output << "
"
9956 puts output.join("
")
9957 if result[:status] == "failed"
9958 output << pastel.red("#{" " * 9}- #{result[:code_desc]}")
9959 result[:message].split(/
/).reject(&:empty?).each do |m|
9960 output << pastel.red("#{" " * 12}#{m}")
9961 output << pastel.red("#{" " * 9}#{m}")
9962 output << pastel.red("#{" " * 9}- #{result[:status]}")
9963 output << pastel.green("#{" " * 9}+ #{result[:code_desc]}")
9964 output << pastel.green("#{" " * 9}+ #{result[:status]}")
9965 when /404/
9966 when /413/
9967 when /429/
9968 msg = "Received HTTP error #{code}"
9969 unless @url && @token
9970 headers = {
9971 all_report_shas = report[:profiles].map { |p| p[:sha256] }
9972 Chef::Log.info "Report to #{ChefUtils::Dist::Automate::PRODUCT}: #{@url}"
9973 Chef::Log.error "send_report: POST to #{@url} returned: #{e.message}"
9974 truncated = { failed: 0, skipped: 0, passed: 0 }
9975 (max_results..res.length - 1).each do |i|
9976 case res[i][:status]
9977 truncated[:failed] += 1
9978 truncated[:passed] += 1
9979 control[:results] = res[0..max_results - 1]
9980 meta_url = URI(@url)
9981 response_str = http_client(meta_url.to_s).post(nil, "{\"sha256\": #{report_shas}}", headers)
9982 p[:controls].each do |c|
9983 c.delete(:waiver_data) if c[:waiver_data] == {}
9984 c[:results].each do |r|
9985 if r[:run_time].is_a?(Float) && r[:run_time] < run_time_limit
9986 any?(&:enabled?)
9987 select(&:enabled?).each_with_object([]) { |profile, arry| arry << profile.inspec_data }
9988 (cookbook_name, profile_name) = arg.split("::")
9989 profiles = select { |profile| /^#{cookbook_name}$/.match?(profile.cookbook_name) && /^#{profile_name}$/.match?(profile.pathname) }
9990 @data["name"]
9991 @data["version"]
9992 { name: name, path: File.dirname(path) }
9993 select(&:enabled?).each_with_object({}) { |input, hash| hash.merge!(input.inspec_data) }
9994 (cookbook_name, input_name) = arg.split("::")
9995 inputs = select { |input| /^#{cookbook_name}$/.match?(input.cookbook_name) && /^#{input_name}$/.match?(input.pathname) }
9996 CONFIG = { "insecure" => true }.freeze
9997 path_parts = [""]
9998 path_parts << "owners"
9999 path_parts << "tar"
10000 rescue URI::Error => _e
10001 @archive_type = ".tar.gz"
10002 path = @target.respond_to?(:path) ? @target.path : path
10003 m = %r{^#{@config['server']}/owners/(?<owner>[^/]+)/compliance/(?<id>[^/]+)/tar$}.match(@target)
10004 if target.respond_to?(:key?) && target.key?(:url)
10005 owner, id = profile.split("/")
10006 profile_path = if target.respond_to?(:key?) && target.key?(:version)
10007 URI("compliance://#{profile}")
10008 uri.to_s.sub(%r{^compliance:\/\/}, "")
10009 def initialize(json_attribs = nil, args = {})
10010 @json_attribs = json_attribs || {}
10011 if Time.now > Time.new(eol_year, 5, 01)
10012 io = File.open(output_path, "a+")
10013 [:doc, log_location]
10014 [:null]
10015 @rest_clean ||=
10016 name = Chef::Config[:node_name] || ohai[:fqdn] || ohai[:machinename] || ohai[:hostname]
10017 cert_name = "chef-#{client_name}"
10018 if result.rassoc("#{cert_name}")
10019 if Chef::Config[:auth_key_registry_type] == "user"
10020 subject = "CN=#{cert_name}"
10021 public_key: "",
10022 base_url = "#{Chef::Config[:chef_server_url]}"
10023 file_path = File.join(@tmpdir, "#{node}.pem")
10024 File.open(file_path, "w") { |f| f.write expiring_cert.key.to_pem }
10025 cert_list = client.get(base_url + "/clients/#{node}/keys")
10026 client.post(base_url + "/clients/#{node}/keys", payload)
10027 cert_hash = cert_list.reduce({}, :merge!)
10028 old_cert_name = cert_hash["name"]
10029 File.open(file_path, "w") { |f| f.write new_key }
10030 client.delete(base_url + "/clients/#{node}/keys/#{old_cert_name}")
10031 tempfile = Tempfile.new("#{Chef::Config[:node_name]}.pfx")
10032 File.open(tempfile, "wb") { |f| f.print new_pfx.to_der }
10033 @run_start_notifications ||= []
10034 @run_failed_notifications ||= []
10035 File.open(path, "w+") do |file|
10036 !File.exists?(path) || (Dir.entries(path).size <= 2)
10037 object.is_a?(Array) ? index == object.size - 1 : true
10038 logger.trace "Loading from cookbook_path: #{cookbook_paths.map { |path| File.expand_path(path) }.join(", ")}"
10039 return "" if parts.length == 0
10040 absolute = parts[0].length == 0 || parts[0].length > 0 && parts[0] =~ /^#{regexp_path_separator}/
10041 parts = parts.map { |part| part.gsub(/^#{regexp_path_separator}+|#{regexp_path_separator}+$/, "") }
10042 result = parts.select { |part| part != "" }.join("/")
10043 absolute ? "/#{result}" : result
10044 ChefUtils.windows? ? "[\\/\\\\]" : "/"
10045 !!(path =~ /^#{regexp_path_separator}/)
10046 suffix = []
10047 ChefUtils.windows? ? left.casecmp(right) == 0 : left == right
10048 path[ancestor.length + 1..-1]
10049 @cache = {}
10050 @cache[path] ||= { "children" => [] }
10051 @cache[path]["children"] = val
10052 if @cache.key?(path)
10053 if !parent.nil? && @cache.key?(parent)
10054 !is_dir && name.include?("-")
10055 require_relative "../../path_utils"
10056 @file_path = file_path || "#{parent.file_path}/#{name}"
10057 Chef::Log.error("Could not read #{path_for_printing} into a Chef object: #{$!}")
10058 !name.start_with?(".")
10059 .map { |child_name| make_child_entry(child_name) }
10060 .select { |new_child| new_child.fs_entry_valid? && can_have_child?(new_child.name, new_child.dir?) }
10061 File.exist?(file_path) && (parent.nil? || parent.can_have_child?(name, dir?))
10062 if file_contents && write_pretty_json && File.extname(name) == ".json"
10063 File.open(file_path, "wb") do |file|
10064 Dir.entries(file_path).select { |p| !p.start_with?(".") }
10065 is_dir && !name.start_with?(".")
10066 super("", nil)
10067 @children ||= begin
10068 result += CHILDREN.map { |name| make_child_entry(name) }
10069 result.select { |c| c && c.exists? }.sort_by(&:name)
10070 repo_paths = root_paths || [ File.dirname(child_paths["cookbooks"][0]) ]
10071 result = "repository at #{repo_paths.join(", ")}"
10072 result << " (One version per cookbook)"
10073 if paths.any? { |path| !repo_paths.include?(File.dirname(path)) }
10074 paths = (child_paths[name] || []).select { |path| File.exist?(path) }
10075 if paths.size == 0
10076 dirs = paths.map { |path| AclsDir.new(name, self, path) }
10077 dirs = paths.map { |path| ClientKeysDir.new(name, self, path) }
10078 dirs = paths.map { |path| ClientsDir.new(name, self, path) }
10079 dirs = paths.map { |path| ContainersDir.new(name, self, path) }
10080 dirs = paths.map { |path| CookbooksDir.new(name, self, path) }
10081 dirs = paths.map { |path| DataBagsDir.new(name, self, path) }
10082 dirs = paths.map { |path| GroupsDir.new(name, self, path) }
10083 dirs = paths.map { |path| NodesDir.new(name, self, path) }
10084 dirs = paths.map { |path| PoliciesDir.new(name, self, path) }
10085 dirs = paths.map { |path| RolesDir.new(name, self, path) }
10086 dirs = paths.map { |path| UsersDir.new(name, self, path) }
10087 .select { |child| child && can_have_child?(child.name, child.dir?) }
10088 entries.select { |entry| !(entry.dir? && entry.children.size == 0 ) }
10089 return recursive && name != "." && name != ".."
10090 return false if name[-3..] != ".rb"
10091 File.open(file_path, "rb", &:read)
10092 if can_have_child?(name, true) || can_have_child?(name, false)
10093 Chef::ChefFS::FileSystem.copy_to(Chef::ChefFS::FilePattern.new("/#{cookbook_path}"), from_fs, self, nil, { purge: true })
10094 Chef::Log.error("Could not read #{path_for_printing} into a Chef object: #{e}")
10095 Chef::Log.error(e.backtrace.join("
"))
10096 super.select { |entry| !(entry.dir? && entry.children.size == 0 ) }
10097 if is_dir && !%w{ root_files .. . }.include?(name)
10098 if %w{ .rb .json }.include? File.extname(name)
10099 name = File.basename(name, ".*")
10100 file_path = "#{parent.file_path}/#{name}"
10101 ext = File.exist?(file_path + ".rb") ? ".rb" : ".json"
10102 name += ext
10103 file_path += ext
10104 Chef::Log.trace "BaseFile: got a file path of #{file_path} for #{name}"
10105 File.basename(name, ".*")
10106 File.extname(file_path) == ".json"
10107 File.extname(file_path) == ".rb"
10108 !name.start_with?(".") && (is_json_file? || is_ruby_file?)
10109 name_valid? && exists?
10110 def delete(_)
10111 if name == "organization" && parent.is_a?(AclDir)
10112 @children = []
10113 @children.find { |child| child.name == name }
10114 root.cannot_be_in_regex ? (name !~ root.cannot_be_in_regex) : true
10115 path_parts = path.split("/")
10116 dir = add_dir(path_parts[0..-2].join("/"))
10117 dir = self
10118 if cause && cause.is_a?(Net::HTTPExceptions) && cause.response.code == "400"
10119 reason ||=
10120 result = @children.find { |child| child.name == name } if @children
10121 @cookbook_name = $1
10122 @version = $2
10123 require_relative "../../../role"
10124 require_relative "../../../node"
10125 require_relative "../../../json_compat"
10126 pth = api_path.start_with?("/") ? api_path : "/#{api_path}"
10127 File.extname(pth).empty? ? pth + ".json" : pth
10128 if $!.response.code == "404"
10129 return [ nil, nil, :none ]
10130 @api_path = api_path || (parent.api_path == "" ? name : "#{parent.api_path}/#{name}")
10131 @children ||= root.get_json(api_path).keys.sort.map do |key|
10132 elsif $!.response.code == "409"
10133 @children.find { |child| child.name == name } if @children
10134 def api_path(options = {})
10135 policy_datas = {}
10136 get_data =
10137 rest.put("#{api_path}/policies/#{policy_name}", policy_data)
10138 rest.delete("#{api_path}/policies/#{policy_name}")
10139 @children = names.uniq.map { |name| make_child_entry(name, true) }
10140 actual_invites = _read_json.inject({}) { |h, val| h[val["username"]] = val["id"]; h }
10141 rest.post(api_path, { "user" => invite })
10142 if File.basename(name, ".*") == "_default"
10143 @children ||= root.get_json(api_path).keys.sort.map { |entry| make_child_entry(entry, true) }
10144 rest.post(api_path, { "name" => name })
10145 pth = "/data_bags/#{parent.name}/#{name}"
10146 @exists = nil
10147 @exists = parent.children.any? { |child| child.name == name }
10148 require_relative "../../../mixin/file_class"
10149 return false if @ruby_only && name !~ /\.rb$/
10150 require_relative "../../../http/simple"
10151 @file = file
10152 return [ false, nil, :none ]
10153 require_relative "../../../cookbook_version"
10154 require_relative "../../../cookbook_uploader"
10155 children.find { |child| child.name == name }
10156 parts = file[:path].split("/")
10157 parts[0, parts.length - 1].each do |part|
10158 return [ !exists?, nil, nil ]
10159 [ are_same, nil, nil ]
10160 def copy_from(other, options = {})
10161 if e.response.code == "500"
10162 is_dir && name.include?("-")
10163 @cookbook_name, dash, @version = name.rpartition("-")
10164 require_relative "../../../server_api"
10165 result = children.find { |child| child.name == name }
10166 result && !!result.dir? == !!is_dir
10167 @org ||= begin
10168 result = [
10169 DataBagsDir.new("data_bags", self, "data"),
10170 result += [
10171 AclsDir.new("acls", self),
10172 pth = if parent.name == "acls"
10173 rest.put("#{api_path}/#{permission}", { permission => acls[permission] })
10174 names = parent.parent.child(name).children.map { |child| child.dir? ? "#{child.name}.json" : child.name }
10175 @children = names.map { |name| make_child_entry(name, true) }
10176 if name != ""
10177 @path = "/"
10178 if parent_path == "."
10179 @root = root
10180 return resolve_path(entry.root, path) if path[0, 1] == "/" && entry.root != entry
10181 if path[0, 1] == "/"
10182 path = path[1, path.length - 1]
10183 @a_root = a_root
10184 @b_root = b_root
10185 yield [ a, b ]
10186 result << [ a_child, b.child(a_child.bare_name) ]
10187 result << [ a.child(b_child.bare_name), b_child ]
10188 are_same, a_value, b_value = a.compare_to(b)
10189 are_same, b_value, a_value = b.compare_to(a)
10190 a_value = a.read if a_value.nil?
10191 a_value = :none
10192 b_value = b.read if b_value.nil?
10193 b_value = :none
10194 are_same = (a_value == b_value)
10195 [ are_same, a_value, b_value ]
10196 result = { "total" => 0, "success_count" => 0, "failed" => [] }
10197 failure = { "src_path" => src_path, "reason" => "Entry #{dest_path} does not exist" }
10198 if options[:force] || compare(src_entry, dest_entry)[0] == false
10199 result["total"] += 1
10200 result["success_count"] += 1
10201 if options[:diff] == false
10202 failure = { "src_path" => src_path, "reason" => e.reason }
10203 ui.warn "#{format_path.call(e.entry)} #{e.reason}." if ui
10204 ui.error "#{format_path.call(e.entry)} failed to #{e.operation}: #{e.message}" if ui
10205 ui.error "#{format_path.call(e.entry)} #{e.reason}." if ui
10206 return false if path == "" # Empty string is not a path
10207 full_regexp_parts = []
10208 @regexp_parts = []
10209 @exact_parts = []
10210 if ["", "."].include?(exact)
10211 if exact == ".."
10212 @regexp_parts << Regexp.new("^#{regexp}$")
10213 @pattern_special_characters ||= /(\*\*|\*|\?|[\*\?\.\|\(\)\[\]\{\}\+\\\\\^\$])/
10214 regexp = ""
10215 exact = ""
10216 when "**"
10217 regexp << ".*"
10218 when "*"
10219 regexp << "[^\\/]*"
10220 when "?"
10221 regexp << "."
10222 if part[0, 1] == "\\" && part.length == 2
10223 exact << part[1, 1] unless exact.nil?
10224 regexp << part[1, 1]
10225 elsif part[0, 1] == "[" && part.length > 1
10226 regexp << "\\#{part}"
10227 key == "name"
10228 require_relative "../../role"
10229 defaults = {
10230 if name =~ /^(.*)-([^-]*)$/
10231 name, revision_id = $1, $2
10232 revision_id ||= "0.0.0"
10233 [ name, revision_id ]
10234 if object_data["name"] != name
10235 yield("Object name '#{object_data["name"]}' doesn't match entry '#{name}'.")
10236 yield("Object revision ID '#{object_data["revision_id"]}' doesn't match entry '#{revision}'.")
10237 members.map { |member| member.is_a?(Hash) ? member["user"]["username"] : member }.sort.uniq
10238 if entry.org != object["name"]
10239 yield("Name must be '#{entry.org}' (is '#{object["name"]}')")
10240 require_relative "../../node"
10241 require_relative "../../api_client"
10242 if result["actors"] && result["actors"].sort.uniq == (result["users"] + result["clients"]).sort.uniq
10243 result["actors"] = {
10244 result << "cookbook #{name.inspect}, #{version.inspect}"
10245 if default_object[key] == value && !preserve_key?(key)
10246 def remove_file_extension(name, ext = ".*")
10247 if %w{ .rb .json }.include?(File.extname(name))
10248 normalize({}, entry)
10249 result[key] = object.is_a?(Hash) && object.key?(key) ? object[key] : value
10250 when /^recipe\[.*\]$/
10251 when /^role\[.*\]$/
10252 r.to_h
10253 result = ""
10254 if object[key].is_a?(Hash)
10255 if object[key].size > 0
10256 result << key
10257 object[key].each_pair do |k, v|
10258 result << " " * key.length
10259 result << " #{k.inspect} => #{v.inspect}
"
10260 result << ", "
10261 result << "
"
10262 result << "#{key} #{object[key].inspect}
"
10263 if object["name"] != base_name
10264 yield("Name must be '#{base_name}' (is '#{object["name"]}')")
10265 require_relative "../../data_bag_item"
10266 if data_bag_item["json_class"] == "Chef::DataBagItem" && data_bag_item["raw_data"]
10267 key == "id"
10268 if object["raw_data"]["id"] != base_name
10269 yield("ID in #{entry.path_for_printing} must be '#{base_name}' (is '#{object["raw_data"]["id"]}')")
10270 yield("Name in #{entry.path_for_printing} must be '#{base_name}' (is '#{object["containername"]}')")
10271 client["admin"] = (client["admin"] == "true") if client["admin"].is_a?(String)
10272 client["validator"] = (client["validator"] == "true") if client["validator"].is_a?(String)
10273 if entry.respond_to?(:org) && entry.org
10274 result[key] = normalize_hash(result[key], { "actors" => [], "groups" => [] })
10275 result[key]["actors"] = result[key]["actors"].sort
10276 result[key]["groups"] = result[key]["groups"].sort
10277 def initialize(chef_config = Chef::Config, cwd = Dir.pwd, options = {}, ui = nil)
10278 if @chef_config[:repo_mode] == "everything" && is_hosted? && !ui.nil?
10279 @chef_config[:chef_server_url] =~ %r{/+organizations/.+}
10280 @chef_fs ||= create_chef_fs
10281 @local_fs ||= create_local_fs
10282 return "/"
10283 @base_path ||= server_path(@cwd)
10284 return "."
10285 elsif server_path[base_path.length, 1] == "/"
10286 elsif base_path == "/" && server_path[0, 1] == "/"
10287 @object_paths ||= begin
10288 get_content = (output_mode != :name_only && output_mode != :name_status)
10289 if output_mode != :name_only && output_mode != :name_status
10290 next if diff_filter && diff_filter !~ /T/
10291 yield "#{new_path}
"
10292 yield "T\t#{new_path}
"
10293 next if diff_filter && diff_filter !~ /D/
10294 yield "D\t#{new_path}
"
10295 result = "diff --knife #{old_path} #{new_path}
"
10296 result << "deleted file
"
10297 result << diff_text(old_path, "/dev/null", old_value, "")
10298 next if diff_filter && diff_filter !~ /A/
10299 yield "A\t#{new_path}
"
10300 result << "new file
"
10301 result << diff_text("/dev/null", new_path, "", new_value)
10302 next if diff_filter && diff_filter !~ /M/
10303 yield "M\t#{new_path}
"
10304 ui.error "#{format_path.call(error.entry)} #{error.reason}." if ui
10305 [ [ :common_subdirectories, old_entry, new_entry ] ]
10306 [ [ :directory_to_file, old_entry, new_entry ] ]
10307 [ [ :deleted, old_entry, new_entry ] ]
10308 [ [ :new_cannot_upload, old_entry, new_entry ] ]
10309 [ [ :file_to_directory, old_entry, new_entry ] ]
10310 [ [ :added, old_entry, new_entry ] ]
10311 [ [ :old_cannot_upload, old_entry, new_entry ] ]
10312 if old_value == :none
10313 [ [ :both_nonexistent, old_entry, new_entry ] ]
10314 [ [ :same, old_entry, new_entry ] ]
10315 if new_value == :none
10316 return [ [ :old_cannot_upload, old_entry, new_entry ] ]
10317 return [ [ :new_cannot_upload, old_entry, new_entry ] ]
10318 if old_value == :none || (old_value.nil? && !old_entry.exists?)
10319 [ [ :added, old_entry, new_entry, old_value, new_value ] ]
10320 [ [ :deleted, old_entry, new_entry, old_value, new_value ] ]
10321 [ [ :modified, old_entry, new_entry, old_value, new_value ] ]
10322 [ [ :error, old_entry, new_entry, nil, nil, e ] ]
10323 json_object.map { |o| sort_keys(o) }
10324 new_hash = {}
10325 json_object.keys.sort.each { |key| new_hash[key] = sort_keys(json_object[key]) }
10326 result = result.gsub(/^--- #{old_tempfile.path}/, "--- #{old_path}")
10327 result = result.gsub(/^\+\+\+ #{new_tempfile.path}/, "+++ #{new_path}")
10328 @chef_fs = chef_fs
10329 with_parent_dir(path + [name], *options) do |parent, name|
10330 elsif path[0] == "cookbooks" && path.length == 2
10331 elsif path[0] == "policy_groups" && path[2] == "policies"
10332 update_json(to_chef_fs_path(path[0..1]), {}, *options) do |group|
10333 group["policies"] ||= {}
10334 group["policies"][path[3]] = { "revision_id" => Chef::JSONCompat.parse(data) }
10335 elsif is_org? && path == [ "users" ]
10336 update_json("members.json", [], *options) do |members|
10337 if members.any? { |member| member["user"]["username"] == name }
10338 members << { "user" => { "username" => name } }
10339 elsif is_org? && path == [ "association_requests" ]
10340 if invitations.any? { |member| member["username"] == name }
10341 invitations << { "username" => name }
10342 elsif path[0] == "file_store" && path[1] == "repo"
10343 entry = Chef::ChefFS::FileSystem.resolve_path(chef_fs, path[2..].join("/"))
10344 elsif path[0] == "policy_groups" && path[2] == "policies" && path.length == 4
10345 policy_group = get_json(to_chef_fs_path(path[0..1]), {})
10346 if !policy_group["policies"] || !policy_group["policies"][path[3]]
10347 elsif is_org? && path[0] == "users" && path.length == 2
10348 if get_json("members.json", []).any? { |member| member["user"]["username"] == path[1] }
10349 elsif is_org? && path[0] == "association_requests" && path.length == 2
10350 if get_json("invites.json", []).any? { |member| member["user"]["username"] == path[1] }
10351 if file.is_a?(Hash) && file.key?("checksum")
10352 relative = ["file_store", "repo", cookbook_type]
10353 relative << "#{path[1]}-#{path[2]}"
10354 relative << path[1]
10355 relative += file[:path].split("/")
10356 value == [] ||
10357 (value == {} && !%w{dependencies attributes recipes}.include?(key)) ||
10358 (value == "" && %w{source_url issues_url}.include?(key)) ||
10359 (value == false && key == "privacy")
10360 raise "set only works with strings: #{path} = #{data.inspect}"
10361 update_json(to_chef_fs_path(path[0..1]), {}) do |group|
10362 unless group["policies"] && group["policies"].key?(path[3])
10363 update_json("members.json", []) do |members|
10364 result = members.reject { |member| member["user"]["username"] == path[1] }
10365 elsif path[0] == "policies" && path.length == 2
10366 with_entry(path[0..0]) do |policies|
10367 next unless policy.name.rpartition("-")[0] == path[1]
10368 elsif path == [ "policies" ]
10369 with_entry([ path[0] ]) do |policies|
10370 policies.children.map { |policy| policy.name[0..-6].rpartition("-")[0] }.uniq
10371 elsif path[0] == "policies" && path[2] == "revisions" && path.length == 3
10372 revisions = []
10373 name, dash, revision = policy.name[0..-6].rpartition("-")
10374 revisions << revision if name == path[1]
10375 elsif path[0] == "policy_groups" && path.length == 2
10376 [ "policies" ]
10377 elsif path[0] == "policy_groups" && path[2] == "policies" && path.length == 3
10378 with_entry(path[0..1]) do |entry|
10379 policies = Chef::JSONCompat.parse(entry.read)["policies"] || {}
10380 entry.children.map { |child| child.name.rpartition("-")[0] }.uniq
10381 result = with_entry([ path[0] ]) do |entry|
10382 .select { |name, version| name == path[1] }
10383 .map { |name, version| version }
10384 if path == [] && ChefZero::VERSION.to_f < 4.4
10385 group = get_json(to_chef_fs_path(path[0..1]), {})
10386 group["policies"] && group["policies"].key?(path[3])
10387 list([ path[0] ]).include?(path[1])
10388 exists_dir?(path[0..1])
10389 path[0] == "sandboxes" || path[0] == "file_store" && path[1] == "checksums" || path == %w{environments _default}
10390 cookbook_path = File.join(cookbook_type, "#{path[1]}-#{path[2]}")
10391 file_data = @memory_store.get(["file_store", "checksums", file["checksum"]])
10392 name_version = entry_name.split("-")
10393 name = name_version[0..-2].join("-")
10394 _to_chef_fs_path(path).join("/")
10395 _to_chef_fs_path(path)[-1]
10396 if path[0] == "data"
10397 path[0] = "data_bags"
10398 if path.length >= 3
10399 path[2] = "#{path[2]}.json"
10400 elsif path[0] == "client_keys"
10401 path[-1] += ".json"
10402 elsif path[0] == "policies" && path[2] == "revisions" && path.length >= 4
10403 path = [ "policies", "#{path[1]}-#{path[3]}.json" ]
10404 if path.length == 2
10405 path = [ path[0], "#{path[1]}-#{path[2]}" ] + path[3..-1]
10406 if path[2] == version
10407 path = path[0..1] + path[3..-1]
10408 elsif path[0] == "acls"
10409 if path[1] == "data"
10410 path[1] = "data_bags"
10411 if path.length == 3 || path == %w{acls organization}
10412 path[-1] = "#{path[-1]}.json"
10413 path = entry.path.split("/")[1..-1]
10414 if path[0] == "data_bags"
10415 path[0] = "data"
10416 path[2] = path[2][0..-6]
10417 if path.size == 2
10418 path << "keys"
10419 path[2..-1] = [ "keys", path[-1][0..-6] ]
10420 if path.length >= 2
10421 path = [ path[0], name, version ] + path[2..-1]
10422 path = path[0..1] + [version] + path[2..-1]
10423 elsif path[0] == "policies"
10424 name, dash, revision = path[1][0..-6].rpartition("-")
10425 path = [ "policies", name, "revisions", revision ]
10426 elsif path.length == 2 && path[0] != "cookbooks"
10427 path[1] = path[1].gsub(/\.(rb|json)$/, "")
10428 to_zero_path(entry)[-1]
10429 path = _to_chef_fs_path(path)
10430 yield get_dir(path[0..-2], options.include?(:create_dir)), path[-1]
10431 create = !(path[0] == "data" && path.size >= 2)
10432 elsif create || path.size == 1
10433 dir = Chef::ChefFS::FileSystem.resolve_path(chef_fs, path[0..1].join("/"))
10434 metadata[:version] || "0.0.0"
10435 Chef::Log.warn("Removing item #{item}")
10436 parts[0..-2].each do |part|
10437 parts = item.split("/")
10438 new_data = {}
10439 filtered_data[part] ||= {}
10440 filtered_data[parts[-1]] = all_data[parts[-1]]
10441 require_relative "../../chef"
10442 short: "-d",
10443 long: "--daemonize",
10444 proc: lambda { |p| true }
10445 load_dot_d(Chef::Config[:solo_d_dir]) if Chef::Config[:solo_d_dir]
10446 Chef::Config[:fips] = config[:fips] if config.key? :fips
10447 if !Chef::Config.key?(:cookbook_path) && !Chef::Config.key?(:chef_repo_path)
10448 Chef::Config[:interval] ||= 1800
10449 cookbooks_path = Array(Chef::Config[:cookbook_path]).detect { |e| Pathname.new(e).cleanpath.to_s =~ %r{/cookbooks/*$} }
10450 long: "--daemonize [WAIT]",
10451 proc: lambda { |wait| /^\d+$/.match?(wait) ? wait.to_i : true }
10452 proc: lambda { |items|
10453 items = items.split(",")
10454 raise Chef::Exceptions::PIDFileLockfileMatch if Chef::Util::PathHelper.paths_eql? (Chef::Config[:pid_file] || "" ), (Chef::Config[:lockfile] || "")
10455 if Chef::Config.local_mode && !Chef::Config.key?(:cookbook_path) && !Chef::Config.key?(:chef_repo_path)
10456 (existing ||= []) << option
10457 long: "--once",
10458 long: "--force-logger",
10459 long: "--force-formatter",
10460 long: "--[no-]profile-ruby",
10461 long: "--[no-]color",
10462 long: "--log_level LEVEL",
10463 proc: lambda { |l| l.to_sym }
10464 long: "--[no-]always-dump-stacktrace",
10465 long: "--user USER",
10466 proc: lambda { |s| s.to_i }
10467 short: "-f",
10468 long: "--[no-]fork",
10469 short: "-W",
10470 long: "--why-run",
10471 long: "--minimal-ohai",
10472 long: "--ez",
10473 proc: lambda { |target|
10474 long: "--disable-config",
10475 short: "-A",
10476 long: "--[no-]fips",
10477 long: "--legacy-mode",
10478 short: "-R",
10479 long: "--local-mode",
10480 long: "--chef-zero-host HOST",
10481 long: "--chef-zero-port PORT",
10482 long: "--[no-]listen",
10483 long: "--[no-]slow-report [COUNT]",
10484 trap("USR1") do
10485 if !Chef::Config[:client_fork] || Chef::Config[:once]
10486 Chef::Application.fatal!("#{e.class}: #{e.message}", e)
10487 uri = URI.parse(url)
10488 elsif uri.scheme == "s3"
10489 object = s3.get_object(bucket: bucket_name, key: uri.path[1..-1])
10490 File.open(path, "wb") do |f|
10491 URI.open(url) do |r|
10492 Chef::Log.error("#{e.class}: #{e}")
10493 Chef::Log.trace("#{e.class}: #{e}
#{e.backtrace.join("
")}")
10494 return unless IO.select([ SELF_PIPE[0] ], nil, nil, sec)
10495 long: "--stdin",
10496 long: "--yaml",
10497 recipe = Chef::Recipe.new("(#{ChefUtils::Dist::Apply::EXEC} cookbook)", "(#{ChefUtils::Dist::Apply::EXEC} recipe)", run_context)
10498 if config[:yaml] || File.extname(@recipe_filename) == ".yml"
10499 if cli_arguments.is_a?(Array) &&
10500 (cli_arguments.empty? || cli_arguments.all? { |file| File.file?(file) } )
10501 cli_arguments.select { |file| !File.file?(file) }.join('", "') + '"')
10502 when :win_evt, "win_evt"
10503 if chef_config[:log_level] == :auto
10504 $0 = "#{client_solo} worker: ppid=#{Process.ppid};start=#{Time.new.strftime("%R:%S")};"
10505 message = "#{e.class}: #{e}
#{e.backtrace.join("
")}"
10506 cause = e.cause if e.respond_to?(:cause)
10507 message << "

>>>> Caused by #{cause.class}: #{cause}
#{cause.backtrace.join("
")}"
10508 cause = cause.respond_to?(:cause) ? cause.cause : nil
10509 def fatal!(msg, err = nil)
10510 msg << "
#{err.backtrace.join("
")}"
10511 def exit!(msg, err = nil)
10512 @chef_rest_v0 ||= Chef::ServerAPI.new(Chef::Config[:chef_server_url], { api_version: "0", inflate_json_class: false })
10513 @chef_rest_v1 ||= Chef::ServerAPI.new(Chef::Config[:chef_server_url], { api_version: "1", inflate_json_class: false })
10514 regex: /^[\-[:alnum:]_\.]+$/
10515 client.name(o["name"] || o["clientname"])
10516 client.public_key(o["public_key"]) if o.key?("public_key")
10517 client.create_key(o["create_key"]) if o.key?("create_key")
10518 n = from_hash(n) if n.instance_of?(Hash)
10519 response[n.name] = n
10520 response = http_api.get("clients/#{name}")
10521 chef_rest_v1.delete("clients/#{@name}")
10522 payload = { name: name }
10523 if new_client["chef_key"]["private_key"]
10524 new_client["private_key"] = new_client["chef_key"]["private_key"]
10525 new_client["public_key"] = new_client["chef_key"]["public_key"]
10526 retries -= 1
10527 Chef::Log.warn("Response: HTTP #{e.response.code} - #{e}")
10528 if (File.exist?(abs_path) && !File.writable?(abs_path)) || !File.writable?(File.dirname(abs_path))
10529 response = http_api.put("clients/#{name}", put_data)
10530 base_put_data = { name: name, admin: false }
10531 post_data = { name: name, admin: false }
10532 api_version: "0",
10533 Chef::ServerAPI.new(Chef::Config[:chef_server_url], { api_version: "0" })
10534 n = json_create(n) if n.instance_of?(Hash)
10535 http_api.delete("clients/#{@name}")
10536 http_api.put("clients/#{name}", { name: name, admin: admin, validator: validator })
10537 @http_api ||= Chef::ServerAPI.new(Chef::Config[:chef_server_url], { api_version: "0" })
10538 @pending_updates = []
10539 ( max_nesting.nil? || rec.nesting_level <= max_nesting ) &&
10540 ( rec.status == :up_to_date && up_to_date ||
10541 rec.status == :skipped && skipped ||
10542 rec.status == :updated && updated ||
10543 rec.status == :failed && failed ||
10544 let(:knife) { Chef::Knife.new }
10545 let(:config_location) { File.expand_path("~/.chef/config.rb") }
10546 chef_config_dir: "/etc/chef")
10547 { "Accept" => "application/json",
10548 let(:request_id) { "1234" }
10549 let(:request_mock) { {} }
10550 let(:url) { URI.parse("https://api.opscode.piab") }
10551 http_response = Net::HTTPSuccess.new("1.1", "200", "successful rest req")
10552 let(:body) { "ninja" }
10553 extra_opts = {}
10554 extra_opts[:editor] = { long: "--editor EDITOR",
10555 default: "/usr/bin/vim" }
10556 expect { Chef::Knife.run(%w{fuuu uuuu fuuuu}) }.to raise_error(SystemExit) { |e| expect(e.status).not_to eq(0) }
10557 deps { other_deps_loaded = true }
10558 let(:command) { KnifeSpecs::TestYourself.new([]) }
10559 let(:fake_config) { "/does/not/exist/knife.rb" }
10560 knife.ui = Chef::Knife::UI.new(stdout, stderr, stdin, {})
10561 [ 2, 3 ].each do |verbosity|
10562 let(:stdin) { StringIO.new }
10563 let(:ui) { Chef::Knife::UI.new(stdout, stderr, stdin, disable_editing: true) }
10564 cmd.ui = ui
10565 let(:knife) {
10566 let(:ui) { Chef::Knife::UI.new(stdout, stderr, stdin, {}) }
10567 knife.ui = ui
10568 response = Net::HTTPForbidden.new("1.1", "403", "Forbidden")
10569 ENV["http_proxy"] = "xyz"
10570 response = Net::HTTPBadRequest.new("1.1", "400", "Bad Request")
10571 response = Net::HTTPBadGateway.new("1.1", "502", "Bad Gateway")
10572 expect(stderr.string).to match(/ERROR: Network Error: .* - y u no shut up/)
10573 let(:knife) { Chef::Knife::UserShow.new }
10574 let(:user_mock) { double("user_mock") }
10575 let(:root_rest) { double("Chef::ServerAPI") }
10576 @user_name = "foobar"
10577 @password = "abc123"
10578 @user = double("Chef::User")
10579 knife.name_args = [ "my_user" ]
10580 knife.name_args = []
10581 @org_name = "abc_org"
10582 knife.name_args << @user_name << @org_name
10583 @org = double("Chef::Org")
10584 let(:orgs) do
10585 [@org]
10586 result = { "organizations" => [] }
10587 allow(@org).to receive(:[]).with("organization").and_return({ "name" => "test" })
10588 let(:user_mock) { double("user_mock", private_key: "private_key") }
10589 knife.name_args = [ "a_user" ]
10590 knife.config[:file] = "/tmp/a_file"
10591 @knife.name_args << @user_name << @password
10592 result = { "password" => [], "recovery_authentication_enabled" => true }
10593 allow(@user).to receive(:[]).with("organization")
10594 expect(@user.root_rest).to receive(:put).with("users/#{@user_name}", result)
10595 let(:knife) { Chef::Knife::UserList.new }
10596 let(:knife) { Chef::Knife::UserEdit.new }
10597 knife.name_args = [ "my_user2" ]
10598 data = { "username" => "my_user2" }
10599 edited_data = { "username" => "edit_user2" }
10600 allow(result).to receive(:[]).with("private_key").and_return(@key)
10601 let(:non_admin_member_org) { Chef::Org.new("non-admin-member") }
10602 let(:solo_admin_member_org) { Chef::Org.new("solo-admin-member") }
10603 let(:username) { "test_user" }
10604 let(:knife) { Chef::Knife::UserDelete.new }
10605 [{ "organization" => { "name" => "non-admin-member" } },
10606 { "organization" => { "name" => "solo-admin-member" } },
10607 { "organization" => { "name" => "shared-admin-member" } },
10608 let(:non_removable_orgs) { [ solo_admin_member_org ] }
10609 let(:non_removable_orgs) { [] }
10610 let(:removable_orgs) { [ shared_admin_member_org ] }
10611 let(:non_removable_orgs) { [ ] }
10612 expect(v.to_hash).to eq(orgs[x].to_hash)
10613 let(:knife) { Chef::Knife::UserCreate.new }
10614 let(:chef_root_rest_v0) { double("Chef::ServerAPI") }
10615 let(:name_args) { [] }
10616 let(:fieldname) { "username" }
10617 let(:name_args) { %w{some_user some_display_name} }
10618 let(:fieldname) { "first name" }
10619 let(:fieldname) { "last name" }
10620 let(:fieldname) { "email" }
10621 allow(@user).to receive(:[]).with("chef_key").and_return(@key)
10622 knife.config[:user_key] = "some_key"
10623 allow(@user).to receive(:[]).with("chef_key").and_return(nil)
10624 @username = "Created #{name_args.first}"
10625 allow(@user).to receive(:[]).with("chef_key").and_return("private_key" => @key)
10626 @uri = "http://www.example.com/1"
10627 allow(@user).to receive(:[]).with("uri").and_return(@uri)
10628 let(:request_body) {
10629 { user: "some_user" }
10630 let(:name_args) { %w{some_user} }
10631 @knife.name_args = [ Chef::Config[:node_name], "sadtag" ]
10632 @node.tags << "sadtag" << "happytag"
10633 expect(@node.tags).to eq(["happytag"])
10634 @knife.name_args = [ Chef::Config[:node_name], "happytag" ]
10635 @knife.name_args = ["cookbook_name"]
10636 @knife.name_args = []
10637 exception = double('403 "Forbidden"', code: "403")
10638 if File.exist?("/usr/bin/gnutar") || File.exist?("/bin/gnutar")
10639 expect(args.to_s).to match(/tar -czf/)
10640 @knife.config = { dry_run: true }
10641 expect(@knife).to receive(:shell_out!).with("footar -czf #{@cookbook.name}.tgz #{@cookbook.name}", { cwd: "/var/tmp/dummy" })
10642 expect(@knife).to receive(:shell_out!).with("footar -tzf #{@cookbook.name}.tgz", { cwd: "/var/tmp/dummy" })
10643 let(:noauth_rest) { double("no auth rest") }
10644 { "cookbook_name" => "mw_mysql", "cookbook_maintainer" => "car", "cookbook_description" => "Installs/Configures mw_mysql", "cookbook" => "https://supermarket.chef.io/api/v1/cookbooks/mw_mysql" },
10645 knife.name_args = ["mysql"]
10646 expect(stdout.string).to match(/#{item["cookbook_name"]}\s/)
10647 knife.name_args = [""]
10648 expect(stdout.string).to eq("
")
10649 { "cookbook_name" => "301", "cookbook_maintainer" => "markhuge", "cookbook_description" => "Installs/Configures 301", "cookbook" => "https://supermarket.chef.io/api/v1/cookbooks/301" },
10650 { "cookbook_name" => "3cx", "cookbook_maintainer" => "obay", "cookbook_description" => "Installs/Configures 3cx", "cookbook" => "https://supermarket.chef.io/api/v1/cookbooks/3cx" },
10651 describe "with -w or --with-uri" do
10652 expect(stdout.string).to match(/#{item["cookbook"]}\s/)
10653 let(:downloader) { {} }
10654 let(:repo) do
10655 knife.config = {}
10656 knife.name_args = %w{foo bar baz}
10657 knife.name_args = ["getting-started", "0.0.0.1"]
10658 knife.name_args = ["getting-started", "0.1.0"]
10659 knife.name_args = ["getting-started", "0.1"]
10660 end # end of run
10661 .with("#{@cookbook_api_url}/apache2")
10662 .with(/use --force.+download.+/i)
10663 @cookbook_data = { "version" => @version,
10664 .with(@cookbook_data["file"])
10665 context "with -f or --file" do
10666 @knife.config[:file] = @file
10667 .with("#{@cookbook_api_url}/apache2/versions/#{@version_us}")
10668 node = Chef::Node.new.tap do |n|
10669 n.automatic_attrs["fqdn"] = "foobar"
10670 n.automatic_attrs["platform"] = "mac_os_x"
10671 { name: ["name"], ipaddress: ["ipaddress"], ohai_time: ["ohai_time"],
10672 cloud: ["cloud"], run_list: ["run_list"], platform: ["platform"],
10673 expect(@query).to receive(:search).with(:node, "*:*", opts)
10674 @knife.config[:hide_by_mins] = 59
10675 expect(@query).to receive(:search).with(:node, "*:*", {})
10676 expect(@stdout.string.match(/\e.*ago/)).to be_nil
10677 let(:stdout_io) { StringIO.new }
10678 let(:stderr_io) { StringIO.new }
10679 let(:name_args) { %w{https://example.test:10443/foo} }
10680 let(:name_args) { %w{foo.test} }
10681 expected_stdout = <<~E
10682 expected_stderr = <<~E
10683 let(:name_args) { %w{ftp://lkj\\blah:example.com/blah} }
10684 ERROR: Given URI: `#{name_args[0]}' is invalid
10685 it "normalizes '*' to 'wildcard'" do
10686 describe "#cn_of" do
10687 let(:subject) { [["CN", "common name"]] }
10688 let(:subject) { [] }
10689 let(:name_args) { %w{https://foo.example.com:8443} }
10690 puts "OUT: #{stdout_io.string}"
10691 puts "ERR: #{stderr_io.string}"
10692 let(:name_args) { %w{http://foo.example.com} }
10693 let(:store) { OpenSSL::X509::Store.new }
10694 let(:trusted_certs_dir) { File.join(CHEF_SPEC_DATA.tr("/", "\\"), "trusted_certs") }
10695 .with("foo.example.com", 8443)
10696 trap(:INT, @old_signal)
10697 .with("foo.example.com") # no error
10698 @knife = Chef::Knife::Ssh.new
10699 @node_foo = {}
10700 @node_foo["fqdn"] = "foo.example.org"
10701 @node_foo["ipaddress"] = "10.0.0.1"
10702 @node_foo["cloud"] = {}
10703 @node_bar = {}
10704 @node_bar["fqdn"] = "bar.example.org"
10705 @node_bar["ipaddress"] = "10.0.0.2"
10706 @node_bar["cloud"] = {}
10707 @node_bar["target"] = "10.0.0.2"
10708 @node_foo["target"] = "10.0.0.1"
10709 @node_bar["prefix"] = "bar"
10710 @node_foo["prefix"] = "foo"
10711 expect(@knife).to receive(:session_from_list).with([["10.0.0.1", nil, "foo"], ["10.0.0.2", nil, "bar"]])
10712 ["foo.example.org", nil, nil],
10713 ["bar.example.org", nil, nil],
10714 @node_foo["cloud"]["public_hostname"] = "ec2-10-0-0-1.compute-1.amazonaws.com"
10715 @node_bar["cloud"]["public_hostname"] = "ec2-10-0-0-2.compute-1.amazonaws.com"
10716 ["ec2-10-0-0-1.compute-1.amazonaws.com", nil, nil],
10717 ["ec2-10-0-0-2.compute-1.amazonaws.com", nil, nil],
10718 @node_foo["cloud"]["public_hostname"] = ""
10719 @node_bar["cloud"]["public_hostname"] = ""
10720 @node_foo["fqdn"] = nil
10721 @node_bar["fqdn"] = nil
10722 @node_bar["fqdn"] = "foo.example.org"
10723 @node_foo["prefix"] = "config"
10724 expect(@knife.get_ssh_attribute({ "fqdn" => "fqdn" })).to eq("fqdn")
10725 @node_foo["target"] = "config"
10726 ssh_config = { timeout: 50, user: "locutus", port: 23, keepalive: true, keepalive_interval: 60 }
10727 @knife.session_from_list([["the.b.org", nil, nil]])
10728 @knife.session_from_list([["the.b.org", 123, nil]])
10729 @knife.session_from_list([["the.b.org", nil, "b-team"]])
10730 @knife.config = {}
10731 Chef::Config[:knife][:ssh_timeout] = nil
10732 Chef::Config[:knife][:ssh_timeout] = 6
10733 let(:session) { double(:session, loop: nil, close: nil) }
10734 let(:command) { "false" }
10735 let(:exit_status) { 0 }
10736 let(:exit_status2) { 0 }
10737 let(:exit_status) { 1 }
10738 let(:exit_status2) { 2 }
10739 @knife.name_args = ["name:foo.example.org", "tmux"]
10740 @knife.name_args = ["*:*", "false"]
10741 let(:exit_code) { 1 }
10742 let(:exit_code) { 0 }
10743 let(:role) { "base" }
10744 knife.name_args = [ role ]
10745 let(:role_mock) { double("role_mock") }
10746 knife.config[:format] = "json"
10747 fake_role_contents = { "foo" => "bar", "baz" => "qux" }
10748 let(:role) {}
10749 Chef::Config[:role_name] = "will"
10750 @setup.name_args = [ "will", "role[monkey]", "role[person]", "role[bucket]" ]
10751 @knife.config = {
10752 @knife.name_args = [ "will", "role[owen]", "role[mauntel]" ]
10753 @role.name("will")
10754 expect(@role.run_list[0]).to eq("role[owen]")
10755 expect(@role.run_list[1]).to eq("role[mauntel]")
10756 @setup.name_args = [ "will", "recipe[orange::chicken]", "role[monkey]", "recipe[duck::type]", "role[person]", "role[bird]", "role[town]" ]
10757 @knife.name_args = [ "will", "role[coke]", "role[pepsi]" ]
10758 expect(@role.run_list[0]).to eq("role[coke]")
10759 expect(@role.run_list[1]).to eq("role[pepsi]")
10760 @setup.name_args = [ "will", "role[monkey]", "role[dude]", "role[fixer]" ]
10761 @knife.name_args = [ "will", "role[dude]", "role[person]" ]
10762 expect(@role.run_list[0]).to eq("role[monkey]")
10763 expect(@role.run_list[1]).not_to eq("role[dude]")
10764 expect(@role.run_list[1]).to eq("role[person]")
10765 expect(@role.run_list[2]).to eq("role[fixer]")
10766 @knife.name_args = [ "will", "role[monkey]", "role[gibbon]" ]
10767 @knife.name_args = [ "will", "recipe[duck::type]", "recipe[duck::mallard]" ]
10768 expect(@role.run_list[1]).to eq("role[gibbon]")
10769 expect(@role.run_list[2]).to eq("recipe[duck::mallard]")
10770 expect(@role.run_list[3]).to eq("role[person]")
10771 expect(@role.run_list[4]).to eq("role[bird]")
10772 expect(@role.run_list[5]).to eq("role[town]")
10773 @setup.name_args = [ "will", "role[monkey]", "role[person]" ]
10774 @knife.name_args = [ "will", "role[monkey]" ]
10775 expect(@role.run_list[0]).to eq("role[person]")
10776 @knife.name_args = [ "will", "recipe[duck::type]" ]
10777 expect(@role.run_list[2]).to eq("role[bird]")
10778 expect(@role.run_list[3]).to eq("role[town]")
10779 @knife.name_args = [ "will" ]
10780 @role.run_list_for("_default") << "role[acorns]"
10781 @role.run_list_for("_default") << "role[barn]"
10782 @knife.config[:after] = "role[tree]"
10783 @knife.name_args = [ "will", "role[pad]" ]
10784 expect(@role.run_list[0]).to eq("role[acorns]")
10785 expect(@role.run_list[1]).to eq("role[barn]")
10786 @knife.config[:after] = "role[acorns]"
10787 @knife.name_args = [ "will", "role[pad]", "role[whackadoo]" ]
10788 expect(@role.run_list[1]).to eq("role[pad]")
10789 expect(@role.run_list[2]).to eq("role[whackadoo]")
10790 expect(@role.run_list[3]).to eq("role[barn]")
10791 @knife.name_args = [ "will", "role[monkey],role[duck]" ]
10792 expect(@role.run_list[1]).to eq("role[monkey]")
10793 expect(@role.run_list[2]).to eq("role[duck]")
10794 @knife.name_args = [ "will", "role[monkey], role[duck]" ]
10795 @knife.name_args = [ "will", "role[monkey]", "role[duck]" ]
10796 @knife.name_args = [ "will", "role[monkey]", "role[duck],recipe[bird::fly]" ]
10797 expect(@role.run_list[3]).to eq("recipe[bird::fly]")
10798 @knife.name_args = [ "will", "role[monkey]", "role[duck],recipe[bird::fly@1.1.3]" ]
10799 expect(@role.run_list[3]).to eq("recipe[bird::fly@1.1.3]")
10800 @knife.name_args = [ "will", "role[monkey]," ]
10801 @knife.name_args = [ "will", "role[blue]," ]
10802 @knife.name_args = [ "will", "role[black]," ]
10803 expect(@role.run_list[0]).to eq("role[blue]")
10804 expect(@role.run_list[1]).to eq("role[black]")
10805 @list = {
10806 @knife.name_args = [ "adam.rb" ]
10807 @knife.name_args = [ "adam.rb", "caleb.rb" ]
10808 Chef::Config[:env_name] = "QA"
10809 @setup.name_args = [ "will", "QA", "role[monkey]", "role[person]", "role[bucket]" ]
10810 @knife.name_args = [ "will", "QA", "role[owen]", "role[mauntel]" ]
10811 expect(@role.run_list_for("QA")[0]).to eq("role[owen]")
10812 expect(@role.run_list_for("QA")[1]).to eq("role[mauntel]")
10813 expect(@role.run_list_for("QA")[2]).to be_nil
10814 @setup.name_args = [ "will", "QA", "recipe[orange::chicken]", "role[monkey]", "recipe[duck::type]", "role[person]", "role[bird]", "role[town]" ]
10815 @setup.name_args = [ "will", "PRD", "recipe[orange::chicken]", "role[monkey]", "recipe[duck::type]", "role[person]", "role[bird]", "role[town]" ]
10816 @knife.name_args = [ "will", "QA", "role[coke]", "role[pepsi]" ]
10817 expect(@role.run_list_for("QA")[0]).to eq("role[coke]")
10818 expect(@role.run_list_for("QA")[1]).to eq("role[pepsi]")
10819 expect(@role.run_list_for("PRD")[0]).to eq("recipe[orange::chicken]")
10820 expect(@role.run_list_for("PRD")[1]).to eq("role[monkey]")
10821 expect(@role.run_list_for("PRD")[2]).to eq("recipe[duck::type]")
10822 expect(@role.run_list_for("PRD")[3]).to eq("role[person]")
10823 expect(@role.run_list_for("PRD")[4]).to eq("role[bird]")
10824 expect(@role.run_list_for("PRD")[5]).to eq("role[town]")
10825 @setup.name_args = [ "will", "QA", "role[monkey]", "role[dude]", "role[fixer]" ]
10826 @knife.name_args = [ "will", "QA", "role[dude]", "role[person]" ]
10827 expect(@role.run_list_for("QA")[1]).not_to eq("role[dude]")
10828 expect(@role.run_list_for("QA")[1]).to eq("role[person]")
10829 @knife.name_args = [ "will", "QA", "role[monkey]", "role[gibbon]" ]
10830 @knife.name_args = [ "will", "QA", "recipe[duck::type]", "recipe[duck::mallard]" ]
10831 expect(@role.run_list_for("QA")).not_to include("role[monkey]")
10832 expect(@role.run_list_for("QA")).not_to include("recipe[duck::type]")
10833 expect(@role.run_list_for("QA")[0]).to eq("recipe[orange::chicken]")
10834 expect(@role.run_list_for("QA")[1]).to eq("role[gibbon]")
10835 expect(@role.run_list_for("QA")[2]).to eq("recipe[duck::mallard]")
10836 expect(@role.run_list_for("QA")[3]).to eq("role[person]")
10837 expect(@role.run_list_for("QA")[4]).to eq("role[bird]")
10838 expect(@role.run_list_for("QA")[5]).to eq("role[town]")
10839 @setup.name_args = [ "will", "QA", "role[monkey]", "role[person]" ]
10840 @knife.name_args = [ "will", "QA", "role[monkey]" ]
10841 expect(@role.run_list_for("QA")[0]).not_to eq("role[monkey]")
10842 expect(@role.run_list_for("QA")[0]).to eq("role[person]")
10843 @knife.name_args = [ "will", "QA", "recipe[duck::type]" ]
10844 expect(@role.run_list_for("QA")[2]).to eq("role[bird]")
10845 expect(@role.run_list_for("QA")[3]).to eq("role[town]")
10846 @knife.name_args = %w{will QA}
10847 expect(@role.run_list_for("QA")[0]).to be_nil
10848 expect(@role.active_run_list_for("QA")).to eq("QA")
10849 expect(@role.run_list_for("QA")[0]).to eq("role[monkey]")
10850 @knife.name_args = [ "will", "QA", "role[pad]" ]
10851 @role.run_list_for("QA") << "role[pencil]"
10852 @role.run_list_for("QA") << "role[pen]"
10853 @knife.config[:after] = "role[pencil]"
10854 @knife.name_args = [ "will", "QA", "role[pad]", "role[whackadoo]" ]
10855 expect(@role.run_list_for("QA")[1]).to eq("role[pencil]")
10856 expect(@role.run_list_for("QA")[2]).to eq("role[pad]")
10857 expect(@role.run_list_for("QA")[3]).to eq("role[whackadoo]")
10858 expect(@role.run_list_for("QA")[4]).to eq("role[pen]")
10859 @knife.name_args = [ "will", "QA", "role[monkey],role[duck]" ]
10860 expect(@role.run_list_for("QA")[1]).to eq("role[duck]")
10861 @knife.name_args = [ "will", "QA", "role[monkey], role[duck]" ]
10862 @knife.name_args = [ "will", "QA", "role[monkey]", "role[duck]" ]
10863 @knife.name_args = [ "will", "QA", "role[monkey]", "role[duck],recipe[bird::fly]" ]
10864 expect(@role.run_list_for("QA")[2]).to eq("recipe[bird::fly]")
10865 @knife.name_args = [ "will", "QA", "role[monkey]", "role[duck],recipe[bird::fly@1.1.3]" ]
10866 expect(@role.run_list_for("QA")[2]).to eq("recipe[bird::fly@1.1.3]")
10867 @knife.name_args = [ "will", "QA", "role[monkey]," ]
10868 expect(@role.run_list_for("QA")[1]).to be_nil
10869 @knife.name_args = [ "will", "QA", "role[blue]," ]
10870 @knife.name_args = [ "will", "QA", "role[black]," ]
10871 expect(@role.run_list_for("QA")[0]).to eq("role[blue]")
10872 expect(@role.run_list_for("QA")[1]).to eq("role[black]")
10873 @role.run_list_for("QA") << "role[walnuts]"
10874 @knife.name_args = [ "will", "PRD", "role[ball]," ]
10875 @role.run_list_for("PRD") << "role[pen]"
10876 expect(@role.run_list_for("PRD")[0]).to eq("role[ball]")
10877 expect(@role.run_list_for("QA")[1]).to eq("role[walnuts]")
10878 expect(@role.run_list_for("PRD")[1]).to eq("role[pen]")
10879 @knife.name_args = [ "adam" ]
10880 @knife.name_args = ["."]
10881 @roles = {}
10882 @knife.name_args = ["dev"]
10883 k = Chef::Knife::Raw.new
10884 k.config[:method] = "GET"
10885 k.name_args = [ "/nodes" ]
10886 { "Content-Type" => "application/json",
10887 let(:org) { double("Chef::Org") }
10888 @org_name = "foobar"
10889 @knife.name_args << @org_name
10890 let(:knife) { Chef::Knife::OrgEdit.new }
10891 original_data = { "org_name" => "my_org" }
10892 data = { "org_name" => "my_org1" }
10893 @org_name = "ss"
10894 name: @org_name,
10895 @knife.name_args << @org_name << @org_full_name
10896 node.run_list = ["role[base]"]
10897 knife.name_args = [ "adam" ]
10898 @knife.name_args = [ "adam", "role[monkey]" ]
10899 expect(@node.run_list[0]).to eq("role[monkey]")
10900 @knife.name_args = [ "adam", "role[monkey],role[duck]" ]
10901 expect(@node.run_list[1]).to eq("role[duck]")
10902 @knife.name_args = [ "adam", "role[monkey], role[duck]" ]
10903 @knife.name_args = [ "adam", "role[monkey]", "role[duck]" ]
10904 @knife.name_args = [ "adam", "role[monkey]", "role[duck],recipe[bird::fly]" ]
10905 @knife.name_args = [ "adam", "role[monkey]," ]
10906 @node.run_list << "role[acorns]"
10907 @node.run_list << "role[zebras]"
10908 expect(@node.run_list[0]).to eq("role[acorns]")
10909 expect(@node.run_list[1]).to eq("role[zebras]")
10910 @node.run_list << "role[monkey]"
10911 expect(@node.run_list[0]).not_to eq("role[monkey]")
10912 expect(@knife.ui).to receive(:output).with({ "knifetest-node" => { "run_list" => [] } })
10913 @node.run_list << "recipe[duck::type]"
10914 @knife.name_args = [ "adam", "role[monkey],recipe[duck::type]" ]
10915 @knife.name_args = [ "adam", "role[monkey], recipe[duck::type]" ]
10916 @node.run_list << "role[blah]"
10917 @knife.name_args = [ "adam", "role[monkey], recipe[duck::type]", "role[blah]" ]
10918 @knife.name_args = [ "adam", "role[blork]" ]
10919 @knife.name_args = %w{adam blork}
10920 expect(@knife.ui).to receive(:warn).with(/did you forget recipe\[\] or role\[\]/)
10921 @node.run_list << "role[barn]"
10922 expect(@node.run_list[1]).to eq("role[monkey]")
10923 expect(@node.run_list[2]).to eq("role[barn]")
10924 @knife.config[:before] = "role[acorns]"
10925 expect(@node.run_list[1]).to eq("role[acorns]")
10926 expect(@node.run_list[2]).to eq("role[duck]")
10927 let(:bootstrap_cli_options) { [ ] }
10928 let(:bootstrap_cli_options) { %w{ } }
10929 let(:bootstrap_cli_options) { %w{ adam staging my-app } }
10930 let(:bootstrap_cli_options) { %w{ adam staging } }
10931 let(:bootstrap_cli_options) { %w{ adam my-app } }
10932 @knife.name_args = %w{adam bar}
10933 editor: "cat",
10934 @node.automatic_attrs = { go: :away }
10935 @node.default_attrs = { hide: :me }
10936 @node.override_attrs = { dont: :show }
10937 @node.normal_attrs = { do_show: :these }
10938 @node.run_list("recipe[foo]")
10939 expect(actual["normal"]).to eq({ "do_show" => "these" })
10940 expect(actual["run_list"]).to eq(["recipe[foo]"])
10941 expect(actual["automatic"]).to eq({ "go" => "away" })
10942 expect(actual["override"]).to eq({ "dont" => "show" })
10943 expect(actual["default"]).to eq({ "hide" => "me" })
10944 view["run_list"] << "role[fuuu]"
10945 @knife.name_args = %w{ adam ben }
10946 @ben_node = Chef::Node.new
10947 @nodes = {}
10948 @nodes[node_name] = "http://localhost:4000/nodes/#{node_name}"
10949 expected = @nodes.inject({}) do |inflatedish, (name, uri)|
10950 inflatedish[name] = Chef::Node.new.tap { |n| n.name(name) }
10951 @knife.name_args = ["adam"]
10952 let(:actor) { "charmander" }
10953 let(:keyname) { "charmander" }
10954 let(:ui) { instance_double("Chef::Knife::UI") }
10955 let(:actor_field_name) { "user" }
10956 let(:list_method) { :list_by_user }
10957 { "uri" => "https://api.opscode.piab/users/charmander/keys/non-expired1", "name" => "non-expired1", "expired" => false },
10958 { "uri" => "https://api.opscode.piab/users/charmander/keys/non-expired2", "name" => "non-expired2", "expired" => false },
10959 let(:list_method) { :list_by_client }
10960 { "uri" => "https://api.opscode.piab/organizations/pokemon/clients/charmander/keys/non-expired1", "name" => "non-expired1", "expired" => false },
10961 { "uri" => "https://api.opscode.piab/organizations/pokemon/clients/charmander/keys/non-expired2", "name" => "non-expired2", "expired" => false },
10962 let(:keyname) { "charmander-key" }
10963 let(:new_keyname) { "charizard-key" }
10964 let(:actor_field_name) { "client" }
10965 let(:key_name) { "charmander-key" }
10966 @knife.name_args = [ "production" ]
10967 @knife.name_args = [ "spec.rb" ]
10968 @knife.name_args = [ "spec.rb", "apple.rb" ]
10969 allow(Dir).to receive(:glob).with("/tmp/environments/*.{json,rb}").and_return(["spec.rb", "apple.rb"])
10970 allow(@knife).to receive(:config).and_return({ all: true })
10971 @knife.name_args = [ ]
10972 @constraints = {
10973 @cookbooks = { "foo" => "= 1.0.1", "bar" => "= 0.0.1" }
10974 @rest_double = double("rest")
10975 @cookbook_data = {}
10976 @cookbook_data[item] = { "url" => "#{@base_url}/#{item}",
10977 expect(@stdout.string).to(match(/#{item}/)) && expect(@stdout.string.lines.count).to(be 4)
10978 expect(@stdout.string).to match(/#{ver[1]}/)
10979 describe "with -a or --all" do
10980 @knife.config[:all] = true
10981 let(:bag_name) { "sudoing_admins" }
10982 let(:item_name) { "ME" }
10983 { "id" => "id", "baz" => "http://localhost:4000/data/bag_o_data/baz",
10984 let(:config) { { format: "json" } }
10985 let(:db_folder) { File.join(tmp_dir, data_bags_path, bag_name) }
10986 let(:db_file) { Tempfile.new(["data_bag_from_file_test", ".json"], db_folder) }
10987 let(:db_file2) { Tempfile.new(["data_bag_from_file_test2", ".json"], db_folder) }
10988 let(:db_folder2) { File.join(tmp_dir, data_bags_path, bag_name2) }
10989 let(:db_file3) { Tempfile.new(["data_bag_from_file_test3", ".json"], db_folder2) }
10990 def new_bag_expects(b = bag_name, d = plain_data)
10991 let(:loader) { double("Knife::Core::ObjectLoader") }
10992 let(:data_bags_path) { "data_bags" }
10993 let(:bag_name2) { "sudoing_admins2" }
10994 knife.name_args = [ bag_name, db_file.path, db_file2.path ]
10995 knife.name_args = [ bag_name, db_folder ]
10996 config[:all] = true
10997 let(:raw_hash) { { "login_name" => "alphaomega", "id" => "item_name" } }
10998 let(:db) { Chef::DataBagItem.from_hash(raw_hash) }
10999 let(:raw_edited_hash) { { "login_name" => "rho", "id" => "item_name", "new_key" => "new_value" } }
11000 let(:is_encrypted?) { false }
11001 let(:data_to_edit) { db.raw_data }
11002 let(:config) { { print_after: true } }
11003 let(:is_encrypted?) { true }
11004 let(:data_to_edit) { raw_hash }
11005 let(:raw_hash) { { "login_name" => "alphaomega", "id" => item_name } }
11006 expect(rest).to receive(:get).with("data/#{bag_name}")
11007 expect(rest).to_not receive(:post).with("data", { "name" => bag_name })
11008 .with("data/#{bag_name}")
11009 .with("data/sudoing_#{name}_admins")
11010 knife.name_args = ["sudoing_#{name}_admins"]
11011 expect(rest).to receive(:post).with("data", { "name" => knife.name_args[0] })
11012 expect(rest).to receive(:post).with("data", { "name" => bag_name })
11013 let(:bag_name) { name }
11014 it "creates a data bag named '#{name}'" do
11015 expect(rest).to receive(:post).with("data", { "name" => bag_name }).ordered
11016 let(:chef_config) { Chef::Config.save } # "dup" to a hash
11017 let(:mock_cert_dir) { ::File.absolute_path(::File.join("spec", "assets", "fake_trusted_certs")) }
11018 let(:crt_files) { ::Dir.glob(::File.join(mock_cert_dir, "*.crt")) }
11019 let(:pem_files) { ::Dir.glob(::File.join(mock_cert_dir, "*.pem")) }
11020 let(:other_files) { ::Dir.glob(::File.join(mock_cert_dir, "*")) - crt_files - pem_files }
11021 echo_file = ::File.read(f).gsub(/^/, "echo.")
11022 expect(bootstrap_context.get_log_location).to eq("\"C:\\chef\\chef.log\"
")
11023 cache_options: ({ path: "c:/chef/cache/checksums", skip_expires: true })
11024 chef-client -c C:\\chef\\client.rb -j C:\\chef\\first-boot.json
11025 let(:config) { { channel: "stable" } }
11026 let(:config) { { channel: "current" } }
11027 let(:custom_url) { "file://something" }
11028 let(:config) { { msi_url: custom_url, install: true } }
11029 yes: nil,
11030 field_separator: ".",
11031 @ui = Chef::Knife::UI.new(@out, @err, @in, @config)
11032 ruby_for_json = { "foo" => "bar" }
11033 ruby_from_editor = TestObject.from_hash({ "bar" => "foo" })
11034 my_editor = "veeeye"
11035 temp_path = "/tmp/bar/baz"
11036 let(:parse_output) { false }
11037 let(:klass) { nil }
11038 let(:parse_output) { true }
11039 let(:klass) { TestObject }
11040 @mock = double("Tempfile")
11041 expect(Tempfile).to receive(:open).with([ "knife-edit-", ".json" ]).and_yield(@mock)
11042 expect(@ui).to receive(:system).with("#{my_editor} #{temp_path}").and_return(true)
11043 expect(@ui).to receive(:system).with("#{my_editor} #{temp_path}").and_return(nil)
11044 expect(@ui).to receive(:system).with("#{my_editor} #{temp_path}").and_return(false)
11045 @tempfile = Tempfile.new([ "knife-edit-", ".json" ])
11046 expect(Tempfile).to receive(:open).with([ "knife-edit-", ".json" ]).and_yield(@tempfile)
11047 expect(@ui).to receive(:system).with("#{my_editor} #{@tempfile.path}").and_return(true)
11048 @ui.config[:with_uri] = true
11049 expect(@ui.format_list_for_display({ marcy: :playground })).to eq({ marcy: :playground })
11050 @ui.config[:with_uri] = false
11051 expect(@ui.format_list_for_display({ marcy: :playground })).to eq([ :marcy ])
11052 expect { @ui.send(method, "hi") }.to raise_error(Errno::EIO)
11053 expect { @ui.send(method, "hi") }.to raise_error(SystemExit)
11054 @config[:verbosity] = 2
11055 expect { @ui.send(method, "hi") }.to raise_error(Errno::EPIPE)
11056 @ui.output("hi")
11057 expect(@out.string).to eq("hi
")
11058 @ui.output({ "hi" => "a", "lo" => "b" })
11059 expect(@out.string).to eq <<~EOM
11060 hi: a
11061 lo: b
11062 @ui.output({})
11063 expect(@out.string).to eq("
")
11064 @ui.output(%w{a b})
11065 @ui.output([ ])
11066 @ui.output([ "a" ])
11067 expect(@out.string).to eq("a
")
11068 @ui.output([ [ "a" ] ])
11069 @ui.output([ %w{a b}, %w{c d}])
11070 @ui.output([ %w{a b}, [ "c" ], [], %w{d e}])
11071 a: b
11072 c: d
11073 x: y
11074 m: n
11075 o: p
11076 @ui.output({ "a" => [], "b" => "c" })
11077 a:
11078 b: c
11079 @ui.output({ "a" => [ "foo" ], "b" => "c" })
11080 a: foo
11081 @ui.output({ "a" => %w{foo bar}, "b" => "c" })
11082 @ui.output({ "a" => [ [ "foo" ] ], "b" => "c" })
11083 @ui.output({ "a" => [ %w{foo bar}, %w{baz bjork} ], "b" => "c" })
11084 @ui.output({ "a" => { "aa" => "bb", "cc" => "dd" }, "b" => "c" })
11085 aa: bb
11086 cc: dd
11087 @ui.output({ "a" => {}, "b" => "c" })
11088 input = { gi: :go }
11089 input = { "gi" => { "go" => "ge" }, "id" => "sample-data-bag-item" }
11090 @ui.config[:attribute] = "gi.go"
11091 expect(@ui.format_for_display(input)).to eq({ "sample-data-bag-item" => { "gi.go" => "ge" } })
11092 input = { "gi" => "go", "hi" => "ho", "id" => "sample-data-bag-item" }
11093 @ui.config[:attribute] = %w{gi hi}
11094 expect(@ui.format_for_display(input)).to eq({ "sample-data-bag-item" => { "gi" => "go", "hi" => "ho" } })
11095 input = { "keys" => "values", "hi" => "ho", "id" => "sample-data-bag-item" }
11096 @ui.config[:attribute] = "keys"
11097 expect(@ui.format_for_display(input)).to eq({ "sample-data-bag-item" => { "keys" => "values" } })
11098 input = { "keys" => { "keys" => "values" }, "hi" => "ho", "id" => "sample-data-bag-item" }
11099 @ui.config[:attribute] = "keys.keys"
11100 expect(@ui.format_for_display(input)).to eq({ "sample-data-bag-item" => { "keys.keys" => "values" } })
11101 @ui.config[:attribute] = "name"
11102 expect(@ui.format_for_display(input)).to eq( { "chef.localdomain" => { "name" => "chef.localdomain" } })
11103 input.default["class"] = "classy!"
11104 @ui.config[:attribute] = "class"
11105 expect(@ui.format_for_display(input)).to eq( { nil => { "class" => "classy!" } } )
11106 input.default["array"] = %w{zero one two}
11107 @ui.config[:attribute] = "array.1"
11108 expect(@ui.format_for_display(input)).to eq( { nil => { "array.1" => "one" } } )
11109 expect(@ui.format_for_display(input)).to eq({ "sample-data-bag-item" => { non_existing_path => nil } })
11110 input = { "keys" => { "with spaces" => { "open" => { "doors" => { "with many.dots" => "when asked" } } } } }
11111 @ui.config[:field_separator] = ";"
11112 expect(@ui.format_for_display(input)).to eq({ nil => { "keys;with spaces;open;doors;with many.dots" => "when asked" } })
11113 @ui.config[:run_list] = true
11114 expect(response["sample-node"]["run_list"][0]).to eq("role[monkey]")
11115 expect(response["sample-node"]["run_list"][1]).to eq("role[churchmouse]")
11116 @item = {
11117 { "version" => "3.0.0", "url" => "http://url/cookbooks/3.0.0" },
11118 { "version" => "2.0.0", "url" => "http://url/cookbooks/2.0.0" },
11119 { "version" => "1.0.0", "url" => "http://url/cookbooks/1.0.0" },
11120 response = {
11121 stdout = double("StringIO", tty?: true)
11122 @ui.config[:color] = true
11123 context "when ui.color? => true" do
11124 expect(@ui.color("a_bus_is", :yellow)).to eql("\e[33ma_bus_is\e[0m")
11125 context "when ui.color? => false" do
11126 expect(@ui.color("a_bus_is", :yellow)).to eql("a_bus_is")
11127 let(:output) { stdout.string }
11128 let(:question) { "monkeys rule" }
11129 let(:answer) { "y" }
11130 let(:default_choice) { nil }
11131 end.to raise_error(SystemExit) { |e| expect(e.status).to eq(3) }
11132 let(:default_choice) { true }
11133 let(:answer) { "" }
11134 let(:answer) { "N" }
11135 let(:default_choice) { false }
11136 let(:answer) { "Y" }
11137 %w{Y y}.each do |answer|
11138 let(:answer) { answer }
11139 %w{N n}.each do |answer|
11140 describe "with --y or --yes passed" do
11141 @ui.config[:yes] = true
11142 expect(output).to eq("")
11143 allow(@ui).to receive(:stdin).and_return(StringIO.new("
"))
11144 let(:plugin_dir) { File.join(home, ".chef", "plugins", "knife") }
11145 allow(File).to receive(:read).with(File.join(home, ".chef", "plugin_manifest.json")).and_return("{ \"_autogenerated_command_paths\": {}}")
11146 let(:presenter) { Chef::Knife::Core::StatusPresenter.new(double(:ui), double(:config, :[] => "")) }
11147 n.automatic_attrs["name"] = "my_node"
11148 n.automatic_attrs["ipaddress"] = "127.0.0.1"
11149 node.automatic_attrs["cloud"] = { "public_ipv4_addrs" => ["2.2.2.2"] }
11150 expect(result["ip"]).to eq("2.2.2.2")
11151 node.automatic_attrs["cloud"] = { "public_ipv4_addrs" => [] }
11152 expect(result["ip"]).to eq("127.0.0.1")
11153 node.automatic_attrs["cloud"] = {}
11154 { "name" => "test_node",
11155 let(:node) { Chef::Node.from_hash(node_data) }
11156 let(:ui) { double "ui" }
11157 let(:base_config) { { editor: "cat" } }
11158 data = subject.view.merge("name" => "foo_new_name_node")
11159 data = updated_data.merge("bad_property" => "bad_value")
11160 expect(loader.list_commands).to eq({ "cool" => ["cool_a"], "cooler" => ["cooler_b"] })
11161 expect(loader.list_commands("cool")).to eq({ "cool" => ["cool_a"] })
11162 gems = [ double("knife-ec2-0.5.12") ]
11163 gem_files = [
11164 expect($LOAD_PATH).to receive(:map).and_return([])
11165 expect(gems[0]).to receive(:matches_for_glob).with(%r{chef/knife/\*\.rb\{(.*),\.rb,(.*)\}}).and_return(gem_files)
11166 expect(Dir).to receive(:[]).with("/usr/lib/ruby/gems/knife-ec2-0.5.12/lib/chef/knife/*.rb").and_return(gem_files)
11167 let(:env_home) { "/home/alice" }
11168 let(:manifest_path) { env_home + "/.chef/plugin_manifest.json" }
11169 allow(ENV).to receive(:[]) { |key| env_dup[key] }
11170 allow(ENV).to receive(:[]).with("HOME").and_return(env_home)
11171 allow(ENV).to receive(:[]).with("HOME").and_return(nil)
11172 files_count = Dir.glob(File.join(@cookbook_repo, cookbook.name.to_s, "**", "*"), File::FNM_DOTMATCH).count { |file| File.file?(file) }
11173 response = Net::HTTPResponse.new("1.0", "200", "OK")
11174 post = Net::HTTP::Post.new(@uri, {})
11175 put = Net::HTTP::Put.new(@uri, {})
11176 subject.make_request(:put, @uri, "bill", @secret_filename, {
11177 content = @file.read(4)
11178 @str = "What a boring string"
11179 expect(@string_part.read(2, 4)).to eql(@str[2, 4])
11180 @string1 = "stream1"
11181 @string2 = "stream2"
11182 @parts = [ @stream1, @stream2 ]
11183 expect(@multipart_stream.read(10)).to eql("#{@string1}#{@string2}"[0, 10])
11184 dst_buf = ""
11185 expect(dst_buf).to eql("#{@string1}#{@string2}"[0, 10])
11186 @ui = Chef::Knife::UI.new(@stdout, @stderr, @stdin, {})
11187 allow(::File).to receive(:directory?).with(/.*\.git/).and_return(false)
11188 @nobranches = Mixlib::ShellOut.new.tap { |s| s.stdout.replace "
" }
11189 @clean_status = Mixlib::ShellOut.new.tap { |s| s.stdout.replace("
") }
11190 expect(@cookbook_repo).to receive(:shell_out!).with("git commit -m \"Import apache2 version 1.2.3\" -- apache2", cwd: @repo_path)
11191 let(:config) { { foo: :bar, color: true } }
11192 let(:run_list) { Chef::RunList.new("recipe[tmux]", "role[base]") }
11193 let(:secret) { nil }
11194 let(:config) { { verbosity: 2, color: true } }
11195 it "adds '-l debug' when verbosity is >= 2" do
11196 let(:config) { { color: false } }
11197 it "adds '--no-color' when color is false" do
11198 let(:chef_config) { { chef_license: "accept-no-persist" } }
11199 let(:chef_config) { { unix_bootstrap_file_cache_path: "/home/opscode/cache" } }
11200 let(:chef_config) { { chef_client_path: "/usr/local/bin/chef-client" } }
11201 let(:chef_config) { { validation_key: "~/my.key" } }
11202 expect(IO).to receive(:read).with(File.expand_path("my.key", ENV["HOME"]))
11203 let(:config) { { chef_node_name: "foobar.example.com" } }
11204 let(:config) { { environment: "prodtastic", color: true } }
11205 let(:config) { { tags: [ "unicorn" ] } }
11206 let(:config) { { first_boot_attributes: { baz: :quux } } }
11207 let(:config) { { policy_name: "my_app_server", policy_group: "staging" } }
11208 let(:secret) { "supersekret" }
11209 let(:config) { { node_ssl_verify_mode: "none" } }
11210 let(:config) { { node_verify_api_cert: true } }
11211 let(:chef_config) { { config_log_location: nil } }
11212 let(:chef_config) { { config_log_location: "" } }
11213 let(:chef_config) { { config_log_location: :win_evt } }
11214 let(:chef_config) { { config_log_location: :syslog } }
11215 let(:chef_config) { { config_log_location: STDOUT } }
11216 let(:chef_config) { { config_log_location: STDERR } }
11217 let(:chef_config) { { config_log_location: "/tmp/ChefLogFile" } }
11218 let(:config) { { bootstrap_version: "awesome" } }
11219 let(:config) { { channel: "unstable" } }
11220 { cookbook.name => cookbook }
11221 let(:output) { StringIO.new }
11222 let(:name_args) { ["test_cookbook"] }
11223 .with( kind_of(Array), { force: nil, concurrency: 3 })
11224 let(:name_args) { ["test_cookbook1"] }
11225 let(:name_args) { ["test_cookbook2"] }
11226 { "test_cookbook" => cookbook,
11227 knife.ui = Chef::Knife::UI.new(@stdout, @stderr, @stdin, {})
11228 expect(@stderr.string).not_to include("'dependency' version '>= 0.0.0'")
11229 expect(@stderr.string).not_to include("'dependency2' version '>= 0.0.0'")
11230 expect(@stderr.string).to include("'dependency' version '>= 0.0.0'")
11231 expect(@stderr.string).to include("'dependency2' version '>= 0.0.0'")
11232 end # run
11233 knife.name_args = [ "cookbook_name" ]
11234 let(:cb) do
11235 let(:rest) { double(Chef::ServerAPI) }
11236 let(:content) { "Example recipe text" }
11237 { "version" => "0.10.0", "url" => "http://url/cookbooks/cookbook_name/0.10.0" },
11238 { "version" => "0.9.0", "url" => "http://url/cookbookx/cookbook_name/0.9.0" },
11239 { "version" => "0.8.0", "url" => "http://url/cookbooks/cookbook_name/0.8.0" },
11240 knife.name_args << "0.1.0"
11241 { "cookbook_name" => "cookbook_name",
11242 [{ "name" => "recipes/default.rb",
11243 knife.name_args = [ "cookbook_name", "0.1.0", "recipes" ]
11244 knife.name_args = [ "cookbook_name", "0.1.0", "recipes", "default.rb" ]
11245 knife.name_args = [ "cookbook_name", "0.1.0", "files", "afile.rb" ]
11246 cb.manifest = {
11247 knife.name_args = ["foobar"]
11248 name = kwargs[:name]
11249 Dir.mkdir("#{cookbook_dir}/#{name}")
11250 File.open("#{cookbook_dir}/#{name}/metadata.rb", "w+") do |f|
11251 f.puts "#{key} #{value.map { |v| "\"#{v}\"" }.join(", ")}"
11252 f.puts "#{key} \"#{value}\""
11253 File.open("#{cookbook_dir}/#{name}/metadata.json", "w+") do |f|
11254 File.open("#{cookbook_dir}/foobar/metadata.json", "w+") do |f|
11255 { "version": "1.0.0", {ImInvalid}}
11256 create_metadata_rb(name: "foo", version: "1.0.0")
11257 create_metadata_rb(name: "bar", version: "2.0.0")
11258 Chef::Config[:cookbook_path] = "/dev/null"
11259 create_metadata_rb(name: "foobar", version: "1.0.0")
11260 expect(json["name"]).to eql("foobar")
11261 expect(json["version"]).to eql("1.0.0")
11262 create_metadata_rb(name: "foobar", version: "1.0.0", depends: [ "foo:bar", ">> 0.2" ])
11263 create_metadata_rb(name: "foobar", version: "1.0.0", depends: [ "foo:bar", "> 0.2", "< 1.0" ])
11264 create_metadata_json(name: "foobar", version: "1.0.0", dependencies: { "foo:bar" => ">> 0.2" })
11265 create_metadata_rb(name: "sounders", version: "2.0.0", beats: "toronto")
11266 @knife.name_args = [ @src ]
11267 if File.exist?(@tgt)
11268 expect(File).to receive(:open).with(@tgt, "w")
11269 @rest_mock = double("rest")
11270 expect(@stdout.string).to match(/#{item}\s+1\.0\.1/)
11271 pattern = /#{Regexp.escape(@cookbook_data[item]['versions'].first['url'])}/
11272 @cookbook_data[item]["versions"] << { "version" => "1.0.0",
11273 expect(@stdout.string).to match(/#{item}\s+1\.0\.1\s+1\.0\.0/)
11274 @knife.name_args = ["foobar", nil]
11275 @knife.name_args = ["foobar"]
11276 all_files: [
11277 cb.version = "1.0.0"
11278 let(:manifest_data) { { all_files: [] } }
11279 @knife.name_args << "1.0.0"
11280 @files = manifest_data.values.map { |v| v.map { |i| i["path"] } }.flatten.uniq
11281 @files_mocks = {}
11282 @files.map { |f| File.basename(f) }.flatten.uniq.each do |f|
11283 @files_mocks[f] = double("#{f}_mock")
11284 allow(@files_mocks[f]).to receive(:path).and_return("/var/tmp/#{f}")
11285 expect(@knife.ui).to receive(:fatal).with(%r{/var/tmp/chef/foobar-1\.0\.0 exists}i)
11286 @files.map { |f| File.dirname(f) }.flatten.uniq.each do |dir|
11287 expect(FileUtils).to receive(:mkdir_p).with("/var/tmp/chef/foobar-1.0.0/#{dir}")
11288 .at_least(:once)
11289 @files.each do |f|
11290 .with("/var/tmp/#{File.basename(f)}", "/var/tmp/chef/foobar-1.0.0/#{f}")
11291 describe "with -f or --force" do
11292 expect(@knife.version).to eq("1.0.0")
11293 expect(@knife).to receive(:available_versions).at_least(:once).and_return(["1.0.0", "2.0.0"])
11294 describe "with -N or --latest" do
11295 .and_return(["1.0.0", "1.1.0", "2.0.0"])
11296 expect(@knife.version.to_s).to eq("2.0.0")
11297 .with("foobar")
11298 .and_return(["1.1.0", "2.0.0", "1.0.0"])
11299 Chef::Version.new("1.1.0"),
11300 Chef::Version.new("2.0.0")])
11301 allow(@knife).to receive(:available_versions).and_return(["1.0.0", "1.1.0", "2.0.0"])
11302 prompt = /Which version do you want to download\?.+1\. foobar 1\.0\.0.+2\. foobar 1\.1\.0.+3\. foobar 2\.0\.0.+/m
11303 describe "with -p or --purge" do
11304 .with(/.+Are you sure you want to purge files.+/)
11305 @knife.version = "1.0.0"
11306 versions = ["1.0.0", "1.1.0"]
11307 expect(@knife).to receive(:available_versions).at_least(:once).and_return(["1.0.0", "1.1.0"])
11308 expect(@knife).to receive(:ask_which_versions_to_delete).and_return(["1.0.0", "1.1.0"])
11309 @cookbook_data = { "foobar" => { "versions" => [{ "version" => "1.0.0" },
11310 { "version" => "1.1.0" },
11311 { "version" => "2.0.0" } ] },
11312 expect(@knife.available_versions).to eq(["1.0.0", "1.1.0", "2.0.0"])
11313 prompt = /Which version\(s\) do you want to delete\?.+1\. foobar 1\.0\.0.+2\. foobar 1\.1\.0.+3\. foobar 2\.0\.0.+4\. All versions.+/m
11314 expect(@knife.ask_which_versions_to_delete).to eq(["1.0.0", "2.0.0"])
11315 object = ""
11316 versions = [:all]
11317 @knife.config = { print_after: nil }
11318 @cookbooks = {}
11319 { "cheezburger" => "1.0.0", "pizza" => "2.0.0", "lasagna" => "3.0.0" }.each do |cookbook_name, version|
11320 @rest_client = double("null rest client", post: { result: :true })
11321 @knife.config[:config_file] = "/home/you/.chef/knife.rb"
11322 @in = StringIO.new("
" * 7)
11323 let(:fqdn) { "foo.example.org" }
11324 let(:ohai) do
11325 o = {}
11326 o[:fqdn] = fqdn
11327 let(:default_admin_key) { "/etc/chef-server/admin.pem" }
11328 let(:default_server_url) { "https://#{fqdn}/organizations/myorg" }
11329 expect(@knife.admin_client_key).to match %r{^[A-Za-z]:/home/you/\.chef/my-webui\.pem$}
11330 @knife.config[:client_key] = "/home/you/a-new-user.pem"
11331 expect(@out.string).to match(/\s*/)
11332 expect(@knife.new_client_key).to match %r{^[A-Za-z]:/home/you/a-new-user\.pem$}
11333 allow(File).to receive(:expand_path).with("/home/you/.chef/#{Etc.getlogin}.pem").and_return("/home/you/.chef/#{Etc.getlogin}.pem")
11334 expect(config_file.string).to match(/^client_name\s+=\s+'#{Etc.getlogin}'$/)
11335 expect(config_file.string).to match(%r{^client_key\s+=\s+'/home/you/.chef/#{Etc.getlogin}.pem'$})
11336 expect(config_file.string).to match(/^chef_server_url\s+=\s+'#{default_server_url}'$/)
11337 expect(::File).to receive(:open).with("/home/you/.chef/credentials", "w")
11338 @knife.name_args = ["/home/bob/.chef"]
11339 expect(File).to receive(:open).with("/home/bob/.chef/client.rb", "w")
11340 @knife.config[:format] = "json"
11341 fake_client_contents = { "foo" => "bar", "baz" => "qux" }
11342 @client_mock = double("client_mock", private_key: "foo_key")
11343 let(:data) do
11344 let(:clients) { %w{ adam ben charlie } }
11345 k.name_args = []
11346 let(:tmpdir) { Dir.mktmpdir }
11347 let(:file_path) { File.join(tmpdir, "client.pem") }
11348 let(:dir_path) { File.dirname(file_path) }
11349 let(:fieldname) { "client name" }
11350 knife.name_args = ["adam"]
11351 describe "with -f or --file" do
11352 let(:stdout) { stdout_io.string }
11353 let(:stderr) { stderr_io.string }
11354 let(:name_args) { [ "." ] }
11355 let(:option_args) { {} }
11356 let(:knife_confirm) { true }
11357 clients = {}
11358 let(:name_args) { [ ] }
11359 let(:option_args) { { delete_validators: true } }
11360 let(:name_args) { [ "^ti" ] }
11361 let(:linux_test) { true }
11362 let(:windows_test) { false }
11363 let(:linux_test) { false }
11364 let(:unix_test) { false }
11365 let(:ssh_test) { false }
11366 expect(rendered_template).to match('{"run_list":\[\]}')
11367 let(:bootstrap_cli_options) { [ "--bootstrap-vault-item", "vault1:item1", "--bootstrap-vault-item", "vault1:item2", "--bootstrap-vault-item", "vault2:item1" ] }
11368 expect(knife.config[:bootstrap_vault_item]).to eq({ "vault1" => %w{item1 item2}, "vault2" => ["item1"] })
11369 let(:bootstrap_cli_options) { [ "--bootstrap-proxy", "1.1.1.1" ] }
11370 let(:bootstrap_cli_options) { [ "--bootstrap-no-proxy", "localserver" ] }
11371 let(:bootstrap_cli_options) { [ "--bootstrap-template", "my-template", "other-template" ] }
11372 let(:builtin_template_path) { File.expand_path(File.join(__dir__, "../../../lib/chef/knife/bootstrap/templates", "example.erb")) }
11373 ["-t", "--bootstrap-template"].each do |t|
11374 expect(knife.render_template).to eq('{"run_list":[]}')
11375 knife.parse_options(["-r", "role[base]"])
11376 expect(knife.render_template).to eq('{"run_list":["role[base]"]}')
11377 knife.parse_options(["-r", "role[base],recipe[cupcakes]"])
11378 expect(knife.render_template).to eq('{"run_list":["role[base]","recipe[cupcakes]"]}')
11379 file = Tempfile.new(["node", ".json"])
11380 File.open(file.path, "w") { |f| f.puts '{"foo":{"bar":"baz"}}' }
11381 it "should have foo => {bar => baz} in the first_boot from cli" do
11382 knife.parse_options(["-j", '{"foo":{"bar":"baz"}}'])
11383 expected_hash = FFI_Yajl::Parser.new.parse('{"foo":{"bar":"baz"},"run_list":[]}')
11384 it "should have foo => {bar => baz} in the first_boot from file" do
11385 knife.parse_options(["--hint", "openstack"])
11386 allow(::File).to receive(:read).and_return('{ "foo" : "bar" }')
11387 expect(knife.render_template).to match(/\{\"foo\":\"bar\"\}/)
11388 let(:options) { ["--bootstrap-no-proxy", setting] }
11389 let(:setting) { "api.opscode.com" }
11390 let(:setting) { "api.opscode.com,172.16.10.*" }
11391 expect(rendered_template).to match(/.*no_proxy\s*"api.opscode.com,172.16.10.\*".*/)
11392 let(:options) { ["--node-ssl-verify-mode", "none"] }
11393 let(:options) { ["--node-ssl-verify-mode", "peer"] }
11394 let(:options) { ["--node-ssl-verify-mode", "all"] }
11395 let(:options) { ["--node-verify-api-cert"] }
11396 let(:options) { ["--no-node-verify-api-cert"] }
11397 let(:options) { [] }
11398 certificates = Dir[File.join(Chef::Config[:trusted_certs_dir], "*.{crt,pem}")]
11399 File.join(__dir__, "../../data/client.d_00")
11400 expect(rendered_template).to match("something '\\\\''/foo/bar'\\\\''")
11401 expect(rendered_template).to match("cat > /etc/chef/client.d/00-foo.rb <<'EOP'")
11402 let(:host_descriptor) { "example.com" }
11403 let(:host_descriptor) { "winrm://myhost" }
11404 let(:config) { { connection_protocol: "winrm" } }
11405 let(:host_descriptor) { "ssh://example.com" }
11406 it "falls back to 'ssh'" do
11407 let(:connection_protocol) { "ssh" }
11408 it "returns true for #{proto}" do
11409 let(:bootstrap_cli_options) { %w{ --policy-name my-app-server } }
11410 let(:bootstrap_cli_options) { %w{ --policy-group staging } }
11411 let(:bootstrap_cli_options) { %w{ --policy-name my-app --policy-group staging } }
11412 && expect(knife.options[:use_sudo_password][:description].to_s).not_to(eq(""))\
11413 && expect(knife.options[:use_sudo_password][:long].to_s).not_to(eq(""))
11414 { base_opts: true,
11415 Chef::Config[:knife][:max_wait] = 9999.0
11416 Chef::Config[:knife][:winrm_user] = "winbob"
11417 Chef::Config[:knife][:winrm_port] = 9999
11418 Chef::Config[:knife][:ca_trust_file] = "trust.me"
11419 Chef::Config[:knife][:winrm_ssl] = true
11420 ca_trust_path: "trust.me",
11421 user: "winbob",
11422 ssl: true,
11423 ca_trust_path: "no trust",
11424 port: 12,
11425 user: "clippy",
11426 Chef::Config[:knife][:ssh_user] = "sshbob"
11427 Chef::Config[:knife][:ssh_port] = 9999
11428 user: "sshbob",
11429 key_files: ["/identity.pem", "/gateway.pem"],
11430 Chef::Config[:knife][:password] = "blah"
11431 Chef::Config[:knife][:ssh_password] = "blah"
11432 Chef::Config[:knife][:use_sudo] = true
11433 Chef::Config[:knife][:ssh_forward_agent] = "blah"
11434 user: "sshalice", # cli
11435 password: "feta cheese", # cli
11436 key_files: ["/identity.pem", "/gateway.pem"], # Config
11437 sudo: true, # ccli
11438 port: 12, # cli
11439 knife.config[:ssh_user] = "do not use"
11440 user: "sshroot",
11441 bastion_user: "me",
11442 key_files: ["/my-identity.pem", "/gateway-identity.pem"],
11443 sudo_options: "-H",
11444 key_files: [],
11445 end # ssh
11446 port: 250,
11447 user: "test",
11448 expect(knife.host_verify_opts).to eq( { verify_host_key: "always" } )
11449 key_files: [ "/identity.pem" ],
11450 key_files: ["/identity.pem"],
11451 key_files: [ "/identity.pem", "/gateway.pem" ],
11452 key_files: [ "/gateway.pem" ],
11453 expect(knife.sudo_opts).to eq({})
11454 expect(knife.sudo_opts).to eq( { sudo: true } )
11455 expect(knife.sudo_opts).to eq( { sudo: false } )
11456 expect(knife.ssh_opts).to eq({})
11457 expected.merge({ ssl: true })
11458 expected.merge({ ca_trust_path: "/trust.me" })
11459 knife.config[:ca_trust_file] = "/trust.me"
11460 let(:node_name) { nil }
11461 Chef::Config[:validation_key] = "/blah"
11462 .with("/path.sh")
11463 .and_return("sh /path.sh")
11464 .with("sh /path.sh")
11465 .and_yield("output here", nil)
11466 .and_return("su - USER -c 'sh /path.sh'")
11467 .with("su - USER -c 'sh /path.sh'")
11468 expect(knife).to receive(:do_connect).with( { opts: "here" } )
11469 let(:expected_error) { Train::Error.new("fingerprint AA:BB is unknown for \"blah,127.0.0.1\"") }
11470 .with(/.*host 'blah \(127.0.0.1\)'.*AA:BB.*Are you sure you want to continue.*/m)
11471 e = Train::Error.new
11472 let(:windows_test) { true }
11473 knife.config[:test_key_a] = "a from cli"
11474 knife.config[:test_key_b] = "b from cli"
11475 Chef::Config[:knife][:test_key_a] = "a from Chef::Config"
11476 Chef::Config[:knife][:test_key_c] = "c from Chef::Config"
11477 Chef::Config[:knife][:alt_test_key_c] = "alt c from Chef::Config"
11478 let(:temp_dir) { "C:/Temp/bootstrap" }
11479 let(:temp_dir) { "/tmp/bootstrap" }
11480 knife.config[:su_user] = "root"
11481 it "is chef-full" do
11482 knife.do_connect({})
11483 expect { knife.do_connect({}) }.not_to raise_error
11484 let(:session_timeout) { 60 }
11485 let(:session_timeout) { nil }
11486 let(:session_timeout) { 16 }
11487 let(:session_timeout) { 15 }
11488 let(:protocol) { "mock" }
11489 let(:family) { "unknown" }
11490 let(:release) { "unknown" } # version
11491 let(:name) { "unknown" }
11492 let(:arch) { "x86_64" }
11493 let(:connection_opts) { {} } # connection opts
11494 let(:host_url) { "mock://user1@example.com" }
11495 let(:mock_connection) { true }
11496 let(:family) { "debian" }
11497 let(:name) { "ubuntu" }
11498 let(:family) { "os" }
11499 let(:name) { "mac_os_x" }
11500 let(:family) { "windows" }
11501 let(:name) { "windows" }
11502 let(:protocol) { "ssh" }
11503 let(:host_url) { "mock://user1@localhost:2200" }
11504 let(:connection_opts) { { user: "user2", host: "example.com", port: 15 } }
11505 let(:host_url) { "localhost" }
11506 let(:connection_opts) { { port: 15, user: "user2" } }
11507 let(:host_url) { "127.0.0.1" }
11508 .and_return double("result", stdout: "C:/a/path")
11509 let(:random) { "wScHX6" }
11510 let(:dir) { "/tmp/chef_#{random}" }
11511 expected_command1 = "mkdir -p '#{dir}'"
11512 expected_command2 = "chown user1 '#{dir}'"
11513 .and_return double("result", stdout: "\r
")
11514 expected_command = "mkdir -p '#{dir}'"
11515 .and_return double("result", stdout: "sudo: unable to resolve host hostname.localhost\r
" + "#{dir}\r
")
11516 expect(cmd).to match(/Test-Path "deleteme\.txt".*/)
11517 expect(cmd).to match(/rm -f "deleteme\.txt".*/)
11518 command_result = double("results", stdout: "", stderr: "failed", exit_status: 1)
11519 expect { subject.run_command!("test") }.to raise_error do |e|
11520 expect(e.stdout).to eq ""
11521 let(:chef_config) { {} }
11522 let(:node_name) { "bevell.wat" }
11523 let(:response_404) { OpenStruct.new(code: "404") }
11524 expect(rest).to receive(:get).with("nodes/#{node_name}")
11525 let(:client) { Chef::ApiClient.new }
11526 let(:client_rest) { double("Chef::ServerAPI (client)") }
11527 expect(node).to receive(:run_list).with([])
11528 allow(node).to receive(:run_list).with([])
11529 tag_receiver = []
11530 config[:tags] = %w{foo bar}
11531 config[:run_list] = "role[base],role[app]"
11532 expect(node).to receive(:run_list).with(["role[base]", "role[app]"])
11533 config[:run_list] = ["role[base]", "role[app]"]
11534 config[:first_boot_attributes] = { baz: :quux }
11535 expect(node).to receive(:normal_attrs=).with({ baz: :quux })
11536 config[:policy_name] = "my-app"
11537 config[:bootstrap_vault_item] = { "vault" => "item1" }
11538 config[:bootstrap_vault_item] = { "vault" => [ "item1" ] }
11539 config[:bootstrap_vault_item] = { "vault" => %w{item1 item2} }
11540 config[:bootstrap_vault_item] = { "vault" => %w{item1 item2}, "vault2" => [ "item3" ] }
11541 config[:bootstrap_vault_json] = '{ "vault": "item1" }'
11542 config[:bootstrap_vault_json] = '{ "vault": [ "item1" ] }'
11543 config[:bootstrap_vault_json] = '{ "vault": [ "item1", "item2" ] }'
11544 config[:bootstrap_vault_json] = '{ "vault": [ "item1", "item2" ], "vault2": [ "item3" ] }'
11545 setup_file_contents('{ "vault": "item1" }')
11546 setup_file_contents('{ "vault": [ "item1" ] }')
11547 setup_file_contents('{ "vault": [ "item1", "item2" ] }')
11548 setup_file_contents('{ "vault": [ "item1", "item2" ], "vault2": [ "item3" ] }')
11549 with_argv([]) do
11550 expect { @knife.run }.to raise_error(SystemExit) { |e| expect(e.status).to eq(1) }
11551 with_argv("--user", "adam") do
11552 expect { @knife.run }.to raise_error(SystemExit) { |e| expect(e.status).to eq(2) }
11553 home_path = "~/.chef/client.pem"
11554 with_argv(*%W{noop knife command -k #{home_path}}) do
11555 with_argv(*%W{noop knife command -k #{full_path}}) do
11556 with_argv(*%W{noop knife command -c #{config_file}}) do
11557 $LOAD_PATH.unshift File.expand_path("../../chef-config/lib", __dir__)
11558 $LOAD_PATH.unshift File.expand_path("../../chef-utils/lib", __dir__)
11559 Dir["lib/chef/knife/**/*.rb"]
11560 .map { |f| f.gsub("lib/", "") }
11561 .map { |f| f.gsub(/\.rb$/, "") }
11562 client "x", {}
11563 cookbook "x", "1.0.0"
11564 data_bag "x", { "y" => {} }
11565 environment "x", {}
11566 node "x", {}
11567 role "x", {}
11568 user "x", {}
11569 knife("upload /").should_succeed ""
11570 knife("diff --name-status /").should_succeed <<~EOM
11571 file "clients/chef-validator.json", { "validator" => true, "public_key" => ChefZero::PUBLIC_KEY }
11572 file "clients/chef-webui.json", { "admin" => true, "public_key" => ChefZero::PUBLIC_KEY }
11573 file "clients/x.json", { "public_key" => ChefZero::PUBLIC_KEY }
11574 file "cookbooks/x/metadata.rb", cb_metadata("x", "1.0.0")
11575 file "data_bags/x/y.json", {}
11576 file "environments/x.json", {}
11577 file "nodes/x.json", { "normal" => { "tags" => [] } }
11578 file "roles/x.json", {}
11579 file "users/admin.json", { "admin" => true, "public_key" => ChefZero::PUBLIC_KEY }
11580 file "users/x.json", { "public_key" => ChefZero::PUBLIC_KEY }
11581 knife("diff --name-status /").should_succeed ""
11582 knife("upload --purge /").should_succeed ""
11583 file "roles/x.json", { "description" => "blarghle" }
11584 knife("upload --no-diff /").should_succeed ""
11585 knife("diff --name-status /").should_succeed "M\t/roles/x.json
"
11586 file "roles/x.json", <<~EOM
11587 file "roles/x.rb", <<~EOM
11588 name "x"
11589 knife("diff --name-status /").should_succeed "M\t/roles/x.rb
"
11590 file "cookbooks/x/metadata.rb", "name 'x'; version '1.0.0'; depends 'x'"
11591 file "clients/y.json", { "public_key" => ChefZero::PUBLIC_KEY }
11592 file "cookbooks/x/blah.rb", ""
11593 file "cookbooks/y/metadata.rb", cb_metadata("y", "1.0.0")
11594 file "data_bags/x/z.json", {}
11595 file "data_bags/y/zz.json", {}
11596 file "environments/y.json", {}
11597 file "nodes/y.json", {}
11598 file "roles/y.json", {}
11599 file "users/y.json", { "public_key" => ChefZero::PUBLIC_KEY }
11600 knife("upload /").should_succeed <<~EOM
11601 knife("upload --no-diff /").should_succeed <<~EOM
11602 knife("upload --purge /").should_fail <<~EOM
11603 cwd "."
11604 file "data_bags/x/y.json", { "foo" => "bar" }
11605 file "data_bags/x/y.json", { "chef_type" => "aaa", "data_bag" => "bbb" }
11606 expect(result["chef_type"]).to eq("aaa")
11607 expect(result["data_bag"]).to eq("bbb")
11608 data_bag "x", { "deleted" => {}, "modified" => {}, "unmodified" => {} }
11609 file "data_bags/x/added.json", {}
11610 file "data_bags/x/modified.json", { "foo" => "bar" }
11611 knife("upload --purge .").should_succeed <<~EOM
11612 knife("upload --purge *").should_succeed <<~EOM
11613 cookbook "x", "1.0.0", { "z.rb" => "" }
11614 file "cookbooks/x/y.rb", "hi"
11615 file "cookbooks/x/metadata.rb", cb_metadata("x", "1.0.0", "#modified")
11616 file "cookbooks/x/z.rb", ""
11617 file "cookbooks/x/metadata.rb", 'name "x"; version "1.0.0"#different'
11618 cookbook "frozencook", "1.0.0", {}, frozen: true
11619 file "cookbooks/x/metadata.json", { name: "x", version: "1.0.0" }
11620 cookbook "x", "1.0.0", { "onlyin1.0.0.rb" => "" }
11621 cookbook "x", "1.0.1", { "onlyin1.0.1.rb" => "hi" }
11622 cookbook "x", "0.9.9", { "onlyin0.9.9.rb" => "hi" }
11623 file "environments/x.json", "{"
11624 error1 = <<~EOH
11625 (right here) ------^
11626 file "environments/x.json", { "name" => "y" }
11627 file "environments/x.json", { "description" => "hi" }
11628 file "data_bags/bag/x.json", { "foo" => "bar" }
11629 file "cookbooks/x-1.0.0/metadata.rb", cb_metadata("x", "1.0.0")
11630 file "cookbooks/x-1.0.0/blah.rb", ""
11631 file "cookbooks/x-2.0.0/metadata.rb", cb_metadata("x", "2.0.0")
11632 file "cookbooks/y-1.0.0/metadata.rb", cb_metadata("y", "1.0.0")
11633 file "cookbooks/x-1.0.0/metadata.rb", cb_metadata("x", "1.0.0", "#modified")
11634 file "cookbooks/x-1.0.0/y.rb", "hi"
11635 knife("upload --purge /cookbooks/x-1.0.0/z.rb").should_fail "ERROR: /cookbooks/x-1.0.0/z.rb cannot be deleted.
"
11636 file "cookbooks/x-1.0.0/z.rb", ""
11637 file "cookbooks/x-1.0.0/onlyin1.0.0.rb", "old_text"
11638 file "cookbooks/x-1.0.0/metadata.rb", cb_metadata("x", "1.0.0", "
chef_version '~> 999.0'")
11639 file "users/x.json", { "admin" => true, "json_class" => "Chef::WebUIUser" }
11640 user "foo", {}
11641 user "bar", {}
11642 user "foobar", {}
11643 organization "foo", { "full_name" => "Something" }
11644 group "blah", {}
11645 file "acls/groups/blah.json", {}
11646 file "containers/x.json", {}
11647 file "cookbook_artifacts/x-1x1/metadata.rb", cb_metadata("x", "1.0.0")
11648 file "groups/x.json", {}
11649 file "invitations.json", [ "foo" ]
11650 file "members.json", [ "bar" ]
11651 file "org.json", { "full_name" => "wootles" }
11652 file "policies/x-1.0.0.json", { "policy_group_list" => [ "x" ] }
11653 file "policies/blah-1.0.0.json", { "policy_group_list" => [ "x" ] }
11654 expect(api.get("association_requests").map { |a| a["username"] }).to eq([ "foo" ])
11655 expect(api.get("users").map { |a| a["user"]["username"] }).to eq([ "bar" ])
11656 knife("diff --name-status --diff-filter=AMT /").should_succeed ""
11657 file "org.json", { "full_name" => "Something" }
11658 cookbook_artifact "x", "1x1", "metadata.rb" => cb_metadata("x", "1.0.0")
11659 container "x", {}
11660 group "x", {}
11661 policy "x", "1.0.0", {}
11662 policy "blah", "1.0.0", {}
11663 policy_group "x", {
11664 policy "x", "1.0.0", { "run_list" => [ "blah" ] }
11665 cookbook_artifact "x", "1x1", { "recipes" => { "default.rb" => "" } }
11666 client "x", { "validator" => true }
11667 cookbook "x", "1.0.0", { "recipes" => { "default.rb" => "" } }
11668 cookbook_artifact "x", "1x1", { "metadata.rb" => cb_metadata("x", "1.0.0") }
11669 data_bag "x", { "y" => { "a" => "b" } }
11670 environment "x", { "description" => "foo" }
11671 group "x", { "groups" => [ "admin" ] }
11672 node "x", { "run_list" => [ "blah" ] }
11673 policy "x", "1.0.0", { "policy_group_list" => [ "x" ] }
11674 policy "y", "1.0.0", { "policy_group_list" => [ "x" ] }
11675 role "x", { "run_list" => [ "blah" ] }
11676 expect(api.get("/")["full_name"]).to eq("Something")
11677 file "org.json", { "full_name" => "Something Else" }
11678 expect(api.get("/")["full_name"]).to eq("Something Else")
11679 expect(api.get("association_requests").map { |a| a["username"] }).to eq(%w{foo foobar})
11680 expect(api.get("association_requests").map { |a| a["username"] }).to eq([ ])
11681 expect(api.get("users").map { |a| a["user"]["username"] }).to eq(%w{bar foo foobar})
11682 org_invite "bar", "foo"
11683 expect(api.get("association_requests").map { |a| a["username"] }).to eq(%w{bar foo})
11684 expect(api.get("users").map { |a| a["user"]["username"] }).to eq([ ])
11685 org_member "bar", "foo"
11686 file "members.json", %w{foo bar}
11687 expect(api.get("users").map { |a| a["user"]["username"] }).to eq(%w{bar foo})
11688 client "x", "{}"
11689 data_bag "x", { "y" => "{}" }
11690 environment "x", "{}"
11691 node "x", "{}"
11692 role "x", "{}"
11693 user "x", "{}"
11694 file "clients/x.json", { "foo" => "bar" }
11695 file "environments/_default.json", { "foo" => "bar" }
11696 file "environments/x.json", { "foo" => "bar" }
11697 file "nodes/x.json", { "foo" => "bar" }
11698 file "roles/x.json", { "foo" => "bar" }
11699 file "users/x.json", { "foo" => "bar" }
11700 name "x"; version "1.0.0"
11701 /data_bags/x/y.json:
11702 knife("show --local /data_bags/x/y.json").should_succeed <<~EOM
11703 knife("show --local /data_bags/x").should_fail "ERROR: /data_bags/x: is a directory
"
11704 environment "x", {
11705 before { file "environments/x.json", "{" }
11706 exception = $!
11707 file "nodes/a_node_in_json.json", { "foo" => "bar" }
11708 file "nodes/a_node_in_ruby.rb", "name 'a_node_in_ruby'"
11709 file "roles/a_role_in_json.json", { "foo" => "bar" }
11710 file "roles/a_role_in_ruby.rb", "name 'a_role_in_ruby'"
11711 %w{a_node_in_json a_node_in_ruby}.each do |file_type|
11712 expect(api.get("nodes/#{file_type}")["name"]).to eq(file_type)
11713 %w{a_role_in_json a_role_in_ruby}.each do |file_type|
11714 expect(api.get("roles/#{file_type}")["name"]).to eq(file_type)
11715 node "cons", { run_list: ["recipe[bar]", "recipe[foo]"] }
11716 knife("search node name:snoc").should_fail("", stderr: "0 items found

", exit_code: 1)
11717 role "cons", {}
11718 role "car", {}
11719 role "cdr", {}
11720 role "cat", {}
11721 let(:role_dir) { "#{@repository_dir}/roles" }
11722 file "roles/cons.json", <<~EOM
11723 file "roles/car.json", <<~EOM
11724 file "roles/cdr.json", <<~EOM
11725 knife("role delete car", input: "Y").should_succeed <<~EOM
11726 let(:out) { "Created role[bah]
" }
11727 knife("role bulk delete ^ca.*", input: "Y").should_succeed <<~EOM
11728 @api.get("/roles", 302, nil, { "Content-Type" => "text", "Location" => "#{real_chef_server_url}/roles" }) do
11729 before { role "x", {} }
11730 knife("raw /nodes/x").should_succeed <<~EOM
11731 knife("raw -m DELETE /roles/x").should_succeed <<~EOM
11732 knife("raw -m PUT -i #{file.path} /roles/x").should_succeed <<~EOM
11733 knife("raw -m POST -i #{file.path} /roles").should_succeed <<~EOM
11734 @api.get("/blah", 200, nil, { "Content-Type" => "application/json" }) do
11735 knife("raw /blah").should_succeed <<~EOM
11736 knife("raw --no-pretty /blah").should_succeed <<~EOM
11737 { "x": "y", "a": "b" }
11738 @api.get("/blah", 200, nil, { "Content-Type" => "text" }) do
11739 knife("raw /blah").should_succeed(<<~EOM)
11740 knife("raw --no-pretty /blah").should_succeed(<<~EOM)
11741 knife("node show cons").should_succeed(/Run List:\s*recipe\[bar\], recipe\[foo\]
/m)
11742 node "cons", {}
11743 node "cons", { run_list: ["recipe[bar]"] }
11744 knife("node run list add cons recipe[foo]").should_succeed(/run_list:
\s*recipe\[bar\]
\s*recipe\[foo\]
/m)
11745 knife("node run list add cons -b recipe[bar] recipe[foo]").should_succeed(/run_list:
\s*recipe\[foo\]
\s*recipe\[bar\]
/m)
11746 knife("node run list add cons -a recipe[bar] recipe[foo]").should_succeed(/run_list:
\s*recipe\[bar\]
\s*recipe\[foo\]
/m)
11747 node "car", {}
11748 node "cdr", {}
11749 node "cat", {}
11750 let(:node_dir) { "#{@repository_dir}/nodes" }
11751 file "nodes/cons.json", <<~EOM
11752 ,
11753 environment "lisp", {}
11754 knife("node delete car", input: "Y").should_succeed <<~EOM
11755 let(:out) { "Created node[bah]
" }
11756 knife("node bulk delete ^ca.*", input: "Y").should_succeed <<~EOM
11757 knife("list /").should_succeed <<~EOM
11758 knife("list -R /").should_succeed <<~EOM
11759 /:
11760 client "client1", {}
11761 client "client2", {}
11762 cookbook "cookbook1", "1.0.0"
11763 cookbook "cookbook2", "1.0.1", { "recipes" => { "default.rb" => "" } }
11764 data_bag "bag1", { "item1" => {}, "item2" => {} }
11765 data_bag "bag2", { "item1" => {}, "item2" => {} }
11766 node "node1", {}
11767 node "node2", {}
11768 policy "policy1", "1.2.3", {}
11769 policy "policy2", "1.2.3", {}
11770 policy "policy2", "1.3.5", {}
11771 role "role1", {}
11772 role "role2", {}
11773 user "user1", {}
11774 user "user2", {}
11775 knife("list -R --flat /").should_succeed <<~EOM
11776 knife("list -Rfp /").should_succeed <<~EOM
11777 it "knife list /cookbooks/*2/*/*.rb returns the one file" do
11778 knife("list /**.rb").should_succeed <<~EOM
11779 knife("list /cookbooks/**.rb").should_succeed <<~EOM
11780 knife("list /**.json").should_succeed <<~EOM
11781 knife("list /data**.json").should_succeed <<~EOM
11782 before { cwd "." }
11783 knife("list -Rfp").should_succeed <<~EOM
11784 before { cwd "cookbooks" }
11785 ./
11786 knife("list -Rfp ..").should_succeed <<~EOM
11787 before { cwd "symlinked" }
11788 context "--local" do
11789 knife("list --local /").should_succeed ""
11790 file "metadata.rb", cb_metadata("cookbook1", "1.0.0")
11791 file "metadata.rb", cb_metadata("cookbook2", "2.0.0")
11792 file "recipes/default.rb", ""
11793 file "item1.json", {}
11794 file "item2.json", {}
11795 file "nodes/node1.json", {}
11796 file "nodes/node2.json", {}
11797 file "roles/role1.json", {}
11798 file "roles/role2.json", {}
11799 file "users/user1.json", {}
11800 file "users/user2.json", {}
11801 knife("list -Rp --local --flat /").should_succeed <<~EOM
11802 /acls:
11803 cookbook_artifact "cookbook_artifact2", "2x2", { "recipes" => { "default.rb" => "" } }
11804 group "group1", {}
11805 group "group2", {}
11806 policy_group "policy_group1", { "policies" => { "policy1" => { "revision_id" => "1.2.3" } } }
11807 policy_group "policy_group2", { "policies" => { "policy2" => { "revision_id" => "1.3.5" } } }
11808 /acls/
11809 environment "b", {
11810 b:
11811 environment "b", {}
11812 environment "y", {}
11813 let(:env_dir) { "#{@repository_dir}/environments" }
11814 cwd(".")
11815 let(:out) { "Created bah
" }
11816 cookbook "blah", "1.0.1"
11817 cookbook "blah", "1.1.1"
11818 cookbook "krad", "1.1.1"
11819 environment "y", {
11820 knife("download --purge /").should_succeed ""
11821 knife("download --no-diff /").should_succeed ""
11822 file "cookbooks/y/metadata.rb", cb_metadata("x", "1.0.0")
11823 knife("download --purge /").should_succeed <<~EOM
11824 knife("download --no-diff /").should_succeed <<~EOM
11825 data_bag "x", { "y" => {}, "z" => {} }
11826 file "data_bags/x/deleted.json", <<~EOM
11827 file "data_bags/x/modified.json", <<~EOM
11828 data_bag "x", {
11829 knife("download --purge .").should_succeed <<~EOM
11830 knife("download --purge *").should_succeed <<~EOM
11831 cookbook "x", "1.0.0", { "metadata.rb" => cb_metadata("x", "1.0.0", "#extra content"), "y.rb" => "hi" }
11832 warning = <<~EOH
11833 file "cookbooks/x-2.0.0/metadata.rb", 'version "2.0.0"'
11834 file "cookbooks/y-1.0.0/metadata.rb", 'version "1.0.0"'
11835 file "cookbooks/x-1.0.0/metadata.rb", 'name "x"; version "1.0.0"#unmodified'
11836 cookbook "x", "1.0.0", { "y.rb" => "hi" }
11837 D\t/cookbooks/x-1.0.0/y.rb
11838 A\t/cookbooks/x-1.0.0/z.rb
11839 }.at_least(:once)
11840 file "clients/x.json", { "validator" => true }
11841 file "cookbooks/x/metadata.rb", cb_metadata("x", "1.0.1")
11842 file "cookbook_artifacts/x-1x1/metadata.rb", cb_metadata("x", "1.0.1")
11843 file "data_bags/x/y.json", { "a" => "b" }
11844 file "environments/x.json", { "description" => "foo" }
11845 file "groups/x.json", { "description" => "foo" }
11846 file "groups/x.json", { "groups" => [ "admin" ] }
11847 file "nodes/x.json", { "normal" => { "tags" => [] }, "run_list" => [ "blah" ] }
11848 file "org.json", { "full_name" => "Something Else " }
11849 file "policies/x-1.0.0.json", { "run_list" => [ "blah" ] }
11850 file "policy_groups/x.json", {
11851 file "roles/x.json", { "run_list" => [ "blah" ] }
11852 knife("diff /").should_succeed ""
11853 before { cwd "data_bags" }
11854 knife("diff --name-status *").should_succeed <<~EOM
11855 file "cookbooks/x/onlyin1.0.0.rb", ""
11856 cookbook "x", "1.0.1", { "onlyin1.0.1.rb" => "" }
11857 cookbook "x", "0.9.9", { "onlyin0.9.9.rb" => "" }
11858 before { environment "x", {} }
11859 before { environment "x", { "description" => "hi" } }
11860 /)
11861 environment "x", { "description" => "hi" }
11862 environment "x", { "description" => "lo" }
11863 file "clients/y.json", {}
11864 file "users/y.json", {}
11865 file "cookbooks/x-1.0.0/onlyin1.0.0.rb", ""
11866 before { file "environments/x.json", {} }
11867 before { file "roles/starring.json", {} }
11868 file "roles/starring.json", { "run_list" => %w{role[minor] recipe[quiche] recipe[soup::chicken]} }
11869 file "roles/minor.json", {}
11870 file "roles/starring.json", { "env_run_lists" => { "desert" => %w{role[minor] recipe[quiche] recipe[soup::chicken]} } }
11871 before { file "nodes/mort.json", {} }
11872 file "nodes/mort.json", { "chef_environment" => "desert" }
11873 file "nodes/mort.json", { "run_list" => %w{role[minor] recipe[quiche] recipe[soup::chicken]} }
11874 before { file "data_bags/bag/item.json", {} }
11875 before { file "environments/desert.json", {} }
11876 file "nodes/mort.json", { "chef_environment" => "desert", "run_list" => [ "role[starring]" ] }
11877 file "nodes/bart.json", { "run_list" => [ "role[minor]" ] }
11878 knife("deps /nodes/*").should_succeed <<~EOM
11879 knife("deps --tree /nodes/*").should_succeed <<~EOM
11880 knife("deps --tree --no-recurse /nodes/*").should_succeed <<~EOM
11881 file "roles/foo.json", { "run_list" => [ "role[bar]" ] }
11882 file "roles/bar.json", { "run_list" => [ "role[baz]" ] }
11883 file "roles/baz.json", { "run_list" => [ "role[foo]" ] }
11884 file "roles/self.json", { "run_list" => [ "role[self]" ] }
11885 exit_code: 2,
11886 stdout: "/blah
",
11887 stdout: "/roles/x.json
",
11888 stdout: "/nodes/x.json
",
11889 stdout: "/cookbooks/x
",
11890 file "roles/starring.json", { "run_list" => [ "recipe[quiche]"] }
11891 file "roles/starring.json", { "run_list" => [ "role[minor]"] }
11892 knife("deps /").should_succeed("/
")
11893 stdout: "/roles
"
11894 before { file "data_bags/bag/item.json", "" }
11895 before { file "cookbooks/blah/metadata.rb", 'name "blah"' }
11896 before { role "starring", {} }
11897 role "starring", { "run_list" => %w{role[minor] recipe[quiche] recipe[soup::chicken]} }
11898 role "minor", {}
11899 cookbook "quiche", "1.0.0", { "metadata.rb" => %Q{name "quiche"
version "1.0.0"
}, "recipes" => { "default.rb" => "" } }
11900 cookbook "soup", "1.0.0", { "metadata.rb" => %Q{name "soup"
version "1.0.0"
}, "recipes" => { "chicken.rb" => "" } }
11901 role "starring", { "env_run_lists" => { "desert" => %w{role[minor] recipe[quiche] recipe[soup::chicken]} } }
11902 before { node "mort", {} }
11903 node "mort", { "chef_environment" => "desert" }
11904 node "mort", { "run_list" => %w{role[minor] recipe[quiche] recipe[soup::chicken]} }
11905 cookbook "kettle", "1.0.0", { "metadata.rb" => %Q{name "kettle"
version "1.0.0"
} }
11906 cookbook "quiche", "1.0.0", { "metadata.rb" => 'name "quiche"
11907 depends "kettle"', "recipes" => { "default.rb" => "" } }
11908 before { data_bag "bag", { "item" => {} } }
11909 before { environment "desert", {} }
11910 node "mort", { "chef_environment" => "desert", "run_list" => [ "role[starring]" ] }
11911 node "bart", { "run_list" => [ "role[minor]" ] }
11912 knife("deps --remote /nodes/*").should_succeed <<~EOM
11913 knife("deps --remote --tree /nodes/*").should_succeed <<~EOM
11914 knife("deps --remote --tree --no-recurse /nodes/*").should_succeed <<~EOM
11915 cookbook "foo", "1.0.0", { "metadata.rb" => 'name "foo"
11916 depends "bar"' }
11917 cookbook "bar", "1.0.0", { "metadata.rb" => 'name "bar"
11918 depends "baz"' }
11919 cookbook "baz", "1.0.0", { "metadata.rb" => 'name "baz"
11920 depends "foo"' }
11921 cookbook "self", "1.0.0", { "metadata.rb" => 'name "self"
11922 depends "self"' }
11923 role "foo", { "run_list" => [ "role[bar]" ] }
11924 role "bar", { "run_list" => [ "role[baz]" ] }
11925 role "baz", { "run_list" => [ "role[foo]" ] }
11926 role "self", { "run_list" => [ "role[self]" ] }
11927 role "starring", { "run_list" => [ "recipe[quiche]"] }
11928 role "starring", { "run_list" => [ "role[minor]"] }
11929 knife("deps --remote /").should_succeed("/
")
11930 knife("deps --remote /roles").should_succeed("/roles
")
11931 cookbook "blah", "1.0.0", { "metadata.rb" => 'name "blah"' }
11932 knife("deps --no-recurse /").should_fail("ERROR: --no-recurse requires --tree
")
11933 file "clients/x.json", {}
11934 file "nodes/x.json", {}
11935 file "users/x.json", {}
11936 knife("list -Rf /").should_succeed <<~EOM
11937 knife("list -Rf --local /").should_succeed <<~EOM
11938 data_bag "empty", {}
11939 knife("delete --both /data_bags/x").should_fail <<~EOM
11940 it "knife delete --both -r /data_bags/x deletes x" do
11941 it "knife delete --both / fails" do
11942 knife("delete --both /").should_fail <<~EOM
11943 it "knife delete --both -r /* fails" do
11944 knife("delete --both -r /*").should_fail <<~EOM
11945 knife("delete --both /").should_fail "ERROR: / (remote) cannot be deleted.
ERROR: / (local) cannot be deleted.
"
11946 file "cookbooks/x/metadata.rb", 'version "1.0.0"'
11947 knife("raw /cookbooks/x").should_succeed(/1.0.0/)
11948 knife("raw /cookbooks/x").should_succeed(/0.9.9/)
11949 before { cookbook "x", "1.0.1", { "onlyin1.0.1.rb" => "hi" } }
11950 before { cookbook "x", "0.9.9", { "onlyin0.9.9.rb" => "hi" } }
11951 cookbook "x", "2.0.11"
11952 cookbook "x", "11.0.0"
11953 knife("raw /cookbooks/x").should_succeed( /2.0.11/ )
11954 policy "x", "1.2.3", {}
11955 policy_group "x", { "policies" => { "x" => { "revision_id" => "1.2.3" } } }
11956 knife("raw /groups/x.json").should_fail(/404/)
11957 let(:right_secret) { "abc" }
11958 let(:wrong_secret) { "ab" }
11959 data_bag "x", {}
11960 data_bag "canteloupe", {}
11961 data_bag "rocket", { "falcon9" => { heavy: "true" }, "atlas" => {}, "ariane" => {} }
11962 data_bag "rocket", {}
11963 let(:db_dir) { "#{@repository_dir}/data_bags" }
11964 data_bag "foo", {}
11965 data_bag "bar", {}
11966 file "data_bags/foo/bar.json", { "id" => "bar", "foo" => "bar " }
11967 file "data_bags/foo/bzr.json", { "id" => "bzr", "foo" => "bar " }
11968 file "data_bags/foo/cat.json", { "id" => "cat", "foo" => "bar " }
11969 file "data_bags/foo/dog.json", { "id" => "dog", "foo" => "bar " }
11970 knife("data bag from file foo #{db_dir}/foo")
11971 let(:out) { "Saved data_bag_item[box]
" }
11972 let(:secret) { "abc" }
11973 data_bag "bag", { "box" => {} }
11974 pretty_json = Chef::JSONCompat.to_json_pretty({ id: "box", foo: "bar" })
11975 pretty_json = Chef::JSONCompat.to_json_pretty({ id: "box", ab: "abc" })
11976 let(:err) { "Created data_bag[foo]
" }
11977 let(:out) { "Created data_bag_item[bar]
" }
11978 let(:exists) { "Data bag foo already exists
" }
11979 pretty_json = Chef::JSONCompat.to_json_pretty({ id: "bar", test: "pass" })
11980 expect(knife("data bag show foo bar --secret #{secret}").stdout).to eq("id: bar
")
11981 expect(knife("data bag show foo").stderr).to eq("")
11982 expect(knife("data bag show foo").stdout).to eq("bar
")
11983 expect(knife("data bag show rocket bar --secret #{secret}").stdout).to eq("id: bar
")
11984 let(:cb_dir) { "#{@repository_dir}/cookbooks" }
11985 knife("cookbook upload x -o #{cb_dir}").should_succeed stderr: <<~EOM
11986 knife("cookbook upload x -o #{cb_dir} --freeze").should_succeed stderr: <<~EOM
11987 knife("cookbook upload x -o #{cb_dir} --freeze").should_fail stderr: <<~EOM
11988 file "cookbooks/x/metadata.rb", cb_metadata("x", "1.0.0", "
depends 'y'")
11989 knife("cookbook upload x -o #{cb_dir}").should_fail stderr: <<~EOM
11990 ERROR: The missing cookbook(s) are: 'y' version '>= 0.0.0'
11991 knife("cookbook upload -a -o #{cb_dir}").should_succeed stderr: <<~EOM
11992 file "test_cookbooks/y/metadata.rb", cb_metadata("y", "1.0.0")
11993 cookbook "x", "1.0.0", { "recipes" => { "default.rb" => "file 'n'", "x.rb" => "" } }
11994 cookbook "x", "0.6.5"
11995 x::x: >= 0.0.0
11996 x:
11997 x::x:
11998 cookbook "x", "0.6.0"
11999 cookbook "y", "0.6.5"
12000 cookbook "y", "0.6.0"
12001 cookbook "z", "0.6.5"
12002 cookbook "x", "1.0.1"
12003 knife("cookbook download -d #{tmpdir} x", input: "2
").should_succeed(stderr: <<~EOM, stdout: "Which version do you want to download?
1. x 1.0.0
2. x 1.0.1

"
12004 cookbook "foo", "1.0.0"
12005 cookbook "foo", "0.6.5"
12006 cookbook "fox", "0.6.0"
12007 cookbook "fox", "0.6.5"
12008 cookbook "fax", "0.6.0"
12009 cookbook "zfa", "0.6.5"
12010 stdout = <<~EOM
12011 stderr = <<~EOM
12012 let(:chef_dir) { File.join(__dir__, "..", "..", "..", "knife", "bin") }
12013 let(:knife) { "ruby '#{chef_dir}/knife'" }
12014 let(:knife_config_flag) { "-c '#{path_to("config/knife.rb")}'" }
12015 versions_list_json = Chef::HTTP::Simple.new("http://[::1]:8900").get("/cookbooks/apache2", "accept" => "application/json")
12016 expect(Dir["#{cache_path}/*"].map { |entry| File.basename(entry) }).to include("apache2-0.0.1")
12017 let(:cmd_args) { [] }
12018 knife("config", "use", *cmd_args, instance_filter: lambda { |instance|
12019 old_wd = Dir.pwd
12020 Dir.chdir(path_to("repo"))
12021 it { is_expected.to eq "default
" }
12022 let(:cmd_args) { %w{--profile production} }
12023 it { is_expected.to eq "production
" }
12024 it { is_expected.to eq "staging
" }
12025 before { file(".chef/context", "development
") }
12026 it { is_expected.to eq "development
" }
12027 it { is_expected.to eq "other
" }
12028 let(:cmd_args) { %w{production} }
12029 before { file(".chef/credentials", <<~EOH) }
12030 it { is_expected.to eq "FATAL: No profiles found, #{path_to(".chef/credentials")} does not exist or is empty
" }
12031 before { file(".chef/credentials", "") }
12032 let(:cmd_args) { %w{staging} }
12033 ENV["CHEF_HOME"] = path_to("chefhome"); file("chefhome/tmp", "")
12034 let(:cmd_args) { %w{development} }
12035 ENV["KNIFE_HOME"] = path_to("knifehome"); file("knifehome/tmp", "")
12036 cmd = knife("config", "show", *cmd_args, instance_filter: lambda { |instance|
12037 before { file(".chef/knife.rb", "node_name 'one'
") }
12038 it { is_expected.to match(%r{^Loading from configuration file .*/#{File.basename(path_to("."))}/.chef/knife.rb$}) }
12039 it { is_expected.to match(/^node_name:\s+one$/) }
12040 before { file("repo/.chef/knife.rb", "node_name 'two'
") }
12041 it { is_expected.to match(%r{^Loading from configuration file .*/#{File.basename(path_to("."))}/repo/.chef/knife.rb$}) }
12042 it { is_expected.to match(/^node_name:\s+two$/) }
12043 file(".chef/knife.rb", "node_name 'one'
")
12044 file("repo/.chef/knife.rb", "node_name 'two'
")
12045 before { file(".chef/credentials", "[default]
client_name = \"three\"
") }
12046 it { is_expected.to match(%r{^Loading from credentials file .*/#{File.basename(path_to("."))}/.chef/credentials$}) }
12047 it { is_expected.to match(/^node_name:\s+three$/) }
12048 file(".chef/credentials", "[default]
client_name = \"three\"
")
12049 before { file(".chef/config.d/abc.rb", "node_name 'one'
") }
12050 it { is_expected.to match(%r{^Loading from .d/ configuration file .*/#{File.basename(path_to("."))}/.chef/config.d/abc.rb$}) }
12051 file("foo/.chef/credentials", "[default]
client_name = \"four\"
")
12052 it { is_expected.to match(%r{^Loading from credentials file .*/#{File.basename(path_to("."))}/foo/.chef/credentials$}) }
12053 it { is_expected.to match(/^node_name:\s+four$/) }
12054 file("bar/.chef/credentials", "[default]
client_name = \"four\"
")
12055 it { is_expected.to match(%r{^Loading from credentials file .*/#{File.basename(path_to("."))}/bar/.chef/credentials$}) }
12056 let(:cmd_args) { %w{node_name} }
12057 it { is_expected.to match(/^node_name:\s+three\Z/) }
12058 let(:cmd_args) { %w{node_name client_key} }
12059 before { file(".chef/credentials", "[default]
client_name = \"three\"
client_key = \"three.pem\"") }
12060 it { is_expected.to match(%r{^client_key:\s+\S*/.chef/three.pem
node_name:\s+three\Z}) }
12061 let(:cmd_args) { %w{knife.ssh_user} }
12062 before { file(".chef/credentials", "[default]
client_name = \"three\"
[default.knife]
ssh_user = \"foo\"
") }
12063 it { is_expected.to match(/^knife.ssh_user:\s+foo\Z/) }
12064 let(:cmd_args) { %w{/name/} }
12065 context "with --all" do
12066 let(:cmd_args) { %w{-a /key_contents/} }
12067 context "with --raw" do
12068 let(:cmd_args) { %w{-r node_name} }
12069 it { is_expected.to eq("three
") }
12070 let(:cmd_args) { %w{--format=json node_name} }
12071 it { expect(JSON.parse(subject)).to eq({ "node_name" => "three" }) }
12072 it { is_expected.to eq <<~EOH.delete("#") }
12073 [prod]
12074 [qa]
12075 client_key = "~/src/qauser.pem"
12076 let(:cmd_args) { %w{--profile prod} }
12077 context "with -i" do
12078 let(:cmd_args) { %w{-i} }
12079 it {
12080 let(:local_listen_warning) { /\Awarn:.*local.*listen.*$/im }
12081 before { file "nodes/x.json", {} }
12082 knife("raw /nodes/x").should_succeed( /"name": "x"/ )
12083 knife("raw --listen /nodes/x").should_succeed( /"name": "x"/, stderr: local_listen_warning )
12084 before(:each) { Chef::Config.chef_zero.port = 9999 }
12085 before(:each) { Chef::Config.chef_zero.host = "0.0.0.0" }
12086 knife("raw -z /nodes/x").should_succeed( /"name": "x"/ )
12087 knife("raw -z --listen /nodes/x").should_succeed( /"name": "x"/, stderr: local_listen_warning )
12088 knife("raw --local-mode --listen /nodes/x").should_succeed( /"name": "x"/, stderr: local_listen_warning )
12089 knife("raw -z --chef-zero-port=9999 --listen /nodes/x").should_succeed( /"name": "x"/, stderr: local_listen_warning )
12090 knife("raw -z --chef-zero-port=9999-20000 --listen /nodes/x").should_succeed( /"name": "x"/, stderr: local_listen_warning )
12091 knife("raw -z --chef-zero-port=9999-9999,19423 --listen /nodes/x").should_succeed( /"name": "x"/, stderr: local_listen_warning )
12092 command_name = command.gsub("_", " ")
12093 [command_name, /^USAGE: knife config #{$1}-profile.*/]
12094 when /(role|node|env) (env )?run list(.*)/
12095 env_part = $2.nil? ? "" : "env_"
12096 ["#{$1} #{$2}run_list#{$3}", /^USAGE: knife #{$1} #{env_part}run_list#{$3}.*/]
12097 [ command_name, /^USAGE: knife #{command_name}.*/]
12098 client "cons", {}
12099 client "car", {}
12100 client "cdr", {}
12101 client "cat", {}
12102 let(:now) { DateTime.now }
12103 let(:last_month) { (now << 1).strftime("%FT%TZ") }
12104 let(:next_month) { (now >> 1).strftime("%FT%TZ") }
12105 let(:out) { "Created key: new" }
12106 client "bah", {}
12107 knife("client key create -k new bah").should_succeed stderr: /^#{out}/, stdout: /.*BEGIN RSA PRIVATE KEY/
12108 date = "2017-12-31T23:59:59Z"
12109 knife("client key create -k new -e #{date} bah").should_succeed stderr: /^#{out}/, stdout: /.*BEGIN RSA PRIVATE KEY/
12110 knife("client key create -f #{tgt}/bah.pem -k new bah").should_succeed stderr: /^#{out}/
12111 expect(File).to exist("#{tgt}/bah.pem")
12112 File.open("#{tgt}/public.pem", "w") { |pub| pub.write(key.public_key.to_pem) }
12113 knife("client key create -p #{tgt}/public.pem -k new bah").should_succeed stderr: /^#{out}/
12114 knife("client delete car", input: "Y").should_succeed <<~EOM
12115 let(:out) { "Created client[bah]
" }
12116 client "concat", {}
12117 knife("client bulk delete ^ca.*", input: "Y").should_succeed <<~EOM
12118 knife("client bulk delete ca.*", input: "Y").should_succeed <<~EOM
12119 knife("client bulk delete ^ca.* -D", input: "Y
Y").should_succeed <<~EOM
12120 file "data_bags/bag1/x.json", {}
12121 knife("list --local -Rfp /").should_succeed <<~EOM
12122 before { file "cookbooks/chefignore", "x.json
" }
12123 file "cookbooks/chefignore", "x.*
"
12124 file "cookbooks/chefignore", "

# blah
#
x.json

"
12125 it "knife list --local -Rfp / returns them" do
12126 it "knife list --local / returns it" do
12127 knife("list --local /").should_succeed "/data_bags
"
12128 it "knife list --local -Rfp / does not return it" do
12129 file "_default.json", {}
12130 knife("list --local -Rfp /").should_succeed ""
12131 file "item2.xml", ""
12132 file "role1.json", {}
12133 file "role2.xml", ""
12134 file "subdir/role.json", {}
12135 before { file "cookbooks/file", "" }
12136 before { file "data_bags/file", "" }
12137 file "cookbooks/a.b/metadata.rb", ""
12138 file "data_bags/.svn/x.json", {}
12139 file "data_bags/a.b/x.json", {}
12140 knife("list --local -fp /data_bags").should_succeed "/data_bags/a.b/
"
12141 file "data_bags/bag/item.json", {}
12142 file "nodes2/node2.json", {}
12143 file "roles2/role2.json", {}
12144 file "users2/user2.json", {}
12145 file "data_bags/bag3/item3.json", {}
12146 file "nodes/node3.json", {}
12147 file "roles/role3.json", {}
12148 file "users/user3.json", {}
12149 knife("list --local -Rfp --chef-repo-path #{path_to("chef_repo2")} /").should_succeed <<~EOM
12150 knife("list --local -Rfp --chef-repo-path #{path_to("chef_r~1")} /").should_succeed <<~EOM
12151 knife("list -z -Rfp --chef-repo-path #{path_to("chef_r~1")} /").should_succeed <<~EOM
12152 Chef::Config["#{object_name}_path".to_sym] = File.join(Chef::Config.chef_repo_path, "#{object_name}s2")
12153 before { cwd "chef_repo2" }
12154 knife("list --local -Rfp").should_succeed <<~EOM
12155 before { cwd "data_bags2" }
12156 it "knife list --local -Rfp ../roles lists roles" do
12157 knife("list --local -Rfp ../roles").should_succeed "/roles/role2.json
"
12158 Chef::Config["#{object_name}_path".to_sym] = [
12159 file "clients2/blah.json", {}
12160 file "cookbooks/blah", ""
12161 file "data_bags/blah", ""
12162 file "data_bags2/blah/item.json", ""
12163 knife("list --local -Rfp /data_bags").should_succeed <<~EOM
12164 file "data_bags/blah/item1.json", ""
12165 file "nodes2/blah.json", {}
12166 file "roles2/blah.json", {}
12167 file "users2/blah.json", {}
12168 it "knife list --local -Rfp / lists data bags" do
12169 it "knife list --local -Rfp / fails" do
12170 let(:cookbook_z_100_metadata_rb) { cb_metadata("z", "1.0.0") }
12171 file "policies/x-111.json", {}
12172 file "policy_groups/x.json", {}
12173 knife("list -z -Rfp /").should_succeed <<~EOM
12174 /data_bags/x/
12175 knife("list -z -Rfp /clients").should_succeed ""
12176 knife("list -z -Rfp /cookbooks").should_succeed ""
12177 it "knife delete -z -r /data_bags/x works" do
12178 knife("list -z -Rfp /data_bags").should_succeed ""
12179 knife("list -z -Rfp /data_bags").should_succeed "/data_bags/x/
"
12180 knife("list -z -Rfp /nodes").should_succeed ""
12181 knife("list -z -Rfp /roles").should_succeed ""
12182 knife("show -z /clients/x.json").should_succeed( /"x"/ )
12183 knife("show -z /data_bags/x/y.json").should_succeed( /"y"/ )
12184 knife("show -z /environments/x.json").should_succeed( /"x"/ )
12185 knife("show -z /nodes/x.json").should_succeed( /"x"/ )
12186 knife("show -z /roles/x.json").should_succeed( /"x"/ )
12187 file "empty.json", {}
12188 file "rolestuff.json", '{"description":"hi there","name":"x"}'
12189 it "knife raw -z -i empty.json -m PUT /clients/x" do
12190 knife("raw -z -i #{path_to("empty.json")} -m PUT /clients/x").should_succeed( /"x"/ )
12191 it "knife raw -z -i empty.json -m PUT /data/x/y" do
12192 knife("raw -z -i #{path_to("empty.json")} -m PUT /data/x/y").should_succeed( /"y"/ )
12193 knife("list --local -Rfp /data_bags").should_succeed "/data_bags/x/
/data_bags/x/y.json
"
12194 knife("raw -z -i #{path_to("empty.json")} -m PUT /environments/x").should_succeed( /"x"/ )
12195 it "knife raw -z -i dummynode.json -m PUT /nodes/x" do
12196 knife("raw -z -i #{path_to("dummynode.json")} -m PUT /nodes/x").should_succeed( /"x"/ )
12197 knife("show -z /nodes/x.json --verbose").should_succeed(/"bar"/)
12198 it "knife raw -z -i empty.json -m PUT /roles/x" do
12199 knife("raw -z -i #{path_to("empty.json")} -m PUT /roles/x").should_succeed( /"x"/ )
12200 knife("raw -z -i #{path_to("rolestuff.json")} -m PUT /roles/x").should_succeed( /"x"/ )
12201 expect(IO.read(path_to("roles/x.json"))).to eq <<~EOM.strip
12202 file "empty.json", { "name" => "z" }
12203 file "empty_x.json", { "name" => "x" }
12204 file "empty_id.json", { "id" => "z" }
12205 it "knife raw -z -i empty.json -m POST /clients" do
12206 knife("raw -z -i #{path_to("empty.json")} -m POST /clients").should_succeed( /uri/ )
12207 it "knife raw -z -i empty.json -m POST /data" do
12208 knife("raw -z -i #{path_to("empty.json")} -m POST /data").should_succeed( /uri/ )
12209 knife("list --local -Rfp /data_bags").should_succeed "/data_bags/z/
"
12210 it "knife raw -z -i empty.json -m POST /data/x" do
12211 knife("raw -z -i #{path_to("empty_x.json")} -m POST /data").should_succeed( /uri/ )
12212 knife("raw -z -i #{path_to("empty_id.json")} -m POST /data/x").should_succeed( /"z"/ )
12213 knife("list --local -Rfp /data_bags").should_succeed "/data_bags/x/
/data_bags/x/z.json
"
12214 knife("raw -z -i #{path_to("empty.json")} -m POST /environments").should_succeed( /uri/ )
12215 it "knife raw -z -i dummynode.json -m POST /nodes" do
12216 knife("raw -z -i #{path_to("dummynode.json")} -m POST /nodes").should_succeed( /uri/ )
12217 knife("show -z /nodes/z.json").should_succeed(/"bar"/)
12218 it "knife raw -z -i empty.json -m POST /roles" do
12219 knife("raw -z -i #{path_to("empty.json")} -m POST /roles").should_succeed( /uri/ )
12220 knife("raw -z -i #{path_to("rolestuff.json")} -m POST /roles").should_succeed( /uri/ )
12221 knife("raw -z -i #{path_to("empty.json")} -m PUT /clients/x").should_fail( /404/ )
12222 it "knife raw -z -i empty.json -m PUT /data/x/y fails with 404" do
12223 knife("raw -z -i #{path_to("empty.json")} -m PUT /data/x/y").should_fail( /404/ )
12224 knife("raw -z -i #{path_to("empty.json")} -m PUT /environments/x").should_fail( /404/ )
12225 it "knife raw -z -i empty.json -m PUT /nodes/x fails with 404" do
12226 knife("raw -z -i #{path_to("empty.json")} -m PUT /nodes/x").should_fail( /404/ )
12227 it "knife raw -z -i empty.json -m PUT /roles/x fails with 404" do
12228 knife("raw -z -i #{path_to("empty.json")} -m PUT /roles/x").should_fail( /404/ )
12229 knife("list -z -Rfp /users").should_succeed ""
12230 knife("show -z /users/x.json").should_succeed( /"x"/ )
12231 it "knife raw -z -i empty.json -m PUT /users/x" do
12232 knife("raw -z -i #{path_to("empty.json")} -m PUT /users/x").should_succeed( /"x"/ )
12233 it "knife raw -z -i empty.json -m POST /users" do
12234 knife("raw -z -i #{path_to("empty.json")} -m POST /users").should_succeed( /uri/ )
12235 it "knife raw -z -i empty.json -m PUT /users/x fails with 404" do
12236 knife("raw -z -i #{path_to("empty.json")} -m PUT /users/x").should_fail( /404/ )
12237 let(:knife_dir) { File.join(__dir__, "..", "..", "..", "knife") }
12238 expect(shell_out!("bundle exec knife -v", cwd: knife_dir).stdout.chomp).to match(/.*: #{Chef::Knife::VERSION}/)
12239 let(:ssh_config) { {} }
12240 Chef::Config[:knife][:ssh_identity_file] = "~/.ssh/aws.rsa"
12241 setup_knife(["*:*", "uptime"])
12242 expect(@knife.config[:ssh_identity_file]).to eq("~/.ssh/aws.rsa")
12243 Chef::Config[:knife][:ssh_identity_file] = "~/.ssh/aws.rsa".freeze
12244 setup_knife(["-i ~/.ssh/aws.rsa", "*:*", "uptime"])
12245 Chef::Config[:knife][:ssh_identity_file] = "~/.ssh/other.rsa"
12246 setup_knife(["-p 31337", "*:*", "uptime"])
12247 Chef::Config[:knife][:ssh_user] = "ubuntu"
12248 Chef::Config[:knife][:ssh_user] = "ubuntu".freeze
12249 Chef::Config[:knife][:ssh_user] = nil
12250 setup_knife(["-x ubuntu", "*:*", "uptime"])
12251 Chef::Config[:knife][:ssh_user] = "root"
12252 expect(@knife.get_ssh_attribute({ "target" => "ec2.public_hostname" })).to eq("ec2.public_hostname")
12253 setup_knife(["-a", "ec2.public_hostname", "*:*", "uptime"])
12254 Chef::Config[:knife][:ssh_attribute] = "fqdn"
12255 expect(@knife.get_prefix_attribute({ "prefix" => "name" })).to eq("name")
12256 setup_knife(["--prefix-attribute", "ec2.public_hostname", "*:*", "uptime"])
12257 Chef::Config[:knife][:ssh_gateway] = nil
12258 setup_knife(["-G user@ec2.public_hostname", "*:*", "uptime"])
12259 Chef::Config[:knife][:ssh_gateway_identity] = "~/.ssh/aws-gateway.rsa"
12260 setup_knife(["--ssh-gateway-identity", "~/.ssh/aws-gateway.rsa", "*:*", "uptime"])
12261 def setup_knife(params = [])
12262 allow(@knife).to receive(:ssh_command) { 0 }
12263 @api.post("/search/node?q=*:*&start=0&rows=1000", 200) do
12264 %({"total":1, "start":0, "rows":[{"data": {"fqdn":"the.fqdn", "target": "the_public_hostname"}}]})
12265 knife_cmd = Mixlib::ShellOut.new("#{knife_path} -v")
12266 knife_cmd = Mixlib::ShellOut.new("#{knife_path} --help")
12267 @server = TinyServer::Manager.new # (:debug => true)
12268 @knife = Chef::Knife::Exec.new
12269 response = { "rows" => [@node], "start" => 0, "total" => 1 }
12270 api.get("/cookbooks/no-such-cookbook", 404, Chef::JSONCompat.to_json({ "error" => "dear Tim, no. -Sent from my iPad" }))
12271 @cookbook_list = { "obsolete-cookbook" => { "versions" => ["version" => "1.0.0"] } }
12272 api.delete("/cookbooks/obsolete-cookbook/1.0.0", 200) { cb100_deleted = true; "[\"true\"]" }
12273 api.delete("/cookbooks/obsolete-cookbook/1.0.0?purge=true", 200) { cb100_deleted = true; "[\"true\"]" }
12274 versions = ["1.0.0", "1.1.0", "1.2.0"]
12275 with_version = lambda { |version| { "version" => version } }
12276 @cookbook_list = { "obsolete-cookbook" => { "versions" => versions.map(&with_version) } }
12277 api.delete("/cookbooks/obsolete-cookbook/1.1.0", 200) { cb110_deleted = true; "[\"true\"]" }
12278 api.delete("/cookbooks/obsolete-cookbook/1.2.0", 200) { cb120_deleted = true; "[\"true\"]" }
12279 stdin << "1
"
12280 hostname_guess = ohai[:fqdn] || ohai[:machinename] || ohai[:hostname] || "localhost"
12281 yaml_file = @name_args[0]
12282 unless ::File.exist?(yaml_file) && ::File.readable?(yaml_file)
12283 ruby_file = if @name_args[1]
12284 if ::File.extname(yaml_file) == ".yml" || ::File.extname(yaml_file) == ".yaml"
12285 yaml_file.gsub(/\.(yml|yaml)$/, ".rb")
12286 unless yaml_hash.is_a?(Hash) && yaml_hash.key?("resources")
12287 ui.warn("No resources found in '#{yaml_file}'") if yaml_hash["resources"].size == 0
12288 ::File.open(ruby_file, "w") do |file|
12289 ui.info("Converted '#{yaml_file}' to '#{ruby_file}'")
12290 ruby_contents = []
12291 type = r.delete("type")
12292 name = r.delete("name")
12293 ruby_contents << "#{type} \"#{name}\" do"
12294 r.each do |k, v|
12295 ruby_contents << "end
"
12296 long: "--local",
12297 arg_arity: [1, -1]
12298 long: "--[no-]diff",
12299 long: "--dry-run",
12300 long: "--[no-]force",
12301 short: "-t",
12302 short: "-0",
12303 files = []
12304 ui.warn "#{format_path(result)}: is a directory. Will not run #{command} on it."
12305 files = [ files[-1] ]
12306 ran = true
12307 files = [ ]
12308 stdin.read.split(/\s+/)
12309 command = name_args.join(" ")
12310 tempfiles = {}
12311 tempfiles[tempfile] = { file: file }
12312 paths = tempfiles.keys.map(&:path).join(" ")
12313 final_command = "#{command} #{paths}"
12314 file[:value] = value
12315 ui.error "#{format_path(e.entry)}: #{e.reason}."
12316 if config[:verbose_commands] || Chef::Config[:verbosity] && Chef::Config[:verbosity] >= 1
12317 command_output = `#{command}`
12318 if config[:force] || new_value != file[:value]
12319 if config[:diff] && new_value != file[:value]
12320 diff = `diff -u #{old_file.path} #{tempfile.path}`
12321 diff.gsub!(old_file.path, "#{format_path(file[:file])} (old)")
12322 diff.gsub!(tempfile.path, "#{format_path(file[:file])} (new)")
12323 long: "--with-orgs",
12324 short: "-l"
12325 @user_name = @name_args[0]
12326 results = root_rest.get("users/#{@user_name}")
12327 results["organizations"] = orgs.map { |o| o["organization"]["name"] }
12328 long: "--file FILE",
12329 File.open(config[:file], "w") do |f|
12330 short: "-e",
12331 unless (@name_args.length == 2 && !config[:enable_external_auth]) || (@name_args.length == 1 && config[:enable_external_auth])
12332 user_name = @name_args[0]
12333 result = root_rest.get("users/#{user_name}")
12334 root_rest.put("users/#{user_name}", result)
12335 short: "-w",
12336 long: "--with-uri",
12337 def initialize(argv = [])
12338 @service_object ||= Chef::Knife::KeyShow.new(@name, @actor, load_method, ui)
12339 @actor = params[0]
12340 @name = params[1]
12341 long: "--all",
12342 if (name_args.length < 1) && ! config.key?(:all)
12343 @invites = {}
12344 rest.get_rest("association_requests").each { |i| @invites[i["username"]] = i["id"] }
12345 @invites.each do |u, i|
12346 if @invites.key?(u)
12347 invited_users = rest.get_rest(api_endpoint).map { |i| i["username"] }
12348 body = { user: u }
12349 original_user = root_rest.get("users/#{@user_name}")
12350 result = root_rest.put("users/#{@user_name}", edited_user)
12351 ui.msg("Saved #{@user_name}.")
12352 File.open(config[:filename], "w") do |f|
12353 File.open(file, "w") do |f|
12354 f.sync = true
12355 api_endpoint = "users/#{u}"
12356 @username = @name_args[0]
12357 org_data.map { |org| Chef::Org.new(org["organization"]["name"]) }
12358 admin_of = []
12359 unremovable = []
12360 admin_of << org
12361 admin_of.each { |org| message << "- #{org.name}
" }
12362 message << <<~EOM
12363 message = <<~EOM
12364 only_admin_of.each { |org| message << "- #{org.name}
" }
12365 short: "-k",
12366 long: "--prevent-keygen",
12367 long: "--prompt-for-password",
12368 short: "-p",
12369 @user_field ||= Chef::UserV1.new
12370 if @name_args.size > 1
12371 user.first_name config[:first_name] || ""
12372 user.last_name config[:last_name] || ""
12373 if !config[:prevent_keygen] && !config[:user_key]
12374 user_hash = {
12375 display_name: "#{user.first_name} #{user.last_name}",
12376 file = config[:file]
12377 if final_user["chef_key"] && final_user["chef_key"]["private_key"]
12378 f.print(final_user["chef_key"]["private_key"])
12379 long: "--[no-]recurse",
12380 long: "--[no-]purge",
12381 long: "--[no-]freeze",
12382 short: "-n",
12383 fs_error, result = Chef::ChefFS::FileSystem.copy_to(pattern, local_fs, chef_fs, config[:recurse] ? nil : 1, config, ui, proc { |entry| format_path(entry) })
12384 name = @name_args[0]
12385 tags = @name_args[1..]
12386 if name.nil? || tags.nil? || tags.empty?
12387 deleted_tags = []
12388 (node.tags << tag).uniq!
12389 ui.info("Created tags #{tags.join(", ")} for node #{name}.")
12390 @cookbook_name = @name_args[0]
12391 noauth_rest.get("#{supermarket_uri}/cookbooks/#{@name_args[0]}/versions/#{name_args[1].tr(".", "_")}")
12392 def get_cookbook_list(items = 10, start = 0, cookbook_collection = {})
12393 cr["items"].each do |cookbook|
12394 new_start = start + cr["items"].length
12395 if new_start < cr["total"]
12396 proc: lambda { |o| Chef::Config.cookbook_path = o.split(":") }
12397 shell_out!("#{tar_cmd} -czf #{cookbook_name}.tgz #{cookbook_name}", cwd: tmp_cookbook_dir)
12398 Chef::Log.trace("
#{e.backtrace.join("
")}")
12399 result = shell_out!("#{tar_cmd} -tzf #{cookbook_name}.tgz", cwd: tmp_cookbook_dir)
12400 data = noauth_rest.get("#{config[:supermarket_site]}/api/v1/cookbooks/#{@name_args[0]}")
12401 return "Other" if e.is_a?(Net::HTTPClientException) && e.response.code == "404"
12402 if http_resp.code.to_i != 201
12403 ui.error (res["error_messages"][0]).to_s
12404 @tar_cmd = "tar"
12405 @tar_cmd = "gnutar"
12406 cookbooks_url = "#{config[:supermarket_site]}/api/v1/search?q=#{query}&items=#{items}&start=#{start}"
12407 long: "--sort-by SORT",
12408 long: "--owned-by USER",
12409 cookbooks_url << "&order=#{config[:sort_by]}" if config[:sort_by]
12410 cookbooks_url << "&user=#{config[:owned_by]}" if config[:owned_by]
12411 short: "-D",
12412 proc: lambda { |o| o.split(":") }
12413 short: "-b",
12414 long: "--use-current-branch",
12415 nv.name_args = [ cookbook ]
12416 unless name_args.last.match(/^(\d+)(\.\d+){1,2}$/) && name_args.size == 2
12417 upstream_file.sub(/^([[:alpha:]]):/, '/\1')
12418 json = IO.read(json)
12419 long: "--force",
12420 @current_cookbook_data ||= noauth_rest.get "#{cookbooks_api_url}/#{@name_args[0]}"
12421 uri = if @name_args.length == 1
12422 config[:file] ||= File.join Dir.pwd, "#{@name_args[0]}-#{version}.tar.gz"
12423 short: "-r",
12424 long: "--run-list",
12425 long: "--sort-reverse",
12426 long: "--hide-by-mins MINS",
12427 @query << " AND " unless @query.empty?
12428 @query << term
12429 opts = { filter_result:
12430 @query ||= ""
12431 time = Time.now.to_i
12432 @query << " " unless @query.empty?
12433 @query << "NOT ohai_time:[#{(time - hide_by_mins * 60)} TO #{time}]"
12434 @query = @query.empty? ? "*:*" : @query
12435 all_nodes = []
12436 Chef::Log.info("Sending query: #{@query}")
12437 q.search(:node, @query, opts) do |node|
12438 all_nodes.sort_by! { |n| n["ohai_time"] || 0 }
12439 @uri = nil
12440 @uri ||= begin
12441 (name_args[0] || Chef::Config.chef_server_url)
12442 ui.error("Given URI: `#{given_uri}' is invalid")
12443 if cn_field_tuple = subject.to_a.find { |field| field[0] == "CN" }
12444 cn.gsub("*", "wildcard").gsub(/[^[:alnum:]\-]/, "_")
12445 cn = cn_of(cert)
12446 filename = cn.nil? ? "#{host}_#{Time.new.to_i}" : normalize_cn(cn)
12447 if uri.scheme == "http"
12448 https_uri = uri.to_s.sub(/^http/, "https")
12449 ui.error("Perhaps you meant to connect to '#{https_uri}'?")
12450 @host = nil
12451 cert_debug_msg = ""
12452 cert_debug_msg << File.expand_path(cert_name) + ": " + message + "
"
12453 true # Maybe the bad certs won't hurt...
12454 ui.msg("Connecting to host #{host}:#{port}")
12455 ui.msg("
#{ui.color("Configuration Info:", :bold)}

")
12456 cn_field_tuple = subject.to_a.find { |field| field[0] == "CN" }
12457 cn = cn_field_tuple[1]
12458 Dir.glob(File.join(glob_dir, "*.{crt,pem}"))
12459 long: "--concurrency NUM",
12460 proc: lambda { |o| o.to_i }
12461 long: "--attribute ATTR",
12462 short: "-m",
12463 long: "--manual-list",
12464 long: "--ssh-port PORT",
12465 proc: Proc.new { |key| key.strip }
12466 proc: Proc.new { |key| key.strip.to_i },
12467 long: "--forward-agent",
12468 long: "--[no-]host-key-verify",
12469 long: "--exit-on-error",
12470 proc: Proc.new { |key| key.strip.to_sym },
12471 long: "--tmux-split",
12472 long: "--[no-]pty",
12473 long: "--[no-]require-pty",
12474 ui.warn "Failed to connect to #{server.host} -- #{$!.class.name}: #{$!.message}"
12475 $!.backtrace.each { |l| Chef::Log.debug(l) }
12476 gw_host, gw_user = config[:ssh_gateway].split("@").reverse
12477 gw_host, gw_port = gw_host.split(":")
12478 prompt = "Enter the password for #{user}@#{gw_host}: "
12479 list = config[:manual] ? @name_args[0].split(" ") : search_nodes
12480 if list.length == 0
12481 if @search_count == 0
12482 ui.fatal("#{@search_count} #{@search_count > 1 ? "nodes" : "node"} found, " +
12483 fqdns = list.map { |v| v[0] }
12484 msg = "Using node attribute '%s' as the prefix: %s"
12485 msg = "Using node attribute '%s' as the ssh target: %s"
12486 Chef::Log.debug(sprintf(msg, "fqdn", item["fqdn"]))
12487 item["fqdn"]
12488 list = []
12489 required_attributes = { fqdn: ["fqdn"], cloud: ["cloud"] }
12490 @search_count += 1
12491 ssh_port = item.dig("cloud", "public_ssh_port")
12492 srv = [host, ssh_port, prefix]
12493 {}.tap do |opts|
12494 opts[:user] = user || config[:ssh_user] || ssh_config[:user]
12495 opts[:keys_only] = true
12496 port ||= ssh_config[:port]
12497 opts[:logger] = Chef::Log.with_child(subsystem: "net/ssh") if Chef::Log.level == :trace
12498 opts[:user_known_hosts_file] = "/dev/null"
12499 Chef::Log.debug("Adding #{host}")
12500 hostspec = session_opts[:user] ? "#{session_opts.delete(:user)}@#{host}" : host
12501 command.sub(/^sudo/, "sudo -p 'knife sudo password: '")
12502 @buffers ||= {}
12503 @buffers[host] = nil
12504 if newline_index = data.index("
")
12505 str = ui.color(host, :cyan) + (" " * (padding + 1)) + data
12506 if config[:on_error] && exit_status != 0
12507 if /^knife sudo password: /.match?(data)
12508 ch.on_extended_data do |_, _type, data|
12509 command = reader.readline("#{ui.color("knife-ssh>", :bold)} ", true)
12510 command = "exit"
12511 puts "Connected to #{ui.list(session.servers_for.collect { |s| ui.color(s.host, :cyan) }, :inline, " and ")}"
12512 when "quit!"
12513 puts "Bye!"
12514 when /^on (.+?); (.+)$/
12515 raw_list = $1.split(" ")
12516 server_list = []
12517 command = $2
12518 tf.puts("caption always '%-Lw%{= BW}%50>%n%f* %t%{-}%+Lw%<'")
12519 window = 0
12520 tf.print("screen -t \"#{server.host}\" #{window} ssh ")
12521 tf.print("-i #{config[:ssh_identity_file]} ") if config[:ssh_identity_file]
12522 server.user ? tf.puts("#{server.user}@#{server.host}") : tf.puts(server.host)
12523 window += 1
12524 exec("screen -c #{tf.path}")
12525 identity = "-i #{config[:ssh_identity_file]} " if config[:ssh_identity_file]
12526 prefix = server.user ? "#{server.user}@" : ""
12527 [""] + session.servers_for[1..].map do |server|
12528 end.join(" \\; ")
12529 tmux_name = "'knife ssh #{@name_args[0].tr(":.", "=-")}'"
12530 cmd = ["tmux new-session -d -s #{tmux_name}",
12531 new_window_cmds.call].join(" ")
12532 exec("tmux attach-session -t #{tmux_name}")
12533 (session.servers_for.size - 1).times do |i|
12534 cmd = "unset PROMPT_COMMAND; echo -e \"\\033]0;#{server.host}\\007\"; ssh #{server.user ? "#{server.user}@#{server.host}" : server.host}"
12535 %w{csshX cssh}.each do |cmd|
12536 cssh_cmd = shell_out!("which #{cmd}").stdout.strip
12537 cssh_cmd << " --ssh_args '-i #{File.expand_path(config[:ssh_identity_file])}'"
12538 cssh_cmd << " #{server.user ? "#{server.user}@#{server.host}" : server.host}"
12539 Chef::Config[:knife][:ssh_user])
12540 @longest = 0
12541 ssh_command(@name_args[1..].join(" "))
12542 if exit_status && exit_status != 0
12543 output "#{format_path(entry)}:"
12544 long: "--repo-mode MODE",
12545 long: "--chef-repo-path PATH",
12546 long: "--chef-zero-host IP",
12547 short: "-b ROW",
12548 long: "--start ROW",
12549 proc: lambda { |i| i.to_i }
12550 long: "--rows INT",
12551 short: "-i",
12552 long: "--id-only",
12553 if @type == "node"
12554 result_items = []
12555 search_args = {}
12556 elsif (not ui.config[:attribute].nil?) && (not ui.config[:attribute].empty?)
12557 q.search(@type, @query, search_args) do |item|
12558 formatted_item = {}
12559 formatted_item = format_for_display({ "id" => item["__display_name"] })
12560 formatted_item[item["__display_name"]] = item.reject { |k| k == "__display_name" }
12561 ui.error("knife search failed: #{msg}")
12562 ui.log("
")
12563 ui.msg("
")
12564 if @name_args[1]
12565 @type = name_args[0]
12566 @query = config[:query]
12567 @type = "node"
12568 @query = name_args[0]
12569 @query = name_args[1]
12570 final_filter = {}
12571 filter_string.delete!(" ")
12572 return_id, attr_path = f.split("=")
12573 final_filter[return_id.to_sym] = attr_path.split(".")
12574 final_filter[f] = f.split(".")
12575 final_filter["__display_name"] = [ "name" ]
12576 @role_name = @name_args[0]
12577 nlist = []
12578 entries.each { |e| nlist << e }
12579 role = Chef::Role.load(@name_args[0])
12580 if @name_args.size < 1
12581 entries = @name_args[1..].map do |entry|
12582 entry.split(",").map(&:strip)
12583 entries = @name_args[1].split(",").map(&:strip)
12584 old_entry = @name_args[1]
12585 new_entry = @name_args[2]
12586 item_to_remove = @name_args[1]
12587 if @name_args.size > 2
12588 long: "--after ITEM",
12589 if @name_args.size < 2
12590 entries = @name_args[2..].map do |entry|
12591 entries = @name_args[2].split(",").map(&:strip)
12592 old_entry = @name_args[2]
12593 new_entry = @name_args[3]
12594 item_to_remove = @name_args[2]
12595 matcher = /#{@name_args[0]}/
12596 roles_to_delete = {}
12597 ui.info "No roles match the expression /#{@name_args[0]}/"
12598 ui.msg("")
12599 ui.msg("Deleted role #{name}")
12600 default: "GET",
12601 long: "--[no-]pretty",
12602 long: "--input FILE",
12603 long: "--proxy-auth",
12604 path = name_args[0]
12605 data = IO.read(config[:input])
12606 headers["x-ops-request-source"] = "web"
12607 ui.error "Error Body: #{e.response.body}" if e.response.body && e.response.body != ""
12608 @org_name, @username = @name_args
12609 if !org_name || !username
12610 org = Chef::Org.new(@org_name)
12611 elsif e.response.code == "403"
12612 long: "--admin",
12613 org_name = @name_args[0]
12614 long: "--all-orgs",
12615 results = results.select { |k, v| !(k.length == 20 && k =~ /^[a-z]+$/) }
12616 ui.msg("Saved #{org_name}.")
12617 @org_name, @org_full_name = @name_args
12618 if !org_name || !org_full_name
12619 org = Chef::Org.from_hash({ "name" => org_name,
12620 ui.info("Created #{org_name}")
12621 short: "-E",
12622 long: "--environment",
12623 @node_name = @name_args[0]
12624 node = Chef::Node.load(@name_args[0])
12625 entries.each { |e| node.run_list << e }
12626 if node.run_list.find { |rli| e == rli.to_s }
12627 ui.warn "#{e} is not in the run list"
12628 unless /^(recipe|role)\[/.match?(e)
12629 ui.warn "(did you forget recipe[] or role[] around it?)"
12630 long: "--before ITEM",
12631 if config[:after] && config[:before]
12632 policy_group, policy_name = @name_args[1..]
12633 if @name_args[0].nil?
12634 (policy_group.nil? || policy_name.nil? || @name_args[1..-1].size > 2)
12635 ui.info "Saving updated #{updated_values.join(", ")} on node #{node.name}"
12636 @node_name ||= @name_args[0]
12637 @node ||= Chef::Node.load(node_name)
12638 if @name_args.length == 0
12639 nodes_to_delete = {}
12640 matcher = /#{name_args[0]}/
12641 ui.msg "No nodes match the expression /#{name_args[0]}/"
12642 ui.msg("Deleted node #{name}")
12643 nodes_by_name[name] = Chef::Node.new.tap { |n| n.name(name) }
12644 long: "--flat",
12645 short: "-1",
12646 patterns = name_args.length == 0 ? [""] : name_args
12647 dir_results = []
12648 results = all_results.select { |result| result.exists? && (!result.dir? || config[:bare_directories]) }.to_a
12649 if results.length == 0 && dir_results.length == 1
12650 output ""
12651 output "#{format_path(result)}:"
12652 return []
12653 result = [ [ result, children ] ]
12654 print_space = results.map(&:length).max + 2
12655 current_line = ""
12656 current_line << (" " * (print_space - result.length))
12657 @ui = ui
12658 key = Chef::Key.send(@load_method, @actor, @name)
12659 long: "--with-details",
12660 long: "--only-expired",
12661 long: "--only-non-expired",
12662 keys = Chef::Key.send(@list_method, @actor)
12663 key["name"] = key["name"] + ":"
12664 max_length = key["name"].length if key["name"].length > max_length
12665 next if !key["expired"] && @config[:only_expired]
12666 next if key["expired"] && @config[:only_non_expired]
12667 display = "#{colorize(key["name"].ljust(max_length))} #{key["uri"]}"
12668 display = "#{display} (expired)" if key["expired"]
12669 short: "-c",
12670 long: "--create-key",
12671 long: "--key-name NAME",
12672 File.open(@config[:file], "w") do |f|
12673 key = Chef::Key.new(@actor, @actor_field_name)
12674 if @config[:public_key] && @config[:create_key]
12675 to_display = "Updated key: #{key.name}"
12676 to_display << " (formally #{@original_name})" if key.name != @original_name
12677 @ui.confirm("Do you really want to delete the key named #{@name} for the #{@actor_field_name} named #{@actor}")
12678 @ui.info("Deleted key named #{@name} for the #{@actor_field_name} named #{@actor}")
12679 if !@config[:public_key] && !@config[:key_name]
12680 display_info("Created key: #{key.name}")
12681 group = rest.get_rest("groups/#{group_name}")
12682 groups.select { |gname| !is_usag?(gname) }
12683 ui.msg "Creating '#{group_name}' group"
12684 long: "--exec CODE",
12685 ChefConfig::PathHelper.home(".chef", "scripts") { |p| config[:script_path] << p }
12686 puts "1. To run the script, use 'Ctrl D'"
12687 puts "2. To exit, use 'Ctrl/Shift C'"
12688 puts "Type here a script..."
12689 test = File.join(path, x)
12690 Chef::Log.trace("Testing: #{test}")
12691 Chef::Log.trace("Found: #{test}")
12692 ui.error("\"#{x}\" not found in current directory or script_path, giving up.")
12693 env_name = @name_args[0]
12694 if config[:all] == true
12695 long: "--mismatch",
12696 if config[:format] == "summary"
12697 unless @name_args.nil? || @name_args.empty?
12698 @name_args.each { |name| environments << name }
12699 constraints = {}
12700 unless env == "_default"
12701 rows = [ "" ]
12702 constraints.each_key { |e| environments << e.to_s }
12703 environments.each { |env| rows << ui.color(env, :bold) }
12704 total = []
12705 environments.each { |n| total << constraints[n][c] }
12706 rows << ui.color(c, :bold)
12707 tag = constraints[e][c] || "latest"
12708 rows << ui.color(tag, color)
12709 Tempfile.open([ "knife-edit-", extension ]) do |file|
12710 unless system("#{config[:editor]} #{file.path}")
12711 fs_error, result = Chef::ChefFS::FileSystem.copy_to(pattern, chef_fs, local_fs, config[:recurse] ? nil : 1, config, ui, proc { |entry| format_path(entry) })
12712 long: "--name-only",
12713 long: "--name-status",
12714 long: "--diff-filter=[(A|D|M|T)...[*]]",
12715 patterns = pattern_args_from(name_args.length > 0 ? name_args : [ "" ])
12716 found_error = Chef::ChefFS::CommandLine.diff_print(pattern, chef_fs, local_fs, config[:recurse] ? nil : 1, output_mode, proc { |entry| format_path(entry) }, config[:diff_filter], ui ) do |diff|
12717 ui.error "Failed on #{format_path(e.entry)} in #{e.operation}: #{e.message}"
12718 long: "--tree",
12719 long: "--remote",
12720 if config[:recurse] == false && !config[:tree]
12721 @root = config[:remote] ? chef_fs : local_fs
12722 if !printed[entry.path] && (config[:recurse] || depth == 0)
12723 if node["chef_environment"] && node["chef_environment"] != "_default"
12724 if node["run_list"]
12725 if role["run_list"]
12726 role["env_run_lists"].each_pair do |env, run_list|
12727 if run_list_item.name =~ /(.+)::[^:]*/
12728 long: "--both",
12729 root = entry.root == chef_fs ? " (remote)" : " (local)"
12730 ui.error "#{format_path_with_root(e.entry)} #{e.reason}."
12731 @name_args[1],
12732 long: "--encrypt",
12733 Chef::Config.key?(:knife) ? Chef::Config[:knife] : {}
12734 @data_bag_path ||= "data_bags"
12735 loader.find_all_object_dirs("./#{data_bags_path}")
12736 loader.find_all_objects("./#{data_bags_path}/#{data_bag}")
12737 data_bags = args.empty? ? find_all_data_bags : [args.shift]
12738 ui.info("Updated data_bag_item[#{dbag.data_bag}::#{dbag.id}]")
12739 paths = []
12740 paths << path
12741 if @name_args.length != 2
12742 item, was_encrypted = load_item(@name_args[0], @name_args[1])
12743 rest.put("data/#{@name_args[0]}/#{@name_args[1]}", item_to_save)
12744 stdout.puts("Saved data_bag_item[#{@name_args[1]}]")
12745 if @name_args.length == 2
12746 rest.delete("data/#{@name_args[0]}/#{@name_args[1]}")
12747 rest.delete("data/#{@name_args[0]}")
12748 rest.get("data/#{@data_bag_name}")
12749 raise unless /^404/.match?(e.to_s)
12750 rest.post("data", { "name" => @data_bag_name })
12751 ui.info("Created data_bag[#{@data_bag_name}]")
12752 create_object({ "id" => @data_bag_item_name }, "data_bag_item[#{@data_bag_item_name}]") do |output|
12753 rest.post("data/#{@data_bag_name}", item)
12754 client_rb << "chef_license \"#{chef_config[:chef_license]}\"
"
12755 client_rb << %Q{node_name "#{config[:chef_node_name]}"
}
12756 client_rb << "# Using default node name (fqdn)
"
12757 client_rb << %Q{log_level :#{chef_config[:config_log_level]}
}
12758 client_rb << %Q{verify_api_cert #{value}
}
12759 client_rb << %Q{ssl_verify_mode :#{value}
}
12760 client_rb << %Q{ssl_verify_mode :#{config[:ssl_verify_mode]}
}
12761 client_rb << "
"
12762 client_rb << "fips true
"
12763 %Q{:#{chef_config[:config_log_location]}
}
12764 %Q{"#{chef_config[:config_log_location]}"
}
12765 start_chef << "#{ChefUtils::Dist::Infra::CLIENT} -c #{client_rb} -j #{first_boot}#{bootstrap_environment_option}
"
12766 If InStr(url, "file://") = 1 Then
12767 If InStr(url, "file:///") = 1 Then
12768 sourcePath = Mid(url, Len("file:///") + 1)
12769 sourcePath = Mid(url, Len("file:") + 1)
12770 sourcePath = Replace(sourcePath, "/", "\\")
12771 if ($ProxyUrl -ne '') {
12772 install_command('"') + "
" + fallback_install_task_command
12773 if config[:msi_url].nil? || config[:msi_url].empty?
12774 url += "&pv=#{machine_os}" unless machine_os.nil?
12775 url += "&m=#{machine_arch}" unless machine_arch.nil?
12776 url += "&channel=#{config[:channel]}"
12777 url += "&v=#{version_to_install}"
12778 file_contents.gsub(/^(.*)$/, 'echo.\1').gsub(/([(<|>)^])/, '^\1')
12779 content << "> #{bootstrap_directory}/trusted_certs/#{File.basename(cert)} (
" +
12780 escape_and_echo(IO.read(File.expand_path(cert))) + "
)
"
12781 root.find do |f|
12782 if f != root
12783 file_on_node = "#{bootstrap_directory}/client.d/#{relative}".tr("/", "\\")
12784 content << "mkdir #{file_on_node}
"
12785 content << "> #{file_on_node} (
" +
12786 escape_and_echo(IO.read(File.expand_path(f))) + "
)
"
12787 command = install_command("'")
12788 ) else (
12789 @highline ||= begin
12790 @prompt ||= begin
12791 raise e if @config[:verbosity] >= 2
12792 lines = message.split("
")
12793 prefix, = first_line.split(":", 2)
12794 padding = " " * prefix_len
12795 stderr.puts "#{padding}#{line}"
12796 log("#{color("DEBUG:", :blue, :bold)} #{message}")
12797 log("#{color("WARNING:", :yellow, :bold)} #{message}")
12798 log("#{color("ERROR:", :red, :bold)} #{message}")
12799 log("#{color("FATAL:", :red, :bold)} #{message}")
12800 Chef::Config[:color] && stdout.tty?
12801 def ask(*args, **options, &block)
12802 prompt.ask(*args, **options, &block)
12803 question += "[#{opts[:default]}] " if opts[:default]
12804 a.empty? ? opts[:default] : a
12805 Tempfile.open([ "knife-edit-", ".json" ]) do |tf|
12806 msg("Saved #{output}")
12807 when "Y", "y"
12808 when "N", "n"
12809 msg("You said no, so I'm done here.")
12810 when ""
12811 msg("I have no idea what to do with '#{answer}'")
12812 msg("Just say Y or N, please.")
12813 justify_width = data.keys.map { |k| k.to_s.size }.max.to_i + 1
12814 if value.is_a?(Array) && value.size == 1 && is_singleton(value[0])
12815 value = value[0]
12816 justified_key = ui.color("#{key}:".ljust(justify_width), :cyan)
12817 buffer << "#{justified_key} #{value}
"
12818 buffer << ui.color("#{key}:
", :cyan)
12819 lines = text_format(value).split("
")
12820 buffer << "
" if !is_singleton(data[index]) && index != data.size - 1
12821 buffer << "#{data}
"
12822 !(value.is_a?(Array) || value.respond_to?(:keys))
12823 File.open(plugin_manifest_path, "w") do |f|
12824 cmd_words, "_")]
12825 result || Chef::Knife.subcommands[args.first.tr("-", "_")]
12826 category_words.map! { |w| w.split("-") }.flatten!
12827 category_words, " ")
12828 files = Dir[File.join(ChefConfig::PathHelper.escape_glob_dir(File.expand_path("../../knife", __dir__)), "*.rb")]
12829 version_file_match = /#{Regexp.escape(File.join('chef', 'knife', 'version.rb'))}/
12830 def find_longest_key(hash, words, sep = "_")
12831 candidate = words.join(sep).tr("-", "_")
12832 args.grep(/^(([[:alnum:]])[[:alnum:]\_\-]+)$/)
12833 ChefConfig::PathHelper.home(".chef", "plugins", "knife") do |p|
12834 result_list = []
12835 result["name"] = node["name"] || node.name
12836 ip = (node["cloud"] && node["cloud"]["public_ipv4_addrs"]&.first) || node["ipaddress"]
12837 fqdn = (node["cloud"] && node["cloud"]["public_hostname"]) || node["fqdn"]
12838 result["ip"] = ip if ip
12839 result["fqdn"] = fqdn if fqdn
12840 result["run_list"] = node.run_list if config["run_list"]
12841 result["ohai_time"] = node["ohai_time"]
12842 summarized = ""
12843 ip = (node[:cloud] && node[:cloud][:public_ipv4_addrs] && node[:cloud][:public_ipv4_addrs].first) || node[:ipaddress]
12844 fqdn = (node[:cloud] && node[:cloud][:public_hostname]) || node[:fqdn]
12845 name = node["name"] || node.name
12846 run_list = node.run_list.map { |rl| "#{rl.type}[#{rl.name}]" }
12847 run_list = node["run_list"]
12848 line_parts = []
12849 if node["ohai_time"]
12850 hours_text = "#{hours} hour#{hours == 1 ? " " : "s"}"
12851 minutes_text = "#{minutes} minute#{minutes == 1 ? " " : "s"}"
12852 seconds_text = "#{seconds} second#{seconds == 1 ? " " : "s"}"
12853 if hours > 24
12854 color = :red
12855 elsif hours >= 1
12856 line_parts << @ui.color(text, color) + " ago" << name
12857 line_parts << "Node #{name} has not yet converged"
12858 line_parts << ip if ip
12859 platform << " #{node["platform_version"]}"
12860 summarized = summarized + line_parts.join(", ") + ".
"
12861 hours = (difference / 3600).to_i
12862 minutes = (difference / 60).to_i
12863 path << ".{json,rb}"
12864 objects.map { |o| File.basename(o) }
12865 objects.delete_if { |o| !File.directory?(o) }
12866 when /\.(js|json)$/
12867 r = klass.new
12868 ui.fatal("File must end in .js, .json, or .rb")
12869 if data.is_a?(Chef::Node)
12870 result["name"] = node.name
12871 summarized << <<~ENV
12872 summarized += <<~MORE
12873 summarized += <<~MOST
12874 @node, @ui, @config = node, ui, config
12875 }.reject do |key|
12876 if node.name && node.name != updated_data["name"]
12877 errors = {}
12878 commands.collect { |k, v| v }.flatten.each do |command|
12879 if paths && paths.is_a?(Array)
12880 if paths.all? { |sc| !File.exist?(sc) }
12881 Chef::Log.error "Missing files:
\t#{errors.values.flatten.join("
\t")}"
12882 if paths.nil? || paths.empty? || (! paths.is_a? Array)
12883 find_longest_key(manifest[KEY]["plugins_paths"], args, "_")
12884 long: "--attribute ATTR1 [--attribute ATTR2] ",
12885 accumulator ||= []
12886 @ui, @config = ui, config
12887 if config[:attribute] && data.length == 1
12888 PP.pp(data, out)
12889 when "summary", /^s/, nil
12890 when "text", /^t/
12891 when "json", /^j/
12892 when "yaml", /^y/
12893 when "pp", /^p/
12894 :pp
12895 { "run_list" => run_list }
12896 { name_or_id_for(data) => subset }
12897 data.respond_to?(:name) ? data.name : data["id"]
12898 config[:field_separator] || "."
12899 if data.is_a?(Array)
12900 elsif data.respond_to?(:[], false) && data.respond_to?(:key?) && data.key?(attr)
12901 ( !data.is_a?(Array) && data.respond_to?(:to_hash) ) ? data.to_hash : data
12902 collected[cookbook][ver["version"]] = ver["url"]
12903 collected[cookbook] = versions["versions"].map { |v| v["version"] }
12904 version_file_match = /#{Regexp.escape(File.join('chef', 'knife', 'version'))}$/
12905 rel_path = file[/(.*)(#{Regexp.escape File.join('chef', 'knife', '')}.*)\.rb/, 2]
12906 long: "--medium",
12907 short: "-l",
12908 long: "--long",
12909 Chef::Log.trace("Staging #{on_disk_path} to #{dest}")
12910 kcm.name_args = [ cookbook.name.to_s ]
12911 def post(to_url, user_id, secret_key_filename, params = {}, headers = {})
12912 def put(to_url, user_id, secret_key_filename, params = {}, headers = {})
12913 def make_request(http_verb, to_url, user_id, secret_key_filename, params = {}, headers = {})
12914 boundary = "----RubyMultipartClient" + rand(1000000).to_s + "ZZZZZ"
12915 parts = []
12916 if value.is_a?(File)
12917 parts << StringPart.new( "--" + boundary + "\r
" +
12918 parts << StringPart.new("\r
")
12919 parts << StringPart.new(value.to_s + "\r
")
12920 parts << StringPart.new("--" + boundary + "--\r
")
12921 url = URI.parse(to_url)
12922 Chef::Log.logger.debug("Signing: method: #{http_verb}, url: #{url}, file: #{content_file}, User-id: #{user_id}, Timestamp: #{timestamp}")
12923 content_body = parts.inject("") { |result, part| result + part.read(0, part.size) }
12924 (content_file && signing_options[:file] = content_file) || (signing_options[:body] = (content_body || ""))
12925 headers = DefaultHeaders.merge(Hash[*headers.map { |k, v| [k.to_s, v] }.flatten])
12926 class << res
12927 @stream, @size = stream, size
12928 @str = str
12929 @part_no = 0
12930 @part_offset = 0
12931 @parts.inject(0) { |size, part| size + part.size }
12932 def read(how_much, dst_buf = nil)
12933 if @part_no >= @parts.size
12934 dst_buf.replace("") if dst_buf
12935 @part_no += 1
12936 result = current_part + (next_part || "")
12937 dst_buf ? dst_buf.replace(result || "") : result
12938 def initialize(repo_path, ui, opts = {})
12939 cmd = git("status --porcelain")
12940 git("checkout #{branch}")
12941 git("checkout -b #{branch}")
12942 git("add #{cookbook_name}")
12943 git("commit -m \"Import #{cookbook_name} version #{version}\" -- #{cookbook_name}")
12944 if system("git merge #{branch}")
12945 ui.info("Merge status (cd #{repo_path}; git status):")
12946 update_count == 0 ? nil : update_count
12947 git("branch --no-color").stdout.lines.any? { |l| l =~ /\s#{Regexp.escape(branch_name)}(?:\s|$)/ }
12948 ref.chomp.split("/")[2]
12949 shell_out!("git #{command}", cwd: repo_path)
12950 @client_d ||= client_d_content
12951 if !(chef_config[:config_log_location].class == IO ) && (chef_config[:config_log_location].nil? || chef_config[:config_log_location].to_s.empty?)
12952 %Q{"#{chef_config[:config_log_location]}"}
12953 client_rb << "file_cache_path \"#{chef_config[:unix_bootstrap_file_cache_path]}\"
"
12954 client_rb << "file_backup_path \"#{chef_config[:unix_bootstrap_file_backup_path]}\"
"
12955 s = "#{client_path} -j /etc/chef/first-boot.json"
12956 if config[:verbosity] && config[:verbosity] >= 3
12957 s << " -l trace"
12958 s << " -l debug"
12959 s << " --no-color" unless config[:color]
12960 if config[:channel] == "stable"
12961 attributes.merge!(tags: config[:tags]) if config[:tags] && !config[:tags].empty?
12962 content << "cat > /etc/chef/trusted_certs/#{File.basename(cert)} <<'EOP'
" +
12963 IO.read(File.expand_path(cert)) + "
EOP
"
12964 file_on_node = "/etc/chef/client.d/#{relative}"
12965 content << "cat > #{file_on_node} <<'EOP'
" +
12966 f.read.gsub("'", "'\\\\''") + "
EOP
"
12967 long: "--freeze",
12968 boolean: true, long: "--[no-]check-dependencies",
12969 if ! config[:all] && @name_args.empty?
12970 upload_ok = 0
12971 cookbooks = []
12972 upload_ok += 1
12973 ui.info "Uploaded #{upload_ok} cookbook#{upload_ok == 1 ? "" : "s"}."
12974 elsif upload_failures > 0 && upload_ok > 0
12975 ui.warn "Uploaded #{upload_ok} cookbook#{upload_ok == 1 ? "" : "s"} ok but #{upload_failures} " +
12976 elsif upload_failures > 0 && upload_ok == 0
12977 ui.error "Failed to upload #{upload_failures} cookbook#{upload_failures == 1 ? "" : "s"}."
12978 @justify_width ||= server_side_cookbooks.map(&:size).max.to_i + 2
12979 upload_set = {}
12980 if e.response.code.to_s == "404"
12981 ui.info("Uploading #{left_justify_name(cb)} [#{cb.version}]")
12982 !/[0-9a-f]{32,}/.match?(info["checksum"])
12983 ui.error "The broken file(s) are: #{broken_filenames.join(" ")}"
12984 ui.error "The missing cookbook(s) are: #{missing_cookbook_names.join(", ")}"
12985 long: "--fqdn FQDN",
12986 node[:fqdn] = config[:fqdn] if config.key?(:fqdn)
12987 class << node
12988 key?(name)
12989 file = @name_args[0]
12990 File.open(json_file, "w") do |f|
12991 ui.stderr.puts "in #{file}:"
12992 ui.stderr.puts "in #{json_file}:"
12993 api_endpoint = env ? "/environments/#{env}/cookbooks?#{num_versions}" : "/cookbooks?#{num_versions}"
12994 short: "-N",
12995 long: "--latest",
12996 dest = File.join(basedir, segment_file["path"].gsub("/", File::SEPARATOR))
12997 Chef::Log.trace("Downloading #{segment_file["path"]} to #{dest}")
12998 valid_responses = {}
12999 valid_responses[(index + 1).to_s] = version
13000 question << "#{index + 1}. #{@cookbook_name} #{version}
"
13001 question += "
"
13002 ui.error("'#{response}' is not a valid value.")
13003 option :all, short: "-a", long: "--all", boolean: true, description: "Delete all versions of the cookbook."
13004 question << "#{available_versions.size + 1}. All versions

"
13005 ui.info("Deleted cookbook[#{@cookbook_name}][#{version}]")
13006 if version == :all
13007 path += "?purge=true" if config[:purge]
13008 ui.msg ""
13009 versions = rest.get("cookbooks/#{cookbook_name}")[cookbook_name]["versions"].map { |v| v["version"] }.flatten
13010 rest.delete("cookbooks/#{cookbook_name}/#{version}#{config[:purge] ? "?purge=true" : ""}")
13011 File.open(File.join(@config_dir, "client.rb"), "w") do |file|
13012 long: "--repository REPO",
13013 long: "--initial",
13014 long: "--admin-client-name NAME",
13015 long: "--admin-client-key PATH",
13016 long: "--validation-key PATH",
13017 Chef::Config[:node_name] = "woot"
13018 ::File.open(config_file_path, "w") do |f|
13019 chef_server_url = '#{chef_server}'
13020 ui.msg("*****")
13021 @new_client_key = config[:client_key] || File.join(chef_config_path, "#{@new_client_name}.pem")
13022 o = Ohai::System.new
13023 o[:fqdn] || o[:machinename] || o[:hostname] || "localhost"
13024 profile = @name_args[0]&.strip
13025 IO.write(context_file, "#{profile}
")
13026 long: "--raw",
13027 if config[:format] == "summary" && !config[:raw]
13028 output_data = {}
13029 if filter =~ %r{^/(.*)/(i?)$}
13030 filter_parts = filter.split(".")
13031 memo.is_a?(Hash) ? memo[filter_part.to_sym] : nil
13032 ui.msg(ui.color("Loading from #{type_of_file} file #{path}", :yellow))
13033 long: "--ignore-knife-rb",
13034 rows = []
13035 profile[:client_key] = profile[:client_key].to_s.gsub(/^#{Regexp.escape(Dir.home)}/, "~") if profile[:client_key]
13036 profile[:profile] = "#{profile[:active] ? "*" : " "}#{profile[:profile]}"
13037 separator ->(row) { (row + 1) % TABLE_HEADER.size == 0 }
13038 if col_index == 1 || (row_index) % TABLE_HEADER.size == 0
13039 mid "-"
13040 @client_name = @name_args[0]
13041 ui.msg("Saved #{client}.")
13042 long: "--validator",
13043 long: "--public-key",
13044 ui.fatal "#{dir} exists, but is not a directory. Please update your file path (--file #{file}) or re-create #{dir} as a directory."
13045 if File.exist?(file) && !File.writable?(file)
13046 clients_to_delete = {}
13047 ui.msg("Deleted client #{name}")
13048 $parent = [System.IO.Path]::GetTempPath();
13049 [string] $name = [System.Guid]::NewGuid();
13050 @host_url = host_url
13051 @opts_in = opts
13052 @config ||= begin
13053 @tmpdir ||= if windows?
13054 run_command!("mkdir -p '#{dir}'")
13055 run_command!("chown #{config[:user]} '#{dir}'") if config[:sudo]
13056 t << content
13057 run_command!("If (Test-Path \"#{path}\") { Remove-Item -Force -Path \"#{path}\" }")
13058 run_command!("rm -f \"#{path}\"")
13059 path.tr("\\", "/")
13060 opts = { target: host_url,
13061 logger: opts_in[:logger] }
13062 return {} unless config[:backend] == "winrm"
13063 opts_out = {}
13064 if opts_in[:ssl]
13065 opts_out[:ssl] = true
13066 opts_out[:self_signed] = opts_in[:self_signed] || false
13067 opts_in.select do |key, _v|
13068 valid_opts.key?(key) && !config.key?(key)
13069 return {} unless config[:backend] == "ssh"
13070 host_cfg.each do |key, _value|
13071 opts_out[key] = host_cfg[key]
13072 def initialize(config: {}, knife_config: nil, chef_config: {}, ui: nil)
13073 @client_path ||=
13074 File.join(@tmpdir, "#{node_name}.pem")
13075 run_list.split(/\s*,\s*/)
13076 @node ||=
13077 (config[:tags] || []).each do |tag|
13078 node.tags << tag
13079 rest.delete("nodes/#{node_name}")
13080 [ items ].flatten.each do |item|
13081 @vault_json ||=
13082 @require_chef_vault ||=
13083 long: "--winrm-no-verify-cert",
13084 long: "--winrm-ssl",
13085 long: "--winrm-basic-auth-only",
13086 long: "--ssh-forward-agent",
13087 long: "--ssh-verify-host-key VALUE",
13088 long: "--node-ssl-verify-mode [peer|none]",
13089 proc: Proc.new { |v|
13090 raise "Invalid value '#{v}' for --node-ssl-verify-mode. Valid values are: #{valid_values.join(", ")}"
13091 long: "--[no-]node-verify-api-cert",
13092 long: "--sudo",
13093 long: "--sudo-preserve-home",
13094 long: "--use-sudo-password",
13095 long: "--su-user NAME",
13096 long: "--node-name NAME",
13097 proc: lambda { |o| o.split(/[\s,]+/) },
13098 long: "--tags TAGS",
13099 long: "--json-attributes",
13100 proc: lambda { |o| Chef::JSONCompat.parse(o) },
13101 proc: lambda { |o| Chef::JSONCompat.parse(File.read(o)) },
13102 accumulator ||= {}
13103 name, path = hint.split("=", 2)
13104 accumulator[name] = path ? Chef::JSONCompat.parse(::File.read(path)) : {}
13105 long: "--bootstrap-url URL",
13106 short: "-m URL",
13107 long: "--msi-url URL",
13108 proc: Proc.new { |i, accumulator|
13109 (vault, item) = i.split(":")
13110 accumulator[vault] ||= []
13111 boolean: true, long: "--[no-]host-key-verify",
13112 value_mapper: Proc.new { |verify| verify ? "always" : "never" }
13113 long: "--prerelease",
13114 long: "--winrm-port PORT"
13115 value_mapper: Proc.new { |value| value == "ssl" }
13116 ui: ui
13117 @server_name ||= host_descriptor.split("@").reverse[0]
13118 bootstrap_files = []
13119 bootstrap_files << File.join(__dir__, "bootstrap/templates", "#{template}.erb")
13120 ChefConfig::PathHelper.home(".chef", "bootstrap", "#{template}.erb") { |p| bootstrap_files << p }
13121 bootstrap_files << Gem.find_files(File.join("chef", "knife", "bootstrap", "#{template}.erb"))
13122 (Chef::Config[:validation_key] &&
13123 ui.msg("#{ui.color(" [#{connection.hostname}]", :cyan)} #{data}")
13124 if r.exit_status != 0
13125 ui.error("#{r.stdout} #{r.stderr}".strip)
13126 limit ||= 0
13127 if e.reason == :bad_su_user_password && limit < 3
13128 limit += 1
13129 ui.warn("Failed to authenticate su - #{config[:su_user]} to #{server_name}")
13130 config[:su_password] = ui.ask("Enter password for su - #{config[:su_user]}@#{server_name}:", echo: false)
13131 if e.message =~ /fingerprint (\S+) is unknown for "(.+)"/ # Train::Transports::SSHFailed
13132 hostname, ip = $2.split(",")
13133 elsif (ssh? && e.cause && e.cause.class == Net::SSH::AuthenticationFailed) || (ssh? && e.class == Train::ClientError && e.reason == :no_ssh_password_or_key_available)
13134 password = ui.ask("Enter password for #{opts[:user]}@#{server_name}:", echo: false)
13135 from_url = host_descriptor =~ %r{^(.*)://} ? $1 : nil
13136 @connection_protocol = from_url || from_knife || "ssh"
13137 limit ||= 1
13138 if !conn_options.key?(:pty) && e.reason == :sudo_no_tty
13139 ui.warn("#{e.message} - trying with pty request")
13140 elsif config[:use_sudo_password] && (e.reason == :sudo_password_required || e.reason == :bad_sudo_password) && limit < 3
13141 if winrm_auth_method == "plaintext" &&
13142 config[:winrm_ssl] != true
13143 ui.error <<~EOM
13144 if config[:ca_trust_file].nil? &&
13145 @connection_opts = {}
13146 opts[:logger] = Chef::Log
13147 opts[:user] = user if user
13148 opts[:port] = port if port
13149 { self_signed: config[:winrm_no_verify_cert] === true }
13150 opts[:forward_agent] = (config[:ssh_forward_agent] === true)
13151 opts[:key_files] = []
13152 split = config[:ssh_gateway].split("@", 2)
13153 if split.length == 1
13154 gw_host = split[0]
13155 gw_user = split[0]
13156 gw_host = split[1]
13157 gw_host, gw_port = gw_host.split(":", 2)
13158 return {} if winrm?
13159 opts = { sudo: false }
13160 opts[:sudo] = true
13161 opts[:sudo_options] = "-H"
13162 ssl: config[:winrm_ssl] === true,
13163 cmd = "sh #{remote_path}"
13164 cmd = "su - #{config[:su_user]} -c '#{cmd}'"
13165 cmd = "sudo " << cmd if config[:use_sudo]
13166 if option == :port
13167 !config[:run_list].nil? && !config[:run_list].empty?
13168 (!!config[:policy_name] ^ config[:policy_group])
13169 return unless opts.is_a?(Hash) || !opts.empty?
13170 if acl[perm].key?("users") && acl[perm].key?("clients")
13171 if member_name == "pivotal" && %w{client user}.include?(member_type)
13172 if member_name == "admins" && member_type == "group" && perms.to_s.split(",").include?("grant")
13173 object_name_matcher = /#{regex}/
13174 objects_to_modify = []
13175 ui.info "No #{object_type} match the expression /#{regex}/"
13176 ui.fatal "Invalid name: #{name}"
13177 ui.fatal "Unknown member type \"#{type}\". The following types are permitted: #{MEMBER_TYPES.join(", ")}"
13178 perms.split(",").each do |perm|
13179 true if rest.get_rest("#{member_type}s/#{member_name}")
13180 ui.fatal "#{member_type} '#{member_name}' does not exist"
13181 gname.length == 32 && gname =~ /^[0-9a-f]+$/
13182 ui.msg "Adding '#{member_name}' to '#{perm}' ACE of '#{object_name}'"
13183 ace = acl[perm]
13184 when "client", "user"
13185 key = "#{member_type}s"
13186 ace[key] << member_name
13187 ace["groups"] << member_name
13188 ui.msg "Removing '#{member_name}' from '#{perm}' ACE of '#{object_name}'"
13189 rest.put_rest("#{object_type}/#{object_name}/_acl/#{ace_type}", ace_type => ace)
13190 ui.msg "Adding '#{member_name}' to '#{group_name}' group"
13191 new_group = {
13192 ui.msg "Removing '#{member_name}' from '#{group_name}' group"
13193 def self.msg(msg = "")
13194 @@chef_config_dir = nil
13195 @@subcommands = {}
13196 snake_case_name.split("_").join(" ")
13197 name.nil? || name.empty?
13198 if args.size == 1 && args[0].strip.casecmp("rehash") == 0
13199 @@subcommands ||= {}
13200 @@subcommand_files ||= Hash.new([])
13201 @subcommands_by_category = Hash.new { |hash, key| hash[key] = [] }
13202 def self.run(args, options = {})
13203 @dependency_loaders ||= []
13204 category_desc = preferred_category ? preferred_category + " " : ""
13205 caller_line.split(/:\d+/).first
13206 ui.fatal("Cannot find subcommand for: '#{args.join(" ")}'")
13207 @name_args.reject! { |name_arg| command_name_joined == name_arg }
13208 puts "Error: " + e.to_s
13209 Chef::Config[:log_level] = :warn
13210 Chef::Config[:log_level] = :info
13211 Chef::Config[:log_level] = :debug
13212 Chef::Config[:log_level] = :trace
13213 Chef::Log.level(Chef::Config[:log_level] || :error)
13214 stdout.puts("USAGE: " + opt_parser.to_s)
13215 raise if raise_exception || ( Chef::Config[:verbosity] && Chef::Config[:verbosity] >= 2 )
13216 ui.info ""
13217 ui.error "#{e.class.name}: #{e.message}"
13218 msg("Created #{pretty_name}")
13219 obj_name = delete_name ? "#{delete_name}[#{name}]" : object
13220 msg("Deleted #{obj_name}")
13221 @rest ||= begin
13222 Chef::Config[:fips] = config[:fips]
13223 @root_rest ||= begin
13224 args.map { |arg| pattern_arg_from(arg) }
13225 ui.warn("Consider writing '#{possible_server_path}' instead of '#{arg}'")
13226 elsif arg[0, 1] == "~"
13227 ui.warn("Using '#{inferred_path}' as the path instead of '#{arg}'.")
13228 if parent && parent != dir
13229 proc: lambda { |path| File.expand_path(path, Dir.pwd) }
13230 short: "-V",
13231 long: "--verbose",
13232 proc: Proc.new { verbosity_level += 1 },
13233 long: "--disable-editing",
13234 short: "-k KEY",
13235 long: "--key KEY",
13236 short: "-s URL",
13237 long: "--server-url URL",
13238 short: "-y",
13239 long: "--yes",
13240 long: "--defaults",
13241 long: "--print-after",
13242 if want_help? || want_version?
13243 ARGV[0] =~ /^(--help|-h)$/
13244 ARGV[0] =~ /^(--version|-v)$/
13245 puts "#{e}
"
13246 describe file("C:\\habitat\\hab.exe") do
13247 it { should exist }
13248 its(%w{directories path}) { should eq ["C:/hab/pkgs/.../*.log"] }
13249 describe command("C:\\habitat\\hab.exe sup -h") do
13250 its(:stdout) { should match(/Running/) }
13251 restart_script = <<-EOH
13252 its(:exit_status) { should eq(0) }
13253 its("content") { should match(/bldr_url.*willem.habitat.sh/) }
13254 it { should_not exist }
13255 its(["bldr_url"]) { should eq "https://bldr.habitat.sh/" }
13256 its(%w{cfg id}) { should eq "hab-sensu-agent" }
13257 its(%w{cfg backend-urls}) { should eq ["ws://127.0.0.1:8081"] }
13258 its(["channel"]) { should eq "stable" }
13259 its(["desired_state"]) { should eq "Down" }
13260 its(["spec_file"]) { should eq "C:\\hab/sup\\default\\specs\\sensu-agent-win.spec" }
13261 its(["topology"]) { should eq "standalone" }
13262 its(["update_strategy"]) { should eq "rolling" }
13263 describe command("C:\\habitat\\hab.exe -V") do
13264 its("stdout") { should match(%r{^hab.*/}) }
13265 its("exit_status") { should eq 0 }
13266 its("stdout") { should match(/C:\\hab\\pkgs\\skylerto\\splunkforwarder/) }
13267 nginx_content = <<-EOF
13268 [http]
13269 its(%w{http listen port}) { should eq 80 }
13270 its(["worker_processes"]) { should eq 2 }
13271 describe send("#{svc_manager}_service", "hab-sup") do
13272 its("content") { should_not match("LimitNOFILE = 65536") }
13273 its("content") { should_not match("env HAB_AUTH_TOKEN=test") }
13274 its("content") { should match(/peer.*127.0.0.2:9632.*127.0.0.3:9632/) }
13275 its(["binding_mode"]) { should eq "relaxed" }
13276 its(["binds"]) { should eq ["prom:prometheus.default"] }
13277 its(["bldr_url"]) { should eq "https://bldr-test.habitat.sh/" }
13278 its(["service_group"]) { should eq "grafana.test" }
13279 its(["update_condition"]) { should eq "latest" }
13280 its(["update_strategy"]) { should eq "at-once" }
13281 its(:content) { should match(%r{ident = "core/vault/1.1.5"}) }
13282 its(:content) { should match(%r{ident = "core/consul"}) }
13283 its(:content) { should match(/desired_state = "up"/) }
13284 its(:content) { should match(/channel = "stable"/) }
13285 its(:content) { should match(/^desired_state = "up"$/) }
13286 its(:content) { should match(/binds = \["rabbitmq:rabbitmq.default", "redis:redis.default"\]/) }
13287 its("stdout") { should match(%r{/hab/pkgs/core/redis}) }
13288 its("stdout") { should match(%r{/hab/pkgs/lamont-granquist/ruby/2.3.1}) }
13289 its(:link_path) { should match(%r{/hab/pkgs/core/htop}) }
13290 its("stdout") { should match(%r{^hab 1.5.71/}) }
13291 its("stdout") { should match /my_signed_cert.*OK/ }
13292 its("stderr") { should be_empty }
13293 its("content") { should match(%r{chef_server_url "https://localhost"}) }
13294 its("content") { should match(/chef_license "accept"/) }
13295 its("content") { should match(%r{rubygems_url "https://rubygems.org/"}) }
13296 its("content") { should match(/require 'aws-sdk'/) }
13297 command "git --version & git --exec-path"
13298 $possibleInstalledPaths = @("C:/Program Files/Git/", "C:/Program Files (x64)/Git/", "c:/git/")
13299 code "Start-Sleep -s 1"
13300 %w{001 002 003}.each do |control|
13301 extract_to File.join(Chef::Config[:file_cache_path], archive.tr(".", "_"))
13302 only_if { debian? }
13303 uid "8019"
13304 nameservers [ "8.8.8.8", "8.8.4.4" ]
13305 search [ "chef.io" ]
13306 users_from_databag = search("users", "*:*")
13307 if platform_family?("rhel", "fedora", "amazon")
13308 level "s0"
13309 range "s0"
13310 user "se_map_test_u"
13311 hour "0,12"
13312 only_if { systemd? }
13313 if ::File.exist?("/etc/systemd/system")
13314 only_if { File.exist?("/etc/yum.conf") && File.readlines("/etc/yum.conf").grep(/http_caching=packages/).empty? }
13315 only_if { rhel? }
13316 sudo "bob" do
13317 user "bob"
13318 sudo "~bob" do
13319 command_aliases [{ name: "STARTSSH", command_list: ["/etc/init.d/ssh start", "/etc/init.d/ssh restart", "! /etc/init.d/ssh stop"] }]
13320 sudo "git" do
13321 user "git"
13322 commands ["/usr/bin/less"]
13323 file "#{base}/private_key.pem" do
13324 key_file "#{base}/mycert.key"
13325 openssl_x509 "#{base}/my_ca.crt" do
13326 ca_key_file "#{base}/my_ca.key"
13327 ca_cert_file "#{base}/my_ca.crt"
13328 path "#{base}/my_ca2.csr"
13329 key_file "#{base}/my_ca2.key"
13330 csr_file "#{base}/my_ca2.csr"
13331 ca_key_file "#{base}/my_ca2.key"
13332 ca_cert_file "#{base}/my_ca2.crt"
13333 openssl_x509_crl "#{base}/my_ca2.crl" do
13334 key_file "#{base}/my_ec_request.key"
13335 mount "/proc" do
13336 mount "/mnt" do
13337 device "/tmp"
13338 device "/etc"
13339 value "1"
13340 type "int"
13341 value "20"
13342 value [ { "User": "/Library/Managed Installs/way_fake.log" } ]
13343 mode "644"
13344 node.normal["launchd"]["label"] = "io.chef.testing.fake"
13345 node.normal["launchd"]["run_at_load"] = true
13346 node.normal["launchd"]["type"] = "agent"
13347 path: [
13348 listen_http "0.0.0.0:9999"
13349 bind [
13350 uptime = `hab svc status core/consul`.match(/standalone\s+up\s+up\s+([0-9]+)/)
13351 raise "consul not restarted" unless !uptime.nil? && uptime.size == 2 && Integer(uptime[1]) < 30
13352 version "2.3.1"
13353 version "1.15.2"
13354 hab_version "1.5.71"
13355 cron_d "noop" do
13356 hour "5"
13357 minute "0"
13358 hour "8"
13359 hour "20"
13360 day "*"
13361 month "11"
13362 weekday "1-5"
13363 log_location windows? ? "C:\\chef\\log_test\\client.log" : "/var/log/chef/log_test/client.log"
13364 raw_data("auth" => "1234")
13365 search "*:*"
13366 raw_data("auth" => "4321")
13367 content '#!/bin/bash
13368 mode "500"
13369 mode "550"
13370 default["openssh"]["client"]["gssapi_authentication"] = "no"
13371 default["openssh"]["client"]["check_host_ip"] = "no"
13372 default["openssh"]["client"]["strict_host_key_checking"] = "no"
13373 default["openssh"]["client"]["protocol"] = "2"
13374 default["openssh"]["server"]["use_dns"] = "no"
13375 default["openssh"]["server"]["syslog_facility"] = "AUTH"
13376 default["openssh"]["server"]["gssapi_authentication"] = "no"
13377 default["openssh"]["server"]["ignore_rhosts"] = "yes"
13378 default["openssh"]["server"]["permit_empty_passwords"] = "no"
13379 default["openssh"]["server"]["tcp_keepalive"] = "yes"
13380 default["openssh"]["server"]["max_start_ups"] = "10"
13381 default["openssh"]["server"]["print_motd"] = "no"
13382 default["openssh"]["server"]["protocol"] = "2"
13383 default["openssh"]["server"]["x11_forwarding"] = "yes"
13384 default["chef_client"]["splay"] = 1800
13385 default["audit"]["reporter"] = "cli"
13386 chef_repo_path "{{pkg.svc_data_path}}/chef"
13387 file_backup_path "{{pkg.svc_data_path}}/{{cfg.file_backup_path}}"
13388 pid_file "{{pkg.svc_data_path}}/{{cfg.pid_file}}"
13389 local_mode "{{cfg.local_mode}}"
13390 {{#if cfg.chef-client.node_name ~}}
13391 node_name "{{cfg.node_name}}"
13392 {{/if ~}}
13393 splay "{{cfg.splay}}"
13394 log_level "{{cfg.log_level}}".to_sym
13395 {{#if cfg.use_member_id_as_uuid ~}}
13396 chef_guid "{{svc.me.member_id}}"
13397 val = threads + 1
13398 (1..val).parallel_map do |i|
13399 if val == i
13400 ret << i
13401 val -= 1
13402 if Time.now - start > 30
13403 expected = (1..threads + 1).to_a.reverse
13404 (1..val).parallel_each do |i|
13405 expect { (0..10).parallel_map { |i| raise "boom" } }.to raise_error(RuntimeError)
13406 expect { (0..10).parallel_each { |i| raise "boom" } }.to raise_error(RuntimeError)
13407 (1..10).parallel_map { |i| i }
13408 expect(ans).to eql((1..10).to_a)
13409 (1..10).parallel_each { |i| i }
13410 (1..2).parallel_map { |i| (1..2).parallel_map { |i| i } }
13411 expect(ans).to eql([[1, 2], [1, 2]])
13412 (1..2).parallel_each { |i| (1..2).parallel_each { |i| i } }
13413 (1..).lazy.parallel_map { |i| i }.first(5)
13414 expect(ans).to eql((1..5).to_a)
13415 (1..).lazy.parallel_each { |i| i }.first(5)
13416 let(:threads) { 10 }
13417 let(:threads) { 0 }
13418 let(:threads) { 1 }
13419 [ [ 1, 2 ], [3, 4]].flat_each { |i| sum += i }
13420 data = { x: "one", y: "two", z: "three" }
13421 @copy = @orig.dup
13422 @copy[:x] = "four"
13423 expect(@orig[:x]).to eq("one")
13424 data = { x: "one", y: "two", z: [1, 2, 3] }
13425 @copy[:z] << 4
13426 expect(@orig[:z]).to eq([1, 2, 3])
13427 data = { x: "one", y: "two", z: ChefUtils::Mash.new({ a: [1, 2, 3] }) }
13428 @copy[:z][:a] << 4
13429 expect(@orig[:z][:a]).to eq([1, 2, 3])
13430 let(:node) { { "kernel" => { "server_core" => true } } }
13431 let(:node) { { "kernel" => { "product_type" => "Workstation" } } }
13432 let(:node) { { "kernel" => { "product_type" => "Server" } } }
13433 let(:node) { { "os_version" => "6.3.9600" } }
13434 let(:node) { { "languages" => { "powershell" => { "version" => "4.0" } } } }
13435 def self.test_which(description, *args, path: ["/dir1", "/dir2" ].join(File::PATH_SEPARATOR), finds: nil, others: [], directory: false, &block)
13436 expect(ENV).to receive(:[]).with("PATH").and_return(path)
13437 expect(ENV).to receive(:[]).with("PATHEXT").and_return(nil)
13438 ["/dir1", "/dir2" ].each do |dir|
13439 test_which("doesn't find it if its false", "foo1", others: [ "/dir1/foo1" ]) do |f|
13440 def self.test_where(description, *args, path: ["/dir1", "/dir2" ].join(File::PATH_SEPARATOR), finds: [], others: [], &block)
13441 virtualization_reports_true_for(:hypervisor?, :physical?, :kvm_host?, node: { "virtualization" => { "system" => "kvm", "role" => "host" } })
13442 virtualization_reports_true_for(:guest?, :virtual?, :lxc?, node: { "virtualization" => { "system" => "lxc", "role" => "guest" } })
13443 virtualization_reports_true_for(:hypervisor?, :physical?, :lxc_host?, node: { "virtualization" => { "system" => "lxc", "role" => "host" } })
13444 virtualization_reports_true_for(:guest?, :virtual?, :parallels?, node: { "virtualization" => { "system" => "parallels", "role" => "guest" } })
13445 virtualization_reports_true_for(:hypervisor?, :physical?, :parallels_host?, node: { "virtualization" => { "system" => "parallels", "role" => "host" } })
13446 virtualization_reports_true_for(:guest?, :virtual?, :virtualbox?, :vbox?, node: { "virtualization" => { "system" => "vbox", "role" => "guest" } })
13447 virtualization_reports_true_for(:hypervisor?, :physical?, :vbox_host?, node: { "virtualization" => { "system" => "vbox", "role" => "host" } })
13448 virtualization_reports_true_for(:guest?, :virtual?, :vmware?, node: { "virtualization" => { "system" => "vmware", "role" => "guest" } })
13449 virtualization_reports_true_for(:hypervisor?, :physical?, :vmware_host?, node: { "virtualization" => { "system" => "vmware", "role" => "host" } })
13450 virtualization_reports_true_for(:guest?, :virtual?, :openvz?, node: { "virtualization" => { "system" => "openvz", "role" => "guest" } })
13451 virtualization_reports_true_for(:hypervisor?, :physical?, :openvz_host?, node: { "virtualization" => { "system" => "openvz", "role" => "host" } })
13452 let(:options) { { platform: "ubuntu" } }
13453 let(:options) { { platform: "raspbian" } }
13454 let(:options) { { platform: "linuxmint" } }
13455 let(:options) { { platform: "debian" } }
13456 let(:options) { { platform: "aix" } }
13457 let(:options) { { platform: "amazon" } }
13458 let(:options) { { platform: "arch" } }
13459 let(:options) { { platform: "centos" } }
13460 let(:options) { { platform: "clearos" } }
13461 let(:options) { { platform: "dragonfly4" } }
13462 let(:options) { { platform: "fedora" } }
13463 let(:options) { { platform: "freebsd" } }
13464 let(:options) { { platform: "gentoo" } }
13465 let(:options) { { platform: "mac_os_x" } }
13466 let(:options) { { platform: "openbsd" } }
13467 let(:options) { { platform: "oracle" } }
13468 let(:options) { { platform: "redhat" } }
13469 let(:options) { { platform: "smartos" } }
13470 let(:options) { { platform: "solaris2" } }
13471 let(:options) { { platform: "suse" } }
13472 let(:options) { { platform: "windows" } }
13473 let(:node) { { "platform" => "opensuseleap", "platform_version" => "15.1", "platform_family" => "suse", "os" => "linux" } }
13474 let(:node) { { "platform" => "opensuse", "platform_version" => "11.0", "platform_family" => "suse", "os" => "linux" } }
13475 let(:options) { { platform: "centos", version: "6" } }
13476 pf_reports_true_for(:rhel?, :rpm_based?, :fedora_derived?, :redhat_based?, :el?, :rhel6?)
13477 let(:options) { { platform: "centos", version: "7" } }
13478 pf_reports_true_for(:rhel?, :rpm_based?, :fedora_derived?, :redhat_based?, :el?, :rhel7?)
13479 let(:options) { { platform: "centos", version: "8" } }
13480 pf_reports_true_for(:rhel?, :rpm_based?, :fedora_derived?, :redhat_based?, :el?, :rhel8?)
13481 let(:options) { { platform: "clearos", version: "7" } }
13482 pf_reports_true_for(:mac_os_x?, :mac?, :osx?, :macos?)
13483 let(:options) { { platform: "opensuse" } }
13484 pf_reports_true_for(:suse?, :rpm_based?)
13485 let(:options) { { platform: "oracle", version: "6" } }
13486 let(:options) { { platform: "oracle", version: "7" } }
13487 let(:options) { { platform: "redhat", version: "6" } }
13488 let(:options) { { platform: "redhat", version: "7" } }
13489 let(:options) { { platform: "redhat", version: "8" } }
13490 allow(RbConfig::CONFIG).to receive(:[]).with("bindir").and_return("/opt/ruby/bin")
13491 env = { "PATH" => nil }
13492 env = { "PATH" => "/bin:/opt/app/bin:/sbin" }
13493 env = { "PATH" => "%SystemRoot%\\system32;%SystemRoot%;%SystemRoot%\\System32\\Wbem;%SYSTEMROOT%\\System32\\WindowsPowerShell\\v1.0\\" }
13494 let(:node) { double("node") }
13495 context "#ci?" do
13496 it "return true if ENV['CI'] is not set" do
13497 it "return true if ENV['CI'] is nil" do
13498 it "return true if ENV['CI'] is set" do
13499 %w{ /etc /usr/lib /lib /run }.each do |base|
13500 it "finds a unit in #{base}" do
13501 it "finds a template in #{base}" do
13502 cloud_reports_true_for(:cloud?, :alibaba?, node: { "alibaba" => {}, "cloud" => {} })
13503 cloud_reports_true_for(:cloud?, :ec2?, node: { "ec2" => {}, "cloud" => {} })
13504 cloud_reports_true_for(:cloud?, :gce?, node: { "gce" => {}, "cloud" => {} })
13505 cloud_reports_true_for(:cloud?, :rackspace?, node: { "rackspace" => {}, "cloud" => {} })
13506 cloud_reports_true_for(:cloud?, :eucalyptus?, :euca?, node: { "eucalyptus" => {}, "cloud" => {} })
13507 cloud_reports_true_for(:cloud?, :linode?, node: { "linode" => {}, "cloud" => {} })
13508 cloud_reports_true_for(:cloud?, :openstack?, node: { "openstack" => {}, "cloud" => {} })
13509 cloud_reports_true_for(:cloud?, :azure?, node: { "azure" => {}, "cloud" => {} })
13510 cloud_reports_true_for(:cloud?, :digital_ocean?, :digitalocean?, node: { "digital_ocean" => {}, "cloud" => {} })
13511 cloud_reports_true_for(:cloud?, :softlayer?, node: { "softlayer" => {}, "cloud" => {} })
13512 expect(described_class.cloud?({ "virtualbox" => {}, "cloud" => nil })).to be false
13513 let(:node) { { "kernel" => { "machine" => arch } } }
13514 arch_reports_true_for(:intel?, :_64_bit?)
13515 let(:arch) { "amd64" }
13516 let(:arch) { "ppc64" }
13517 arch_reports_true_for(:ppc64?, :_64_bit?)
13518 let(:arch) { "ppc64le" }
13519 arch_reports_true_for(:ppc64le?, :_64_bit?)
13520 let(:arch) { "s390x" }
13521 arch_reports_true_for(:s390x?, :_64_bit?)
13522 let(:arch) { "ia64" }
13523 let(:arch) { "sparc64" }
13524 let(:arch) { "aarch64" }
13525 arch_reports_true_for(:_64_bit?, :arm?)
13526 let(:arch) { "arch64" }
13527 let(:arch) { "arm64" }
13528 let(:arch) { "sun4v" }
13529 arch_reports_true_for(:sparc?, :_64_bit?)
13530 let(:arch) { "sun4u" }
13531 let(:arch) { "i86pc" }
13532 arch_reports_true_for(:i386?, :intel?, :_32_bit?)
13533 let(:arch) { "i386" }
13534 let(:arch) { "i686" }
13535 let(:arch) { "powerpc" }
13536 arch_reports_true_for(:powerpc?, :_32_bit?)
13537 let(:arch) { "armhf" }
13538 arch_reports_true_for(:armhf?, :_32_bit?, :arm?)
13539 let(:arch) { "armv6l" }
13540 let(:arch) { "armv7l" }
13541 let(:arch) { "s390" }
13542 arch_reports_true_for(:s390?, :_32_bit?)
13543 val ||= ""
13544 def +(other)
13545 to_s + other
13546 def *(other)
13547 to_s * other
13548 (self <=> other) == 0
13549 def !=(other)
13550 (self <=> other) != 0
13551 def <(other)
13552 (self <=> other) < 0
13553 def <=(other)
13554 (self <=> other) < 1
13555 def >(other)
13556 (self <=> other) > 0
13557 def >=(other)
13558 (self <=> other) > -1
13559 def =~(other)
13560 futures = map do |item|
13561 max_queue: 0,
13562 each do |k, v|
13563 if v.is_a?(Mash) || v.is_a?(Array)
13564 self[k] = v.dup
13565 if key.is_a?(Symbol) && include?(key = key.to_s)
13566 def key?(key)
13567 super(*keys.map { |k| convert_key(k) })
13568 each { |key, val| h[key.to_sym] = val }
13569 value.collect { |e| convert_value(e) }
13570 node["kernel"]["server_core"] == true
13571 node["kernel"]["product_type"] == "Workstation"
13572 node["kernel"]["product_type"] == "Server"
13573 extra_path ||= __extra_path
13574 exts.unshift("")
13575 filename = File.join(path, "#{cmd}#{ext}")
13576 def kvm?(node = __getnode)
13577 node.dig("virtualization", "system") == "kvm" && node.dig("virtualization", "role") == "guest"
13578 def kvm_host?(node = __getnode)
13579 node.dig("virtualization", "system") == "kvm" && node.dig("virtualization", "role") == "host"
13580 def lxc?(node = __getnode)
13581 node.dig("virtualization", "system") == "lxc" && node.dig("virtualization", "role") == "guest"
13582 def lxc_host?(node = __getnode)
13583 node.dig("virtualization", "system") == "lxc" && node.dig("virtualization", "role") == "host"
13584 node.dig("virtualization", "system") == "parallels" && node.dig("virtualization", "role") == "guest"
13585 node.dig("virtualization", "system") == "parallels" && node.dig("virtualization", "role") == "host"
13586 def vbox?(node = __getnode)
13587 node.dig("virtualization", "system") == "vbox" && node.dig("virtualization", "role") == "guest"
13588 def vbox_host?(node = __getnode)
13589 node.dig("virtualization", "system") == "vbox" && node.dig("virtualization", "role") == "host"
13590 def vmware?(node = __getnode)
13591 node.dig("virtualization", "system") == "vmware" && node.dig("virtualization", "role") == "guest"
13592 node.dig("virtualization", "system") == "vmware" && node.dig("virtualization", "role") == "host"
13593 node.dig("virtualization", "system") == "vmware" && node.dig("vmware", "host", "type") == "vmware_desktop"
13594 node.dig("virtualization", "system") == "vmware" && node.dig("vmware", "host", "type") == "vmware_vsphere"
13595 def openvz?(node = __getnode)
13596 node.dig("virtualization", "system") == "openvz" && node.dig("virtualization", "role") == "guest"
13597 node.dig("virtualization", "system") == "openvz" && node.dig("virtualization", "role") == "host"
13598 def guest?(node = __getnode)
13599 node.dig("virtualization", "role") == "guest"
13600 node.dig("virtualization", "role") == "host"
13601 def vagrant?(node = __getnode)
13602 vagrant_key?(node) || vagrant_domain?(node) || vagrant_user?(node)
13603 node.key?("vagrant")
13604 node.key?("domain") && !node["domain"].nil? && node["domain"].include?("vagrantup.com")
13605 file_exist?("/usr/sbin/update-rc.d")
13606 file_exist?("/usr/sbin/invoke-rc.d")
13607 file_exist?("/etc/init.d/#{script}")
13608 file_exist?("/etc/init/#{script}.conf")
13609 file_exist?("/etc/xinetd.d/#{script}")
13610 file_exist?("/etc/rc.d/#{script}")
13611 file_exist?("/etc/init.d/#{script}") ||
13612 def arch?(node = __getnode)
13613 node["platform_family"] == "arch"
13614 def aix?(node = __getnode)
13615 node["platform_family"] == "aix"
13616 def debian?(node = __getnode)
13617 node["platform_family"] == "debian"
13618 def fedora?(node = __getnode)
13619 node["platform_family"] == "fedora"
13620 def macos?(node = __getnode)
13621 node ? node["platform_family"] == "mac_os_x" : macos_ruby?
13622 alias_method :mac_os_x?, :macos?
13623 def rhel?(node = __getnode)
13624 node["platform_family"] == "rhel"
13625 alias_method :el?, :rhel?
13626 def rhel6?(node = __getnode)
13627 node["platform_family"] == "rhel" && node["platform_version"].to_f >= 6.0 && node["platform_version"].to_f < 7.0
13628 def rhel7?(node = __getnode)
13629 node["platform_family"] == "rhel" && node["platform_version"].to_f >= 7.0 && node["platform_version"].to_f < 8.0
13630 def rhel8?(node = __getnode)
13631 node["platform_family"] == "rhel" && node["platform_version"].to_f >= 8.0 && node["platform_version"].to_f < 9.0
13632 def amazon?(node = __getnode)
13633 node["platform_family"] == "amazon"
13634 def smartos?(node = __getnode)
13635 node["platform_family"] == "smartos"
13636 def suse?(node = __getnode)
13637 node["platform_family"] == "suse"
13638 def gentoo?(node = __getnode)
13639 node["platform_family"] == "gentoo"
13640 def freebsd?(node = __getnode)
13641 node["platform_family"] == "freebsd"
13642 def openbsd?(node = __getnode)
13643 node["platform_family"] == "openbsd"
13644 def netbsd?(node = __getnode)
13645 node["platform_family"] == "netbsd"
13646 def windows?(node = __getnode(true))
13647 node ? node["platform_family"] == "windows" : windows_ruby?
13648 def rpm_based?(node = __getnode)
13649 fedora_derived?(node) || node["platform_family"] == "suse"
13650 redhat_based?(node) || node["platform_family"] == "amazon"
13651 def bsd_based?(node = __getnode)
13652 node["platform"] == "linuxmint"
13653 node["platform"] == "ubuntu"
13654 node["platform"] == "raspbian"
13655 node["platform"] == "debian"
13656 node["platform"] == "amazon"
13657 node["platform"] == "redhat"
13658 node["platform"] == "centos"
13659 node.dig("os_release", "name") == "CentOS Stream"
13660 node.dig("lsb", "id") == "CentOSStream"
13661 node["platform"] == "oracle"
13662 node["platform"] == "scientific"
13663 node["platform"] == "clearos"
13664 node["platform"] == "fedora"
13665 node["platform"] == "arch"
13666 node["platform"] == "solaris2"
13667 node["platform"] == "smartos"
13668 node["platform"] == "omnios"
13669 node["platform"] == "openindiana"
13670 node["platform"] == "aix"
13671 node["platform"] == "freebsd"
13672 node["platform"] == "openbsd"
13673 node["platform"] == "netbsd"
13674 node["platform"] == "dragonfly"
13675 node["platform"] == "mac_os_x"
13676 node["platform"] == "gentoo"
13677 node["platform"] == "slackware"
13678 node["platform"] == "suse"
13679 node["platform"] == "opensuse" || node["platform"] == "opensuseleap"
13680 node["platform"] == "windows"
13681 def linux?(node = __getnode)
13682 node["os"] == "linux"
13683 def darwin?(node = __getnode)
13684 node["os"] == "darwin"
13685 !!(node && node.read("chef_packages", "chef", "chef_effortless"))
13686 def docker?(node = __getnode)
13687 !!(node && node.read("virtualization", "systems", "docker") == "guest")
13688 def systemd?(node = __getnode)
13689 file_exist?("/proc/1/comm") && file_open("/proc/1/comm").gets.chomp == "systemd"
13690 def kitchen?(node = __getnode)
13691 def ci?(node = __getnode)
13692 %w{ /etc /usr/lib /lib /run }.any? do |load_path|
13693 file_exist?("#{load_path}/systemd/system/#{svc_name}")
13694 env_path = env ? env["PATH"] : __env_path
13695 env_path = "" if env_path.nil?
13696 path_separator = ChefUtils.windows? ? ";" : ":"
13697 [ __ruby_bindir, __gem_bindir ].compact.each do |path|
13698 ChefUtils.windows? ? %w{} : %w{/usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /sbin /bin}
13699 def cloud?(node = __getnode)
13700 !node["cloud"].nil?
13701 def alibaba?(node = __getnode)
13702 node.key?("alibaba")
13703 def ec2?(node = __getnode)
13704 node.key?("ec2")
13705 def gce?(node = __getnode)
13706 node.key?("gce")
13707 def linode?(node = __getnode)
13708 node.key?("linode")
13709 def azure?(node = __getnode)
13710 node.key?("azure")
13711 def _64_bit?(node = __getnode)
13712 .include?(node["kernel"]["machine"])
13713 def _32_bit?(node = __getnode)
13714 !_64_bit?(node)
13715 def i386?(node = __getnode)
13716 _32_bit?(node) && intel?(node)
13717 def intel?(node = __getnode)
13718 def sparc?(node = __getnode)
13719 %w{sun4u sun4v}.include?(node["kernel"]["machine"])
13720 def ppc64?(node = __getnode)
13721 %w{ppc64}.include?(node["kernel"]["machine"])
13722 def ppc64le?(node = __getnode)
13723 %w{ppc64le}.include?(node["kernel"]["machine"])
13724 def powerpc?(node = __getnode)
13725 %w{powerpc}.include?(node["kernel"]["machine"])
13726 def arm?(node = __getnode)
13727 def armhf?(node = __getnode)
13728 def s390x?(node = __getnode)
13729 %w{s390x}.include?(node["kernel"]["machine"])
13730 def s390?(node = __getnode)
13731 %w{s390}.include?(node["kernel"]["machine"])
13732 GEM = "chef-cli"
13733 let(:env) { {} }
13734 let(:home) { "/Users/example.user" }
13735 let(:env_pwd) { "/path/to/cwd" }
13736 env["CD"] = env_pwd
13737 env["PWD"] = env_pwd
13738 allow(File).to receive(:exist?).with("#{env_pwd}/.chef").and_return(true)
13739 let(:cwd) { Dir.pwd }
13740 let(:knife_home) { "/path/to/knife/home" }
13741 env["CD"] = "/home/someuser/prod/chef-repo" # windows
13742 env["PWD"] = "/home/someuser/prod/chef-repo" # unix
13743 let(:config_content) { "" }
13744 let(:config_content) { "{{{{{:{{" }
13745 let(:config_content) { ":foo
:bar
raise 'oops'
:baz
" }
13746 let!(:confd_file) do
13747 let(:syntax_error_content) { "{{{{{:{{" }
13748 let(:home) { "C:/Users/example.user" }
13749 let(:credentials_file) { "#{home}/.chef/credentials" }
13750 let(:context_file) { "#{home}/.chef/context" }
13751 content = <<~EOH
13752 node_name = 'barney'
13753 knife = {
13754 client_key = """
13755 stub_const("ENV", env)
13756 let(:content) { "<<<<<" }
13757 expect(path_helper.join("", "a", "b")).to eq("#{path_helper.path_separator}a#{path_helper.path_separator}b")
13758 it "joins ending with '' add a / to the end" do
13759 expect(path_helper.join("a", "b", "")).to eq("a#{path_helper.path_separator}b#{path_helper.path_separator}")
13760 it "dirname('abc') is '.'" do
13761 expect(path_helper.dirname("abc")).to eq(".")
13762 it "dirname('/') is '/'" do
13763 it "dirname('a/b/c') is 'a/b'" do
13764 expect(path_helper.dirname(path_helper.join("a", "b", "c"))).to eq(path_helper.join("a", "b"))
13765 it "dirname('a/b/c/') is 'a/b'" do
13766 expect(path_helper.dirname(path_helper.join("a", "b", "c", ""))).to eq(path_helper.join("a", "b"))
13767 it "dirname('/a/b/c') is '/a/b'" do
13768 expect(path_helper.dirname(path_helper.join("", "a", "b", "c"))).to eq(path_helper.join("", "a", "b"))
13769 it "path_separator is \\" do
13770 expected = "C:\\foo\\bar\\baz"
13771 expect(path_helper.join("C:\\foo/", "bar", "baz", windows: true)).to eq(expected)
13772 expect(path_helper.join("C:\\foo\\", "bar", "baz", windows: true)).to eq(expected)
13773 expect(path_helper.join("C:\\foo\\", "bar/", "/baz", windows: true)).to eq(expected)
13774 expect(path_helper.join("C:\\foo", "bar", "baz", windows: true)).to eq(expected)
13775 expect(path_helper.cleanpath("/a/b\\c/d/", windows: true)).to eq("\\a\\b\\c\\d")
13776 expect(path_helper.cleanpath("\\\\a/b\\c/d/", windows: true)).to eq("\\\\a\\b\\c\\d")
13777 expect(path_helper.cleanpath("/a///b/c/d/", windows: false)).to eq("/a/b/c/d")
13778 expected = "/foo/bar/baz"
13779 expect(path_helper.join("/foo/", "bar", "baz", windows: false)).to eq(expected)
13780 expect(path_helper.join("/foo/", "bar/", "/baz", windows: false)).to eq(expected)
13781 expect(path_helper.join("/foo", "bar", "baz", windows: false)).to eq(expected)
13782 expect(path_helper.cleanpath("/a/b\\c/d/", windows: false)).to eq("/a/b/c/d")
13783 expect(path_helper.cleanpath("\\\\a/b\\c/d/", windows: false)).to eq("//a/b/c/d")
13784 expect(path_helper.join("C:\\foo/", "bar", "baz")).to eq(expected)
13785 expect(path_helper.join("C:\\foo\\", "bar", "baz")).to eq(expected)
13786 expect(path_helper.join("C:\\foo\\", "bar/", "/baz")).to eq(expected)
13787 expect(path_helper.join("C:\\foo", "bar", "baz")).to eq(expected)
13788 expect(path_helper.cleanpath("/a/b\\c/d/")).to eq("\\a\\b\\c\\d")
13789 expect(path_helper.cleanpath("\\\\a/b\\c/d/")).to eq("\\\\a\\b\\c\\d")
13790 expect(path_helper.cleanpath("/a///b/c/d/")).to eq("/a/b/c/d")
13791 expect(path_helper.join("/foo/", "bar", "baz")).to eq(expected)
13792 expect(path_helper.join("/foo/", "bar/", "/baz")).to eq(expected)
13793 expect(path_helper.join("/foo", "bar", "baz")).to eq(expected)
13794 expect(path_helper.cleanpath("\\\\a/b\\c/d/")).to eq("//a/b/c/d")
13795 it "Adds the \\\\?\\ prefix if the path exceeds MAX_LENGTH and does not have it" do
13796 long_path = "C:\\" + "a" * 250 + "\\" + "b" * 250
13797 prefixed_long_path = "\\\\?\\" + long_path
13798 expect(path_helper.windows_max_length_exceeded?("C:\\" + "a" * 250 + "\\" + "b" * 6)).to be_truthy
13799 expect(path_helper.windows_max_length_exceeded?("C:\\" + "a" * 250 + "\\" + "b" * 5)).to be_falsey
13800 expect(path_helper.windows_max_length_exceeded?("\\\\?\\C:\\" + "a" * 250 + "\\" + "b" * 250)).to be_falsey
13801 expect(path_helper.printable?("\tThere's no way,
\t *no* way,
\t that you came from my loins.
")).to be_falsey
13802 expect(path_helper.canonical_path("\\\\?\\C:/windows/win.ini")).to eq("\\\\?\\c:\\windows\\win.ini")
13803 it "adds the \\\\?\\ prefix if it is missing" do
13804 expect(path_helper.canonical_path("C:/windows/win.ini")).to eq("\\\\?\\c:\\windows\\win.ini")
13805 expect(path_helper.canonical_path("\\\\?\\C:\\CASE\\INSENSITIVE")).to eq("\\\\?\\c:\\case\\insensitive")
13806 path = "C:\\this\\*path\\[needs]\\escaping?"
13807 escaped_path = "C:\\\\this\\\\\\*path\\\\\\[needs\\]\\\\escaping\\?"
13808 args = ["this/*path", "[needs]", "escaping?"]
13809 path = "C:/this/*path/[needs]/escaping?"
13810 escaped_path = "C:/this/\\*path/\\[needs\\]/escaping\\?"
13811 escaped_path = "this/\\*path/\\[needs\\]/escaping\\?"
13812 let(:is_windows) { true }
13813 let(:is_windows) { false }
13814 let(:enabled) { "0" }
13815 context "on *nix" do
13816 let(:fips_path) { "/proc/sys/crypto/fips_enabled" }
13817 let(:enabled) { "1" }
13818 let(:win_reg_entry) { { "Enabled" => enabled } }
13819 let(:enabled) { 1 }
13820 let(:enabled) { 0 }
13821 let(:arch) { Win32::Registry::KEY_READ | 0x100 }
13822 before { stub_const("::RbConfig::CONFIG", { "target_cpu" => "i386" } ) }
13823 let(:arch) { Win32::Registry::KEY_READ | 0x200 }
13824 before { stub_const("::RbConfig::CONFIG", { "target_cpu" => "x86_64" } ) }
13825 before { stub_const("::RbConfig::CONFIG", { "target_cpu" => nil } ) }
13826 let(:extra_config_options) { [ "node_name=bobotclown" ] }
13827 let(:extra_config_options) { [ "http_retries=" ] }
13828 let(:extra_config_options) { [ "node_name = bobo" ] }
13829 let(:extra_config_options) { [ "http_retries=9000" ] }
13830 let(:extra_config_options) { [ "boolean_thing=true" ] }
13831 let(:extra_config_options) { [ "http_retries:9000" ] }
13832 let(:extra_config_options) { [ "cookbook_path=cookbooks/" ] }
13833 let(:extra_config_options) { ["data_bag_path=data_bags/", "cookbook_path=cookbooks", "chef_repo_path=."] }
13834 it "var_chef_dir is /var/chef" do
13835 it "var_root_dir is /var" do
13836 it "etc_chef_dir is /etc/chef" do
13837 it "var_chef_dir is C:\\chef" do
13838 it "var_root_dir is C:\\" do
13839 it "etc_chef_dir is C:\\chef" do
13840 [ false, true ].each do |is_windows|
13841 context "On #{is_windows ? "Windows" : "Unix"}" do
13842 allow(ChefConfig::Config).to receive(:env).and_return({ "SYSTEMDRIVE" => "C:" })
13843 let(:fips_enabled) { false }
13844 let(:fips_enabled) { true }
13845 let(:target_mode_primary_cache_path) { ChefUtils.windows? ? "#{primary_cache_path}\\#{target_mode_host}" : "#{primary_cache_path}/#{target_mode_host}" }
13846 context "and config_dir is /a/b/c/" do
13847 backup_path = is_windows ? "#{primary_cache_path}\\backup" : "#{primary_cache_path}/backup"
13848 before { ChefConfig::Config[:chef_server_url] = "https://chef.example/" }
13849 expected = [ "/home/anne/repo", "/home/anne/other_repo"].map { |p| File.expand_path(p) }
13850 data_bag_path = is_windows ? "#{primary_cache_path}\\data_bags" : "#{primary_cache_path}/data_bags"
13851 let(:secret_exists) { true }
13852 let(:secret_exists) { false }
13853 any_match = ChefConfig::Config[:user_valid_regex].any? { |regex| regex.match("a") }
13854 let(:locales) { locale_array.join("
") }
13855 let(:locale_array) { [expected_locale, "en_US.UTF-8"] }
13856 let(:expected_locale) { "C.UTF-8" }
13857 let(:locale_array) { ["en_CA.UTF-8", expected_locale, "en_NZ.UTF-8"] }
13858 let(:expected_locale) { "en_US.UTF-8" }
13859 let(:locale_array) { ["en_CA.utf8", "en_US.utf8", "en_NZ.utf8"] }
13860 let(:locale_array) { ["en.ISO8859-1", expected_locale] }
13861 let(:expected_locale) { "en.UTF-8" }
13862 let(:locale_array) { [expected_locale, "en_CA.UTF-8", "en_GB.UTF-8"] }
13863 let(:expected_locale) { "en_AU.UTF-8" }
13864 let(:locale_array) { ["en_AU.utf8", "en_CA.utf8", "en_GB.utf8"] }
13865 let(:locale_array) { ["af_ZA", "af_ZA.ISO8859-1", "af_ZA.ISO8859-15", "af_ZA.UTF-8"] }
13866 let(:locale_array) { [] }
13867 it "should default to 'en_US.UTF-8'" do
13868 ENV["ftp_proxy"] = nil
13869 ENV["no_proxy"] = nil
13870 let(:http_proxy) { "http://localhost:7979" }
13871 let(:https_proxy) { "https://localhost:7979" }
13872 let(:ftp_proxy) { "ftp://localhost:7979" }
13873 let(:proxy_user) { "http_user" }
13874 let(:proxy_pass) { "http_pass" }
13875 it "exports ENV['http_proxy']" do
13876 expect(ENV).to receive(:[]=).with("http_proxy", "http://http_user:http_pass@localhost:7979")
13877 expect(ENV).to receive(:[]=).with("HTTP_PROXY", "http://http_user:http_pass@localhost:7979")
13878 it "exports ENV['ftp_proxy']" do
13879 expect(ENV).to receive(:[]=).with("ftp_proxy", "ftp://http_user:http_pass@localhost:7979")
13880 expect(ENV).to receive(:[]=).with("FTP_PROXY", "ftp://http_user:http_pass@localhost:7979")
13881 expect(ENV).to receive(:[]=).with("http_proxy", "http://localhost:7979")
13882 expect(ENV).to receive(:[]=).with("HTTP_PROXY", "http://localhost:7979")
13883 expect(ENV).to receive(:[]=).with("http_proxy", "http://localhost:1111")
13884 expect(ENV).to receive(:[]=).with("HTTP_PROXY", "http://localhost:1111")
13885 expect(ENV["http_proxy"]).to eq(nil)
13886 expect(ENV["ftp_proxy"]).to eq(nil)
13887 expect(ENV["no_proxy"]).to eq(nil)
13888 it "exports ENV['no_proxy']" do
13889 expect(ENV).to receive(:[]=).with("no_proxy", "localhost")
13890 expect(ENV).to receive(:[]=).with("NO_PROXY", "localhost")
13891 let(:scheme) { "http" }
13892 let(:host) { "test.example.com" }
13893 let(:port) { 8080 }
13894 let(:proxy) { "#{proxy_prefix}#{proxy_host}:#{proxy_port}" }
13895 let(:proxy_prefix) { "http://" }
13896 let(:proxy_host) { "proxy.mycorp.com" }
13897 let(:proxy_port) { 8080 }
13898 let(:proxy_prefix) { "" }
13899 let(:env) do
13900 let(:scheme) { "https" }
13901 it { is_expected.to eq nil }
13902 (full_path.length - 1).downto(0) do |i|
13903 end || Dir.pwd
13904 if creds.key?("node_name") && creds.key?("client_name")
13905 message = ""
13906 message << "#{e.class.name}: #{e.message}
"
13907 if file_line = e.message[/#{Regexp.escape(config_file_path)}:\d+/]
13908 line = file_line[/:(\d+)$/, 1].to_i
13909 line_nr = filtered_trace.first[/#{Regexp.escape(config_file_path)}:(\d+)/, 1]
13910 key_path = find_default_key(["#{Config[:node_name]}.pem", "user.pem"])
13911 config_file_lines = []
13912 IO.readlines(file).each_with_index { |l, i| config_file_lines << "#{(i + 1).to_s.rjust(3)}: #{l.chomp}" }
13913 if line == 1
13914 return end_slash == path.size ? "." : path_separator(windows: windows)
13915 elsif slash == end_slash - 1
13916 return path[0..slash - 1]
13917 ChefConfig.logger.trace("Path '#{path}' is longer than #{WIN_MAX_PATH}, prefixing with'\\\\?\\'")
13918 path.insert(0, "\\\\?\\")
13919 unless /^\\\\?\\/.match?(path)
13920 if /[^[:print:]]/.match?(string)
13921 if add_prefix && abs_path !~ /^\\\\?\\/
13922 abs_path.insert(0, "\\\\?\\")
13923 path.gsub(/[\\\{\}\[\]\*\?]/) { |x| "\\" + x }
13924 @@home_dir = nil
13925 @@home_dir ||= all_homes { |p| break p }
13926 if @@home_dir
13927 path = File.join(@@home_dir, *args)
13928 block_given? ? (yield path) : path
13929 valid_paths = paths.select { |home_path| home_path && Dir.exist?(home_path.force_encoding("utf-8")) }
13930 joined_paths.each { |p| yield p }
13931 sip_paths = [
13932 cmd_args = []
13933 field = ""
13934 field << (word || esc.gsub(/\\(.)/, "\\1"))
13935 fqdn.split(".").reduce(hash) do |h, k|
13936 v = h[k]
13937 if Hash === v
13938 train_config = {}
13939 return matches.to_s.split(/\s*,\s*/).compact.any? do |m|
13940 match = "*" + match unless match.start_with?("*")
13941 Dir["#{PathHelper.escape_glob_dir(path)}/*.rb"].select { |entry| File.file?(entry) }.sort
13942 def <<(_msg); end
13943 def add(_severity, _message = nil, _progname = nil); end
13944 def trace(_progname = nil, &block); end
13945 def debug(_progname = nil, &block); end
13946 def info(_progname = nil, &block); end
13947 def warn(_progname = nil, &block); end
13948 def error(_progname = nil, &block); end
13949 def fatal(_progname = nil, &block); end
13950 reg_type =
13951 when "x86_64"
13952 policy["Enabled"] != 0
13953 File.exist?(fips_path) && File.read(fips_path).chomp != "0"
13954 if drive && path[0] == "\\" && path.split("\\")[2] == "chef"
13955 path = PathHelper.join(drive, path.split("\\", 3)[2])
13956 @etc_chef_dir ||= {}
13957 @etc_chef_dir[windows] ||= begin
13958 path = windows ? "C:\\" : "/var"
13959 drive = File.expand_path(__FILE__).split("/", 2)[0]
13960 if option.empty? || !option.include?("=")
13961 key, value = option.split(/\s*=\s*/, 2)
13962 url = uri.to_s.strip
13963 %r{^http://} =~ url || %r{^https://} =~ url || /^chefzero:/ =~ url
13964 Array(path).map { |path| File.expand_path(path) }
13965 File.expand_path("..", path)
13966 path = cwd
13967 new_path = File.expand_path("..", path)
13968 if new_path == path
13969 File.exist?(path) && File.readable?(path) && File.writable?(path)
13970 configuration[:chef_server_url].split("/")[0..-3].join("/")
13971 if value.is_a?(String) && value[0] == ":"
13972 value[1..].to_sym
13973 default(:solo_d_dir) { PathHelper.join(config_dir, "solo.d") }
13974 if chef_server_url.to_s =~ %r{/organizations/(.*)$}
13975 default :hints, {}
13976 principal_valid_regex_part = '[^"\/\\\\\[\]\:;|=,+*?<>]+'
13977 default :user_valid_regex, [ /^(#{principal_valid_regex_part}\\)?#{principal_valid_regex_part}$/ ]
13978 default :group_valid_regex, [ /^(#{principal_valid_regex_part}\\)?#{principal_valid_regex_part}$/ ]
13979 default :user_valid_regex, [ /^[^-+~:,\t\r
\f\0]+[^:,\t\r
\f\0]*$/ ]
13980 default :group_valid_regex, [ /^[^-+~:,\t\r
\f\0]+[^:,\t\r
\f\0]*$/ ]
13981 default( :user_home ) { PathHelper.home || Dir.pwd }
13982 default :watchdog_timeout, 2 * (60 * 60) # 2 hours
13983 export_no_proxy(no_proxy) if key?(:no_proxy) && no_proxy
13984 password_class = user_class + "\\:"
13985 path = "#{scheme}://#{path}" unless path.include?("://")
13986 if user && !user.empty?
13987 path = uri.to_s
13988 ENV["#{scheme}_proxy".upcase] = path unless ENV["#{scheme}_proxy".upcase]
13989 ENV["no_proxy"] = value unless ENV["no_proxy"]
13990 proxy_env_var = ENV["#{scheme}_proxy"].to_s.strip
13991 if %r{^.*://}.match?(proxy_env_var)
13992 URI.parse("#{scheme}://#{proxy_env_var}")
13993 guesses = locales.grep(/^en_.*UTF-?8$/i)
13994 guessed_locale.gsub(/UTF-?8$/i, "UTF-8")
13995 File.expand_path(__FILE__)
13996 FRAMEWORK_NAMES = Hash.new { |h, k| k.split(/(?<=active|action)/).map(&:capitalize).join(" ") }
13997 npm_version = version.gsub(/\./).with_index { |s, i| i >= 2 ? "-" : s }
13998 if framework == "rails"
13999 glob << "/version.rb"
14000 glob << "/#{framework}/lib/*"
14001 glob << "/gem_version.rb"
14002 major, minor, tiny, pre = version.split(".", 4)
14003 pre = pre ? pre.inspect : "nil"
14004 ruby.gsub!(/^(\s*)MAJOR(\s*)= .*?$/, "\\1MAJOR = #{major}")
14005 ruby.gsub!(/^(\s*)MINOR(\s*)= .*?$/, "\\1MINOR = #{minor}")
14006 File.open(file, "w") { |f| f.write ruby }
14007 if File.exist?("#{framework}/package.json") && JSON.parse(File.read("#{framework}/package.json"))["version"] != npm_version
14008 Dir.chdir("#{framework}") do
14009 cmd += "cd #{framework} && " unless framework == "rails"
14010 cmd += "bundle exec rake package && " unless framework == "rails"
14011 cmd += "gem build #{gemspec} && mv #{framework}-#{version}.gem #{root}/pkg/"
14012 task build: [:clean, gem]
14013 sh "gem install --pre #{gem}"
14014 otp = ""
14015 otp = " --otp " + `ykman oath accounts code -s rubygems.org`.chomp
14016 sh "gem push #{gem}#{otp}"
14017 npm_otp = ""
14018 npm_otp = " --otp " + `ykman oath accounts code -s npmjs.com`.chomp
14019 npm_tag = ""
14020 if /[a-z]/.match?(version)
14021 npm_tag = " --tag pre"
14022 local_major_version = version.split(".", 4)[0]
14023 npm_tag = remote_major_version <= local_major_version ? " --tag latest" : " --tag v#{local_major_version}"
14024 sh "npm publish#{npm_tag}#{npm_otp}"
14025 header = "## Rails #{version} (#{Date.today.strftime('%B %d, %Y')}) ##

"
14026 replace = "## Rails #{version} (#{Date.today.strftime('%B %d, %Y')}) ##
"
14027 contents = File.read(fname).sub(/^(## Rails .*)
/, replace)
14028 task :release_summary, [:base_release, :release] do |_, args|
14029 release_regexp = args[:base_release] ? Regexp.escape(args[:base_release]) : /\d+\.\d+\.\d+/
14030 until contents.first =~ /^## Rails #{release_regexp}.*$/ ||
14031 contents.first =~ /^Please check.*for previous changes\.$/ ||
14032 task update_versions: FRAMEWORKS.map { |f| "#{f}:update_versions" } + ["rails:update_versions"]
14033 unless ENV["SKIP_TAG"] || `git tag | grep '^#{tag}$'`.strip.empty?
14034 app_name = "verify-#{version}-#{Time.now.to_i}"
14035 sh "rails _#{version}_ new #{app_name} --skip-bundle" # Generate with the right version.
14036 substitute.call("Gemfile", /^gem 'rails.*/, "gem 'rails', '#{version}'")
14037 substitute.call("app/models/user.rb", /end
\z/, <<~CODE)
14038 <div class="field">
14039 Avatar: <%= form.file_field :avatar %>
14040 substitute.call("app/views/users/show.html.erb", /description %>
<\/p>/, <<~CODE)
14041 description %>
</p>
14042 <p>
14043 <% if @user.avatar.attached? -%>
14044 <%= image_tag @user.avatar.representation(resize_to_limit: [500, 500]) %>
14045 </p>
14046 puts "- Viewing /users"
14047 File.open("pkg/commit_message.txt", "w") do |f|
14048 sh "git tag -s -m '#{tag} release' #{tag}"
14049 sh "git push --tags"
14050 @gem_version.segments[0, 3].tap { |v| v[2] -= 1 }.join(".")
14051 @version.include?("rc")
14052 Dir.chdir("pkg/") do
14053 if versions.any?(&:rc?)
14054 example_test = <<~RUBY
14055 expected_map = {
14056 10 => 10, # test_oneline
14057 12 => 14, # declarative
14058 16 => 19, # declarative w/parens
14059 expect = %r{\AF

Failure:
TestUnitReporterTest::ExampleTest#woot \[[^\]]+\]:
boo

bin/rails test test/test_unit/reporter_test\.rb:\d+

\z}
14060 @output.stub(:tty?, true) do
14061 expect = %r{\e\[32m\.\e\[0m}
14062 expect = %r{\e\[33mS\e\[0m}
14063 error.set_backtrace([ "some_test.rb:4" ])
14064 st.time = 10
14065 class Foo < Rails::Railtie ; config.to_prepare { $to_prepare = true } ; end
14066 get "/"
14067 $ran_block = []
14068 Rails.env = "foo"
14069 @plugin = engine "blog"
14070 app_file "config/routes.rb", <<-RUBY
14071 mount Weblog::Engine, :at => '/', :as => 'weblog'
14072 scope "/:user", :user => "anonymous" do
14073 mount Blog::Engine => "/blog"
14074 root :to => 'main#index'
14075 get '/weblog' => "weblogs#index", as: 'weblogs'
14076 render inline: "<%= blog.post_path(1) -%>"
14077 @plugin.write "lib/blog.rb", <<-RUBY
14078 action: "index",
14079 render inline: "<%= main_app.root_path %>"
14080 render inline: "<%= asset_path 'images/foo.png', skip_pipeline: true %>"
14081 render inline: "<%= file_field_tag :image, direct_upload: true %>"
14082 render inline: "<%= blog.posts_path %>"
14083 render inline: "<%= weblog.weblogs_path %>"
14084 @app ||= begin
14085 get "/john/blog/posts", {}, { "SCRIPT_NAME" => "/foo" }
14086 get "/engine_route", {}, { "SCRIPT_NAME" => "/foo" }
14087 get "/url_for_engine_route", {}, { "SCRIPT_NAME" => "/foo" }
14088 get "/metrics/generate_blog_route", {}, { "SCRIPT_NAME" => "/foo" }
14089 get "/metrics/generate_blog_route_in_view", {}, { "SCRIPT_NAME" => "/foo" }
14090 get "/someone/blog/generate_application_route", {}, { "SCRIPT_NAME" => "/foo" }
14091 post "posts", to: "posts#create"
14092 post "/posts", TestInput.new("foo=bar")
14093 tmp_path("foo_bar")
14094 mountable = is_mountable ? "--mountable" : ""
14095 rails("plugin new #{engine_path} --full #{mountable}")
14096 File.open("Gemfile", "w") do |f|
14097 f.write <<-GEMFILE.gsub(/^ {12}/, "")
14098 path = "#{app_path}/tmp"
14099 file_name = "#{path}/v0.1.4~alpha+nightly"
14100 @plugin.write "app/assets/javascripts/engine.js.erb", "<%= :alert %>();"
14101 @plugin.write "Rakefile", <<-RUBY
14102 migrations_count = Dir["#{app_path}/db/migrate/*.rb"].length
14103 assert_no_match(/\d+_create_users/, output.join("
"))
14104 @blog = engine "blog" do |plugin|
14105 plugin.write "lib/blog.rb", <<-RUBY
14106 @api = engine "api" do |plugin|
14107 plugin.write "lib/api.rb", <<-RUBY
14108 @core = engine "core" do |plugin|
14109 plugin.write "lib/core.rb", <<-RUBY
14110 @api.write "db/migrate/2_create_keys.rb", <<-RUBY
14111 @plugin.write "lib/bukkits.rb", <<-RUBY
14112 $test_autoload_once_paths = []
14113 $test_autoload_paths = []
14114 @plugin.write "app/views/bukkit/index.html.erb", "Hello <%= bukkits %>"
14115 [200, {'Content-Type' => 'text/html'}, ["I am a Sprokkit"]]
14116 get "/sprokkit", :to => Sprokkit
14117 controller "foo", <<-RUBY
14118 get 'foo', :to => 'foo#index'
14119 get 'foo', to: 'bar#index'
14120 get 'bar', to: 'bar#index'
14121 get "/foo"
14122 get "/bar"
14123 @plugin.write "lib/tasks/foo.rake", <<-RUBY
14124 en:
14125 foo: "1"
14126 bar: "1"
14127 baz: "1"
14128 ).map { |path| File.expand_path(path) }
14129 app_file "app/locales/en.yml", <<-YAML
14130 foo: "2"
14131 bar: "2"
14132 foo: "3"
14133 assert_equal "2", I18n.t(:foo)
14134 assert_equal "1", I18n.t(:bar)
14135 get "bar", to: "bar#index"
14136 get "/admin/foo/bar"
14137 @app = app
14138 endpoint lambda { |env| [200, {'Content-Type' => 'text/html'}, ['Hello World']] }
14139 mount(Bukkits::Engine => "/bukkits")
14140 get("/bukkits")
14141 root to: "foo#index"
14142 mount(Bukkits::Engine => "/:username")
14143 get("/arunagw")
14144 get "/foo" => lambda { |env| [200, {'Content-Type' => 'text/html'}, ['foo']] }
14145 get("/bukkits/foo")
14146 endpoint lambda { |env| [200, {'Content-Type' => 'text/html'}, ['hello']] }
14147 env = Rack::MockRequest.env_for("/")
14148 get "/bar" => "bar#index", as: "bar"
14149 mount Bukkits::Engine => "/bukkits", as: "bukkits"
14150 get "/foo" => "foo#index", as: "foo"
14151 get "/foo/show" => "foo#show"
14152 get "/from_app" => "foo#from_app"
14153 render inline: "<%= help_the_engine %>"
14154 render inline: "<%= (self.respond_to?(:bar_path) || self.respond_to?(:something)) %>"
14155 render inline: "<%= foo_path %>, <%= main_app.bar_path %>"
14156 controller "bar", <<-RUBY
14157 get("/bar")
14158 <%= form_for(Bukkits::Post.new) do |f| %>
14159 <%= f.text_field :title %>
14160 <% end %>
14161 mount Bukkits::Awesome::Engine => "/bukkits", :as => "bukkits"
14162 get "/foo" => "foo#index"
14163 @plugin.write "db/seeds.rb", <<-RUBY
14164 app_file "db/seeds.rb", <<-RUBY
14165 mount lambda{|env| [200, {}, ["foo"]]} => "/foo"
14166 mount lambda{|env| [200, {}, ["bar"]]} => "/bar"
14167 get("/foo")
14168 get("/bukkits/bar")
14169 engine_dir = @plugin.path.chomp("/").split("/").last
14170 engine_path = File.join(@plugin.path, "..", engine_dir)
14171 controller "main", <<-RUBY
14172 render inline: '<%= render partial: "shared/foo" %>'
14173 render inline: '<%= render partial: "shared/bar" %>'
14174 get "/foo" => "main#foo"
14175 get "/bar" => "main#bar"
14176 app_file "app/views/shared/_foo.html.erb", <<-RUBY
14177 @blog.write "app/views/shared/_bar.html.erb", <<-RUBY
14178 app_file "app/views/shared/_bar.html.erb", <<-RUBY
14179 // Bukkit's foo js
14180 // App's foo js
14181 // Blog's bar js
14182 // App's bar js
14183 add_to_config("config.railties_order = [:all, :main_app, Blog::Engine]")
14184 get("/assets/foo.js")
14185 get("/assets/bar.js")
14186 assert_equal <<~EXPECTED, Rails.application.send(:ordered_railties).flatten.map(&:class).map(&:name).join("
") << "
"
14187 path: \#{request.path}
14188 mount Bukkits::Engine => "/"
14189 path: /
14190 get("/")
14191 last_response.body.split("
").map(&:strip)
14192 get '/bar' => 'bar#index', :as => 'bar'
14193 mount Bukkits::Engine => "/bukkits", :as => "bukkits"
14194 get '/bukkit' => 'bukkit#index'
14195 get("/bukkits/bukkit", {}, { "SCRIPT_NAME" => "/foo" })
14196 main_app.bar_path: \#{main_app.bar_path}
14197 frameworks = <<~RUBY
14198 File.open("#{app_path}/config/application.rb", "w") { |f| f.puts frameworks + "
" + environment }
14199 output = `#{command}`
14200 assert_predicate $?, :success?, "Command did not succeed: #{command}
#{output}"
14201 property("Bogus") { raise }
14202 property("Goodbye") { "World" }
14203 property "Middleware", ["Rack::Lock", "Rack::Static"]
14204 get :routes, params: { query: "rails_info_" }
14205 get :routes, params: { query: "" }
14206 get :routes, params: { query: "rails/info/route" }
14207 get :routes, params: { query: "/rails/info/routes" }
14208 get :routes, params: { query: "rails/info/routes" }
14209 get :routes, params: { query: "rails/info/routes.html" }
14210 get :routes, params: { query: "test/nested_route" }
14211 get :routes, params: { query: "GE" }
14212 get :routes, params: { query: "get" }
14213 get :routes, params: { query: "GET" }
14214 get :routes, params: { query: "rails_info" }
14215 get :routes, params: { query: "rails/:test" }
14216 get "/up" => "rails/health#show", as: :rails_health_check
14217 app ||= ->(_) { block.call; [200, {}, []] }
14218 def initialize(starts = [], finishes = [])
14219 starts << [name, id, payload]
14220 finishes << [name, id, payload]
14221 response = [].freeze
14222 gemspec = File.read(gemspec_path).gsub(/"TODO.*"/, "http://example.com".inspect)
14223 gem "rails", path: #{File.expand_path("../..", __dir__).inspect}
14224 @root = Rails::Paths::Root.new("/foo/bar")
14225 root = Rails::Paths::Root.new("/fiz/baz")
14226 root.path = "/root"
14227 assert_equal ["app"], root["app"].to_ary
14228 assert_equal ["/root/app"], root["app"].to_a
14229 @root.add "app"
14230 assert_equal ["/foo/bar/app"], @root["app"].to_a
14231 @root.add "app", with: "/foo/bar"
14232 assert_equal ["/foo/bar"], @root["app"].to_a
14233 root["app"].to_a
14234 assert_equal ["/foo/bar/app/models"], @root["app/models"].to_a
14235 @root.add "app/models", with: "/foo/bar/baz"
14236 assert_equal ["/foo/bar/baz"], @root["app/models"].to_a
14237 @root.add "app/models", with: "baz"
14238 @root.add "app", with: ["/app", "/app2"]
14239 assert_equal ["/app", "/app2"], @root["app"].to_a
14240 @root["app"].push "app2"
14241 assert_equal ["/foo/bar/app", "/foo/bar/app2"], @root["app"].to_a
14242 @root["app"] << "app2"
14243 @root["app"].concat ["app2", "/app3"]
14244 assert_equal ["/foo/bar/app", "/foo/bar/app2", "/app3"], @root["app"].to_a
14245 @root["app"].unshift "app2"
14246 assert_equal ["/foo/bar/app2", "/foo/bar/app"], @root["app"].to_a
14247 @root.add "app", with: "/app"
14248 @root["app"] = "/app"
14249 @root.add "app", with: "/app", autoload_once: true
14250 @root.add "app", with: ["/app", "/app2"], autoload_once: true
14251 assert_equal 1, @root.autoload_once.select { |p| p == @root["app"].expanded.first }.size
14252 @root["app"] << "/app2"
14253 @root["app"].eager_load!
14254 @root["app"].skip_eager_load!
14255 @root.add "app", with: "/app", eager_load: true
14256 @root.add "app", with: ["/app", "/app2"], eager_load: true
14257 @root.add "app", with: "/app", eager_load: true, autoload_once: true
14258 assert_equal 1, @root.eager_load.select { |p| p == @root["app"].expanded.first }.size
14259 @root["app"].glob = "*.rb"
14260 assert_equal "*.rb", @root["app"].glob
14261 @root["app"].glob = "*.{rb,yml}"
14262 assert_equal ["rb", "yml"], @root["app"].extensions
14263 @root.add "app", with: "/app", glob: "*.rb"
14264 @root.add "app", glob: "*.rb"
14265 @root["app"] = "app2"
14266 assert_equal ["/foo/bar/app2"], @root["app"].to_a
14267 @root["app"] = "app"
14268 @root["app"].load_path!
14269 @root["app/models"] = "app/models"
14270 @root.add "app", with: "/app", load_path: true
14271 assert_equal ["/app"], @root.load_paths
14272 @root["app"].autoload!
14273 @root.add "app", with: "/app", autoload: true
14274 root = Rails::Paths::Root.new("foo")
14275 def to_a; [200, {}, []]; end
14276 path ||= uri_or_host.path
14277 new_body = []
14278 body.each { |part| new_body << part }
14279 app = self
14280 @routes = TestSet.new ->(c) { app.controller = c }
14281 url = URI("http://example.org/blogs")
14282 send_request(url, "GET", nil, "/FOO")
14283 send_request(url, "GET", nil)
14284 @output = StringIO.new("".encode("UTF-8"))
14285 backtrace = ["lib/my_code.rb", backtrace_gem_line("rails")]
14286 def self.name; "Foo"; end
14287 app = ->(env) {
14288 if params[:t]
14289 assert_nil app.call(make_env("t" => nil))
14290 assert_nil app.call(make_env("t" => [nil]))
14291 [[[nil]], [[[nil]]]].each do |data|
14292 assert_nil app.call(make_env("t" => data))
14293 path = tmp_path(*%w[app] + args)
14294 (+"").tap do |body|
14295 response[2].each { |chunk| body << chunk }
14296 def build_app(options = {})
14297 Dir["#{app_path}/config/initializers/**/*.rb"].each do |initializer|
14298 routes = File.read("#{app_path}/config/routes.rb")
14299 if routes =~ /(
\s*end\s*)\z/
14300 File.open("#{app_path}/config/routes.rb", "w") do |f|
14301 f.puts $` + "
ActionDispatch.deprecator.silence { match ':controller(/:action(/:id))(.:format)', via: :all }
" + $1
14302 File.open("#{app_path}/config/database.yml", "w") do |f|
14303 config.hosts << proc { true }
14304 <<: *default
14305 @app.config.hosts << proc { true }
14306 get "/" => "omg#index"
14307 path = "#{@path}/#{file}"
14308 File.open(path, "w") { |f| f.puts string }
14309 File.delete("#{@path}/#{file}")
14310 dir = "#{app_path}/random/#{name}"
14311 app.insert(4, "$:.unshift(\"#{dir}/lib\")")
14312 app.insert(5, "require #{name.inspect}")
14313 File.open("#{app_path}/config/application.rb", "r+") do |f|
14314 command = "bin/rails #{Shellwords.join args}#{' 2>&1' unless stderr}"
14315 fork = false if args.first == "t" || args.grep(/\Atest(:|\z)/).any?
14316 $stdin.reopen(File::NULL, "r")
14317 case $!
14318 exit! $!.status
14319 err_write.puts "#{$!.class}: #{$!}"
14320 $-v = $-w = false
14321 load "./bin/rails"
14322 output = `cd #{app_path}; #{command}`
14323 raise "rails command failed (#{$?.exitstatus}): #{command}
#{output}" unless allow_failure || $?.success?
14324 if environment =~ /(Rails::Application\s*)/
14325 File.open("#{app_path}/config/application.rb", "w") do |f|
14326 f.puts $` + $1 + "
#{str}
" + $'
14327 if environment =~ /(
\s*end\s*end\s*)\z/
14328 f.puts $` + "
#{str}
" + $1
14329 if environment =~ /(
\s*end\s*)\z/
14330 File.open("#{app_path}/config/environments/#{env}.rb", "w") do |f|
14331 contents.sub!(/#{str}/, "")
14332 def app_file(path, contents, mode = "w")
14333 file_name = "#{app_path}/#{path}"
14334 File.open(file_name, mode) do |f|
14335 FileUtils.mkdir_p("#{app_path}/#{path}")
14336 FileUtils.rm_rf "#{app_path}/#{path}"
14337 $:.reject! { |path| path =~ %r'/(#{to_remove.join('|')})/' }
14338 output = `#{cmd}`
14339 File.open("#{app_template_path}/config/boot.rb", "w") do |f|
14340 contents.sub!(/^Bundler\.require.*/, "%w(sprockets/railtie importmap-rails).each { |r| require r }")
14341 @foo ||= 0
14342 @foo += 1
14343 @bar ||= 0
14344 @bar += 1
14345 $arr << 1
14346 $arr << 2
14347 $arr << 3
14348 $arr << 4
14349 $arr << 5
14350 $with_arg = arg
14351 $arr << two
14352 foo = Foo.new
14353 bar = Bar.new
14354 assert_equal [1, 1], [bar.foo, bar.bar]
14355 $arr = []
14356 assert_equal [5, 1, 2], $arr
14357 assert_equal [5, 3, 1, 4, 2], $arr
14358 assert_equal [1, 2, 3, 4], $arr
14359 assert_equal [2, 3, 4], $arr
14360 assert_equal [1, 3], $arr
14361 $with_arg = nil
14362 @path = File.expand_path("lib", Rails.root)
14363 name = :tas
14364 output = capture(:stdout) { Rails::Generators.invoke :model, [] }
14365 model_generator.expect(:start, nil, [["Account"], {}])
14366 assert_no_match(/[^:]plugin/, output)
14367 self.class.class_eval(<<-end_eval, __FILE__, __LINE__ + 1)
14368 template = File.join(Rails.root, "lib", "templates", "active_record", "model", "model.rb")
14369 File.open(template, "w") { |f| f.write "empty" }
14370 output = capture(:stdout) { Rails::Generators.invoke :usage_template, ["--help"] }
14371 assert_match(/:: 2 ::/, output)
14372 expect = %r{Running:

PostTest
F

Failure:
PostTest#test_truth \[[^\]]+test/post_test\.rb:6\]:
wups!

bin/rails test test/post_test\.rb:4}
14373 switch_env("BUNDLE_GEMFILE", "") { `bin/rails test #{arguments}` }
14374 run_generator ["testapp", "--pretend"]
14375 content = capture(:stderr) { run_generator([destination_root, "-d", "unknown"]) }
14376 run_generator [destination_root, "--ruby", "foo/bar/baz", "--full"]
14377 assert_file "bin/rails", /#!foo\/bar\/baz/
14378 assert_file "bin/rails", /#!\/usr\/bin\/env/
14379 content = capture(:stderr) { run_generator([destination_root, "-m", "non/existent/path"]) }
14380 apply_stub = -> (path, *) { applied = path }
14381 run_generator [destination_root, "--skip-git", "--full"]
14382 run_generator [destination_root, "--skip-keeps", "--full"]
14383 assert_file "#{application_path}/config/application.rb", /^require\s+["']rails["']/
14384 assert_file "#{application_path}/config/application.rb", /^# require\s+["']active_record\/railtie["']/
14385 assert_file "#{application_path}/config/application.rb", /^# require\s+["']active_storage\/engine["']/
14386 assert_file "#{application_path}/config/application.rb", /^# require\s+["']action_mailer\/railtie["']/
14387 assert_file "#{application_path}/config/application.rb", /^# require\s+["']action_mailbox\/engine["']/
14388 assert_file "#{application_path}/config/application.rb", /^# require\s+["']action_text\/engine["']/
14389 assert_file "#{application_path}/config/application.rb", /^# require\s+["']action_cable\/engine["']/
14390 assert_file "#{application_path}/config/application.rb", /^require\s+["']rails\/test_unit\/railtie["']/
14391 assert_file "#{application_path}/config/application.rb", /\s+require\s+["']rails\/all["']/
14392 assert_file "#{application_path}/config/application.rb", /#\s+require\s+["']active_record\/railtie["']/
14393 assert_file "#{application_path}/config/application.rb", /#\s+require\s+["']active_storage\/engine["']/
14394 assert_file "#{application_path}/config/application.rb", /#\s+require\s+["']action_mailer\/railtie["']/
14395 assert_file "#{application_path}/config/application.rb", /#\s+require\s+["']action_cable\/engine["']/
14396 run_generator [destination_root, "-a", "none"]
14397 rails_path = File.expand_path("../../..", Rails.root)
14398 assert_file "Gemfile", %r{^gem ["']rails["'], path: ["']#{Regexp.escape rails_path}["']$}
14399 Rails.stub(:gem_version, Gem::Version.new("2.1.0")) do
14400 assert_file "Gemfile", %r{^gem ["']rails["'], github: ["']rails/rails["'], branch: ["']2-1-stable["']$}
14401 Rails.stub(:gem_version, Gem::Version.new("2.1.0.alpha")) do
14402 assert_file "Gemfile", %r{^gem ["']rails["'], github: ["']rails/rails["'], branch: ["']main["']$}
14403 assert_file "myproject/Gemfile", %r{^gem ["']rails["'], github: ["']rails/rails["'], branch: ["']main["']$}
14404 @bundle_commands = []
14405 @bundle_command_stub ||= -> (command, *) { @bundle_commands << command }
14406 option_args, positional_args = args.partition { |arg| arg.start_with?("--") }
14407 rails_gem_pattern = /^gem ["']rails["'], .+/
14408 @bundle_command_stub = -> (command, *) do
14409 /, #{constraint}/
14410 assert_file "Gemfile", %r/^\s*gem ["']#{name}["']#{constraint_pattern}/
14411 assert_no_match %r/gem ["']#{name}["']/, content
14412 assert_match(/@product_line = ProductLine\.find\(params\[:id\]\)/, m)
14413 %w(index show).each do |view|
14414 %w(edit new).each do |view|
14415 assert_match(/post product_lines_url, params: \{ product_line: \{ product_id: @product_line\.product_id, title: @product_line\.title, user_id: @product_line\.user_id \} \}/, test)
14416 assert_match(/@admin_roles = Admin::Role\.all/, m)
14417 assert_match(/@admin_role = Admin::Role\.new/, m)
14418 assert_match(/@admin_role = Admin::Role\.new\(admin_role_params\)/, m)
14419 assert_match(/@admin_role\.save/, m)
14420 assert_match(/@admin_role\.destroy!/, m)
14421 assert_match(/@admin_role = Admin::Role\.find\(params\[:id\]\)/, m)
14422 content = File.read(route_path).gsub(/\.routes\.draw do/) do |match|
14423 assert_file "config/routes.rb", /\.routes\.draw do\s*\|map\|\s*$/
14424 content.gsub!(/^
/, "")
14425 assert_file "config/routes.rb", /\.routes\.draw do
end
\z/
14426 run_generator [ "posts", "--resource-route=false" ]
14427 output = run_generator [ "posts", "--no-helper" ]
14428 output = run_generator [ "posts", "--helper=false" ]
14429 run_generator ["post", "title", "body:text", "author"]
14430 assert_match(/t\.string :title/, up)
14431 assert_match(/t\.text :body/, up)
14432 assert_match(/t\.string :name/, up)
14433 assert_match(/permit\(:name, :currency_id, :user_id\)/, m)
14434 assert_match(/^\W{4}<%= form\.text_field :name %>/, content)
14435 assert_match(/^\W{4}<%= form\.text_field :currency_id %>/, content)
14436 assert_match(/^\W{2}<%= @accounts.each do |account| %>/, content)
14437 assert_match(/^\W{4}<%= render account %>/, content)
14438 assert_match(/<%= link_to "Show this account", account %>/, content)
14439 assert_match(/<%= render @account %>/, content)
14440 assert_match(/permit\(:video, photos: \[\], images: \[\]\)/, m)
14441 assert_match(/^\W{4}<%= form\.file_field :video %>/, content)
14442 assert_match(/^\W{4}<%= form\.file_field :photos, multiple: true %>/, content)
14443 assert_match(/^\W{4}<%= link_to message\.video\.filename, message\.video if message\.video\.attached\? %>/, content)
14444 assert_match(/^\W{6}<div><%= link_to photo\.filename, photo %>/, content)
14445 assert_match(/permit\(:content\)/, m)
14446 assert_match(/^\W{4}<%= form\.rich_text_area :content %>/, content)
14447 run_generator ["posts", "--db=secondary"]
14448 run_generator ["user", "name", "password:digest"]
14449 assert_match(/<%= form\.password_field :password %>/, content)
14450 assert_match(/password_digest: <%= BCrypt::Password.create\("secret"\) %>/, content)
14451 with_new_plugin(engine_path, "--mountable", "--api") do
14452 with_new_plugin(engine_path, "--full", "--api") do
14453 assert_match(/@users = User\.all/, m)
14454 assert_match(/@user = User\.new/, m)
14455 assert_match(/@user = User\.new\(user_params\)/, m)
14456 assert_match(/@user\.save/, m)
14457 assert_match(/@user\.update\(user_params\)/, m)
14458 assert_match(/@user\.destroy/, m)
14459 assert_match(/@user = User\.find\(params\[:id\]\)/, m)
14460 assert_match(/params\.require\(:user\)\.permit\(:name, :age\)/, content)
14461 assert_match(/params\.fetch\(:user, \{\}\)/, content)
14462 assert_match(/params\.require\(:line_item\)\.permit\(:product_id, :cart_id\)/, content)
14463 assert_match(/params\.require\(:message\)\.permit\(:video, photos: \[\]\)/, content)
14464 assert_match(/params\.require\(:message\)\.permit\(photos: \[\]\)/, content)
14465 assert_match(/post users_url, params: \{ user: \{ age: @user\.age, name: @user\.name, organization_id: @user\.organization_id, organization_type: @user\.organization_type \} \}/, content)
14466 run_generator ["User", "name:string", "age:integer", "--no-helper"]
14467 run_generator ["User", "name:string", "age:integer", "--no-layout"]
14468 run_generator ["User", "--orm=unknown"]
14469 assert_match(/@users = User\.find\(:all\)/, m)
14470 assert_no_match(/@users = User\.all/, m)
14471 run_generator ["Admin::User", "--model-name=User"]
14472 assert_match("@users = User.all", m)
14473 assert_match("redirect_to [:admin, @user]", m)
14474 assert_match %{"Show this user", [:admin, user]}, content
14475 assert_match %{"Destroy this user", [:admin, @user]}, content
14476 assert_match %{"Show this user", [:admin, @user]}, content
14477 assert_match %{model: [:admin, user]}, content
14478 assert_no_match %r/\b(new_|edit_)?users?_(path|url)/, content
14479 run_generator ["User", "--api"]
14480 assert_match(/@user\.errors/, m)
14481 content = run_generator ["--help"]
14482 %w(
14483 ).each { |path| assert_file path }
14484 run_generator ["account", "--actions", "index", "new"]
14485 assert_no_match(/\[WARNING\]/, content)
14486 plugin_file "test/post_test.rb", <<-RUBY
14487 expect = %r{Running:

PostTest
F

Failure:
PostTest#test_truth \[[^\]]+test/post_test.rb:6\]:
wups!

bin/test (/private)?#{plugin_path}/test/post_test.rb:4}
14488 capture(:stderr) { run_test_command("test/post_test.rb --fail-fast") })
14489 a = 1
14490 plugin_file "test/#{name}_test.rb", <<-RUBY
14491 assert #{pass}, 'wups!'
14492 File.open("#{plugin_path}/#{path}", mode) do |f|
14493 filled_in = File.read(gemspec_path).gsub(/"TODO.*"/, "http://example.com".inspect)
14494 repository_path = File.expand_path("../../..", __dir__)
14495 File.write(gemfile_path, "gem 'rails', path: #{repository_path.inspect}
", mode: "a")
14496 assert_file ".git/HEAD", /main/
14497 git_version = `git --version`[/\d+.\d+.\d+/]
14498 assert_file ".git/HEAD", /master/
14499 run_generator [destination_root, "--full", "-M", "-O", "-C", "-T", "--skip-active-storage", "--skip-active-job"]
14500 assert_no_match(/\s+require\s+["']rails\/all["']/, content)
14501 assert_file "bin/rails", /#\s+require\s+["']active_job\/railtie["']/
14502 assert_file "bin/rails", /#\s+require\s+["']active_record\/railtie["']/
14503 assert_file "bin/rails", /#\s+require\s+["']active_storage\/engine["']/
14504 assert_file "bin/rails", /#\s+require\s+["']action_mailer\/railtie["']/
14505 assert_file "bin/rails", /#\s+require\s+["']action_cable\/engine["']/
14506 assert_file "bin/rails", /#\s+require\s+["']rails\/test_unit\/railtie["']/
14507 assert_file "Gemfile", /# gem "debug"/
14508 run_generator [destination_root, "-T", "--full"]
14509 run_generator [destination_root, "-T", "--mountable", "--dummy-path", "my_dummy_app"]
14510 run_generator [destination_root, "--api", "--mountable", "--skip-action-mailer", "--skip-active-job"]
14511 run_generator [destination_root, "--full", "--skip-action-mailer", "--skip-active-job"]
14512 output = `bin/rails db:migrate 2>&1`
14513 assert $?.success?, "Command failed: #{output}"
14514 assert_file "bin/rails", /\s+require\s+["']rails\/all["']/
14515 assert_match "<%= csrf_meta_tags %>", contents
14516 assert_match "<%= csp_meta_tag %>", contents
14517 assert_match "<%= yield %>", contents
14518 folders_with_keep = %w(
14519 assert_file("#{folder}/.keep")
14520 run_generator [destination_root, "--full", "--api"]
14521 rails_version = "1.2.3.4.pre5"
14522 assert_file "bin/rails", /ENGINE_PATH = File\.expand_path\("\.\.\/lib\/bukkits\/engine", __dir__\)/
14523 assert_file "bin/rails", /ENGINE_ROOT = File\.expand_path\("\.\.", __dir__\)/
14524 assert_file "bin/rails", %r|APP_PATH = File\.expand_path\("\.\./test/dummy/config/application", __dir__\)|
14525 assert_file "bin/rails", /#!\/usr\/bin\/env ruby/
14526 run_generator [destination_root, "--dummy_path", "spec/dummy", "--skip-test"]
14527 assert_file "spec/dummy/config/application.rb", /#\s+require\s+["']rails\/test_unit\/railtie["']/
14528 output = `bin/test 2>&1`
14529 run_generator [destination_root, "--mountable", "--api"]
14530 run_generator([destination_root, "--dummy_path", "spec/dummy", "--skip-test"])
14531 run_generator [destination_root, "--skip-gemspec", "--full"]
14532 assert_no_match(/#{year}/, contents)
14533 name = "TODO: Write your name"
14534 ["--full", "--mountable"].each do |option|
14535 assert_match(/<%= yield %>/, view)
14536 assert_match(%r|APP_PATH = File\.expand_path\("\.\./test/dummy/config/application", __dir__\)|, content)
14537 silence(:stdout) { generator.send(*args, &block) }
14538 g = generator ["Foo"]
14539 assert_file "config/routes.rb", /get 'account\/foo'/, /get 'account\/bar'/
14540 content.split("
").each do |line|
14541 assert_no_match(/^\s+$/, line, "Don't indent blank lines")
14542 assert_match(/test "foo"/, test)
14543 assert_match(/test "bar"/, test)
14544 assert_match(/<%= @greeting %>/, view)
14545 run_generator [ "admin/role", "name:string", "description:string", "--api" ]
14546 g = generator ["line_item"]
14547 g = generator ["admin/foo"]
14548 assert_name g, "Admin::Foo", :class_name
14549 g = generator ["Admin::Foo"]
14550 assert_name g, "Admin::Foo", :name
14551 g = generator ["Post"]
14552 g = generator ["Stadium"]
14553 g = generator ["Sheep"]
14554 g = generator ["Hidden"]
14555 g = generator ["Admin::Foo"], model_name: "User"
14556 g = generator ["User"]
14557 run_generator ["account", "--parent", "Admin::Account"]
14558 run_generator ["account", "--database", "secondary"]
14559 run_generator ["account", "--parent", "Admin::Account", "--database", "secondary"]
14560 run_generator ["account", "--migration", "false", "--database", "secondary"]
14561 run_generator ["account", "--migration", "false"]
14562 run_generator ["account", "--migration", "false", "--database", "secondary", "--migration", "false", "--parent", "Admin::Account"]
14563 content = capture(:stderr) { run_generator ["BFF"] }
14564 run_generator ["account", "--parent", "admin/account"]
14565 assert_file "app/models/admin.rb", /"admin_"/
14566 run_generator ["account", "--no-migration"]
14567 assert_match(/t\.integer :user_id/, up)
14568 assert_match(/t\.string :order_id/, up)
14569 assert_match(/t.string :title, limit: 40/, up)
14570 assert_match(/t.decimal :price, precision: 5, scale: 2/, up)
14571 output = run_generator ["Account", "--skip"]
14572 error = capture(:stderr) { run_generator ["Account"], behavior: :revoke }
14573 error = capture(:stderr) { run_generator ["Account", "--force"] }
14574 run_generator ["LineItem", "no:integer", "Off:boolean", "ON:boolean"]
14575 run_generator ["account", "--skip-fixture"]
14576 content = run_generator ["account", "-r", "factory_girl"]
14577 content = capture(:stderr) { run_generator ["object"] }
14578 run_generator ["account", "--db=secondary"]
14579 expected_file = <<~FILE
14580 assert_match(/t\.references :user,.*\snull: false/, up)
14581 assert_match(/t\.belongs_to :user,.*\snull: false/, up)
14582 assert_match(/t\.belongs_to :user/, up)
14583 assert_match(/# t\.index \[:artist_id, :music_id\]/, change)
14584 assert_match(/^\s*$/, change)
14585 assert_migration "db2/migrate/#{migration}.rb", /.*/
14586 content = run_generator ["notifier", "foo", "bar", "--template-engine=haml"]
14587 assert_match(/haml \[not found\]/, content)
14588 run_generator ["Farm::Animal", "moos"]
14589 assert_match(/mail to: "to@example\.org"/, foo)
14590 assert_match(/@greeting = "Hi"/, foo)
14591 assert_match(/mail to: "to@example\.org"/, bar)
14592 assert_match(/@greeting = "Hi"/, bar)
14593 run_generator ["admin/refresh_counters", "--queue", "admin"]
14594 destination File.expand_path("../fixtures/tmp", __dir__)
14595 setup { Rails.application.config.root = Pathname("../fixtures").expand_path(__dir__) }
14596 test: {
14597 erb = ERB.new(File.read(file), trim_mode: "-", eoutvar: "@output_buffer")
14598 assert klass.start(["new", "blah"])
14599 generator = klass.start(["new", "blah"])
14600 assert_equal "~> 4.1.13", specifier_for["4.1.13"]
14601 assert_equal "~> 4.1.6.rc1", specifier_for["4.1.6.rc1"]
14602 assert_equal ["~> 4.1.7", ">= 4.1.7.1"], specifier_for["4.1.7.1"]
14603 assert_equal ["~> 4.1.7", ">= 4.1.7.1.2"], specifier_for["4.1.7.1.2"]
14604 assert_equal ["~> 4.1.7", ">= 4.1.7.1.rc2"], specifier_for["4.1.7.1.rc2"]
14605 assert_equal "~> 4.2.0.beta1", specifier_for["4.2.0.beta1"]
14606 assert_equal "~> 5.0.0.beta1", specifier_for["5.0.0.beta1"]
14607 run_generator ["awesome", "--namespace", "false"]
14608 run_generator ["rails/awesome", "--namespace", "false"]
14609 run_generator ["--to", "invalid-db"]
14610 run_generator ["--to", "postgresql"]
14611 assert_match 'gem "pg", "~> 1.1"', content
14612 run_generator ["--to", "mysql"]
14613 assert_match 'gem "mysql2", "~> 0.5"', content
14614 run_generator ["--to", "sqlite3"]
14615 assert_match 'gem "sqlite3", "~> 1.4"', content
14616 run_generator ["--to", "mysql", "--force"]
14617 run_generator ["account", "--skip-helper"]
14618 run_generator ["account", "foo", "--skip-routes"]
14619 run_generator ["admin/dashboard", "index", "show"]
14620 run_generator ["chat", "speak", "mute"]
14621 run_generator ["chat", "--skip-assets"]
14622 x.report("before") { }
14623 x.report("after") { }
14624 x.report("with_patch") { }
14625 x.report("without_patch") { }
14626 ["-v", "--version"].each do |str|
14627 define_method(:puts) { |string| output = string }
14628 define_method(:exit) { |code| exit_code = code }
14629 argv = ["zomg", "how", "are", "you"]
14630 assert_equal ["--help"] + argv.drop(1), args
14631 }.new ["new"]
14632 define_method(:puts) { |msg| message = msg }
14633 assert_equal ["--hello-world"], args
14634 file.puts "--hello --world"
14635 define_method(:puts) { |msg| }
14636 }.new ["new", "--rc=#{file.path}"]
14637 assert_equal ["--hello", "--world"], args
14638 file.puts "--hello"
14639 file.puts "--world"
14640 }.new ["new", "tenderapp", "--love", "--rc=#{file.path}"]
14641 assert_equal ["tenderapp", "--hello", "--world", "--love"], args
14642 scrubber = ARGVScrubber.new ["new", "--no-rc"]
14643 quietly { system "#{File.expand_path("../../exe/rails", __dir__)} new test --no-rc" }
14644 output = `#{File.expand_path("../../exe/rails", __dir__)} new mysecondapp`
14645 assert_file "Gemfile", /^# gem "image_processing"/
14646 assert_file "#{application_path}/config/application.rb", /#\s+require\s+["']action_mailbox\/engine["']/
14647 assert_file "#{application_path}/config/application.rb", /#\s+require\s+["']action_text\/engine["']/
14648 run_generator [app_root, "-d", "postgresql"]
14649 File.open(absolute, "r") do |f|
14650 assert_no_match %r{/^[ \t]+$/}, line
14651 assert_gem "sqlite3", '"~> 1.4"'
14652 run_generator([destination_root, "-d", "mysql"])
14653 assert_gem "mysql2", '"~> 0.5"'
14654 assert_gem "pg", '"~> 1.1"'
14655 run_generator([destination_root, "-d", "jdbc"])
14656 assert_gem "puma", /"\W+ \d/
14657 assert_file "Gemfile", /^# gem "redis"/
14658 assert_file ".gitattributes", /\.enc diff=/
14659 assert_no_match %r/\.enc diff=/, content
14660 assert_file "config/application.rb", /#\s+require\s+["']rails\/test_unit\/railtie["']/
14661 assert_match(/#\s+require\s+["']active_job\/railtie["']/, content)
14662 assert_match(/#\s+require\s+["']active_storage\/engine["']/, content)
14663 assert_match(/#\s+require\s+["']action_mailer\/railtie["']/, content)
14664 quietly { `./bin/rails g scaffold User` }
14665 action :file, "lib/test_file.rb", "here's test data"
14666 run_generator [path, "-d", "postgresql"]
14667 mock_original_env = -> do
14668 ensure_environment_is_set = -> *_args do
14669 command_check = -> command, *_ do
14670 assert_match(/\d+\.\d+\.\d+/, content)
14671 assert_match(/ruby "#{Gem::Version.new(Gem::VERSION) >= Gem::Version.new("3.3.13") ? Gem.ruby_version : RUBY_VERSION}"/, content)
14672 assert_match(/#{ENV["rvm_ruby_string"]}/, content)
14673 Gem.stub(:ruby_version, Gem::Version.new("2.7.0")) do
14674 generator([destination_root], ["--minimal", "--no-skip-action-text"])
14675 generator([destination_root], ["--minimal", "--no-skip-active-storage"])
14676 option_args << "--no-skip-bundle"
14677 gemfile_contents.sub!(/^(gem "rails").*/, "\\1, path: #{File.expand_path("../../..", __dir__).inspect}")
14678 quietly { system({ "BUNDLE_GEMFILE" => "Gemfile" }, "yes | bin/rails app:update", exception: true) }
14679 capture(:stdout) { generator.send(*args, &block) }
14680 assert_match(/# gem "rack-cors"/, content)
14681 assert_file "config/application.rb", /#\s+require\s+["']action_cable\/engine["']/
14682 assert_file "config/application.rb", /#\s+require\s+["']action_mailer\/railtie["']/
14683 { api: true, update: true }, { destination_root: destination_root, shell: @shell }
14684 action :invoke, "model", ["my_model"]
14685 action :invoke, "rails:model", ["my_model"]
14686 action(:create_file, "lib/test_file.rb") { "here's block data" }
14687 assert_file "Gemfile", /source "http:\/\/gems\.github\.com"
/
14688 action :gem, "rspec", ">= 2.0.0.a5"
14689 action :gem, "RedCloth", ">= 4.1.0", "< 4.2.0"
14690 action :gem, "nokogiri", version: ">= 1.4.2"
14691 action :gem, "faker", version: [">= 0.1.0", "< 0.3.0"]
14692 assert_match(/gem "rspec", ">= 2\.0\.0\.a5"/, content)
14693 assert_match(/gem "RedCloth", ">= 4\.1\.0", "< 4\.2\.0"/, content)
14694 assert_match(/gem "nokogiri", ">= 1\.4\.2"/, content)
14695 assert_match(/gem "faker", ">= 0\.1\.0", "< 0\.3\.0"/, content)
14696 File.open("Gemfile", "a") { |f| f.write("# Some content...") }
14697 action :gem, "rspec"
14698 assert_file "Gemfile", /^gem "rspec"$/
14699 assert_file "Gemfile", /^gem "rspec-rails"$/
14700 action :gem, "rspec", github: "dchelimsky/rspec", tag: "1.2.9.rc1"
14701 assert_file "Gemfile", /gem "rspec", github: "dchelimsky\/rspec", tag: "1\.2\.9\.rc1"/
14702 action :gem, "rspec", comment: "Use RSpec"
14703 assert_file "Gemfile", /# Use RSpec
gem "rspec"/
14704 action :gem, "rspec-rails", group: [:development, :test]
14705 assert_file "Gemfile", /^gem "rspec", require: false$/
14706 assert_file "Gemfile", /^gem "rspec-rails", group: \[:development, :test\]$/
14707 action :gem, "rspec", ">=2.0.0"
14708 assert_file "Gemfile", /^gem "rspec", ">=2\.0\.0"$/
14709 action :gem, -"frozen_gem", -"1.0.0"
14710 assert_file "Gemfile", /^gem "frozen_gem", "1\.0\.0"$/
14711 gem "foo"
14712 gem "bar"
14713 gem "baz"
14714 action :github, "user/repo", a: "correct", other: true do
14715 github "user/repo", a: "correct", other: true do
14716 github "user/repo2", a: "correct", other: true do
14717 action :github, "user/repo2", a: "correct", other: true do
14718 File.open("Gemfile", "a") { |f| f.write('gem "rspec-rails"') }
14719 autoload_paths = 'config.autoload_paths += %w["#{Rails.root}/app/extras"]'
14720 assert_runs ["git rm README", "git add ."], nil do
14721 action :git, rm: "README", add: "."
14722 action :vendor, "vendor_file.rb", "# vendor data"
14723 puts "one"
14724 puts "two"
14725 action(:vendor, "vendor_file.rb") { code }
14726 action(:lib, "my_library.rb") { code }
14727 action(:rakefile, "myapp.rake") { code }
14728 assert_runs "rake log:clear", env: { "RAILS_ENV" => "development" } do
14729 assert_runs "rake log:clear", env: { "RAILS_ENV" => "production" } do
14730 assert_runs "rails log:clear", env: { "RAILS_ENV" => "development" } do
14731 assert_runs "rails log:clear", env: { "RAILS_ENV" => "production" } do
14732 route_commands = ['get "foo"', 'get "bar"', 'get "baz"']
14733 action :route, "get 'foo'
get 'bar'", namespace: :baz
14734 get 'foo'
14735 get 'bar'
14736 action :route, "get 'foo'
get 'bar'", namespace: %w[baz qux]
14737 action :route, "get 'foo1'
get 'bar1'", namespace: %w[baz qux]
14738 action :route, "get 'foo2'
get 'bar2'", namespace: %w[baz hoge]
14739 action :route, "get 'foo3'
get 'bar3'", namespace: %w[baz qux hoge]
14740 get 'foo2'
14741 get 'bar2'
14742 get 'foo3'
14743 get 'bar3'
14744 get 'foo1'
14745 get 'bar1'
14746 revoke :route, "get 'foo2'", namespace: %w[baz qux]
14747 revoke :route, "get 'foo3'", namespace: %w[baz qux hoge]
14748 assert_equal("YES
", action(:log, "YES"))
14749 assert_equal("", action(:log, "YES"))
14750 assert_equal("", action(:log, :yes, "YES"))
14751 def action(...)
14752 capture(:stdout) { generator.send(...) }
14753 def revoke(...)
14754 action(...)
14755 def assert_runs(commands, config = {}, &block)
14756 command_matcher = command_matcher.sub(/^sudo\\ /, '\A\1.*')
14757 args = [/#{command_matcher}\z/, *config_matcher]
14758 %r{
14759 (?:[ ]{2}.+
|
)*
14760 }x
14761 assert_match %r"^#{Regexp.escape 'import "trix"'}", content
14762 @run_commands = []
14763 run_command_stub = -> (command, *) { @run_commands << command }
14764 old, ENV[key] = ENV[key], value
14765 @routes = nil
14766 @hello = "world"
14767 in_plugin_context(plugin_path) { `bin/rails --help` }
14768 in_plugin_context(plugin_path) { system({ "RAILS_ENV" => "test" }, "bin/rails runner 'puts Rails.env'") }
14769 Process.spawn("bin/rails #{command}", in: fd, out: fd, err: fd)
14770 output = +""
14771 if IO.select([io], [], [], 0.1)
14772 output << io.read(1)
14773 defined?(PTY) && PTY.respond_to?(:open)
14774 mock.expect :swap, nil, [:foo]
14775 mock.expect :delete, nil, [:foo]
14776 get "/", to: "my#index", as: :my_route
14777 <h1>Hello world</h1>
14778 get "/one", to: "action#one"
14779 get "/two", to: "action#two"
14780 get "/one", to: "posts#one"
14781 get "/two", to: "users#two"
14782 assert_includes run_unused_routes_command(["-g", "one"]), <<~OUTPUT
14783 assert_includes run_unused_routes_command(["-c", "posts"]), <<~OUTPUT
14784 app_file "test/some_test.rb", ""
14785 run_test_command("test", "./test/*_test.rb")
14786 run_test_command("test", "--seed", "1234", "-e", "development")
14787 run_test_command("test", "-n", "test_some_code")
14788 run_test_command("test", "-n", "/some_code/")
14789 run_test_command("test", "-n", "some code")
14790 run_test_command("test", "--name", "test_some_code")
14791 run_test_command("test", "--name=test_some_code")
14792 app_file "Rakefile", ""
14793 run_test_command("test:all", "-n", "test_some_code")
14794 run_test_command("test:models", "-n", "test_some_code")
14795 app_file "Rakefile", <<~RUBY, "a"
14796 args = ["-u", "thin", "-e", "production"]
14797 args = ["-e", "production"]
14798 args = ["-e", "prod"]
14799 args = ["-u", "thin"]
14800 output = run_command("--using", "tin")
14801 output = run_command("--using", "t")
14802 args = ["-d"]
14803 switch_env "PORT", "1234" do
14804 assert_equal "1.2.3.4", options[:Host]
14805 args = ["--dev-caching"]
14806 args = ["--no-dev-caching"]
14807 args = ["--early-hints"]
14808 assert_equal "0.0.0.0", options[:Host]
14809 args = ["-b", "127.0.0.1"]
14810 assert_equal "127.0.0.1", options[:Host]
14811 args = ["-p", "5678"]
14812 args = ["-p", "3000"]
14813 args = ["-P", "/somewhere/else.pid"]
14814 server_options = parse_arguments(["-p", "3001"])
14815 server_options = parse_arguments(["--port", "3001"])
14816 server_options = parse_arguments(["-p3001", "-C", "--binding", "127.0.0.1"])
14817 switch_env "PORT", "3001" do
14818 Dir.chdir("..") do
14819 args = %w(-p 4567 -b 127.0.0.1 -c dummy_config.ru -d -e test -P tmp/server.pid -C)
14820 expected = "bin/rails server -p 4567 -b 127.0.0.1 -c dummy_config.ru -d -e test -P tmp/server.pid -C --restart"
14821 args = %w(-u webrick -b 127.0.0.1 -p 4567)
14822 def parse_arguments(args = [])
14823 command_output = `echo "puts 'Hello world'" | #{app_path}/bin/rails runner -`
14824 app_file "lib/foo.rb", "# Lib file"
14825 app_file "foo.rb", <<-RUBY
14826 assert_equal <<~OUTPUT, run_routes_command([ "-c", "PostController" ])
14827 get '/cart', to: 'cart#show'
14828 post '/cart', to: 'cart#create'
14829 assert_equal <<~MESSAGE, run_routes_command([ "-g", "show" ])
14830 assert_equal <<~MESSAGE, run_routes_command([ "-g", "POST" ])
14831 assert_equal <<~MESSAGE, run_routes_command([ "-g", "basketballs" ])
14832 assert_equal <<~MESSAGE, run_routes_command([ "-g", "/cart" ])
14833 assert_equal <<~MESSAGE, run_routes_command([ "-g", "/photos/7" ])
14834 assert_equal <<~MESSAGE, run_routes_command([ "-g", "/cats" ])
14835 output = run_routes_command(["-c", "cart"])
14836 output = run_routes_command(["-c", "Cart"])
14837 output = run_routes_command(["-c", "CartController"])
14838 output = run_routes_command(["-c", "user_permission"])
14839 output = run_routes_command(["-c", "UserPermission"])
14840 assert_equal <<~OUTPUT, run_routes_command([ "-c", "Admin::PostController" ])
14841 output = IO.stub(:console_size, [0, 27]) do
14842 run_routes_command([ "--expanded" ])
14843 --[ Route 1 ]--------------
14844 --[ Route 2 ]--------------
14845 --[ Route 3 ]--------------
14846 --[ Route 4 ]--------------
14847 --[ Route 5 ]--------------
14848 --[ Route 6 ]--------------
14849 --[ Route 7 ]--------------
14850 --[ Route 8 ]--------------
14851 --[ Route 9 ]--------------
14852 --[ Route 10 ]-------------
14853 --[ Route 11 ]-------------
14854 --[ Route 12 ]-------------
14855 --[ Route 13 ]-------------
14856 --[ Route 14 ]-------------
14857 --[ Route 15 ]-------------
14858 --[ Route 16 ]-------------
14859 --[ Route 17 ]-------------
14860 --[ Route 18 ]-------------
14861 --[ Route 19 ]-------------
14862 --[ Route 20 ]-------------
14863 --[ Route 21 ]-------------
14864 --[ Route 22 ]-------------
14865 --[ Route 23 ]-------------
14866 --[ Route 24 ]-------------
14867 output = run_routes_command([ "--unused" ])
14868 def run_routes_command(args = [])
14869 app_file "db/some_seeds.rb", "# FIXME: note in db directory"
14870 app_file "lib/some_file.rb", "# TODO: note in lib directory"
14871 app_file "test/some_test.rb", "
" * 100 + "# FIXME: note in test directory"
14872 assert_equal <<~OUTPUT, run_notes_command(["--annotations", "FIXME"])
14873 app_file "spec/spec_helper.rb", "# TODO: note in spec"
14874 add_to_config %q{ config.annotations.register_extensions("scss", "sass") { |annotation| /\/\/\s*(#{annotation}):?\s*(.*)$/ } }
14875 app_file "app/models/profile.rb", '"# TODO: do something"'
14876 def run_notes_command(args = [])
14877 lambda { |n, &b| dependencies.each { |m, *ds| ds.each(&b) if m == n } })
14878 add_to_config "config.hosts = []"
14879 add_to_config "config.hosts = IPAddr.new('0.0.0.0/0')"
14880 add_to_config "config.ssl_options = { redirect: { host: 'example.com' } }"
14881 render plain: ""
14882 get "/?nothing=true"
14883 env = ::Rack::MockRequest.env_for("/foo/?something")
14884 add_to_config "config.active_record.shard_resolver = ->(*) { }"
14885 output = run_initializers_command(["-e", "production"]).split("
")
14886 app_file ".gitignore", ""
14887 write_invalid_yaml = %(ruby -e "File.write ARGV[0], 'foo: bar: bad'")
14888 def run_edit_command(file = @encrypted_file, key: nil, editor: "cat", **options)
14889 args = [ file ]
14890 args.push("--key", key) if key
14891 app_file("tmp/restart.txt", "")
14892 app_file("tmp/caching-dev.txt", "")
14893 username: "foo",
14894 password: "bar",
14895 }.sort
14896 assert_match("development", parse_arguments([ "-e", "dev" ])[:environment])
14897 dbconsole = parse_arguments(["--db", "custom", "-e", "development"])
14898 app_db_config({}) do
14899 Rails::Command.invoke(:dbconsole, ["--db", "i_do_not_exist"])
14900 Rails::Command.invoke(:dbconsole, ["-h"])
14901 Rails::Command.invoke(:dbconsole, ["--help"])
14902 def start(config = {}, argv = [])
14903 setup { build_app }
14904 args = ["--to", to]
14905 provides_secret_key_base: <%= [secret_key_base] == [secret_key_base].compact %>
14906 args = environment ? ["--environment", environment] : []
14907 args = [path, ("--enroll" if enroll), ("--disenroll" if disenroll)].compact
14908 run_edit_command(editor: %(ruby -e "File.write ARGV[0], ENV['CONTENT']"), **options)
14909 content = "foo: #{content_path}"
14910 if %r"config/credentials(?:/.*)?\.yml\.enc$".match?(content_path)
14911 console = Rails::Console.new(app, parse_arguments(["-s"]))
14912 start ["--sandbox"]
14913 start ["-e", "production"]
14914 app = build_app(nil)
14915 start ["-e", "special-production"]
14916 start ["-e", "prod"]
14917 ["dev"]
14918 assert_match("dev", parse_arguments(["-e", "dev"])[:environment])
14919 def start(argv = [])
14920 desc "bar [paths...]", "description of bar"
14921 def bar(*paths); end
14922 Rails::Command::HelpfulCommand.perform("help", [], {})
14923 Rails::Command::HelpfulCommand.perform("foo", ["--help"], {})
14924 Rails::Command::HelpfulCommand.perform("bar", ["--help"], {})
14925 def perform(*); end
14926 def foo(*); end
14927 Rails::Command::Nesting::NestedCommand.perform("nested", ["--help"], {})
14928 Rails::Command::Nesting::NestedCommand.perform("foo", ["--help"], {})
14929 self.bin = "FOO"
14930 raise "not populated" if ARGV.empty? || ARGV != args
14931 ARGV << "isolate this"
14932 @tmp_path = File.expand_path("fixtures/tmp", __dir__)
14933 File.write File.join(@tmp_path, ".example.rb"), <<-CODE
14934 puts 'foo'
14935 temp_file "stats.rb", code do |path|
14936 temp_file "foo_test.rb", code do |path|
14937 class A < B
14938 function foo(x, y, z) {
14939 doX();
14940 $(function () {
14941 bar();
14942 var baz = function ( x ) {
14943 alert('foo');
14944 // var b = 2;
14945 var a = 1;
14946 /*
14947 1 / 2;
14948 // call();
14949 //
14950 <!-- This is an HTML comment -->
14951 <%# This is a great comment! %>
14952 <div>
14953 <%= hello %>
14954 square = (x) -> x * x
14955 math =
14956 cube: (x) -> x * square x
14957 fill = (container, liquid = "coffee") ->
14958 $('.shopping_cart').bind 'click', (event) =>
14959 constructor: (@name) ->
14960 move: (meters) ->
14961 alert @name + " moved #{meters}m."
14962 move: ->
14963 dir = File.expand_path "fixtures/tmp", __dir__
14964 path = "#{dir}/#{name}"
14965 backtrace = [ "(irb):1",
14966 assert_equal "(irb):1", result[0]
14967 assert_equal "bin/rails:4:in `<main>'", result[1]
14968 add_to_env_config "development", <<~'RUBY'
14969 app_file "extras0/x.rb", "X = 0"
14970 app_file "extras1/y.rb", "Y = 0"
14971 engine("blog") do |bukkit|
14972 app_dir "lib"
14973 extras = %w(e1 e2 e3)
14974 add_to_config %(config.autoload_once_paths << "\#{Rails.root}/#{extra}")
14975 extras = extras.map { |extra| "#{app_path}/#{extra}" }
14976 app_file "app/models/child.rb", <<~RUBY
14977 logger = ->(_msg) { }
14978 add_to_config %(config.autoload_once_paths << "\#{Rails.root}/extras")
14979 out, _err = capture_io { boot }
14980 get 'pages/:id', to: 'pages#show'
14981 get "/pages/foo"
14982 output = rails("-v")
14983 get "/" => "omg#index", as: :omg
14984 relative_url = "/hello"
14985 app_file "test/unit/foo_test.rb", <<-RUBY
14986 get '/posts'
14987 version = output.match(/(\d+)_create_users\.rb/)[1]
14988 app_file "db/schema.rb", ""
14989 app_file "db/schema.rb", <<-RUBY
14990 app_file "db/structure.sql", ""
14991 app_file "db/structure.sql", <<-SQL
14992 version_1 = output_1.match(/(\d+)_create_users\.rb/)[1]
14993 version_2 = output_2.match(/(\d+)_add_email_to_users\.rb/)[1]
14994 User.create! name: "Jon", email: "jon@doe.com"
14995 Expected: ["id", "name"]
14996 Actual: ["id", "name", "age"]
14997 app_file "lib/tasks/hooks.rake", <<-RUBY
14998 puts "before: " + has_user_table.to_s
14999 puts "after: " + has_user_table.to_s
15000 assert_not_equal 0, $?.to_i
15001 assert_equal 0, $?.to_i, result
15002 rails "test", "#{app_path}/test/#{name}", allow_failure: true
15003 assert_match "FooTest", rails("test:all", "--verbose")
15004 suites.each { |suite| create_test_file suite, "foo_#{suite}" }
15005 run_test_command("") .tap do |output|
15006 app_file "test/unit/chu_2_koi_test.rb", <<-RUBY
15007 Dir.chdir(app_path) { FileUtils.rm_r "test/#{directory}" }
15008 run_test_command("test\\\\models").tap do |output|
15009 pos_cases = {
15010 assert_match "PostTest:FirstFilter", output, "for #{cmd} (#{name})"
15011 assert_match "PostTest:SecondFilter", output, "for #{cmd} (#{name})"
15012 assert_match "2 runs, 2 assertions", output, "for #{cmd} (#{name})"
15013 test "foo" do
15014 app_file "config/boot.rb", <<-RUBY
15015 10.times do |n|
15016 matches = @test_output.match(/(\d+) runs, (\d+) assertions, (\d+) failures/)
15017 file = app_file "test/fail_test.rb", <<-RUBY
15018 @proc = ->{ }
15019 output = Dir.chdir(app_path) { `echo ".tables" | rails dbconsole` }
15020 rails "db:drop:all", "db:create:all", "db:migrate"
15021 output = Dir.chdir(app_path) { `bin/rake test TESTOPTS=-v` }
15022 filter_map { |line| JSON.parse(line) if line.start_with?("{") }
15023 output = Dir.chdir(app_path) { `bin/rake test TESTOPTS='-v --seed=1234'` }
15024 output = Dir.chdir(app_path) { `bin/rake db:migrate test:models TESTOPTS='-v' && echo ".tables" | rails dbconsole` }
15025 output = Dir.chdir(app_path) { `bin/rake test echo` }
15026 run_test_command("").tap do |output|
15027 output = Dir.chdir(app_path) { `bin/rake test` }
15028 output = Dir.chdir(app_path) { `DEFAULT_TEST_EXCLUDE="test/smoke/**/*_test.rb" bin/rake test` }
15029 rails "generate", "model", "user", "name:string"
15030 id: 1
15031 id: 2
15032 id: 3
15033 def create_fixture_test(path = :unit, name = "test")
15034 app_file "test/#{path}/#{name}_test.rb", <<-RUBY
15035 puts "\#{User.count} users (\#{__FILE__})"
15036 def create_test_file(path = :unit, name = "test", pass: true, print: true)
15037 puts "#{name.camelize}Test" if #{print}
15038 test "one" do
15039 WR2.write "y" # Allow two to run
15040 test "two" do
15041 WR1.write "x" # Allow one to run
15042 Q2 << "y"
15043 Q1 << "x"
15044 file_content = ERB.new(<<-ERB, trim_mode: "-").result_with_hash(with: with.to_s)
15045 parallelize(workers: 2, with: :<%= with %>, threshold: #{threshold})
15046 app_file "test/unit/env_test.rb", <<-RUBY
15047 rails "generate", "scaffold", "user", "name:string"
15048 get 'foo', to: 'foo#index', as: 'test_foo'
15049 app("test")
15050 File.open("#{app_path}/config/boot.rb", "w") do |f|
15051 pid = nil
15052 add_to_config(<<~CODE)
15053 app_file "app/models/user.rb", <<-MODEL
15054 assert_match "/rails runner", rails("runner", "--help")
15055 assert_match "42", rails("runner", "puts User.count")
15056 output = rails("runner", "puts ARGV.join(',')", "--foo", "a1", "-b", "a2", "a3", "--moo")
15057 assert_equal "--foo,a1,-b,a2,a3,--moo", output.chomp
15058 app_file "bin/count_users.rb", <<-SCRIPT
15059 assert_match "42", rails("runner", "bin/count_users.rb")
15060 assert_match "[]", Dir.chdir(app_path) {
15061 app_file "bin/dollar0.rb", <<-SCRIPT
15062 assert_match %w( a b ).to_s, rails("runner", "bin/program_name.rb", "a", "b")
15063 assert_match "42", Dir.chdir(app_path) { `cat bin/count_users.rb | bin/rails runner -` }
15064 assert_match "production", rails("runner", "-e", "production", "puts Rails.env")
15065 assert_match "production", rails("runner", "-e", "prod", "puts Rails.env")
15066 app_file "app/models/task.rb", <<-MODEL
15067 assert_match "42", rails("runner", "puts Task.count")
15068 get '*foo', to: 'foo#index'
15069 assert_welcome get("/")
15070 get "/", to: "foo#index"
15071 get "up" => "rails/health#show", as: :rails_health_check
15072 get "/up"
15073 render inline: "<%= foo_or_bar? %>"
15074 mount lambda { |env| [200, {}, [env["PATH_INFO"]]] }, at: "/blog"
15075 mount lambda { |env| [200, {}, [env["PATH_INFO"]]] }, at: "/blog", as: "my_blog"
15076 get '/foo' => 'foo#index'
15077 get 'admin/foo', to: 'admin/foo#index'
15078 get 'foo', to: 'foo#index'
15079 get "/admin/foo"
15080 add_to_config <<-R
15081 get '/win' => lambda { |e| [200, {'Content-Type'=>'text/plain'}, ['WIN']] }
15082 get "/win"
15083 app_file "config/routes.rb", <<-R
15084 get 'lol' => 'hello#index'
15085 app_file "app/models/user.rb", <<-RUBY
15086 @_model_name ||= ActiveModel::Name.new(self.class, nil, "User")
15087 get 'custom', to: 'foo#custom'
15088 get 'mapping', to: 'foo#mapping'
15089 direct(:custom) { "http://www.microsoft.com" }
15090 resolve("User") { "/profile" }
15091 get 'foo', to: 'foo#bar'
15092 get "/custom"
15093 direct(:custom) { "http://www.apple.com" }
15094 resolve("User") { "/dashboard" }
15095 get 'foo', to: 'foo#baz'
15096 ::InitializeRackApp = lambda { |env| [200, {}, ["InitializeRackApp"]] }
15097 root :to => 'foo#index'
15098 direct(:custom) { 'http://www.apple.com' }
15099 resolve('User') { '/profile' }
15100 get ':locale/foo', to: 'foo#index', as: 'foo'
15101 get 'users', to: 'foo#users', as: 'users'
15102 direct(:microsoft) { 'http://www.microsoft.com' }
15103 get "/en/foo"
15104 get ':locale/bar', to: 'bar#index', as: 'foo'
15105 direct(:apple) { 'http://www.apple.com' }
15106 get "/en/bar"
15107 get '/url', to: 'url#index'
15108 controller "url", <<-RUBY
15109 get "/url"
15110 get '/bar', to: 'foo#index', as: 'foo'
15111 <%= params[:id] %>
15112 get "/pages/foo.bar"
15113 render :show, formats: [:awesome], handlers: [:rubby]
15114 app_file "lib/tasks/app.rake", <<-RUBY
15115 backtrace = rails("boom", allow_failure: true).lines.grep(/:\d+:in /)
15116 rails "generate", "model", "product", "name:string"
15117 output = rails("db:test:prepare", "test")
15118 app_file "app/models/hello.rb", <<-RUBY
15119 puts "Answer: " + Hello::TEST.to_s
15120 output = rails("test")
15121 with_rails_env("test") { rails("db:migrate") }
15122 rails "generate", "model", "Product"
15123 rails "generate", "model", "Cart"
15124 output = rails("db:test:prepare", "--trace")
15125 rails "g", "model", "post", "title:string"
15126 output = rails("db:migrate:redo", "--trace")
15127 assert_no_match(/^\*\* Invoke db:structure:dump\s+$/, output)
15128 rails "generate", "model", "post", "title:string"
15129 assert File.exist?(File.join(app_path, "lib", "templates", "erb", dir))
15130 assert File.exist?(File.join(app_path, "lib", "templates", "rails", dir))
15131 app_file "template.rb", ""
15132 output = rails("db:drop")
15133 output = rails("db:create:#{namespace}")
15134 output = rails("db:drop:#{namespace}")
15135 if schema_format == "ruby"
15136 rails "db:migrate:#{database}", "db:schema:dump:#{database}"
15137 assert_equal "[]", animals_tables[]
15138 assert_equal "[]", ar_tables[]
15139 rails("db:migrate:#{name}")
15140 if name == "primary"
15141 rails("db:migrate:#{name}", "db:schema:dump:#{name}")
15142 output = rails("db:test:prepare:#{name}", "--trace")
15143 ar_tables = lambda { rails("runner", "-e", "test", "p ActiveRecord::Base.connection.tables").strip }
15144 output = rails("db:setup")
15145 output = rails("db:setup:#{namespace}")
15146 output = rails("db:reset")
15147 output = rails("db:reset:#{namespace}")
15148 down_output = rails("db:migrate:down:#{namespace}", "VERSION=#{version}")
15149 up_output = rails("db:migrate:up:#{namespace}", "VERSION=#{version}")
15150 down_output = rails("db:migrate:down", "VERSION=#{version}")
15151 up_output = rails("db:migrate:up", "VERSION=#{version}")
15152 if db_config.name == "primary"
15153 FileUtils.mv(Dir.glob("#{app_path}/db/migrate/**/*dogs.rb").first, "db/animals_migrate/") unless Dir.glob("#{app_path}/db/animals_migrate/**/*dogs.rb").first
15154 FileUtils.rm(Dir.glob("#{app_path}/db/migrate/**/*dogs.rb").first) if Dir.glob("#{app_path}/db/migrate/**/*dogs.rb").first
15155 app_path("/app/models/dog.rb") do |file_name|
15156 file = File.read("#{app_path}/app/models/dog.rb")
15157 File.open("#{app_path}/app/models/animals_base.rb", "w") do |file|
15158 file.write(<<~EOS)
15159 rails "generate", "model", "book", "title:string"
15160 rails "generate", "model", "dog", "name:string"
15161 rails("db:drop:all")
15162 dummy_task = <<~RUBY
15163 app_file("Rakefile", dummy_task, "a+")
15164 rails("db:migrate", "foo")
15165 entries = output.scan(/^== (\d+).+migrated/).map(&:first).map(&:to_i)
15166 assert_equal [1, 2, 3, 4], entries
15167 db_up_and_down "01"
15168 db_up_and_down "01", "primary"
15169 db_up_and_down "02", "animals"
15170 rails "generate", "model", "recipe", "title:string"
15171 assert_equal "12", cache_size_a[]
15172 assert_equal "0", cache_size_b[]
15173 primary_version = File.basename(Dir[File.join(app_path, "db", "migrate", "*.rb")].first).to_i
15174 animals_version = File.basename(Dir[File.join(app_path, "db", "animals_migrate", "*.rb")].first).to_i
15175 output = rails("db:seed")
15176 database: <%=
15177 %>
15178 <% else %>
15179 <% 5.times do |i| %>
15180 shard_<%= i %>:
15181 <<: *development
15182 File.open("test/models/book_test.rb", "w") do |file|
15183 test "a book" do
15184 assert_no_match(/add_column\(:users, :email, :string\)/, output)
15185 output = rails("db:migrate", "VERSION=0")
15186 assert_match(/add_column\(:users, :email, :string\)/, output)
15187 output = rails("db:rollback", "STEP=2")
15188 assert_match(/up\s+\d{14}\s+Create users/, output)
15189 assert_match(/up\s+\d{14}\s+Add email to users/, output)
15190 rails "db:rollback", "STEP=1"
15191 assert_match(/up\s+\d{3,}\s+Create users/, output)
15192 assert_match(/up\s+\d{3,}\s+Add email to users/, output)
15193 assert_match(/down\s+\d{3,}\s+Add email to users/, output)
15194 rails "db:rollback", "STEP=2"
15195 rails "db:forward", "STEP=2"
15196 assert_match(/up\s+\d{14}\s+\** NO FILE \**/, output)
15197 output = rails("db:migrate", "VERSION='0 '", allow_failure: true)
15198 output = rails("db:migrate", "VERSION=1.", allow_failure: true)
15199 output = rails("db:migrate", "VERSION=1_", allow_failure: true)
15200 assert_match(/down\s+\d{3,}\s+Create users/, output)
15201 output = rails("generate", "model", "author", "name:string")
15202 version = output =~ %r{[^/]+db/migrate/(\d+)_create_authors\.rb} && $1
15203 rails "db:migrate:up", "db:migrate:down", "VERSION=#{version}"
15204 rails "generate", "model", "reviews", "book_id:integer"
15205 assert_match(/execute\("SELECT 1"\)/, output)
15206 File.write("log/test.log", "test")
15207 File.write("log/dummy.log", "dummy")
15208 File.write("#{app_path}/config/database.yml", <<~YAML)
15209 <% 1 %>
15210 <<: *<%= ENV["DB"] || "sqlite" %>
15211 FileUtils.chmod("-w", "db")
15212 FileUtils.chmod("+w", "db")
15213 output = rails("db:drop:_unsafe", "--trace")
15214 assert_match(/up\s+\d{14}\s+Create books/, output)
15215 args = ["generate", "model", "book", "title:string"]
15216 rails "db:drop", "db:create"
15217 rails "runner", <<~RUBY
15218 t.virtual :pages_plus_1, type: :integer, as: "pages + 1", stored: true
15219 rails "generate", "model", "admin::book", "title:string"
15220 assert_equal '["posts"]', list_tables[]
15221 assert_equal '["posts", "comments", "schema_migrations", "ar_internal_metadata", "users"]', list_tables[]
15222 assert_equal columns, '["gooseid", "name"]'
15223 rails("db:prepare", "db:drop", "db:create")
15224 app_file "db/schema.rb", "# Not touched"
15225 destructive_tasks = ["db:drop:all", "db:drop", "db:purge:all", "db:truncate_all", "db:purge", "db:schema:load", "db:test:purge"]
15226 app, _ = Rack::Builder.parse_file("#{app_path}/config.ru")
15227 @app = rackup
15228 @logs ||= Rails.logger.logged(:info).join("
")
15229 get "/blah"
15230 head "/blah"
15231 post "/", _method: "put"
15232 assert_match 'Started PUT "/"', logs
15233 post "/", _method: "head"
15234 assert_match 'Started GET "/" for 1.2.3.4', logs
15235 rails("generate", "scaffold", "Pet", "name:string", "--database=animals")
15236 app_file "app/jobs/user_job.rb", <<-RUBY
15237 get "/", to: "users#index"
15238 assert_match(/pid='\d+'/, comment)
15239 assert_match(/\/\*action='index',controller='users',pid='\d+'\*\//, comment)
15240 assert_match(/\/\*action='index',namespaced_controller='users',pid='\d+'\*\//, comment)
15241 assert_match(/\/\*job='UserJob',pid='\d+'\*\//, comment)
15242 add_to_config "config.active_record.query_log_tags = [ { dynamic: ->(context) { context[:controller]&.dynamic_content } } ]"
15243 add_to_config "config.active_record.query_log_tags = [ { dynamic: ->(context) { context[:job]&.dynamic_content } } ]"
15244 render html: "<h1>Welcome to Rails!</h1>"
15245 [200, { "Content-Type" => "text/html" }, ["<p>Hello, World!</p>"]]
15246 [ name, id ].join("/")
15247 render [ Customer.new('david', 1), Customer.new('dingus', 2) ]
15248 <% cache customer do %>
15249 <%= customer.name %>
15250 config.root = "#{app_path}"
15251 app_path(*path).to_s
15252 @output = rails("generate", "scaffold", "Pet", "name:string", "--database=animals")
15253 output = rails("destroy", "scaffold", "Pet", "--database=animals")
15254 output = rails("generate", "scaffold", "Dog", "name:string", "--database=animals")
15255 get "foo"
15256 flash[:notice] = "notice"
15257 get "/?flash=true"
15258 session[:foo] = 1
15259 cookies[:foo] = '1'
15260 cipher = "aes-256-gcm"
15261 session[:foo] = session[:foo] + 1
15262 get '/dump_flash' => "test#dump_flash"
15263 request.session[:foo] = "bar"
15264 get "/read_session" => "test#read_session"
15265 get "/test_action" => "test#test_action"
15266 app.paths["public"] = File.join(rails_root, "public")
15267 app_file "public/foo.txt", "foo"
15268 def remote_ip(env = {})
15269 env = Rack::MockRequest.env_for("/").merge(env).merge!(
15270 endpoint = Proc.new do |e|
15271 [200, {}, ["Hello"]]
15272 assert_equal "1.1.1.1", remote_ip("REMOTE_ADDR" => "1.1.1.1")
15273 assert_equal "1.1.1.2", remote_ip("HTTP_CLIENT_IP" => "1.1.1.2")
15274 app.config.action_dispatch.trusted_proxies = [IPAddr.new("4.2.42.0/24"), /^4\.2\.42\.43$/, "4.2.42.44"]
15275 assert_equal "1.1.1.1",
15276 assert_equal "10.0.0.0",
15277 assert_match(/oops/, log, log)
15278 get "/foo", to: "foo#index"
15279 match "/406", to: "foo#not_acceptable", via: :all
15280 [404, { "Content-Type" => "text/plain" }, ["YOU FAILED"]]
15281 <% raise 'boooom' %>
15282 get "/foo?x[y]=1&x[y][][w]=2"
15283 malicious_url = "/foo?#{'[test]' * limit}=test"
15284 File.expand_path("#{app_path}/../new_app")
15285 expected = "Wed, 30 May 1984 19:43:31 GMT"
15286 get "/expires/expires_etag", { private: true }, { "HTTP_IF_NONE_MATCH" => etag }
15287 get "/rails/mailers", {}, { "REMOTE_ADDR" => "4.2.42.42" }
15288 mailer "notifier", <<-RUBY
15289 ["notifier", "confirm"].each do |keyword|
15290 text_template "#{keyword}/foo", <<-RUBY
15291 <p>Hello, World!</p>
15292 get "/rails/mailers", {}, { "SCRIPT_NAME" => "/my_app" }
15293 <p>Hello, <%= @name %>!</p>
15294 Hello, <%= @name %>!
15295 Notifier.foo(params[:name] || "World")
15296 assert_match %r[<p>Hello, Ruby!</p>], last_response.body
15297 <%= image_tag attachments['pixel.png'].url %>
15298 message = ::Mail.new do
15299 body '<p>Goodbye, World!</p>'
15300 mail to: "to@example.org", cc: "cc@example.com", bcc: "bcc@example.com"
15301 assert_match "<dd id=\"to\">to@example.org</dd>", last_response.body
15302 assert_match "<dd id=\"cc\">cc@example.com</dd>", last_response.body
15303 assert_match "<dd id=\"bcc\">bcc@example.com</dd>", last_response.body
15304 <%= @template %>
15305 app_file "app/models/post.rb", <<-MODEL
15306 p = Post.create(title: "omg")
15307 app_file "app/models/post.rb", <<-RUBY
15308 e = assert_raise(NameError) { User }
15309 e = assert_raise(NameError) { Post }
15310 get '/unload', to: lambda { |env| [200, {}, [ActiveRecord::Base.descendants.collect(&:to_s).sort.uniq.to_json]] }
15311 initial = [
15312 ].collect(&:to_s).sort
15313 get "/load"
15314 get "/unload"
15315 get '/c', to: lambda { |env| [200, {"Content-Type" => "text/plain"}, [User.counter.to_s]] }
15316 get "/c"
15317 $counter ||= 0
15318 get '/c', to: lambda { |env| User.name; [200, {"Content-Type" => "text/plain"}, [$counter.to_s]] }
15319 $counter += 1
15320 $counter ||= 1
15321 get '/c', to: lambda { |env| [200, {"Content-Type" => "text/plain"}, [$counter.to_s]] }
15322 get '/title', to: lambda { |env| [200, {"Content-Type" => "text/plain"}, [Post.new.title]] }
15323 get "/title"
15324 add_column :posts, :body, :text, default: "BODY"
15325 get "/body"
15326 self.response_body = ["OK"]
15327 puts "Error loading metal: \#{e.class} \#{e.message}"
15328 get "/:controller(/:action)"
15329 get "/omg/show"
15330 2.times do |i|
15331 events = []
15332 callback = ->(*_) { events << _ }
15333 assert_not_includes $:, "#{app_path}/app/models"
15334 app_file "lib/foo.rb", <<-RUBY
15335 assert_includes $:, "#{app_path}/lib"
15336 app_file "app/anything/foo.rb", <<-RUBY
15337 app_file "lib/zoo.rb", <<-ZOO
15338 app_file "lib/zoo/reptile_house.rb", <<-ZOO
15339 config.eager_load_paths << "#{app_path}/lib"
15340 app_file "config/another_locale.yml", "en:
foo: ~"
15341 app_file "app/models/foo.rb", <<-RUBY
15342 @foo = I18n.t(:foo)
15343 get "/i18n"
15344 fr:
15345 assert_fallbacks de: [:de, :en]
15346 assert_fallbacks de: [:de, :'en-US', :en]
15347 test "config.i18n.fallbacks.map = { :ca => :'es-ES' } initializes fallbacks with a mapping ca => es-ES" do
15348 I18n::Railtie.config.i18n.fallbacks.map = { ca: :'es-ES' }
15349 assert_fallbacks ca: [:ca, :"es-ES", :es]
15350 test "[shortcut] config.i18n.fallbacks = [{ :ca => :'es-ES' }] initializes fallbacks with a mapping ca => es-ES" do
15351 I18n::Railtie.config.i18n.fallbacks = [{ ca: :'es-ES' }]
15352 test "[shortcut] config.i18n.fallbacks = [:'en-US', { :ca => :'es-ES' }] initializes fallbacks with the given arguments" do
15353 I18n::Railtie.config.i18n.fallbacks = [:'en-US', { ca: :'es-ES' }]
15354 assert_fallbacks ca: [:ca, :"es-ES", :es, :'en-US', :en]
15355 I18n::Railtie.config.i18n.fallbacks = { ca: :en }
15356 assert_fallbacks ca: [:ca, :en]
15357 $order = []
15358 config.to_prepare { $order << :to_prepare }
15359 get "/foo", :to => lambda { |env| [200, {}, []] }, :as => :foo
15360 app_file "app/mailers/foo.rb", <<-RUBY
15361 render inline: "<%= from_app_helper -%> <%= from_foo_helper %>"
15362 render inline: "<%= respond_to?(:from_bar_helper) -%>"
15363 render json: { omg: 'omg' }
15364 assert_equal '{"omg":"omg"}', last_response.body
15365 add_to_config "config.encoding = '#{charset}'"
15366 assert_nothing_raised { [1, 2, 3].sample }
15367 Dir.chdir("#{app_path}/app") do
15368 app_file "app/models/a.rb", "A = 1"
15369 app_file "app/models/m.rb", "module M; end"
15370 app_file "app/models/post.rb", <<~RUBY
15371 def self.is_a?(_)
15372 def self.<(_)
15373 output = rails("help")
15374 output = rails("-h")
15375 output = rails("")
15376 output = gem_rails("")
15377 expected = { rails: { orm: :data_mapper, test_framework: :rspec, helper: false } }
15378 c.generators.aliases = { rails: { test_framework: "-w" } }
15379 expected = { rails: { test_framework: "-w" } }
15380 g.plugin aliases: { generator: "-g" },
15381 rails: { orm: :data_mapper },
15382 plugin: { generator: true },
15383 assert_equal({ plugin: { generator: "-g" } }, c.generators.aliases)
15384 rails "generate", "mailer", "notifier", "foo"
15385 output = rails("generate", "--help")
15386 output = rails("destroy", "--help")
15387 rails("generate", "model", "post", "title:string")
15388 output = rails("generate", "model", "post", "title:string", "body:string")
15389 output = rails("generate", "model", "post", "title:string", "body:string", "--skip-collision-check")
15390 output = rails("generate", "model", "post", "title:string", "body:string", "--force")
15391 expected = %w(
15392 File.open(model_file, "a") { |f| f.write("# Add comment to model") }
15393 rails("generate", "scaffold", "post", "title:string")
15394 Process.spawn("#{app_path}/bin/rails dbconsole #{options}", in: fd, out: fd, err: fd)
15395 resets { Time.zone = "UTC" }
15396 <%= Current.customer&.name || 'noone' %>,<%= Time.zone.name %>
15397 a = b = c = nil
15398 ActiveSupport::Reloader.to_complete { a = b = c = 1 }
15399 ActiveSupport::Reloader.to_complete { b = c = 2 }
15400 assert_equal "Once upon a time in a world...",
15401 app_file "app/models/post.rb", <<-CODE
15402 assert_output "> ", @primary
15403 in: @replica, out: @replica, err: @replica
15404 assert_output "> ", @primary, 30
15405 options = "--sandbox -- --singleline --nocolorize"
15406 write_prompt "Post.count", "=> 0"
15407 write_prompt "Post.count", "=> 1"
15408 output = `#{app_path}/bin/rails console --sandbox`
15409 options = "-e test -- --verbose --singleline --nocolorize"
15410 write_prompt "a = 1", "a = 1"
15411 super(@io)
15412 with_rails_env("") do
15413 with_rack_env("") do
15414 app_file "lib/my_logger.rb", <<-RUBY
15415 assert_changes -> { File.exist?(File.join(app_path, "db", "schema.rb")) }, from: false, to: true do
15416 Rails.env = "test"
15417 config.root = '#{new_app}'
15418 File.delete("#{app_path}/config.ru")
15419 Dir.chdir("#{app_path}") do
15420 config.filter_parameters += [ :foo, 'bar', lambda { |key, value|
15421 filters = [/foo/, :bar, "baz.qux"]
15422 render inline: "<%= csrf_meta_tags %>"
15423 render inline: "<%= begin; form_for(Post.new) {|f| f.text_field(:name)}; rescue => e; e.to_s; end %>"
15424 get "/posts"
15425 render inline: "<%= begin; form_with(model: Post.new) {|f| f.text_field(:name)}; rescue => e; e.to_s; end %>"
15426 assert_no_match(/id=('|")post_name('|")/, last_response.body)
15427 assert_match(/id=('|")post_name('|")/, last_response.body)
15428 def to_key; [1]; end
15429 render inline: "<%= begin; form_for(Post.new) {}; rescue => e; e.to_s; end %>"
15430 get "/posts/1"
15431 put "/posts/1", params
15432 script_name: "/bar",
15433 %w(title)
15434 post "/posts.json", '{ "title": "foo", "name": "bar" }', "CONTENT_TYPE" => "application/json"
15435 post "/posts", post: { "title" => "zomg" }
15436 post "/posts", post: { "title" => "zomg" }, format: "json"
15437 app "test"
15438 format.html { render plain: "HTML" }
15439 format.xml { render plain: "XML" }
15440 get "/", {}, { "HTTP_ACCEPT" => "application/xml" }
15441 get "/", { format: :xml }, { "HTTP_ACCEPT" => "application/xml" }
15442 session_options = { key: "_myapp_session", cookie_only: true }
15443 /#\s*(#{tag}):?\s*(.*)$/
15444 <%= Rails.env %>:
15445 foo: "bar"
15446 baz: 1
15447 foo: 0
15448 assert_equal({ foo: 0, bar: { baz: 1 } }, actual)
15449 assert_equal([ :foo, :bar ], actual.keys)
15450 assert_equal([ 0, baz: 1], actual.values)
15451 assert_equal({ foo: 0, bar: { baz: 1 } }, actual.to_h)
15452 assert_equal({ baz: 1 }, actual[:bar])
15453 - foo
15454 - bar
15455 - baz
15456 qux: 2
15457 key: <%= 'custom key' %>
15458 key: foo:
15459 set_custom_config <<~RUBY, "'custom', env: 'production'"
15460 key: 'walrus'
15461 YAML.stub :load, { "development" => { "key" => "value" } } do
15462 render inline: "<%= stylesheet_link_tag '/application.css' %>"
15463 smtp_settings = { domain: "example.com", open_timeout: 5, read_timeout: 5 }
15464 smtp_settings = { domain: "example.com" }
15465 email: {
15466 root: "#{Dir.tmpdir}/email",
15467 output = rails("routes", "-g", "active_storage")
15468 ActiveRecord::Base.configurations = { production: { db1: { adapter: "mysql2" } } }
15469 def new(app); self; end
15470 ActiveRecord::Base.configurations = { production: { db1: { adapter: "postgresql" } } }
15471 I18n.exception_handler = ->(exception, *) {
15472 I18n.backend.store_translations :en, i18n: { plural: { rule: lambda { |n| [0, 1].include?(n) ? :one : :other } } }
15473 I18n.backend.store_translations :en, pears: { pear: "pear", pears: "pears" }
15474 assert_equal "one or none", I18n.t(:apples, count: 0)
15475 assert_equal "pears", I18n.t(:pears, count: 0)
15476 rails "generate", "model", "article"
15477 File.write("log/test.log", "zomg!")
15478 output = `bin/setup 2>&1`
15479 output.sub!(/^Resolving dependencies\.\.\.
/, "")
15480 output.gsub!(/^The dependency .* will be unused .*\.
/, "")
15481 output.sub!(/^yarn install v.*?$/, "yarn install")
15482 output.sub!(/^\[.*?\] Resolving packages\.\.\.$/, "[1/4] Resolving packages...")
15483 output.sub!(/^Done in \d+\.\d+s\.
/, "Done in 0.00s.
")
15484 output.gsub!(/^warning:\s.*
/, "")
15485 rails ["assets:precompile", "--trace"]
15486 env.each { |k, v| ENV[k.to_s] = v }
15487 env.each_key { |k| ENV.delete k.to_s }
15488 app_file "app/assets/javascripts/demo.js.erb", "a = <%= image_path('rails.png').inspect %>;"
15489 get '*path', to: lambda { |env| [200, { "Content-Type" => "text/html" }, ["Not an asset"]] }
15490 assert_equal "alert();
", File.read(file)
15491 app_file "app/models/user.rb", <<-eoruby
15492 //= link_tree ../images
15493 images_should_compile = ["a.png", "happyface.png", "happy_face.png", "happy.face.png",
15494 images_should_compile = ["a-*.png", "happyface-*.png", "happy_face-*.png", "happy.face-*.png",
15495 app_file "app/assets/stylesheets/application.css.erb", "body { background: '<%= asset_path('rails.png') %>'; }"
15496 assert_match(/assets\/rails-([0-z]+)\.png/, File.read(file))
15497 assert_match(/production_assets\/rails-([0-z]+)\.png/, File.read(file))
15498 assert_match(/application-([0-z]+)\.css/, assets["assets"]["application.css"])
15499 assert_match(/rails-([0-z]+)\.png/, assets["assets"]["rails.png"])
15500 add_to_config "config.assets.prefix = '/x'"
15501 assert_match(/test-([0-z]+)\.css/, assets["assets"]["test.css"])
15502 get "/assets/#{asset_path}"
15503 app_file "app/assets/stylesheets/application.css.erb", "p { background-image: url(<%= asset_path('rails.png') %>) }"
15504 assert_match(/\/assets\/rails-([0-z]+)\.png/, File.read(file))
15505 app_file "app/assets/images/rails.png", "p { url: change }"
15506 app_file "app/assets/config/manifest.js", "//= link_tree ../images"
15507 assert asset_path = assets["assets"].find { |(k, _)| /.png/.match?(k) }[1]
15508 app_file "public/assets/application.css", "a { color: green; }"
15509 files = Dir["#{app_path}/public/assets/**/*"]
15510 assert_equal 0, files.length, "Expected no assets, but found #{files.join(', ')}"
15511 app_file "app/assets/javascripts/demo.js.erb", "<%= :alert %>();"
15512 get '/omg', :to => "omg#index"
15513 get "/omg"
15514 %w[app lib vendor].each do |dir|
15515 app_file "#{dir}/assets/#{dir}_test.erb", "testing"
15516 assert_match(/<script src="\/assets\/application-([0-z]+)\.js"><\/script>/, last_response.body)
15517 assert_no_match(/<script src="\/assets\/xmlhr-([0-z]+)\.js"><\/script>/, last_response.body)
15518 app_file "app/assets/javascripts/xmlhr.js.erb", "<%= Post.name %>"
15519 get "/posts", {}, { "HTTPS" => "off" }
15520 get "/posts", {}, { "HTTPS" => "on" }
15521 app_file "app/assets/javascripts/image_loader.js.erb", "var src='<%= image_path('rails.png') %>';"
15522 app_file "app/assets/javascripts/app.js.erb", "var src='<%= image_path('rails.png') %>';"
15523 assert_match "src='/sub/uri/assets/rails.png'", File.read(Dir["#{app_path}/public/assets/app-*.js"].first)
15524 app_file "app/assets/javascripts/xmlhr.js", "function f1() { alert(); }"
15525 get '/posts', :to => "posts#index"
15526 get '/posts', to: "posts#index"
15527 assert_match(/<script src="\/assets\/application(\.debug|\.self)?-([0-z]+)\.js(\?body=1)?"><\/script>/, last_response.body)
15528 cases = {
15529 app_file "app/views/posts/#{view_method}.html.erb", "<%= #{view_method} '#{contents}', skip_pipeline: true %>"
15530 assert_match(tag_match, body, "Expected `#{view_method}` to produce a match to #{tag_match}, but did not: #{body}")
15531 app_file "app/views/posts/#{view_method}.html.erb", "<%= #{view_method} '#{contents}', skip_pipeline: true %> "
15532 /\/assets\/application-.*.\.js/ => {},
15533 app_file "app/views/posts/version_#{index}.html.erb", "<%= asset_path('application.js', #{options_hash}) %>"
15534 assert_match(tag_match, body, "Expected `asset_path` with `#{options_hash}` to produce a match to #{tag_match}, but did not: #{body}")
15535 app_file "app/views/posts/#{view_method}.html.erb", "<%= #{ view_method } 'application.js' %>"
15536 assert_match(tag_match, body, "Expected `#{view_method}` to produce a match to #{ tag_match }, but did not: #{ body }")
15537 @loader ||= Class.new do
15538 @cwd = Dir.pwd
15539 ["bin", "script"].each do |script_dir|
15540 exe = "#{script_dir}/rails"
15541 write "foo/bar/#{exe}"
15542 write "foo/#{exe}", keyword
15543 Dir.chdir("foo/bar")
15544 config.root = __dir__
15545 def jruby_skip(message = "")
15546 [path, (begin_line..end_line)]
15547 @begins_to_ends = {}
15548 def on_def(begin_line, *)
15549 def first_arg(arg, *)
15550 parts << part
15551 opts.on("--warnings", "-w", "Run with Ruby warnings enabled") { }
15552 opts.on("-e", "--environment ENV", "Run tests in the ENV environment") { }
15553 env_index = argv.index("--environment") || argv.index("-e")
15554 w_index = argv.index("--warnings") || argv.index("-w")
15555 def run_from_rake(test_command, argv = [])
15556 success = system("rails", test_command, *argv, *Shellwords.split(ENV["TESTOPTS"] || ""))
15557 def run(argv = [])
15558 if filters.any? { |_, lines| lines.any? }
15559 path = path.tr("\\", "/")
15560 when /(:\d+)+$/.match?(path)
15561 file, *lines = path.split(":")
15562 filters << [ file, lines ]
15563 filters << [ path, [] ]
15564 arg.start_with?("/") && arg.end_with?("/")
15565 if filter.is_a?(String) && !filter.start_with?("test_")
15566 filter = filter.gsub(/\s+/, "_")
15567 def ===(method)
15568 @filters.any? { |filter| filter === method }
15569 elsif filter =~ %r%/(.*)/% # Regexp filtering copied from minitest.
15570 lines.map { |line| Filter.new(@runnable, file, line) }
15571 @line = line.to_i if line
15572 test_file == @file && test_range.include?(@line)
15573 if output_inline? && result.failure && (!result.skipped? || options[:verbose])
15574 file.sub(/^#{app_root}\/?/, "")
15575 @app_root ||= self.class.app_root ||
15576 options[:color] && io.respond_to?(:tty?) && io.tty?
15577 codes = { red: 31, green: 32, yellow: 33 }
15578 def run(reporter, options = {})
15579 ).tap { |arr|
15580 }.each do |task|
15581 @comments = []
15582 @comments << Annotation.new(lineno, $1, $2) if value =~ pattern
15583 parser.error? ? [] : parser.comments
15584 lineno = 0
15585 lineno += 1
15586 list << Annotation.new(lineno, $1, $2)
15587 @@directories ||= %w(app config db lib test)
15588 @@extensions ||= {}
15589 extensions[/\.(#{exts.join("|")})$/] = block
15590 register_extensions("builder", "rb", "rake", "ruby") do |tag|
15591 ParserExtractor.new(/#\s*(#{tag}):?\s*(.*)$/)
15592 register_extensions("yml", "yaml") do |tag|
15593 PatternExtractor.new(/#\s*(#{tag}):?\s*(.*)$/)
15594 register_extensions("css", "js") do |tag|
15595 PatternExtractor.new(/\/\/\s*(#{tag}):?\s*(.*)$/)
15596 PatternExtractor.new(/<%\s*#\s*(#{tag}):?\s*(.*?)\s*%>/)
15597 def to_s(options = {})
15598 s = +"[#{line.to_s.rjust(options[:indent])}] "
15599 s << "[#{tag}] " if options[:tag]
15600 s << text
15601 def self.enumerate(tag = nil, options = {})
15602 tag ||= Annotation.tags.join("|")
15603 @tag = tag
15604 dirs.inject({}) { |h, dir| h.update(find_in(dir)) }
15605 results = {}
15606 Dir.glob("#{dir}/*") do |item|
15607 options[:indent] = results.flat_map { |f, a| a.map(&:line) }.max.to_s.size
15608 puts "#{file}:"
15609 @cipher = "aes-128-gcm"
15610 secrets ||= {}
15611 FileUtils.mv("#{path}.tmp", path)
15612 @root.join("config", "secrets.yml.key")
15613 @root.join("config", "secrets.yml.enc").to_s
15614 if path.end_with?(".enc")
15615 tmp_file = "#{File.basename(path)}.#{Process.pid}"
15616 @@options ||= {}
15617 @@eager_load_namespaces ||= []
15618 @@watchable_files ||= []
15619 @@watchable_dirs ||= {}
15620 @@to_prepare_blocks ||= []
15621 super || @@options.key?(name.to_sym)
15622 if name.end_with?("=")
15623 @@options[:"#{name[0..-2]}"] = args.first
15624 @instance ||= new
15625 def <=>(other) # :nodoc:
15626 @@load_counter ||= 0
15627 @load_index = (@@load_counter += 1)
15628 var_name = "@#{type}"
15629 blocks << blk if blk
15630 def call_app(request, env) # :doc:
15631 sprintf('Started %s "%s" for %s at %s',
15632 @root = {}
15633 def []=(path, value)
15634 glob = self[path] ? self[path].glob : nil
15635 def add(path, options = {})
15636 @root[path] = Path.new(self, path, with, options)
15637 def [](path)
15638 values.tap(&:uniq!)
15639 filter_by(&:load_path?)
15640 paths - path.children.flat_map { |p| yield(p) ? [] : p.existent }
15641 }.uniq
15642 keys = @root.keys.find_all { |k|
15643 k.start_with?(@current) && k != @current
15644 def <<(path)
15645 @paths << path
15646 map do |p|
15647 $1.split(",") if @glob =~ /\{([\S]+)\}/
15648 if @glob && File.directory?(path)
15649 if !does_exist && File.symlink?(f)
15650 expanded.select { |d| File.directory?(d) }
15651 files = Dir.glob(@glob, base: path)
15652 files.map! { |file| File.join(path, file) }
15653 send_data @email.to_s, filename: "#{@email_action}.eml"
15654 def show_previews? # :doc:
15655 candidates = []
15656 params[:path].to_s.scan(%r{/|$}) { candidates << $` }
15657 if formats.any? { |f| @email.mime_type == f }
15658 def find_part(format) # :doc:
15659 options[:group] ||= :default
15660 @options[:group] == group || @options[:group] == :all
15661 select { |i| i.before == initializer.name || i.name == initializer.after }.each(&block)
15662 def initializer(name, opts = {}, &blk)
15663 layout -> { request.xhr? ? false : "application" }
15664 @page_title = "Routes"
15665 normalized_path = ("/" + query).squeeze("/")
15666 query_without_url_or_path_suffix = query.gsub(/(\w)(_path$)/, '\1').gsub(/(\w)(_url$)/, '\1')
15667 match ||= (query === route_wrapper.verb)
15668 map(&:first)
15669 class << self # :nodoc:
15670 value ||= yield
15671 value = value.join(", ") if value.is_a?(Array)
15672 info * "
"
15673 (+"<table>").tap do |table|
15674 table << %(<tr><td class="name">#{CGI.escapeHTML(name.to_s)}</td>)
15675 table << %(<td class="value">#{formatted_value}</td></tr>)
15676 table << "</table>"
15677 %(<html><body style="background-color: #{color}"></body></html>).html_safe
15678 def setup # :nodoc:
15679 args += ["--skip-bundle"] unless args.include?("--no-skip-bundle") || args.include?("--dev")
15680 args += ["--skip-bootsnap"] unless args.include?("--no-skip-bootsnap") || args.include?("--skip-bootsnap")
15681 def generator(args = default_arguments, options = {}, config = {})
15682 Dir.glob("#{dirname}/[0-9]*_*.rb").grep(/\d+_#{file_name}.rb$/).first
15683 assert content =~ /(\s+)def #{method}(\(.+\))?(.*?)
\1end/m, "Expected to have method #{method}"
15684 @_file_name ||= super.sub(/_test\z/i, "")
15685 @fixture_name ||=
15686 (namespace_dirs + [table_name]).join("_")
15687 attributes_hash.map { |k, v| "#{k}: #{v}" }.join(", ")
15688 ["#{name}", '"secret"']
15689 ["#{name}", "@#{singular_table_name}.#{name}"]
15690 attribute = attributes.find { |attr| attr.name == name }
15691 directory ".", "test"
15692 template "unit_test.rb", File.join("test/models", class_path, "#{file_name}_test.rb")
15693 @_file_name ||= super.sub(/_mailer\z/i, "")
15694 template "unit_test.rb", File.join("test/jobs", class_path, "#{file_name}_job_test.rb")
15695 @_file_name ||= super.sub(/_job\z/i, "")
15696 @controller_class_path = name.include?("/") ? name.split("/") : name.split("::")
15697 (controller_class_path + [controller_file_name]).map!(&:camelize).join("::")
15698 @controller_i18n_scope ||= controller_file_path.tr("/", ".")
15699 @orm_class ||= begin
15700 template "task.rb", File.join("lib/tasks", "#{file_name}.rake")
15701 params = others.map { |name| ":#{name}" }
15702 params += attachments.map { |name| "#{name}: []" }
15703 params.join(", ")
15704 if !options[:skip_git] && !options[:pretend]
15705 opts[:force] = force
15706 opts[:skip_git] = true
15707 opts[:dummy_app] = true
15708 if engine? && !api?
15709 insert_into_file "#{dummy_path}/config/application.rb", indent(<<~RUBY, 4), after: /^\s*config\.load_defaults.*
/
15710 bin_file = engine? ? "bin/rails.tt" : "bin/test.tt"
15711 entry = "
gem '#{name}', path: '#{relative_path}'"
15712 if !engine? || !with_dummy_app?
15713 build(:assets_manifest) if !api? && engine?
15714 @name ||= begin
15715 underscored.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
15716 underscored.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
15717 @namespaced_name ||= name.tr("-", "/")
15718 full? || mountable? || options[:engine]
15719 options[:skip_test].blank? || options[:dummy_path] != "test/dummy"
15720 @modules ||= namespaced_name.camelize.split("::")
15721 unwrapped_code = "#{unwrapped_code}".strip.gsub(/\s$
/, "")
15722 str = +"module #{mod}
"
15723 str << (content.present? ? "
end" : "end")
15724 @camelized ||= name.gsub(/\W/, "_").squeeze("_").camelize
15725 [">= #{gem_version}"]
15726 if /-\d/.match?(original_name)
15727 elsif /[^\w-]+/.match?(original_name)
15728 elsif /^\d/.match?(camelized)
15729 argument :attributes, type: :array, default: [], banner: "field[:type][:index] field[:type][:index]"
15730 log ""
15731 [ "", "# Ignore master key for decrypting credentials and more.", "/#{MASTER_KEY_PATH}", "" ].join("
")
15732 @_file_name ||= super.sub(/_helper\z/i, "")
15733 log "Adding #{key_path} to store the encryption key: #{key}"
15734 [ "", "/#{key_path}", "" ].join("
")
15735 opt[:database] ||= opt[:to]
15736 /(\b#{all_database_gem_names.join('\b|\b')}\b)/
15737 /^gem.*\b#{gem_name}\b.*/
15738 gem_name_and_version.map! { |segment| "\"#{segment}\"" }
15739 say ""
15740 routing_code = actions.map { |action| "get '#{file_name}/#{action}'" }.join("
")
15741 name.sub(/_?controller$/i, "")
15742 argument :reports, type: :array, default: ["before", "after"]
15743 def #{method}(*args, &block)
15744 @generator.send(:#{method}, *args, &block)
15745 insert_into_file "config/application.rb", %(require "sprockets/railtie"), after: /require\(["']rails\/all["']\)
/
15746 minimal: [
15747 api: [
15748 build(:db)
15749 def file(*args, &block)
15750 def after_bundle(&block) # :doc:
15751 @argv = argv
15752 File.expand_path("~/.railsrc")
15753 if ["--version", "-v"].include?(argument)
15754 if argument == "new"
15755 ["--help"] + argv.drop(1)
15756 if argv.find { |arg| arg == "--no-rc" }
15757 argv.reject { |arg| arg == "--no-rc" }
15758 railsrc(argv) { |rc_argv, rc| insert_railsrc_into_argv!(rc_argv, rc) }
15759 if (customrc = argv.index { |x| x.include?("--rc=") })
15760 fname = File.expand_path(argv[customrc].gsub(/--rc=/, ""))
15761 puts "Using #{extra_args.join(" ")} from #{railsrc}"
15762 argv.take(1) + extra_args + argv.drop(1)
15763 args[0] = args[0].dup if args[0].is_a?(String) && args[0].frozen?
15764 template(source + ".js", destination + ".js")
15765 def file_path # :doc:
15766 @file_path ||= (class_path + [file_name]).join("/")
15767 def class_path # :doc:
15768 def class_name # :doc:
15769 (class_path + [file_name]).map!(&:camelize).join("::")
15770 def human_name # :doc:
15771 def plural_name # :doc:
15772 def i18n_scope # :doc:
15773 @i18n_scope ||= file_path.tr("/", ".")
15774 def table_name # :doc:
15775 @table_name ||= begin
15776 (class_path + [base]).join("_")
15777 def index_helper(type: nil) # :doc:
15778 [plural_route_name, ("index" if uncountable?), type].compact.join("_")
15779 def show_helper(arg = "@#{singular_table_name}", type: :url) # :doc:
15780 def edit_helper(...) # :doc:
15781 def new_helper(type: :url) # :doc:
15782 def route_url # :doc:
15783 @route_url ||= controller_class_path.collect { |dname| "/" + dname }.join + "/" + plural_file_name
15784 @url_helper_prefix ||= (class_path + [file_name]).join("_")
15785 resource_name = "#{prefix}#{base_name}"
15786 @class_path = name.include?("/") ? name.split("/") : name.split("::")
15787 self.attributes = (attributes || []).map do |attr|
15788 names << "#{a.name}_type" if a.polymorphic?
15789 def self.check_class_collision(options = {}) # :doc:
15790 name != name.underscore &&
15791 Dir.glob("#{dirname}/[0-9]*_*.rb")
15792 migration_lookup_at(dirname).grep(/\d+_#{file_name}.rb$/).first
15793 numbered_destination = File.join(dir, ["%migration_number%", base].join("_"))
15794 if type && !valid_type?(type)
15795 raise Error, "Could not generate field '#{name}' with unknown type '#{type}'."
15796 attr_options[:index] = { unique: true }
15797 when /(string|text|binary|integer)\{(\d+)\}/
15798 return $1, limit: $2.to_i
15799 when /decimal\{(\d+)[,.-](\d+)\}/
15800 return :decimal, precision: $1.to_i, scale: $2.to_i
15801 when /(references|belongs_to)\{(.+)\}/
15802 type = $1
15803 provided_options = $2.split(/[,.-]/)
15804 options = Hash[provided_options.map { |opt| [opt.to_sym, true] }]
15805 return type, {}
15806 def initialize(name, type = nil, index_type = false, attr_options = {})
15807 @field_type ||= case type
15808 @default ||= case type
15809 %w(id type).map { |t| "#{name}_#{t}" }
15810 @column_name ||= reference? ? "#{name}_id" : name
15811 name.end_with?("_id")
15812 name == "password" && type == :digest
15813 type == :token
15814 type == :rich_text
15815 (+"").tap { |s| options_for_migration.each { |k, v| s << ", #{k}: #{v.inspect}" } }
15816 has_uniq_index? ? ", unique: true" : ""
15817 module Erb # :nodoc:
15818 view_base_path = File.join("app/views", class_path, file_name + "_mailer")
15819 [:text, :html]
15820 [name, file_format, handler].compact.join(".")
15821 @mysql_socket ||= [
15822 ].find { |f| File.exist?(f) } unless Gem.win_platform?
15823 class Error < Thor::Error # :nodoc:
15824 @desc ||= if usage_path
15825 @namespace ||= super.delete_suffix("_generator").sub(/:generators:/, ":")
15826 in_base = options.delete(:in) || base_name
15827 defaults = if options[:type] == :boolean
15828 { banner: "" }
15829 { desc: "#{name.to_s.humanize} to be invoked", banner: "NAME" }
15830 hooks[name] = [ in_base, as_hook ]
15831 def self.class_option(name, options = {}) # :nodoc:
15832 __dir__
15833 if base.name && !base.name.end_with?("Base")
15834 if base.name.include?("::")
15835 nesting = class_name.split("::")
15836 def indent(content, multiplier = 2) # :doc:
15837 spaces = " " * multiplier
15838 content.each_line.map { |line| line.blank? ? line : "#{spaces}#{line}" }.join
15839 def namespaced? # :doc:
15840 @namespace_dirs ||= namespace.name.split("::").map(&:underscore)
15841 @namespaced_path ||= namespace_dirs.join("/")
15842 def self.banner # :doc:
15843 def self.base_name # :doc:
15844 @base_name ||= if base = name.to_s.split("::").first
15845 @generator_name ||= if generator = name.to_s.split("::").last
15846 if generator_name && (c = config[generator_name.to_sym]) && c.key?(name)
15847 elsif base_name && (c = config[base_name.to_sym]) && c.key?(name)
15848 @hooks ||= from_superclass(:hooks, {})
15849 no_tasks {
15850 @shebang ||= begin
15851 paths = [
15852 source_root && File.expand_path("../USAGE", source_root),
15853 @app_const_base ||= app_name.gsub(/\W/, "_").squeeze("_").camelize
15854 @app_const ||= "#{app_const_base}::Application"
15855 if /^\d/.match?(app_const)
15856 class AppBase < Base # :nodoc:
15857 desc: "Name of the app"
15858 Rails.gem_version.prerelease? ? "main" : [*Rails.gem_version.segments.first(2), "stable"].join("-")
15859 @argv = [*positional_argv, *option_argv]
15860 @gem_filter = lambda { |gem| true }
15861 def builder # :doc:
15862 @builder ||= begin
15863 def build(meth, *args) # :doc:
15864 ->(&block) { option_reasons.each_key(&block) },
15865 ->(key, &block) { option_reasons[key]&.each(&block) }
15866 [name, reasons - revoked.to_a]
15867 option_reasons = {}
15868 (option_reasons[implication.to_s] ||= []) << reason.to_s
15869 due_to = reasons.map { |reason| "--#{reason.dasherize}" }.join(", ")
15870 def create_root # :doc:
15871 raise Error, "The template [#{rails_template}] could not be loaded. Error: #{e}"
15872 when /^https?:\/\//
15873 GemfileEntry.new "puma", ">= 5.0", "Use the Puma web server [https://github.com/puma/puma]"
15874 @required_railties ||= {
15875 %(require "rails/all")
15876 %(#{"# " if !required}require "#{railtie}")
15877 def comment_if(value) # :doc:
15878 question = "#{value}?"
15879 comment ? "# " : ""
15880 def keeps? # :doc:
15881 def sqlite3? # :doc:
15882 def skip_action_text? # :doc:
15883 (comment.gsub(/^/, "# ").chomp + "
" if comment),
15884 ("# " if commented_out),
15885 options.dev? || options.edge? || options.main?
15886 %(Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main"))
15887 patch = gem_version.segments[0, 3].join(".")
15888 ["~> #{patch}", ">= #{gem_version}"]
15889 using_node? and `yarn --version`[/\d+\.\d+\.\d+/]
15890 shebangs = Dir["bin/*"].map { |file| IO.read(file).lines.first }.join
15891 rubies = shebangs.scan(%r{#!/usr/bin/env (ruby.*)}).flatten.uniq
15892 binfixups = (rubies - %w(ruby)).map do |ruby|
15893 has_cr = Dir["bin/*"].any? { |file| IO.read(file).include? "\r" }
15894 if has_cr || (Gem.win_platform? && !binfixups.empty?)
15895 binfixups.unshift 'sed -i "s/\r$//g" bin/*'
15896 unless Dir["bin/*"].all? { |file| File.executable? file }
15897 when /^2\.7/
15898 bullseye = Gem.ruby_version >= Gem::Version.new("2.7.4")
15899 when /^3\.0/
15900 bullseye = Gem.ruby_version >= Gem::Version.new("3.0.2")
15901 packages << "python"
15902 if options[:css] && options[:css] != "tailwind" && options[:css] != "sass" && options[:javascript] == "importmap"
15903 if !using_node? && options[:css] == "tailwind"
15904 elsif !using_node? && options[:css] == "sass"
15905 GemfileEntry.new("redis", ">= 4.0.1", comment, {}, true)
15906 say_status :run, "bundle #{command}"
15907 full_command = %Q["#{Gem.ruby}" "#{bundle_command}" #{command}]
15908 !(options[:skip_bundle] || options[:pretend])
15909 Gem.rubygems_version >= Gem::Version.new("3.3.22") ? "windows" : "mswin mswin64 mingw x64_mingw"
15910 !(options[:skip_system_test] || options[:skip_test] || options[:api])
15911 !options[:skip_bootsnap] && !options[:dev] && !defined?(JRUBY_VERSION)
15912 git_source(:github) { |repo| "https://github.com/\#{repo}.git" }
15913 platforms = ["--add-platform=x86_64-linux"]
15914 git_version = `git --version`[/\d+\.\d+\.\d+/]
15915 if Gem::Version.new(git_version) >= Gem::Version.new("2.28.0")
15916 def initialize(*) # :nodoc:
15917 parts, message = [ quote(name) ], name.dup
15918 message << " (#{_versions.join(", ")})"
15919 str << "# #{comment_line}"
15920 str << "
"
15921 str << "gem #{parts.join(", ")}"
15922 str = names.map(&:inspect)
15923 str = str.join(", ")
15924 log :gemfile, "group #{str}"
15925 def github(repo, options = {}, &block)
15926 str = [quote(repo)]
15927 log :github, "github #{str}"
15928 def add_source(source, options = {}, &block)
15929 def environment(data = nil, options = {})
15930 data ||= yield if block_given?
15931 def git(commands = {})
15932 run "git #{commands}"
15933 run "git #{cmd} #{options}"
15934 rails_command "generate #{what} #{args.join(" ")}", options
15935 def rake(command, options = {})
15936 existing_line_pattern = /^[ ]{,#{existing_block_indent}}\S.+
?/
15937 empty_block_pattern = /(#{namespace_pattern})((?:\s*end
){1,#{namespace.size}})/
15938 ending.sub!(/\A\s*end
/, "") while !ending.empty? && beginning.sub!(/^[ ]*namespace .+ do
\s*\z/, "")
15939 def log(*args) # :doc:
15940 args << (behavior == :invoke ? :green : :red)
15941 def execute_command(executor, command, options = {}) # :doc:
15942 sudo = options[:sudo] && !Gem.win_platform? ? "sudo " : ""
15943 config = {
15944 in_root { run("#{sudo}#{Shellwords.escape Gem.ruby} bin/#{executor} #{command}", config) }
15945 def quote(value) # :doc:
15946 return value.map do |k, v|
15947 return "#{value}
" unless value.is_a?(String)
15948 gsub_file path, /
?\z/, options do |match|
15949 match.end_with?("
") ? "" : "
#{str}
"
15950 cummulative_margin = "\\#{i + 1}[ ]{2}"
15951 blank_or_indented_line = "^[ ]*
|^#{cummulative_margin}.*
"
15952 /^([ ]*).+\.routes\.draw do[ ]*
#{pattern}/
15953 rails: {
15954 actions: "-a",
15955 orm: "-o",
15956 javascripts: ["-j", "--js"],
15957 stylesheets: "-y",
15958 template_engine: "-e",
15959 test_framework: "-t"
15960 test_unit: {
15961 @templates_path ||= []
15962 @after_generate_callbacks ||= []
15963 @fallbacks ||= {}
15964 hide_namespaces "assets", "helper", "css", "js"
15965 api: true,
15966 options[:mailer] ||= {}
15967 options[:mailer][:template_engine] ||= :erb
15968 sorted_groups.each { |b, n| print_list(b, n) }
15969 groups = Hash.new { |h, k| h[k] = [] }
15970 base = namespace.split(":").first
15971 rails.map! { |n| n.delete_prefix("rails:") }
15972 [[ "rails", rails ]] + groups.sort.to_a
15973 def find_by_namespace(name, base = nil, context = nil) # :nodoc:
15974 lookups = []
15975 lookups << "#{name}:#{context}" if context
15976 unless name.to_s.include?(?:)
15977 lookups << "#{name}:#{name}"
15978 lookups << "rails:#{name}"
15979 lookups << "#{name}"
15980 def invoke(namespace, args = ARGV, config = {})
15981 names = namespace.to_s.split(":")
15982 if klass = find_by_namespace(names.pop, names.any? && names.join(":"))
15983 args << "--help" if args.empty? && klass.arguments.any?(&:required?)
15984 (@@generated_files ||= []) << file
15985 @command_type ||= "generator"
15986 @file_lookup_paths ||= [ "{#{lookup_paths.join(',')}}", "**", "*_generator.rb" ]
15987 @@generated_files = []
15988 { engine: true }, { destination_root: ENGINE_ROOT }
15989 @_all ||= ::Rails::Railtie.subclasses.map(&:instance) +
15990 def each(*args, &block)
15991 _all.each(*args, &block)
15992 def -(others)
15993 _all - others
15994 @paths ||= begin
15995 glob: "{*,*/concerns}",
15996 paths.add "config/initializers", glob: "**/*.rb"
15997 call_stack = caller_locations.map { |l| l.absolute_path || l.path }
15998 File.dirname(call_stack.detect { |p| !p.match?(%r[railties[\w.-]*/lib/rails|rack[\w.-]*/lib/rack]) })
15999 @endpoint ||= nil
16000 define_method(:table_name_prefix) { "#{name}_" }
16001 class_eval "def use_relative_model_naming?; true; end", __FILE__, __LINE__
16002 @helpers ||= begin
16003 @env_config ||= {}
16004 if !isolated? || (app == self)
16005 def routes? # :nodoc:
16006 def run_tasks_blocks(*) # :nodoc:
16007 paths["lib/tasks"].existent.sort.each { |ext| load(ext) }
16008 while root_path && File.directory?(root_path) && !File.exist?("#{root_path}/#{flag}")
16009 root_path = parent != root_path && parent
16010 root = File.exist?("#{root_path}/#{flag}") ? root_path : default
16011 @_all_autoload_paths ||= begin
16012 @_all_load_paths ||= begin
16013 elsif caching == false && File.exist?(FILE)
16014 def insert_before(...)
16015 @operations << -> middleware { middleware.insert_before(...) }
16016 def insert_after(...)
16017 @operations << -> middleware { middleware.insert_after(...) }
16018 def swap(...)
16019 @operations << -> middleware { middleware.swap(...) }
16020 def use(...)
16021 @operations << -> middleware { middleware.use(...) }
16022 def delete(...)
16023 @delete_operations << -> middleware { middleware.delete(...) }
16024 def move_before(...)
16025 @delete_operations << -> middleware { middleware.move_before(...) }
16026 def move_after(...)
16027 @delete_operations << -> middleware { middleware.move_after(...) }
16028 def unshift(...)
16029 @operations << -> middleware { middleware.unshift(...) }
16030 def +(other) # :nodoc:
16031 @aliases = Hash.new { |h, k| h[k] = {} }
16032 @options = Hash.new { |h, k| h[k] = {} }
16033 @fallbacks = {}
16034 @templates = []
16035 @hidden_namespaces = []
16036 method = method.to_s.delete_suffix("=").to_sym
16037 if method == :rails
16038 if method == :rails || args.first.is_a?(Hash)
16039 @controller_class && @controller_class.try(:view_paths).to_a.flat_map { |path| Dir["#{view_path(path)}.*"] }.none?
16040 @routes ||= begin
16041 def help(command_name = nil, *)
16042 if command_name == "test"
16043 Minitest.run(%w(--help))
16044 desc "test [PATHS...]", "Run tests except system tests"
16045 $LOAD_PATH << Rails::Command.root.join("test").to_s
16046 desc name, "Run tests in test/#{name}"
16047 perform("test/#{name}", *args)
16048 perform("test/**/*_test.rb", *args)
16049 perform("test/models", "test/helpers", "test/unit", *args)
16050 Rails::Command::RakeCommand.perform("test:prepare", [], {})
16051 @default_options = options || {}
16052 trap(:INT) { exit }
16053 Hash.new([])
16054 server.to_s == "Rack::Handler::Puma"
16055 class_option :port, aliases: "-p", type: :numeric,
16056 class_option :binding, aliases: "-b", type: :string,
16057 class_option :config, aliases: "-c", type: :string, default: "config.ru",
16058 class_option :using, aliases: "-u", type: :string,
16059 class_option :pid, aliases: "-P", type: :string,
16060 @original_options = local_options - %w( --restart )
16061 after_stop_callback = -> { say "Exiting" unless options[:daemon] }
16062 user_flag = {}
16063 if command.start_with?("--")
16064 option = command.split("=")[0]
16065 elsif command =~ /\A(-.)/
16066 if option.aliases.any? { |name| user_flag[name] } || user_flag["--#{option.name}"]
16067 name = :Port
16068 name = :Host
16069 default_host = environment == "development" ? "localhost" : "0.0.0.0"
16070 gem "#{server}"
16071 desc "runner [<'Some.ruby(code)'> | <filename.rb> | -]",
16072 if code_or_file == "-"
16073 error "Run '#{self.class.executable} -h' for help."
16074 error ""
16075 code_or_file.ends_with?(".rb")
16076 rake.init("rails", [task, *args])
16077 rake_tasks.map { |t| [ t.name_with_args, t.comment ] }
16078 self.bin = "rails"
16079 run_plugin_generator %w( --help )
16080 def self.banner(*) # :nodoc:
16081 class_option :rc, type: :string, default: File.join("~", ".railsrc"),
16082 plugin_args << "--help" unless type == "new"
16083 extra_args = File.read(railsrc).split(/
+/).flat_map(&:split)
16084 say "Using #{extra_args.join(" ")} from #{railsrc}"
16085 tag = (annotations.length > 1)
16086 Rails::Command.invoke :application, [ "--help" ]
16087 say "Type 'rails' for help."
16088 def help(*)
16089 class_option :key, aliases: "-k", type: :string,
16090 def edit(*)
16091 def show(*)
16092 @content_path ||= args[0]
16093 say "WARNING: #{error.message}", :red
16094 missing_db = database ? "'#{database}' database is not" : "No databases are"
16095 def find_cmd_and_exec(commands, *args) # :doc:
16096 class_option :mode, enum: %w( html list line column ), type: :string,
16097 class_option :database, aliases: "--db", type: :string,
16098 say "Editing #{content_path}..."
16099 available_environments.find { |env| path.end_with?("#{env}.yml.enc") }
16100 def initialize(app, options = {})
16101 def initialize(args = [], local_options = {}, config = {})
16102 console_options = []
16103 aliases = {
16104 desc: "The environment to run `#{self.command_name}` in (e.g. test / development / production)."
16105 def initialize(...)
16106 Dir["config/environments/*.rb"].map { |filename| File.basename(filename, ".*") }
16107 @subclasses ||= []
16108 puts "#{base.camelize}:"
16109 path = "#{base}/#{raw_path}_#{command_type}"
16110 warn "[WARNING] Could not load #{command_type} #{path.inspect}. Error: #{e.message}.
#{e.backtrace.join("
")}"
16111 path = path.delete_prefix("#{base}/")
16112 pieces = namespace.split(":")
16113 path = pieces.join("/")
16114 paths << "#{path}/#{pieces.last}"
16115 def exit_on_failure? # :nodoc:
16116 def desc(usage = nil, description = nil, options = {})
16117 @namespace ||= super.chomp("_command").sub(/:command:/, ":")
16118 command, args = "help", [command]
16119 def banner(command = nil, *)
16120 command.formatted_usage(self).gsub(/^#{namespace}:(\w+)/) { executable($1) }
16121 def help(shell, *) # :nodoc:
16122 @command_name ||= if command = name.to_s.split("::").last
16123 @class_usage ||= ERB.new(File.read(usage_path), trim_mode: "-").result(binding)
16124 if meth == "perform"
16125 @usage ||= meth
16126 prefix.concat([basename, name.to_s].uniq).join(":")
16127 path = File.join("../commands", *namespace.delete_prefix("rails:").split(":"), path)
16128 path = File.expand_path(path, __dir__)
16129 def invoke_command(command, *) # :nodoc:
16130 Dir.chdir(File.expand_path("../..", APP_PATH)) unless File.exist?(File.expand_path("config.ru"))
16131 @hidden_commands ||= []
16132 def invoke(full_namespace, args = [], **config)
16133 args = ["--help"] if rails_new_with_no_path?(args)
16134 command.perform("help", [], config)
16135 lookups = [ namespace ]
16136 Pathname.new(File.expand_path("../..", APP_PATH))
16137 args == ["new"]
16138 when /^(.+):(\w+)$/
16139 [$1, $2]
16140 ["help", "help"]
16141 ["help", "help_extended"]
16142 ["version", "version"]
16143 args = ["--describe", task] if HELP_MAPPINGS.include?(args[0])
16144 @command_type ||= "command"
16145 @file_lookup_paths ||= [ "{#{lookup_paths.join(',')}}", "**", "*_command.rb" ]
16146 rb: {
16147 line_comment: /^\s*#/,
16148 end_block_comment: /^=end/,
16149 class: /^\s*class\s+[_A-Z]/,
16150 method: /^\s*def\s+[_a-z]/,
16151 erb: {
16152 line_comment: %r{((^\s*<%#.*%>)|(<!--.*-->))},
16153 css: {
16154 line_comment: %r{^\s*/\*.*\*/},
16155 scss: {
16156 line_comment: %r{((^\s*/\*.*\*/)|(^\s*//))},
16157 js: {
16158 line_comment: %r{^\s*//},
16159 begin_block_comment: %r{^\s*/\*},
16160 end_block_comment: %r{\*/},
16161 method: /function(\s+[_a-zA-Z][\da-zA-Z]*)?\s*\(/,
16162 coffee: {
16163 begin_block_comment: /^\s*###/,
16164 end_block_comment: /^\s*###/,
16165 method: /[-=]>/,
16166 def initialize(lines = 0, code_lines = 0, classes = 0, methods = 0)
16167 @lines += 1
16168 if !line.match?(/^\s*$/) && (patterns[:line_comment].nil? || !line.match?(patterns[:line_comment]))
16169 @code_lines += 1
16170 if file_path.end_with? "_test.rb"
16171 def calculate_directory_statistics(directory, pattern = /^(?!\.).*?\.(rb|js|ts|css|scss|coffee|rake|erb)$/)
16172 path = "#{directory}/#{file_name}"
16173 if File.directory?(path) && !file_name.start_with?(".")
16174 code_loc = 0
16175 @statistics.each { |k, v| code_loc += v.code_lines unless TEST_TYPES.include? k }
16176 test_loc = 0
16177 @statistics.each { |k, v| test_loc += v.code_lines if TEST_TYPES.include? k }
16178 print " | #{v.rjust(width_for(k))}"
16179 print "+----------------------"
16180 print "+#{'-' * (width_for(k) + 2)}"
16181 puts "+-----+-------+"
16182 print "| #{name.ljust(20)} "
16183 print "| #{statistics.send(k).to_s.rjust(width_for(k))} "
16184 puts "| #{m_over_c.to_s.rjust(3)} | #{loc_over_m.to_s.rjust(5)} |"
16185 Signal.trap("INT") { puts; exit(1) }
16186 @root = "#{Rails.root}/"
16187 line.start_with?(@root) ? line.from(@root.size) : line
16188 @overrides = {}
16189 @main.tag = "rails.main"
16190 @once.tag = "rails.once"
16191 each { |loader| loader.logger = logger }
16192 each(&:log!)
16193 @route_sets = []
16194 @external_routes = []
16195 @updater ||= begin
16196 dirs = @external_routes.each_with_object({}) do |dir, hash|
16197 hash[dir.to_s] = %w(rb)
16198 paths.each { |path| load(path) }
16199 @run_after_load_paths ||= -> { }
16200 app_name = app.class.name ? app.railtie_name.chomp("_application") : ""
16201 get "/" => "rails/welcome#index", internal: true
16202 metastore: "rails:/",
16203 entitystore: "rails:/",
16204 @hosts = []
16205 when "5.0"
16206 self.ssl_options = { hsts: { subdomains: true } }
16207 when "5.1"
16208 when "5.2"
16209 when "6.0"
16210 when "6.1"
16211 when "7.0"
16212 when "7.1"
16213 self.log_file_size = 100 * 1024 * 1024
16214 if config.is_a?(Hash) && config.values.all?(Hash)
16215 if shared.is_a?(Hash) && shared.values.all?(Hash)
16216 @session_options = options || {}
16217 path = paths["log"].first
16218 f = File.open path, "a"
16219 if method.end_with?("=")
16220 @configurations[:"#{method[0..-2]}"] = args.first
16221 :routes, :helpers, :app_env_config, :secrets] # :nodoc:
16222 def run_load_hooks! # :nodoc:
16223 yaml = name.is_a?(Pathname) ? name : Pathname.new("#{paths["config"].existent.first}/#{name}.yml")
16224 config = {} if config.nil? && shared.is_a?(Hash)
16225 if config.is_a?(Hash) && shared.is_a?(Hash)
16226 @app_env_config ||= super.merge(
16227 def initializer(name, opts = {}, &block)
16228 def self.add_lib_to_load_path!(root) # :nodoc:
16229 path = File.join root, "lib"
16230 if File.exist?(path) && !$LOAD_PATH.include?(path)
16231 File.file?(path) ? files << path.to_s : dirs[path.to_s] = [:rb]
16232 [files, dirs]
16233 def initialize!(group = :default) # :nodoc:
16234 def config # :nodoc:
16235 @secrets ||= begin
16236 def to_app # :nodoc:
16237 railties.each { |r| r.run_tasks_blocks(app) }
16238 railties.each { |r| r.run_runner_blocks(app) }
16239 railties.each { |r| r.run_server_blocks(app) }
16240 if railtie == :main_app
16241 all = (railties - order)
16242 if r == self
16243 Dir.chdir("..")
16244 include: %w(
16245 lib/active_support/**/*.rb
16246 lib/active_record/**/*.rb
16247 lib/active_model/**/*.rb
16248 lib/action_view/**/*.rb
16249 lib/action_mailer/**/*.rb
16250 lib/active_job/**/*.rb
16251 lib/action_cable/**/*.rb
16252 app/**/active_storage/**/*.rb
16253 lib/active_storage/**/*.rb
16254 app/**/action_mailbox/**/*.rb
16255 lib/action_mailbox/**/*.rb
16256 app/**/action_text/**/*.rb
16257 lib/action_text/**/*.rb
16258 lib/**/*.rb
16259 exclude: %w(
16260 rdoc_files.include("#{cdr}/#{pattern}")
16261 rdoc_files.exclude("#{cdr}/#{pattern}")
16262 if Dir.exist?(api_dir) && !ENV["ALL"]
16263 options << "-g" # link to GitHub, SDoc flag
16264 super.unshift([ "Core extensions", "", "", build_core_ext_subtree(core_exts, visited) ])
16265 [ klass.name, klass.document_self_or_methods ? klass.path : "", "",
16266 klass.name != "ActiveSupport" && klass.in_files.any? { |file| file.absolute_name.include?("core_ext") }
16267 ).each do |railtie|
16268 groups.concat hash.map { |k, v| k if v.map(&:to_s).include?(env) }
16269 opts.on("-b", "--backtrace", "Show the complete backtrace") do
16270 opts.on("-f", "--fail-fast", "Abort test run on first failure or error") do
16271 opts.on("-c", "--[no-]color", "Enable color in the output") do |value|
16272 errors_on_guides = {}
16273 puts "
Could not validate #{f} because of #{e}"
16274 print "E"
16275 guides = Dir["./output/*.html"]
16276 ENV.key?("ONLY") ? select_only(guides) : guides
16277 prefixes = ENV["ONLY"].split(",").map(&:strip)
16278 prefixes.any? { |p| guide.start_with?("./output/#{p}") }
16279 if error_list.size == 0
16280 error_summary = error_detail = ""
16281 if %r{https?://api\.rubyonrails\.org}.match?(url)
16282 %(<a href="#{api_link(url)}">#{content}</a>)
16283 %(<a href="#{url}" title="#{title}">#{content}</a>)
16284 %(<a href="#{url}">#{content}</a>)
16285 header_with_id = text.scan(/(.*){#(.*)}/)
16286 %(<h#{header_level} id="#{header_with_id[0][1].strip}">#{header_with_id[0][0].strip}</h#{header_level}>)
16287 %(<h#{header_level}>#{text}</h#{header_level}>)
16288 if text =~ %r{^NOTE:\s+Defined\s+in\s+<code>(.*?)</code>\.?$}
16289 %(<div class="note"><p>Defined in <code><a href="#{github_file_url($1)}">#{$1}</a></code>.</p></div>)
16290 elsif text =~ /^\[<sup>(\d+)\]:<\/sup> (.+)$/
16291 linkback = %(<a href="#footnote-#{$1}-ref"><sup>#{$1}</sup></a>)
16292 %(<p class="footnote" id="footnote-#{$1}">#{linkback} #{$2}</p>)
16293 text.gsub(/\[<sup>(\d+)\]<\/sup>/i) do
16294 %(<sup class="footnote" id="footnote-#{$1}-ref">) +
16295 %(<a href="#footnote-#{$1}">#{$1}</a></sup>)
16296 ::Rouge::Lexer.find(code_type) ? code_type : "plaintext"
16297 /^\$ /
16298 when "irb"
16299 /^irb.*?> /
16300 css_class = \
16301 %(<div class="#{css_class}"><p>#{$2.strip}</p></div>)
16302 tree = version || edge
16303 root = file_path[%r{(\w+)/}, 1]
16304 path = \
16305 when /\A(action|active)_/
16306 if %r{https?://api\.rubyonrails\.org/v\d+\.}.match?(url)
16307 url.sub("api", "edgeapi")
16308 url.sub(/(?<=\.org)/, "/#{version}")
16309 @raw_body = body
16310 if @node_ids[dom_id]
16311 if @node_ids[dom_id].size > 1
16312 new_node_id = "#{duplicate_nodes[-2][:id]}-#{duplicate_nodes.last[:id]}"
16313 dom_id = "#{nodes[-2][:id]}-#{dom_id}"
16314 @node_ids[dom_id] = nodes
16315 escaped_chars = Regexp.escape('\\/`*_{}[]()#+-.!:,;|&<>^~=\'"')
16316 text.downcase.gsub(/\?/, "-questionmark")
16317 .gsub(/!/, "-bang")
16318 .gsub(/[#{escaped_chars}]+/, " ").strip
16319 .gsub(/\s+/, "-")
16320 if /^-{40,}$/.match?(@raw_body)
16321 @raw_header, _, @raw_body = @raw_body.partition(/^-{40,}$/).map(&:strip)
16322 @headings_for_index = []
16323 hierarchy = []
16324 if /^h[3-6]$/.match?(node.name)
16325 when "h3"
16326 @headings_for_index << [1, node, node.inner_html]
16327 when "h4"
16328 hierarchy = hierarchy[0, 1] + [node]
16329 @headings_for_index << [2, node, node.inner_html]
16330 when "h5"
16331 hierarchy = hierarchy[0, 2] + [node]
16332 when "h6"
16333 hierarchy = hierarchy[0, 3] + [node]
16334 node[:id] = dom_id(hierarchy) unless node[:id]
16335 node.inner_html = "#{node_index(hierarchy)} #{node.inner_html}"
16336 doc.css("h3, h4, h5, h6").each do |node|
16337 node.inner_html = "<a class='anchorlink' href='##{node[:id]}'>#{node.inner_html}</a>"
16338 raw_index = ""
16339 if level == 1
16340 raw_index += "1. [#{label}](##{node[:id]})
"
16341 elsif level == 2
16342 doc.at("ol")[:class] = "chapters"
16343 @index = <<-INDEX.html_safe
16344 <div id="subCol">
16345 <h3 class="chapter"><img src="images/chapters_icon.gif" alt="" />Chapters</h3>
16346 @index_counter[2] = @index_counter[3] = @index_counter[4] = 0
16347 @index_counter[3] = @index_counter[4] = 0
16348 @index_counter[4] = 0
16349 @view.content_for(:page_title) { @title }
16350 def guide(name, url, options = {}, &block)
16351 link = content_tag(:a, href: url) { name }
16352 result << content_tag(:dd, "Work in progress", class: "work-in-progress")
16353 result << content_tag(:dd, capture(&block))
16354 @documents_by_section ||= YAML.load_file(File.expand_path("../source/#{@language ? @language + '/' : ''}documents.yaml", __dir__))
16355 base_path = File.expand_path("../assets", __dir__)
16356 images_path = File.join(base_path, "images/**/*")
16357 @all_images = Dir.glob(images_path).reject { |f| File.directory?(f) }.map { |item|
16358 elsif position == "L"
16359 c = capture(&block)
16360 @direction = direction || "ltr"
16361 epub_filename = +"ruby_on_rails_guides_#{@version || @edge[0, 7]}"
16362 epub_filename << ".#{@language}" if @language
16363 epub_filename << ".epub"
16364 @guides_dir = File.expand_path("..", __dir__)
16365 @source_dir += "/#{@language}" if @language
16366 @output_dir += "/#{@language}" if @language
16367 Dir.entries("#{@source_dir}/epub").grep(GUIDES_RE).map do |entry|
16368 guides << "epub/#{entry}"
16369 prefixes = @only.split(",").map(&:strip)
16370 FileUtils.cp_r(Dir.glob("#{@guides_dir}/assets/*"), @output_dir)
16371 if guide.end_with?(".md")
16372 guide.sub(/md\z/, "html")
16373 @all || !File.exist?(fout) || File.mtime(fout) < File.mtime(fin)
16374 layout = @epub ? "epub/layout" : "layout"
16375 [@source_dir],
16376 if guide =~ /\.(\w+)\.erb$/
16377 result = view.render(layout: layout, formats: [$1.to_sym], template: $`)
16378 body = File.read("#{@source_dir}/#{guide}")
16379 File.open(output_path, "w") do |f|
16380 html.scan(/<h\d\s+id="([^"]+)/).flatten.each do |anchor|
16381 anchors += Set.new(html.scan(/<p\s+class="footnote"\s+id="([^"]+)/).flatten)
16382 anchors += Set.new(html.scan(/<sup\s+class="footnote"\s+id="([^"]+)/).flatten)
16383 html.scan(/<a\s+href="#([^"]+)/).flatten.each do |fragment_identifier|
16384 puts "*** BROKEN LINK: ##{fragment_identifier}, perhaps you meant ##{guess}."
16385 |epub|
16386 entries = Dir.entries(output_dir) - %w[. ..]
16387 entries.reject! { |item| File.extname(item) == ".epub" }
16388 zipfile_path = path == "" ? e : File.join(path, e)
16389 subdir = Dir.entries(disk_file_path) - %w[. ..]
16390 Nokogiri::XML(toc).xpath("//ncx:content", "ncx" => "http://www.daisy.org/z3986/2005/ncx/")
16391 output_dir = File.absolute_path(File.join(output_dir, ".."))
16392 puts "=> Using output dir: #{output_dir}"
16393 name.match?(/\A\d/)
16394 puts "=> Using book dir: #{book_dir}"
16395 toc = File.read("toc.ncx")
16396 toc_html = File.read("toc.html")
16397 doc = open_toc_doc(toc)
16398 doc.each do |c|
16399 name = c[:src]
16400 FileUtils.mv(name, "rails_#{name}")
16401 toc.gsub!(name, "rails_#{name}")
16402 toc_html.gsub!(name, "rails_#{name}")
16403 opf.gsub!(name, "rails_#{name}")
16404 File.write("toc.ncx", toc)
16405 head = Nokogiri::XML::Node.new "head", doc
16406 css = Nokogiri::XML::Node.new "link", doc
16407 css["rel"] = "stylesheet"
16408 css["type"] = "text/css"
16409 css["href"] = "#{Dir.pwd}/stylesheets/epub.css"
16410 $:.unshift __dir__
16411 as_lib = File.expand_path("../activesupport/lib", __dir__)
16412 ap_lib = File.expand_path("../actionpack/lib", __dir__)
16413 av_lib = File.expand_path("../actionview/lib", __dir__)
16414 env_value = ->(name) { ENV[name].presence }
16415 git_source(:github) { |repo| "https://github.com/#{repo}.git" }
16416 gem "rails", github: "rails/rails", branch: "main"
16417 gem "activesupport", "~> 7.0.0"
16418 puts " #{name} ".center(80, "=")
16419 x.report("fast_blank?") { value.fast_blank? }
16420 gem "rack", "~> 2.0"
16421 local: {
16422 user = User.create!(
16423 profile: {
16424 io: ::StringIO.new("dummy"),
16425 gem "rails", "~> 7.0.0"
16426 gem "activerecord", "~> 7.0.0"
16427 gem "activejob", "~> 7.0.0"
16428 routing (/^replies@/i) => :replies
16429 get "/" => "test#index"
16430 @xml.to_tag(:some_tag, lambda { |o| o[:builder].br }, @options)
16431 assert_xml "<br/>"
16432 @xml.to_tag(:tag, lambda { |o, t| o[:builder].b(t) }, @options)
16433 assert_xml "<b>tag</b>"
16434 @xml.to_tag(:tag, obj, @options)
16435 assert_xml "<yo>tag</yo>"
16436 @xml.to_tag(:b, "Howdy", @options)
16437 assert_xml "<b>Howdy</b>"
16438 @xml.to_tag(:b, "blue", @options.merge(type: "color"))
16439 assert_xml("<b type=\"color\">blue</b>")
16440 @xml.to_tag(:b, :name, @options)
16441 assert_xml("<b type=\"symbol\">name</b>")
16442 @xml.to_tag(:b, true, @options)
16443 assert_xml("<b type=\"boolean\">true</b>")
16444 @xml.to_tag(:b, 3.14, @options)
16445 assert_xml("<b type=\"float\">3.14</b>")
16446 @xml.to_tag(:b, BigDecimal("1.2"), @options)
16447 assert_xml("<b type=\"decimal\">1.2</b>")
16448 @xml.to_tag(:b, Date.new(2001, 2, 3), @options)
16449 assert_xml("<b type=\"date\">2001-02-03</b>")
16450 @xml.to_tag(:b, DateTime.new(2001, 2, 3, 4, 5, 6, "+7"), @options)
16451 assert_xml("<b type=\"dateTime\">2001-02-03T04:05:06+07:00</b>")
16452 @xml.to_tag(:b, Time.new(1993, 02, 24, 12, 0, 0, "+09:00"), @options)
16453 assert_xml("<b type=\"dateTime\">1993-02-24T12:00:00+09:00</b>")
16454 @xml.to_tag(:b, time, @options)
16455 assert_xml("<b type=\"dateTime\">1993-02-24T13:00:00+01:00</b>")
16456 @xml.to_tag(:b, ["first_name", "last_name"], @options)
16457 assert_xml("<b type=\"array\"><b>first_name</b><b>last_name</b></b>")
16458 @xml.to_tag(:b, { first_name: "Bob", last_name: "Marley" }, @options)
16459 assert_xml("<b><first-name>Bob</first-name><last-name>Marley</last-name></b>")
16460 @xml.to_tag(:b, "Bob", @options.merge(skip_types: 1))
16461 assert_xml("<b>Bob</b>")
16462 assert_xml "<New---York type=\"integer\">33</New---York>"
16463 sleep 0.1 while t.status != "sleep"
16464 parser = @parsing["date"]
16465 assert_equal Time.new(2013, 11, 12, 02, 11, 00, 0), parser.call("2013-11-12T02:11:00Z")
16466 parser = @parsing["float"]
16467 assert_equal 0.0, parser.call("")
16468 [1, true, "1"].each do |value|
16469 [0, false, "0"].each do |value|
16470 assert_equal "[]", parser.call("[]")
16471 assert_equal "[]", parser.call([])
16472 assert_equal "{}", parser.call({})
16473 { "sku" => "BL394D", "quantity" => 4, "description" => "Basketball" }
16474 parser = @parsing["yaml"]
16475 assert_equal({ 1 => "test" }, parser.call(1 => "test"))
16476 assert_equal({ "1 => 'test'" => nil }, parser.call("{1 => 'test'}"))
16477 assert_equal expected_base64.gsub(/
/, " ").strip, parser.call(base64, "encoding" => "base64")
16478 hash = Hash.from_xml(<<-eoxml)
16479 <blog>
16480 </logo>
16481 </blog>
16482 assert hash["blog"].key?("logo")
16483 file = hash["blog"]["logo"]
16484 Hash.from_xml(<<~eoxml)
16485 <!ENTITY a "&b;&b;&b;&b;&b;&b;&b;&b;&b;&b;">
16486 <!ENTITY b "&c;&c;&c;&c;&c;&c;&c;&c;&c;&c;">
16487 <!ENTITY c "&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;">
16488 <!ENTITY d "&e;&e;&e;&e;&e;&e;&e;&e;&e;&e;">
16489 <!ENTITY e "&f;&f;&f;&f;&f;&f;&f;&f;&f;&f;">
16490 <!ENTITY f "&g;&g;&g;&g;&g;&g;&g;&g;&g;&g;">
16491 ]>
16492 &a;
16493 </member>
16494 xml_string = "<root/>"
16495 assert_equal({ "root" => {} }, ActiveSupport::XmlMini.parse(xml_string))
16496 <posts type="array">
16497 <post>a post</post>
16498 </posts>
16499 <products foo="bar"/>
16500 <book name="awesome" id="12345" />
16501 <book name="america" id="67890" />
16502 <root>
16503 </root>
16504 xml_string = "<root></root>"
16505 FILES_DIR = File.expand_path("../fixtures/xml", __dir__)
16506 attack_xml = <<-EOT
16507 <member>x&a;</member>
16508 %b;
16509 (0..127).each do |byte|
16510 char = [byte].pack("U")
16511 string = (0xC0..0x17E).to_a.reject { |c| [0xD7, 0xF7].include?(c) }.pack("U*")
16512 def with_env_tz(new_tz = "US/Eastern")
16513 assert_equal Time.utc(2000, 6, 30, 20), zone.utc_to_local(Time.utc(2000, 7)) # dst offset -0400
16514 assert_equal Time.new(1999, 12, 31, 19, 0, 0, -18000), zone.utc_to_local(Time.utc(2000, 1)) # standard offset -0500
16515 assert_equal Time.new(2000, 6, 30, 20, 0, 0, -14400), zone.utc_to_local(Time.utc(2000, 7)) # dst offset -0400
16516 assert_equal Time.utc(1999, 12, 31, 19, 0, 0, 1), zone.utc_to_local(Time.utc(2000, 1, 1, 0, 0, 0, 1)) # standard offset -0500
16517 assert_equal Time.utc(2000, 6, 30, 20, 0, 0, 1), zone.utc_to_local(Time.utc(2000, 7, 1, 0, 0, 0, 1)) # dst offset -0400
16518 assert_equal Time.new(1999, 12, 31, 19, 0, usec, -18000), zone.utc_to_local(Time.utc(2000, 1, 1, 0, 0, 0, 1)) # standard offset -0500
16519 assert_equal Time.new(2000, 6, 30, 20, 0, usec, -14400), zone.utc_to_local(Time.utc(2000, 7, 1, 0, 0, 0, 1)) # dst offset -0400
16520 assert_equal Time.utc(2000, 7, 1, 4), zone.local_to_utc(Time.utc(2000, 7)) # dst offset -0400
16521 define_method("test_map_#{name.downcase.gsub(/[^a-z]/, '_')}_to_tzinfo") do
16522 name = zone.name.downcase.gsub(/[^a-z]/, "_")
16523 assert_equal Time.utc(2000, 1, 1, 5), zone.now.utc
16524 assert_equal Time.new(2010, 1, 31, 22, 0, 0, -7200), zone.utc_to_local(Time.utc(2010, 2)) # daylight saving offset -0200
16525 assert_equal Time.new(2010, 3, 31, 21, 0, 0, -10800), zone.utc_to_local(Time.utc(2010, 4)) # standard offset -0300
16526 travel_to(Time.utc(2000, 1, 1, 4, 59, 59)) # 1 sec before midnight Jan 1 EST
16527 travel_to(Time.utc(2000, 1, 1, 5)) # midnight Jan 1 EST
16528 travel_to(Time.utc(2000, 1, 2, 4, 59, 59)) # 1 sec before midnight Jan 2 EST
16529 travel_to(Time.utc(2000, 1, 2, 5)) # midnight Jan 2 EST
16530 date = Date.new(2014, 2, 18)
16531 time = ActiveSupport::TimeZone["Hawaii"].local(2007, 2, 5, 15, 30, 45)
16532 assert_equal Time.utc(2007, 2, 5, 15, 30, 45), time.time
16533 time = ActiveSupport::TimeZone["Hawaii"].local(1850, 2, 5, 15, 30, 45)
16534 assert_equal [45, 30, 15, 5, 2, 1850], time.to_a[0, 6]
16535 twz = zone.local(2006, 4, 2, 1, 59, 59) # 1 second before DST start
16536 assert_equal Time.utc(2006, 4, 2, 1, 59, 59), twz.time
16537 assert_equal Time.utc(2006, 4, 2, 6, 59, 59), twz.utc
16538 assert_equal Time.utc(2006, 4, 2, 7), twz2.utc
16539 assert_equal Time.utc(2006, 4, 2, 3, 30), twz3.time # twz is created for 3:30AM
16540 assert_equal Time.utc(2006, 4, 2, 7, 30), twz3.utc
16541 twz = zone.local(2006, 10, 29, 1)
16542 assert_equal Time.utc(2014, 10, 25, 22, 0, 0), zone.local(2014, 10, 26, 1, 0, 0)
16543 twz = zone.at(secs)
16544 assert_equal [1850, 1, 1, 0], [twz.utc.year, twz.utc.mon, twz.utc.day, twz.utc.hour]
16545 assert_equal Time.utc(1999, 12, 31, 19, 0, 0 + Rational(3, 4)), twz.time
16546 assert_equal Time.utc(2000, 1, 1, 0, 0, 0 + Rational(3, 4)), twz.utc
16547 twz = zone.iso8601("1999-12-31")
16548 assert_equal Time.utc(1999, 12, 31, 0, 0, 0), twz.time
16549 assert_equal Time.utc(1999, 12, 31, 5, 0, 0), twz.utc
16550 assert_equal [0, 0, 19, 31, 12, 1883], twz.to_a[0, 6]
16551 twz = zone.iso8601("2050-12-31T19:00:00-10:00") # i.e., 2050-01-01 05:00:00 UTC
16552 assert_equal [0, 0, 0, 1, 1, 2051], twz.to_a[0, 6]
16553 with_env_tz("EET") do
16554 assert_equal [0, 29, 3, 25, 3, 2012], twz.to_a[0, 6]
16555 assert_equal [0, 29, 3, 11, 3, 2012], twz.to_a[0, 6]
16556 assert_equal Time.utc(2013, 3, 10, 2, 0, 0), twz.time
16557 assert_equal Time.utc(2013, 3, 10, 3, 0, 0), twz.time
16558 assert_equal Time.utc(2014, 10, 25, 22, 0, 0), zone.parse("2014-10-26T01:00:00")
16559 assert_equal Time.utc(2021, 3, 28, 0, 0, 0), twz.time
16560 twz = zone.parse("1999-12-31 19:00:00")
16561 (-12..13).each do |timezone_offset|
16562 twz = zone.parse("1883-12-31 19:00:00")
16563 twz = zone.parse("2050-12-31 19:00:00 -10:00") # i.e., 2050-01-01 05:00:00 UTC
16564 zone.stub(:now, zone.local(1999, 12, 31)) do
16565 twz = zone.parse("19:00:00")
16566 assert_equal Time.local(2000, 2, 1), zone.parse("Feb", Time.local(2000, 1, 1))
16567 assert_equal Time.local(2005, 2, 1), zone.parse("Feb 2005", Time.local(2000, 1, 1))
16568 assert_equal Time.local(2005, 2, 2), zone.parse("2 Feb 2005", Time.local(2000, 1, 1))
16569 twz = zone.parse("2012-03-25 03:29:00")
16570 twz = zone.parse("2012-03-11 02:29:00")
16571 zone.stub(:now, zone.local(1999, 12, 31, 12, 59, 59)) do
16572 twz = zone.parse("2012-12-01")
16573 twz = zone.parse("Mon May 28 2012 00:00:00 GMT-0700 (PDT)")
16574 assert_equal Time.utc(2012, 5, 28, 7, 0, 0), twz.utc
16575 twz = zone.parse("2013-03-10 02:00:00")
16576 assert_equal Time.utc(2014, 10, 25, 22, 0, 0), zone.parse("2014-10-26 01:00:00")
16577 twz = zone.rfc3339("2050-12-31T19:00:00-10:00") # i.e., 2050-01-01 05:00:00 UTC
16578 twz = zone.strptime("1999-12-31 12:00:00", "%Y-%m-%d %H:%M:%S")
16579 twz = zone.strptime("1999-12-31 12:00:00 PST", "%Y-%m-%d %H:%M:%S %Z")
16580 twz = zone.strptime("1999-12-31 12:00:00 -08", "%Y-%m-%d %H:%M:%S %:::z")
16581 twz = zone.strptime("1999-12-31 12:00:00 -08:00", "%Y-%m-%d %H:%M:%S %:z")
16582 twz = zone.strptime("1999-12-31 12:00:00 -08:00:00", "%Y-%m-%d %H:%M:%S %::z")
16583 twz = zone.strptime("1999-12-31 12:00:00 %Z", "%Y-%m-%d %H:%M:%S %%Z")
16584 assert_equal Time.local(2000, 2, 1), zone.strptime("Feb", "%b", Time.local(2000, 1, 1))
16585 assert_equal Time.local(2005, 2, 1), zone.strptime("Feb 2005", "%b %Y", Time.local(2000, 1, 1))
16586 assert_equal Time.local(2005, 2, 2), zone.strptime("2 Feb 2005", "%e %b %Y", Time.local(2000, 1, 1))
16587 assert_raise(ArgumentError) { zone.strptime("1999-12-31", "%Y/%m/%d") }
16588 time = zone.strptime(time_str, "%s")
16589 time = zone.strptime(time_str, "%Q")
16590 assert_equal Time.utc(2014, 10, 25, 22, 0, 0), zone.strptime("2014-10-26 01:00:00", "%Y-%m-%d %H:%M:%S")
16591 travel_to(Time.utc(2014, 10, 25, 21)) do # 1 hour before TZ change
16592 travel_to(Time.utc(2014, 10, 25, 22)) do # after TZ change
16593 assert_equal "+09:00:00", twz.strftime("%::z")
16594 assert zone =~ /New_York/
16595 1.upto(all.length - 1) do |i|
16596 assert all[i - 1] < all[i]
16597 mappings = {
16598 expected_time = Time.new(2004, 11, 24, 1, 4, 44)
16599 outer_expected_time = Time.new(2004, 11, 24, 1, 4, 44)
16600 inner_expected_time = Time.new(2004, 10, 24, 1, 4, 44)
16601 initial_expected_time = Time.new(2004, 11, 24, 1, 4, 44)
16602 subsequent_expected_time = Time.new(2004, 10, 24, 1, 4, 44)
16603 traveled_time = Time.new(2004, 11, 24, 1, 4, 44) + duration_usec
16604 expected_time = Time.new(2004, 11, 24, 1, 4, 44) + duration_usec
16605 assert_equal((expected_time + 0.5).to_f, Time.now.to_f)
16606 Time.now.usec != 0
16607 travel_to Time.utc(2014, 10, 10, 10, 10, 50, 999999) do
16608 assert_operator expected_time.to_fs(:db), :<, Time.now.to_fs(:db)
16609 def <<(arg); end
16610 assert_called(@object, :<<) do
16611 @object << 2
16612 assert_called_with(@object, :<<, [ 2 ]) do
16613 assert_called_with(@object, :<<, [ 2 ], returns: 10) do
16614 assert_equal(10, @object << 2)
16615 assert_nil(@object << 2)
16616 assert_called_with(@object, :<<, [ 4567 ]) do
16617 assert_changes(-> { counter }) do
16618 self.file_fixture_path = File.expand_path("../file_fixtures", __dir__)
16619 Class === constant && constant < Foo
16620 assert_changes -> { failures.count }, from: 0, to: 1 do
16621 self.num += 1
16622 self.num -= 1
16623 @object.num = 0
16624 assert_no_difference ["@object.num", -> { another_object.num }] do
16625 assert_difference "@object.num + 1", +2 do
16626 local_scope = "foo"
16627 assert_difference [ "@object.num", "@object.num + 1" ], +1 do
16628 assert_difference ["@object.num", "1 + 1"] do
16629 assert_difference ["@object.num", "1 + 1"], 1, "something went wrong" do
16630 assert_difference "@object.num" => 1, "@object.num + 1" => 1 do
16631 assert_difference({ "@object.num" => 0 }, "Object Changed") do
16632 assert_difference -> { @object.num } => 1, -> { @object.num + 1 } => 1 do
16633 assert_difference "@object.num" => 1, "1 + 1" => 1 do
16634 assert_changes -> { @object.num } do
16635 assert_changes "@object.num", from: 0, to: 1 do
16636 assert_changes "@object.num", from: 0, to: 2 do
16637 @new_object = 42
16638 @object = nil
16639 assert_changes -> { token }, to: /\w{32}/ do
16640 assert_changes -> { token }, from: /\w{32}/, to: /\w{32}/ do
16641 assert_changes "@object.num", "@object.num should be 1", to: 1 do
16642 assert_no_changes -> { token }, from: /\w{32}/ do
16643 lines = "HEY
" * 12
16644 --- expected
16645 +++ actual
16646 @@ -10,4 +10,5 @@
16647 expected = <<~MSG
16648 assert_no_changes -> { 1 } do # this assertion passes
16649 @called_back = []
16650 @called_back << :foo
16651 assert_equal [:foo, :bar], @called_back
16652 @called_back << :bar
16653 assert_equal [:foo, :bar, :bar], @called_back
16654 assert_match "#{self.class}: #{name}
", @out.string
16655 def flush(*)
16656 @logger.tagged("BCX") { @logger.info "Funky time" }
16657 @logger.tagged("BCX") { @logger.tagged("Jason") { @logger.info "Funky time" } }
16658 @logger.tagged("BCX", "Jason", "New") { @logger.info "Funky time" }
16659 assert_equal "[BCX] [Jason] [New] Funky time
", @output.string
16660 @logger.tagged(%w(BCX Jason New)) { @logger.info "Funky time" }
16661 @logger.tagged("BCX", %w(Jason New)) { @logger.info "Funky time" }
16662 @logger.info "a"
16663 @logger.info "b"
16664 assert_equal %w(B), @logger.pop_tags(1)
16665 @logger.info "c"
16666 @logger.info "d"
16667 assert_equal "[A] [B] [C] a
[A] [B] b
[A] c
d
", @output.string
16668 @logger.tagged("BCX") { |logger| logger.info "Funky time" }
16669 @logger.tagged(nil, "", "New") { @logger.info "Funky time" }
16670 @logger.tagged("OMG") { @logger.info "Cool story" }
16671 @logger.tagged("Jason") { @logger.info "Funky time" }
16672 @logger.tagged("BCX", "Jason", "New").info "Funky time"
16673 @logger.tagged("BCX", %w(Jason New)).info "Funky time"
16674 @logger.tagged(nil, "", "New").info "Funky time"
16675 logger = @logger.tagged("BCX")
16676 @logger.tagged("tag") { @logger.info [1, 2, 3] }
16677 assert_equal "[tag] [1, 2, 3]
", @output.string
16678 @@events = []
16679 original_event = ActiveSupport::Notifications::Event.new("open_party.doodle", Time.at(0), Time.at(10), "id", { foo: "bar" })
16680 (name == :bar) || super
16681 @logger.info("Foo")
16682 @lock.exclusive { @lock.exclusive { } }
16683 exclusive_thread = Thread.new { @lock.exclusive { } }
16684 sharing_thread = Thread.new { @lock.sharing { } }
16685 exclusive_threads = (1..2).map do
16686 @lock.exclusive { }
16687 @lock.exclusive(purpose: :load, compatible: [:load, :unload]) { }
16688 @lock.exclusive(purpose: :red, compatible: [:green, :purple]) { }
16689 @lock.exclusive(purpose: :blue, compatible: [:green]) { }
16690 @lock.exclusive(purpose: :green, compatible: []) { }
16691 unload_params = [:unload, [:unload, :load]]
16692 @lock.sharing { }
16693 @lock.exclusive(purpose: :x, compatible: [:x], after_compatible: [:x]) { }
16694 threads = [
16695 @lock.exclusive(purpose: :x) { }
16696 @lock.yield_shares(compatible: [:x, :y]) do
16697 @lock.exclusive(purpose: :z) { }
16698 @lock.yield_shares(compatible: [:x, :y]) { }
16699 @lock.exclusive(purpose: :y) { }
16700 assert(Array(threads).all? { |t| t.join(0.001).nil? })
16701 @thread = Thread.new { @latch.wait }
16702 assert_equal(true, wrapper.secure_compare!("and_another_one", on_rotation: -> { @witness = true }))
16703 @buffer << "<script>"
16704 @buffer << "<script>".html_safe
16705 @buffer << "hello &amp; goodbye".html_safe
16706 @buffer << "Hello"
16707 @buffer << ERB::Util.html_escape("<script>")
16708 assert_match(/^--- #{str}/, yaml)
16709 data = { "str" => ActiveSupport::SafeBuffer.new(str) }
16710 assert_equal({ "str" => str }, YAML.load(yaml))
16711 chop: nil,
16712 delete: "foo",
16713 gsub: ["foo", "bar"],
16714 next: nil,
16715 sub: ["foo", "bar"],
16716 succ: nil,
16717 tr: ["foo", "bar"],
16718 tr_s: ["foo", "bar"],
16719 @buffer.public_send("#{unsafe_method}!", *dummy_args)
16720 buffer[0] = "<"
16721 buffer[2] = "<"
16722 buffer[0, 3] = "<"
16723 buffer[1, 3] = "<"
16724 @buffer.gsub!("", "<>")
16725 assert_equal "hello&lt;&gt;", clean + @buffer
16726 multiplied_safe_buffer = "<br />".html_safe * 2
16727 multiplied_unsafe_buffer = @buffer.gsub("", "<>") * 2
16728 assert_equal "<>hello", @buffer + clean
16729 clean = "<script>".html_safe
16730 assert_not_predicate @buffer.gsub!("", "").clone_empty, :html_safe?
16731 new_buffer = @buffer[0, 0]
16732 safe_string = "foo".html_safe.gsub!("f", '<script>alert("lolpwnd");</script>')
16733 safe_string = "<div>foo</div>".html_safe
16734 safe_string = "<div>foo</div>"
16735 unsafe_string = +'<script>alert("XSS");</script>'
16736 x = "foo %s bar".html_safe % ["qux"]
16737 x = "foo %{x} bar".html_safe % { x: "qux" }
16738 x = "foo %{x} bar".html_safe % { x: "<br/>" }
16739 assert_equal "foo &lt;br/&gt; bar", x
16740 x = "foo %{x} bar".html_safe % { x: "<br/>".html_safe }
16741 assert_equal "foo <br/> bar", x
16742 x = "Hello".html_safe
16743 assert_nil x[/a/, 1]
16744 a = "foo123".html_safe
16745 a2 = a.sub(/([a-z]+)([0-9]+)/) { $2 + $1 }
16746 a.sub!(/([a-z]+)([0-9]+)/) { $2 + $1 }
16747 b2 = b.gsub(/([a-z]+)([0-9]+)/) { $2 + $1 }
16748 b.gsub!(/([a-z]+)([0-9]+)/) { $2 + $1 }
16749 a = "aaa".html_safe.gsub!(/a/).with_index { |m, i| i }
16750 { digest: salt == "salt" ? "SHA1" : "MD5" }
16751 make_coordinator.rotate(digest: "MD5") { {} }
16752 { digest: "MD5" } if salt == "salt"
16753 md5_codec = (make_coordinator.rotate(digest: "MD5"))["salt"]
16754 md4_codec = (make_coordinator.rotate(digest: "MD4"))["salt"]
16755 { digest: "SHA1" } if salt == "salt"
16756 def self.===(other)
16757 Exception === other && other.respond_to?(:weird?)
16758 @result = "alldead"
16759 @result = "weird"
16760 @result = "killed"
16761 @result = "sos_first"
16762 @result = "sos_cool_error"
16763 i = 10
16764 reloader.to_prepare { i += 1 }
16765 reloader.to_prepare(prepend: true) { i = 0 }
16766 r = new_reloader { true }
16767 r.to_run { invoked = true }
16768 r.wrap { }
16769 r = new_reloader { false }
16770 called = []
16771 reloader.to_run { called << :reloader_run }
16772 reloader.wrap { called << :body }
16773 @reloader ||= new_reloader { true }
16774 test_hashes = [
16775 [{ "foo" => "bar" }, { "foo" => "bar" }, %w'food'],
16776 [{ "foo" => "bar" }, { "foo" => "[FILTERED]" }, %w'foo'],
16777 [{ "foo" => "bar", "bar" => "foo" }, { "foo" => "[FILTERED]", "bar" => "foo" }, %w'foo baz'],
16778 [{ "foo" => "bar", "baz" => "foo" }, { "foo" => "[FILTERED]", "baz" => "[FILTERED]" }, %w'foo baz'],
16779 [{ "foo" => { "foo" => "bar", "bar" => "foo" } }, { "foo" => "[FILTERED]" }, %w'f banana'],
16780 filter_words << "blah"
16781 filter_words << lambda { |key, value|
16782 value.replace("world!") if original_params["barg"]["blah"] == "bar" && key == "hello"
16783 [{ "foo" => "bar" }, { "foo" => mask }, %w'foo'],
16784 [{ "foo" => "bar", "bar" => "foo" }, { "foo" => mask, "bar" => "foo" }, %w'foo baz'],
16785 [{ "foo" => "bar", "baz" => "foo" }, { "foo" => mask, "baz" => mask }, %w'foo baz'],
16786 [{ "foo" => { "foo" => "bar", "bar" => "foo" } }, { "foo" => mask }, %w'f banana'],
16787 [{ "foo" => "bar" }.with_indifferent_access, ["blah"]],
16788 [{ "foo" => "bar" }.with_indifferent_access, []]
16789 [{ 13 => "bar" }, { 13 => "[FILTERED]" }, %w'13'],
16790 [{ 20 => "bar" }, { 20 => "bar" }, %w'13'],
16791 patterns = [/A.a/, /b.B/i, "ccC", :ddD]
16792 keys = ["Aaa", "Bbb", "Ccc", "Ddd"]
16793 deep_patterns = [/A\.a/, /b\.B/i, "c.C", :"d.D"]
16794 deep_keys = ["A.a", "B.b", "C.c", "D.d"]
16795 procs = [proc { }, proc { }]
16796 a["else_where"] = 56
16797 test = [[:allow_concurrency, true], [:else_where, 56]]
16798 a.each_with_index do |(key, value), index|
16799 a[:test_key] = 56
16800 assert_equal 56, a["test_key"]
16801 parent[:foo] = true
16802 parent[:foo] = :bar
16803 child[:foo] = :baz
16804 a[:foo] = :bar
16805 a.foo = nil
16806 a.foo!
16807 a[:baz] = :quz
16808 assert_equal "#<ActiveSupport::OrderedOptions {:foo=>:bar, :baz=>:quz}>", a.inspect
16809 @hash = Hash.new
16810 @hash[key] = @values[index]
16811 assert @hash.all? { |k, v| @ordered_hash[k] == v }
16812 key, value = "purple", "5422a8"
16813 key, value = "white", "ffffff"
16814 bad_key = "black"
16815 assert_equal @ordered_hash, @ordered_hash.each_key { |k| keys << k }
16816 values = []
16817 assert_equal @ordered_hash, @ordered_hash.each_value { |v| values << v }
16818 keys << key
16819 assert_equal copy, @ordered_hash.delete_if { |k, _| k == "pink" }
16820 (copy = @ordered_hash.dup).delete("pink")
16821 @ordered_hash.reject! { |k, _| k == "pink" }
16822 new_ordered_hash = @ordered_hash.reject { |k, _| k == "pink" }
16823 other_hash["purple"] = "800080"
16824 other_hash["violet"] = "ee82ee"
16825 assert_equal @keys + ["purple", "violet"], merged.keys
16826 hash[:a] = 0
16827 hash[:b] = 0
16828 merged = hash.merge(b: 2, c: 7) do |key, old_value, new_value|
16829 new_value + 1
16830 hash.merge!(a: 1, c: 7) do |key, old_value, new_value|
16831 new_value + 3
16832 hash = Hash[:foo, :bar]
16833 [1, 2],
16834 [3, 4],
16835 [ "missing value" ]
16836 ]]
16837 flash = { a: ActiveSupport::OrderedHash[:b, 1, :c, 2] }.with_indifferent_access
16838 @ordered_hash.each { |*v| ordered_hash_values << v }
16839 @ordered_hash.each_pair { |*v| ordered_hash_values << v }
16840 @ordered_hash[:array] = %w(a b c)
16841 values = @deserialized_ordered_hash.map { |_, value| value }
16842 @ordered_hash[:rails] = "snowman"
16843 @options = { hello: "world" }
16844 local_options = { "cool" => true }
16845 local_options = { cool: true }
16846 local_options = { hello: "moon" }
16847 expected = { conditions: { method: :get, domain: "www" } }
16848 with_options conditions: { method: :get, domain: "www" } do |outer|
16849 expected = { conditions: { method: :post, domain: "www" } }
16850 with_options html: { class: "foo", style: { margin: 0, display: "block" } } do |outer|
16851 outer.with_options html: { title: "bar", style: { margin: "1em", color: "#fff" } } do |inner|
16852 expected = { html: { class: "foo", title: "bar", style: { margin: "1em", display: "block", color: "#fff" } } }
16853 local_lambda = lambda { { lambda: true } }
16854 local_proc = proc { }
16855 merge! fizz: "buzz"
16856 expected = { hello: "world", foo: "bar", fizz: "buzz" }
16857 delegate :to_hash, :deep_merge, to: :@hash
16858 @hash = hash
16859 assert_equal("(755) 6123-4567", number_helper.number_to_phone(75561234567, pattern: /(\d{3,4})(\d{4})(\d{4})/, area_code: true))
16860 assert_equal("133-1234-5678", number_helper.number_to_phone(13312345678, pattern: /(\d{3})(\d{4})(\d{4})/))
16861 assert_equal("-$ 1,234,567,890.50", number_helper.number_to_currency(-1234567890.50, format: "%u %n"))
16862 assert_equal("1,234,567,890.50 K&#269;", number_helper.number_to_currency("1234567890.50", unit: "K&#269;", format: "%n %u"))
16863 assert_equal("1,234,567,890.50 - K&#269;", number_helper.number_to_currency("-1234567890.50", unit: "K&#269;", format: "%n %u", negative_format: "%n - %u"))
16864 assert_equal("0.00", number_helper.number_to_currency(+0.0, unit: "", negative_format: "(%n)"))
16865 assert_equal("-$1,11", number_helper.number_to_currency("-1,11"))
16866 assert_equal("-$0,11", number_helper.number_to_currency("-0,11"))
16867 assert_equal("-$,11", number_helper.number_to_currency("-,11"))
16868 assert_equal("$0.00", number_helper.number_to_currency("-0.0"))
16869 assert_equal("1.000,000%", number_helper.number_to_percentage(1000, delimiter: ".", separator: ","))
16870 assert_equal("-0.13 %", number_helper.number_to_percentage("-0.13", precision: nil, format: "%n %"))
16871 assert_equal("1,23,456.78", number_helper.number_to_delimited("123456.78", delimiter_pattern: /(\d+?)(?=(\d\d)+(\d)(?!\d))/))
16872 assert_equal("111.2346" + "0" * 96, number_helper.number_to_rounded("111.2346", precision: 100))
16873 volume = { unit: "ml", thousand: "lt", million: "m3" }
16874 distance = { mili: "mm", centi: "cm", deci: "dm", unit: "m", ten: "dam", hundred: "hm", thousand: "km" }
16875 assert_equal "4", number_helper.number_to_human(4, units: { unit: "", ten: "tens " })
16876 assert_equal "123", number_helper.number_to_human(123, units: { thousand: "k" })
16877 options = { "raise" => true }
16878 assert_equal({ "raise" => true }, options)
16879 assert_equal("$x.", number_helper.number_to_currency("x."))
16880 number: {
16881 currency: { format: { unit: "&$", format: "%u - %n", negative_format: "(%u - %n)", precision: 2 } },
16882 human: {
16883 format: {
16884 format: "%n %u",
16885 units: {
16886 byte: "b",
16887 kb: "k"
16888 deci: { one: "Tenth", other: "Tenths" },
16889 unit: "u",
16890 ten: { one: "Ten", other: "Tens" },
16891 thousand: "t",
16892 million: "m",
16893 billion: "b",
16894 trillion: "t",
16895 percentage: { format: { delimiter: "", precision: 2, strip_insignificant_zeros: true } },
16896 precision: { format: { delimiter: "", significant: true } }
16897 custom_units_for_number_to_human: { mili: "mm", centi: "cm", deci: "dm", unit: "m", ten: "dam", hundred: "hm", thousand: "km" }
16898 assert_equal("&$ - 10.00", number_to_currency(10, locale: "ts"))
16899 assert_equal("(&$ - 10.00)", number_to_currency(-10, locale: "ts"))
16900 assert_equal("-10.00 - &$", number_to_currency(-10, locale: "ts", format: "%n - %u"))
16901 assert_equal("$10.00", number_to_currency(10, locale: "empty"))
16902 assert_equal("-$10.00", number_to_currency(-10, locale: "empty"))
16903 number: { format: { separator: ";" } }
16904 assert_equal("&$ - 10;00", number_to_currency(10, locale: "ts"))
16905 currency: { format: { unit: "@", format: "%n %u" } }
16906 assert_equal("-10.00 @", number_to_currency(-10, locale: "no_negative_format"))
16907 assert_equal("1.00", number_to_rounded(1.0, locale: "ts"))
16908 assert_equal("1%", number_to_percentage(1, locale: "ts"))
16909 assert_equal("1.24%", number_to_percentage(1.2434, locale: "ts"))
16910 assert_equal("2 k", number_to_human_size(2048, locale: "ts"))
16911 assert_equal("42 b", number_to_human_size(42, locale: "ts"))
16912 assert_equal "2 t", number_to_human(2000, locale: "ts")
16913 assert_equal "1 Tenth", number_to_human(0.1, locale: "ts")
16914 assert_equal "1.3 Tenth", number_to_human(0.134, locale: "ts")
16915 assert_equal "2 Tenths", number_to_human(0.2, locale: "ts")
16916 assert_equal "1 Ten", number_to_human(10, locale: "ts")
16917 assert_equal "1.2 Ten", number_to_human(12, locale: "ts")
16918 assert_equal "2 Tens", number_to_human(20, locale: "ts")
16919 @events = []
16920 @named_events = []
16921 @subscription = @notifier.subscribe { |*args| @events << event(*args) }
16922 payload[:my_key] = "success!"
16923 payload[:some_key][:key_two] = "great_success!"
16924 event = e
16925 listener = ->(event) do
16926 event_name = "foo"
16927 actual_times = []
16928 times = (1..4).map { |s| Time.new(2020, 1, 1) + s }
16929 [times[0], times[2]],
16930 [times[1], times[3]],
16931 events1 = []
16932 events2 = []
16933 callback1 = lambda { |event| events1 << event }
16934 callback2 = lambda { |event| events2 << event }
16935 expected = [name, name]
16936 callback = lambda { |*_| events << _.first }
16937 expected = [name, name2, name]
16938 assert_equal [[:foo]], @events
16939 assert_equal [["named.subscription", :foo], ["named.subscription", :foo]], @events
16940 @matched_events = []
16941 @notifier.subscribe(/subscription/) { |*args| @matched_events << event(*args) }
16942 @publishes = []
16943 def finish(*args); @finishes << args; end
16944 def publish(*args); @publishes << args; end
16945 assert_equal [[:foo], [:foo]], @events
16946 assert_equal [[:foo]] * 4, @events
16947 @notifier.subscribe("1") { |*args| events << args }
16948 assert_equal [["1"]], events
16949 @notifier.subscribe(/\d/) { |*args| events << args }
16950 assert_equal [["1"], ["a.1"], ["1.a"]], events
16951 @another = []
16952 @notifier.subscribe { |*args| @another << args }
16953 assert_equal [[:foo]], @another
16954 assert_equal 2, instrument(:awesome) { 1 + 1 }
16955 assert_equal 2, instrument(:awesome) { |p| p[:result] = 1 + 1 }
16956 1 + 1
16957 time = Time.now.to_f
16958 event = event(:foo, time, time + 0.01, random_id, {})
16959 notifier.subscribe(:symbol) { |*_| }
16960 notifier.subscribe(Object.new) { |*_| }
16961 @finishes = []
16962 @payload = { foo: Object.new }
16963 assert_equal 2, instrumenter.instrument("awesome") { |p| p[:result] = 1 + 1 }
16964 event.record { |p| p[:result] = 1 + 1 }
16965 @events << [:start, name, id, payload]
16966 @events << [:finish, name, id, payload]
16967 @events << [:call, name, start, finish, id, payload]
16968 notifier.finish "hi", 2, {}
16969 notifier.finish "hi", 1, {}
16970 [:start, "hi", 1, {}],
16971 [:start, "hi", 2, {}],
16972 [:finish, "hi", 2, {}],
16973 [:finish, "hi", 1, {}],
16974 notifier.start "hi", 1, {}
16975 [:finish, "hi", 1, {}]
16976 notifier.start("hi.world", 1, {})
16977 notifier.finish("hi.world", 2, {})
16978 notifier.start("hello.world", 1, {})
16979 notifier.finish("hello.world", 2, {})
16980 [:start, "hi.world", 1, {}],
16981 [:finish, "hi.world", 2, {}],
16982 [:start, "hello.world", 1, {}],
16983 [:finish, "hello.world", 2, {}]
16984 str.to_s.unpack("U*").map { |cp| cp.to_s(16) }.join(" ")
16985 @wrapped_string = string.gsub(/[^\u0000-\u007F]/, "?")
16986 str = +""
16987 mb_a = (+"a").mb_chars
16988 mb_b = (+"b").mb_chars
16989 assert_equal "ab", mb_a + "b"
16990 assert_equal "ab", "a" + mb_b
16991 assert_equal "ab", mb_a + mb_b
16992 assert_equal "ab", mb_a << "b"
16993 assert_equal "ab", (+"a") << mb_b
16994 assert_equal "abb", mb_a << mb_b
16995 assert(("a".mb_chars + "b").kind_of?(@proxy_class))
16996 assert(("a".mb_chars + "b".mb_chars).kind_of?(@proxy_class))
16997 assert(((+"a").mb_chars << "b").kind_of?(@proxy_class))
16998 assert(((+"a").mb_chars << "b".mb_chars).kind_of?(@proxy_class))
16999 @whitespace = "
\t "
17000 @chars.split(//).each do |character|
17001 proxy.public_send("#{method}!")
17002 assert_nil(@chars =~ /wrong/u)
17003 assert_equal "", (+"").mb_chars.insert(0, "")
17004 @chars[2] = "a"
17005 before = @chars.to_s
17006 assert_raise(IndexError) { @chars[10] = "a" }
17007 assert_raise(IndexError) { @chars[10, 4] = "a" }
17008 assert_raise(IndexError) { @chars[/ii/] = "a" }
17009 assert_raise(IndexError) { @chars[/()/, 10] = "a" }
17010 assert_raise(RangeError) { @chars[10..12] = "a" }
17011 assert_raise(ArgumentError) { @chars.rjust(10, "") }
17012 assert_raise(ArgumentError) { @chars.ljust(10, "") }
17013 assert_raise(ArgumentError) { @chars.center(10, "") }
17014 assert_equal "", "".mb_chars.reverse
17015 assert_nil "".mb_chars.slice(-1..1)
17016 assert_nil "".mb_chars.slice(-1, 1)
17017 assert_equal "", "".mb_chars.slice(0..10)
17018 assert_equal "", @chars.slice(4..10)
17019 chars.slice!(0, 2)
17020 assert_raise(TypeError) { @chars.slice(2..3, 1) }
17021 assert_raise(TypeError) { @chars.slice(1, 2..3) }
17022 assert_raise(ArgumentError) { @chars.slice(1, 1, 1) }
17023 assert_equal "", "".mb_chars.upcase
17024 assert_equal "ll", "hello".mb_chars.method(:slice).call(2..3) # Defined on Chars
17025 chars = +"hello".mb_chars
17026 assert_equal "jello", "hello".mb_chars.method(:gsub).call(/h/, "j") # Defined on String
17027 example = chars("")
17028 ["", 0],
17029 ["abc", 3],
17030 [[0x0924, 0x094D, 0x0930].pack("U*"), 2],
17031 [%w(cr lf), 1],
17032 [%w(cr n), 2],
17033 [%w(lf n), 2],
17034 [%w(control n), 2],
17035 [%w(cr extend), 2],
17036 [%w(lf extend), 2],
17037 [%w(control extend), 2],
17038 [%w(n cr), 2],
17039 [%w(n lf), 2],
17040 [%w(n control), 2],
17041 [%w(extend cr), 2],
17042 [%w(extend lf), 2],
17043 [%w(extend control), 2],
17044 [%w(l l), 1],
17045 [%w(l v), 1],
17046 [%w(l lv), 1],
17047 [%w(l lvt), 1],
17048 [%w(lv v), 1],
17049 [%w(lv t), 1],
17050 [%w(v v), 1],
17051 [%w(v t), 1],
17052 [%w(lvt t), 1],
17053 [%w(t t), 1],
17054 [%w(r r), 1],
17055 [%w(n extend), 1],
17056 [%w(n spacingmark), 1],
17057 [%w(n n), 2],
17058 [%w(n cr lf n), 3],
17059 [%w(n l v t), 2],
17060 [%w(cr extend n), 3],
17061 assert_equal "#{good}#{good}", chars("#{bad}#{bad}").tidy_bytes
17062 assert_equal "#{good}#{good}#{good}", chars("#{bad}#{bad}#{bad}").tidy_bytes
17063 assert_equal "#{good}a", chars("#{bad}a").tidy_bytes
17064 assert_equal "a#{good}a", chars("a#{bad}a").tidy_bytes
17065 assert_equal "a#{good}", chars("a#{bad}").tidy_bytes
17066 byte_string = "\270\236\010\210\245"
17067 tidy_string = [0xb8, 0x17e, 0x8, 0x2c6, 0xa5].pack("U*")
17068 l: 0x1100, v: 0x1160, t: 0x11A8, lv: 0xAC00, lvt: 0xAC01, cr: 0x000D, lf: 0x000A,
17069 end.pack("U*")
17070 @config.rotate :signed, "older secret", salt: "salt", digest: "SHA1"
17071 @config.rotate :signed, "old secret", salt: "salt", digest: "SHA256"
17072 [ "older secret", salt: "salt", digest: "SHA1" ],
17073 [ "old secret", salt: "salt", digest: "SHA256" ] ], @config.signed
17074 assert_equal [ [ "old raw key", cipher: "aes-256-gcm" ] ], @config.encrypted
17075 assert_rotate [digest: "SHA256"], [digest: "SHA1"], [digest: "MD5"]
17076 assert_rotate [secret("new")], [secret("old")], [secret("older")]
17077 assert_rotate [secret("new")], [secret("old")], purpose: "purpose"
17078 def self.dump(*); ""; end
17079 assert_rotate [secret("new"), url_safe: true], [secret("old"), url_safe: false]
17080 assert_rotate [secret("new"), on_rotation: proc { called = true }], [secret("old")]
17081 assert_rotate [secret("same"), on_rotation: proc { called = true }], [secret("same")]
17082 codec = make_codec(secret("new"), on_rotation: proc { called = true })
17083 called = ""
17084 codec = make_codec(secret("new"), on_rotation: proc { called += "via constructor" })
17085 DATA = [{ "a_boolean" => true, "a_number" => 123, "a_string" => "abc" }]
17086 assert_roundtrip data, codec, { purpose: "x" }, { purpose: "x" }
17087 assert_no_roundtrip data, codec, { purpose: "x" }, { purpose: "y" }
17088 assert_no_roundtrip data, codec, { purpose: "x" }, {}
17089 assert_no_roundtrip data, codec, {}, { purpose: "x" }
17090 assert_roundtrip data, codec, { purpose: :x }, { purpose: :x }
17091 assert_roundtrip data, codec, { purpose: :x }, { purpose: "x" }
17092 assert_roundtrip data, codec, { purpose: "x" }, { purpose: :x }
17093 message = encode(data, codec, purpose: "x")
17094 assert_roundtrip "a string", codec, { purpose: "x", expires_in: 1.year }, { purpose: "x" }
17095 JSON.dump(value) << "!"
17096 JSON.load(value.chomp!("!"))
17097 { "a_number" => 123, "a_time" => Time.local(2004), "an_object" => { "key" => "value" } },
17098 ["a string", 123, Time.local(2004), { "key" => "value" }],
17099 def roundtrip(data, codec, encode_options = {}, decode_options = {})
17100 assert_rotate [cipher: "aes-256-gcm"], [cipher: "aes-256-cbc"]
17101 @secrets ||= {}
17102 secret_generator = ->(salt) { salt + "!" }
17103 secret_generator = ->(salt, foo:, bar: nil) { foo + bar }
17104 coordinator.rotate(foo: "foo", bar: "bar")
17105 coordinator.rotate { { foo: "foo", bar: "bar" } }
17106 @data = { "some" => "data", "now" => Time.utc(2010) }
17107 data, hash = @verifier.generate(@data).split("--")
17108 assert_not @verifier.valid_message?("#{data.reverse}--#{hash}")
17109 assert_not @verifier.valid_message?("#{data}--#{hash.reverse}")
17110 data = "??"
17111 message = verifier.generate({ :foo => 123, "bar" => Time.utc(2010) })
17112 exp = { "foo" => 123, "bar" => "2010-01-01T00:00:00.000Z" }
17113 @data = { some: "data", now: Time.utc(2010) }
17114 secret_generator = ->(salt, secret_length:) { salt[0] * secret_length }
17115 secret_generator = ->(salt, secret_length:, foo:, bar: nil) { foo[bar] * secret_length }
17116 coordinator.rotate { { foo: "foo", bar: 0 } }
17117 secret_generator = proc { |*args, **kwargs| [SECRET_GENERATOR.call(*args, **kwargs), "signing secret"] }
17118 SECRET_GENERATOR = proc { |salt, secret_length:| "".ljust(secret_length, salt) }
17119 @data = { some: "data", now: Time.local(2010) }
17120 text, iv = @verifier.verify(@encryptor.encrypt_and_sign(@data)).split("--")
17121 assert_not_decrypted([iv, text] * "--")
17122 assert_not_decrypted([text, munge(iv)] * "--")
17123 assert_not_decrypted([munge(text), iv] * "--")
17124 assert_not_decrypted([munge(text), munge(iv)] * "--")
17125 text, iv = @encryptor.encrypt_and_sign(@data).split("--")
17126 assert_not_verified([iv, text] * "--")
17127 assert_not_verified([text, munge(iv)] * "--")
17128 assert_not_verified([munge(text), iv] * "--")
17129 assert_not_verified([munge(text), munge(iv)] * "--")
17130 message = encryptor.encrypt_and_sign({ :foo => 123, "bar" => Time.utc(2010) })
17131 bad_encoding_characters = "
!@#"
17132 assert_not_verified("#{::Base64.encode64 message.to_s}--#{::Base64.encode64 iv.to_s}")
17133 data = "x" * 10001
17134 data = 1
17135 text, iv, auth_tag = encryptor.encrypt_and_sign(@data).split("--")
17136 assert_aead_not_decrypted(encryptor, [iv, text, auth_tag] * "--")
17137 assert_aead_not_decrypted(encryptor, [munge(text), iv, auth_tag] * "--")
17138 assert_aead_not_decrypted(encryptor, [text, munge(iv), auth_tag] * "--")
17139 assert_aead_not_decrypted(encryptor, [text, iv, munge(auth_tag)] * "--")
17140 assert_aead_not_decrypted(encryptor, [munge(text), munge(iv), munge(auth_tag)] * "--")
17141 assert_aead_not_decrypted(encryptor, [text, iv] * "--")
17142 assert_aead_not_decrypted(encryptor, [text, iv, auth_tag[0..-2]] * "--")
17143 @secrets ||= Hash.new { |h, k| h[k] = SecureRandom.random_bytes(32) }
17144 data = "this_is_data"
17145 t = Tempfile.new ["development", "log"]
17146 t.write "hi mom!"
17147 f = File.open(t.path, "w")
17148 str = +"\x80"
17149 fname = File.join Dir.tmpdir, "lol", "rofl.log"
17150 f = File.open(fname, "w")
17151 @logger.add(Logger::INFO) { @message }
17152 @logger.info { @message }
17153 threads = (1..2).collect do |thread_number|
17154 info { "info" }
17155 info "#{color("cool", :red)}, #{color("isn't it?", :blue, bold: true)}"
17156 info "#{color("rad", :green, bold: true, underline: true)}, #{color("isn't it?", :yellow, italic: true)}"
17157 info "#{color("bogus", :red, true)}"
17158 assert_equal "\e[31mcool\e[0m, \e[1m\e[34misn't it?\e[0m", @logger.logged(:info).last
17159 assert_equal "\e[1;4m\e[32mrad\e[0m, \e[3m\e[33misn't it?\e[0m", @logger.logged(:info).last
17160 [] # Make an allocation
17161 i = 0
17162 ActiveSupport.on_load(:basic_hook) { i += 1 }
17163 block = proc { i += incr }
17164 i += incr
17165 i += obj.incr + incr_amt
17166 @incr = incr
17167 @a, @b = a, b
17168 { foo: "hello", bar: "world" }
17169 [ BigDecimal("2.5"), %("#{BigDecimal('2.5')}") ]]
17170 [ 'a "string" with quotes & an ampersand', %("a \\"string\\" with quotes \\u0026 an ampersand") ],
17171 [ "http://test.host/posts/1", %("http://test.host/posts/1")],
17172 [ [1, "a", :b, nil, false], %([1,\"a\",\"b\",null,false]) ]]
17173 [ 1.5..2.5, %("1.5..2.5")]]
17174 HashlikeTests = [[ Hashlike.new, %({\"bar\":\"world\",\"foo\":\"hello\"}) ]]
17175 [ MyStruct.new(nil, nil), %({\"name\":null,\"value\":null}) ]]
17176 [ Custom.new(nil), "null" ],
17177 [ Custom.new(:a), '"a"' ],
17178 [ Custom.new([ :foo, "bar" ]), '["foo","bar"]' ],
17179 [ Custom.new(foo: "hello", bar: "world"), '{"bar":"world","foo":"hello"}' ],
17180 [ Custom.new(Hashlike.new), '{"bar":"world","foo":"hello"}' ],
17181 [ Custom.new(Custom.new(Custom.new(:a))), '"a"' ]]
17182 PathnameTests = [[ Pathname.new("lib/index.rb"), %("lib/index.rb") ]]
17183 DateTimeTests = [[ DateTime.civil(2005, 2, 1, 15, 15, 10), %("2005/02/01 15:15:10 +0000") ]]
17184 StandardDateTimeTests = [[ DateTime.civil(2005, 2, 1, 15, 15, 10), %("2005-02-01T15:15:10.000+00:00") ]]
17185 if json.start_with?("{") && json.end_with?("}")
17186 assert_equal %({"exitstatus":#{$?.exitstatus},"pid":#{$?.pid}}), ActiveSupport::JSON.encode($?)
17187 assert_equal %({\"a\":\"b\"}), ActiveSupport::JSON.encode(a: :b)
17188 assert_equal %({\"a\":1}), ActiveSupport::JSON.encode("a" => 1)
17189 assert_equal %({\"a\":[1,2]}), ActiveSupport::JSON.encode("a" => [1, 2])
17190 assert_equal %({"1":2}), ActiveSupport::JSON.encode(1 => 2)
17191 assert_equal %({\"a\":\"b\",\"c\":\"d\"}), sorted_json(ActiveSupport::JSON.encode(a: :b, c: :d))
17192 assert_equal "{\"\\u003c\\u003e\":\"\\u003c\\u003e\"}", ActiveSupport::JSON.encode("<>" => "<>")
17193 assert_equal %w( "$" "A" "A0" "A0B" "_" "a" "0" "1" ).sort, object_keys(ActiveSupport::JSON.encode(values))
17194 assert_equal %({"a":1}), ActiveSupport::JSON.encode({ "a" => 1, :b => 2, :c => 3 }, { only: "a" })
17195 assert_equal %({"b":2}), ActiveSupport::JSON.encode({ "foo" => "bar", :b => 2, :c => 3 }, { except: ["foo", :c] })
17196 assert_equal %("2005-02-01T15:15:10.000-05:00"), ActiveSupport::JSON.encode(Time.local(2005, 2, 1, 15, 15, 10))
17197 assert_equal '{"time":"2009/01/01 00:00:00 +0000"}', { time: Time.utc(2009) }.to_json
17198 json = h.to_json only: [:foo]
17199 assert_equal({ "foo" => "hello" }, JSON.parse(json))
17200 json = obj.to_json only: ["foo"]
17201 struct = Struct.new(:foo, :bar).new
17202 struct.foo = "hello"
17203 struct.bar = "world"
17204 json = struct.to_json only: [:foo]
17205 klass = Struct.new(:foo, :bar)
17206 struct = klass.new "hello", "world"
17207 assert_equal({ "foo" => { "foo" => "hello" } }, JSON.parse(json))
17208 person = {
17209 name: "John",
17210 address: {
17211 city: "London",
17212 country: "UK"
17213 json = person.as_json only: [:address, :city]
17214 assert_equal({ "address" => { "city" => "London" } }, json)
17215 json = person.to_json only: [:address, :city]
17216 assert_equal(%({"address":{"city":"London"}}), json)
17217 people = [
17218 { name: "John", address: { city: "London", country: "UK" } },
17219 { name: "Jean", address: { city: "Paris", country: "France" } }
17220 json = people.as_json only: [:address, :city]
17221 { "address" => { "city" => "London" } },
17222 { "address" => { "city" => "Paris" } }
17223 json = people.to_json only: [:address, :city]
17224 assert_equal(%([{"address":{"city":"London"}},{"address":{"city":"Paris"}}]), json)
17225 @people = [
17226 def each(*, &blk)
17227 @people.each do |p|
17228 json = People.new.as_json only: [:address, :city]
17229 json = People.new.to_json only: [:address, :city]
17230 def as_json(options = {})
17231 options[:only] = %w(foo bar)
17232 f.foo = "hello"
17233 f.bar = "world"
17234 hash = { "foo" => f, "other_hash" => { "foo" => "other_foo", "test" => "other_test" } }
17235 assert_equal({ "foo" => { "foo" => "hello", "bar" => "world" },
17236 array = [f, { "foo" => "other_foo", "test" => "other_test" }]
17237 assert_equal([{ "foo" => "hello", "bar" => "world" },
17238 { "foo" => "other_foo", "test" => "other_test" }], ActiveSupport::JSON.decode(array.to_json))
17239 json = { foo: OptionsTest.new }.as_json
17240 assert_equal({ "foo" => :default }, json)
17241 Struct.new("Custom", :name, :sub)
17242 json_strings = ""
17243 json_string_and_date = ""
17244 json_custom = ""
17245 assert_equal({ "name" => "David",
17246 assert_equal({ "name" => "David", "email" => "sample@example.com" },
17247 assert_equal({ "name" => "David", "date" => "2010-01-01" },
17248 data = Data.define(:name, :email).new("test", "test@example.com")
17249 assert_equal({ "name" => "test", "email" => "test@example.com" },
17250 h[:foo] = "hello"
17251 h[:bar] = "world"
17252 assert_equal %({"foo":"hello","bar":"world"}), JSON.dump(h)
17253 assert_equal %({"foo":"hello","bar":"world"}), JSON.generate(h)
17254 { "number" => Float::NAN }
17255 json_object[1..-2].scan(/([^{}:,\s]+):/).flatten.sort
17256 %q({"return\\"To\\":":{"\/categories":"\/"}}) => { "return\"To\":" => { "/categories" => "/" } },
17257 %q({"returnTo":{"\/categories":1}}) => { "returnTo" => { "/categories" => 1 } },
17258 %(["2007-01-01 01:12:34 Z", "2007-01-01 01:12:35 Z"]) => [Time.utc(2007, 1, 1, 1, 12, 34), Time.utc(2007, 1, 1, 1, 12, 35)],
17259 %({"a": "2007-01-01 01:12:34 Z\
was my birthday"}) => { "a" => "2007-01-01 01:12:34 Z
was my birthday" },
17260 %({"a":1}) => { "a" => 1 },
17261 %({"a": ""}) => { "a" => "" },
17262 %({"a":"\\""}) => { "a" => "\"" },
17263 %({"a": false}) => { "a" => false },
17264 %q({"a": "http:\/\/test.host\/posts\/1"}) => { "a" => "http://test.host/posts/1" },
17265 %q({"a": "\u003cunicode\u0020escape\u003e"}) => { "a" => "<unicode escape>" },
17266 %q({"a": "\u003cbr /\u003e"}) => { "a" => "<br />" },
17267 %q({"b":["\u003ci\u003e","\u003cb\u003e","\u003cu\u003e"]}) => { "b" => ["<i>", "<b>", "<u>"] },
17268 %q([{"d":"1970-01-01", "s":"\u0020escape"},{"d":"1970-01-01", "s":"\u0020escape"}]) =>
17269 %q([{"d":"1970-01-01","s":"http:\/\/example.com"},{"d":"1970-01-01","s":"http:\/\/example.com"}]) =>
17270 [{ "d" => Date.new(1970, 1, 1), "s" => "http://example.com" },
17271 { "d" => Date.new(1970, 1, 1), "s" => "http://example.com" }],
17272 %q({"a":"
"}) => { "a" => "
" },
17273 %q({"a":"\u000a"}) => { "a" => "
" },
17274 %q({"a":"Line1\u000aLine2"}) => { "a" => "Line1
Line2" },
17275 expected = { "a" => "2007-01-01 01:12:34 Z" }
17276 assert_equal expected, ActiveSupport::JSON.decode(%({"a": "2007-01-01 01:12:34 Z"}))
17277 I18n.stub(:default_locale, :"en-GB") do
17278 ].each do |camel, under, human, title|
17279 inflect.human(/_cnt$/i, '\1_count')
17280 inflect.human(/^prefx_/i, '\1')
17281 inflect.plural(/$/, "s")
17282 inflect.plural(/z$/i, "ces")
17283 inflect.singular(/s$/, "")
17284 inflect.singular(/es$/, "")
17285 inflect.irregular("el", "los")
17286 assert_equal("luces", "luz".pluralize(:es))
17287 assert_equal("los", "el".pluralize(:es))
17288 assert_equal("agua", "agua".pluralize(:es))
17289 inflect.plural(/(quiz)$/i, '\1zes')
17290 inflect.singular(/(database)s$/i, '\1')
17291 [ :all, [] ].each do |scope|
17292 @date = Date.parse("2008-7-2")
17293 @time = Time.utc(2008, 7, 2, 16, 47, 1)
17294 assert_equal now.strftime("%a, %d %b %Y %H:%M:%S %z"), I18n.localize(now)
17295 assert_equal @date.strftime("%Y-%m-%d"), I18n.localize(@date)
17296 assert_equal @date.strftime("%Y-%m-%d"), I18n.localize(@date, format: :default)
17297 assert_equal @date.strftime("%B %d, %Y"), I18n.localize(@date, format: :long)
17298 assert_equal @time.strftime("%a, %d %b %Y %H:%M:%S %z"), I18n.localize(@time)
17299 assert_equal @time.strftime("%a, %d %b %Y %H:%M:%S %z"), I18n.localize(@time, format: :default)
17300 assert_equal @time.strftime("%d %b %H:%M"), I18n.localize(@time, format: :short)
17301 assert_equal @time.strftime("%B %d, %Y %H:%M"), I18n.localize(@time, format: :long)
17302 assert_equal "a, b, and c", %w[a b c].to_sentence
17303 I18n.backend.store_translations "en", support: { array: { two_words_connector: " & " } }
17304 assert_equal "a & b", %w[a b].to_sentence
17305 I18n.backend.store_translations "en", support: { array: { last_word_connector: " and " } }
17306 assert_equal "a, b and c", %w[a b c].to_sentence
17307 assert_equal "a, b, and c", %w[a b c].to_sentence(locale: "empty")
17308 @strings = { "a" => 1, "b" => 2 }
17309 @nested_strings = { "a" => { "b" => { "c" => 3 } } }
17310 @symbols = { a: 1, b: 2 }
17311 @nested_symbols = { a: { b: { c: 3 } } }
17312 @mixed = { :a => 1, "b" => 2 }
17313 @nested_mixed = { "a" => { b: { "c" => 3 } } }
17314 @integers = { 0 => 1, 1 => 2 }
17315 @nested_integers = { 0 => { 1 => { 2 => 3 } } }
17316 @illegal_symbols = { [] => 3 }
17317 @nested_illegal_symbols = { [] => { [] => 3 } }
17318 foo = { "foo" => SubclassingHash.new.tap { |h| h["bar"] = "baz" } }.with_indifferent_access
17319 foo = { "foo" => NonIndifferentHash.new.tap { |h| h["bar"] = "baz" } }.with_indifferent_access
17320 foo = { "foo" => IndifferentHash.new.tap { |h| h["bar"] = "baz" } }.with_indifferent_access
17321 assert_equal "a", @strings.__send__(:convert_key, :a)
17322 hashes = { :@strings => @strings, :@symbols => @symbols, :@mixed => @mixed }
17323 method_map = { '[]': 1, fetch: 1, values_at: [1],
17324 has_key?: true, include?: true, key?: true,
17325 member?: true }
17326 assert_equal(expected, hash.__send__(meth, "a"),
17327 assert_equal(expected, hash.__send__(meth, :a),
17328 assert_equal [1, 2], @strings.values_at("a", "b")
17329 assert_equal [1, 2], @strings.values_at(:a, :b)
17330 assert_equal [1, 2], @symbols.values_at("a", "b")
17331 assert_equal [1, 2], @symbols.values_at(:a, :b)
17332 assert_equal [1, 2], @mixed.values_at("a", "b")
17333 assert_equal [1, 2], @mixed.values_at(:a, :b)
17334 assert_equal [1, 2], @mixed.fetch_values("a", "b")
17335 assert_equal [1, 2], @mixed.fetch_values(:a, :b)
17336 assert_equal [1, 2], @mixed.fetch_values(:a, "b")
17337 assert_equal [1, "c"], @mixed.fetch_values(:a, :c) { |key| key }
17338 assert_raise(KeyError) { @mixed.fetch_values(:a, :c) }
17339 hash["a"] = 1
17340 hash["b"] = true
17341 hash["c"] = false
17342 hash["d"] = nil
17343 hash[:a] = 1
17344 hash["b"] = 2
17345 hash[3] = 3
17346 assert_equal 1, hash["a"]
17347 assert_equal 2, hash["b"]
17348 hash[:a] = "a"
17349 hash["b"] = "b"
17350 hash.update({ "a" => 1 }, { "b" => 2 })
17351 hash[:a] = "failure"
17352 hash["b"] = "failure"
17353 other = { "a" => 1, :b => 2 }
17354 merged = hash.merge({ "a" => 1 }, { "b" => 2 })
17355 hash[:a] = 42
17356 assert hash.key?("b")
17357 hash["b"] = 3
17358 other = { "a" => 4, :b => 2, "c" => 10 }
17359 merged = hash.merge(other) { |key, old, new| old > new ? old : new }
17360 merged = hash.merge(other_indifferent) { |key, old, new| old + new }
17361 hash = HashWithIndifferentAccess.new("some" => "value", "other" => "value")
17362 get_hash = proc { { a: "foo" }.with_indifferent_access }
17363 assert_equal "foo", hash.delete("a")
17364 assert_equal({ "a" => 1 }, hash)
17365 indifferent_strings.select! { |k, v| v == 1 }
17366 assert_equal({ "a" => 1 }, indifferent_strings)
17367 indifferent_strings.reject! { |k, v| v != 1 }
17368 assert_equal({ "aa" => 1, "bb" => 2 }, hash)
17369 assert_equal(1, hash[:a])
17370 assert_equal(1, hash["a"])
17371 hash = ActiveSupport::HashWithIndifferentAccess.new(@strings).transform_keys({ "a" => "x", "y" => "z" })
17372 assert_nil(hash["a"])
17373 assert_equal(1, hash["x"])
17374 assert_equal(2, hash["b"])
17375 assert_nil(hash["y"])
17376 assert_nil(hash["z"])
17377 hash = ActiveSupport::HashWithIndifferentAccess.new(@strings).transform_keys({ "a" => "A", "q" => "Q" }) { |k| k * 3 }
17378 assert_equal(1, hash["A"])
17379 assert_equal(2, hash["bbb"])
17380 assert_nil(hash["q"])
17381 assert_nil(hash["Q"])
17382 assert_equal({ "aa" => { "bb" => { "cc" => 3 } } }, hash)
17383 assert_equal(3, hash[:a][:b][:c])
17384 assert_equal(3, hash["a"]["b"]["c"])
17385 indifferent_strings.transform_keys! { |k| k * 2 }
17386 assert_equal({ "aa" => 1, "bb" => 2 }, indifferent_strings)
17387 hash.transform_keys!({ "a" => "x", "y" => "z" })
17388 hash.transform_keys!({ "a" => "A", "q" => "Q" }) { |k| k * 3 }
17389 hash.deep_transform_keys! { |k| k * 2 }
17390 hash.deep_transform_keys! { |k| k.to_sym }
17391 assert_equal({ "a" => 2, "b" => 4 }, hash)
17392 assert_equal({ "a" => 2, "b" => 4 }, indifferent_strings)
17393 assert_equal("a", key)
17394 hash_contain_nil_value = @strings.merge("z" => nil)
17395 hash = HashWithIndifferentAccess.new { |h, k| h[k] = [] }
17396 hash[:a] << 1
17397 assert_equal [1], hash[:a]
17398 hash = { content: [{ :foo => :bar, "bar" => "baz" }] }
17399 assert_equal [:foo, "bar"], hash[:content].first.keys
17400 hash = { "urls" => { "url" => [ { "address" => "1" }, { "address" => "2" } ] } }.with_indifferent_access
17401 assert_equal "1", hash[:urls][:url].first[:address]
17402 array << { "address" => "1" }
17403 hash = { "urls" => { "url" => array } }.with_indifferent_access
17404 hash = { "urls" => { "url" => array.freeze } }.with_indifferent_access
17405 h[:first] = 1
17406 assert_equal 1, h["first"]
17407 h["first"] = 1
17408 h = HashWithIndifferentAccess.new(a: { b: "b" })
17409 dup = h.dup
17410 dup[:a][:c] = "c"
17411 assert_equal "c", h[:a][:c]
17412 h = { "user" => { "id" => 5 } }.with_indifferent_access
17413 ["user", :user].each { |user| [:id, "id"].each { |id| assert_equal 5, h[user][id], "h[#{user.inspect}][#{id.inspect}] should be 5" } }
17414 h = { user: { id: 5 } }.with_indifferent_access
17415 h.default = "1234"
17416 data = { "this" => { "views" => 1234 } }.with_indifferent_access
17417 h = Hash.new { 5 }.merge(1 => 2).with_indifferent_access
17418 assert_equal "foo", h.default("foo")
17419 original = { Object.new => 2, 1 => 2, [] => true }
17420 assert_not(indiff.keys.any? { |k| k.kind_of? String }, "A key was converted to a string!")
17421 hash_1 = HashWithIndifferentAccess.new(a: "a", b: "b", c: { c1: "c1", c2: "c2", c3: { d1: "d1" } })
17422 hash_2 = HashWithIndifferentAccess.new(a: 1, c: { c1: 2, c3: { d2: "d2" } })
17423 hash_3 = { a: 1, c: { c1: 2, c3: { d2: "d2" } } }
17424 hash.store("test1", 11)
17425 hash[:test2] = 2
17426 hash["test2"] = 22
17427 expected = { "test1" => 11, "test2" => 22 }
17428 hash[:foo] = 3
17429 original = { a: "x", b: "y", c: 10 }.with_indifferent_access
17430 expected = { a: "x", b: "y" }.with_indifferent_access
17431 [["a", "b"], [:a, :b]].each do |keys|
17432 original = { "login" => "bender", "password" => "shiny", "stuff" => "foo" }
17433 original = { :a => 1, "b" => 2, :c => 3, "d" => 4 }.with_indifferent_access
17434 expected = { a: 1, b: 2 }.with_indifferent_access
17435 remaining = { c: 3, d: 4 }.with_indifferent_access
17436 assert hash.key?("a")
17437 hash.default_proc = proc { |h, v| raise "walrus" }
17438 hash.default_proc = proc { |h, k| k + 1 }
17439 hash.default_proc = proc { |h, k| raise "walrus" }
17440 normal_hash[:a] = 1
17441 normal_hash = Hash.new { 1 + 2 }
17442 @foo = "bar"
17443 value = [1, 2, 3].freeze
17444 hash[:key] = value
17445 hash = Hash.new(3)
17446 2 + 1
17447 h = { foo: :bar }
17448 h.default = :baz
17449 h.default_proc = ->(hash, key) { hash[key] = :baz }
17450 if pid = fork
17451 assert_no_difference -> { count } do
17452 assert_difference -> { count }, +1 do
17453 def new_checker(files = [], dirs = {}, &block)
17454 @tmpfiles ||= %w(foo.rb bar.rb baz.rb).map { |f| tmpfile(f) }
17455 Dir.mktmpdir(nil, __dir__) { |dir| @tmpdir = dir; super }
17456 checker = new_checker { i += 1 }
17457 checker = new_checker(tmpfiles) { i += 1 }
17458 touch(tmpfiles[1..-1])
17459 checker = new_checker([], tmpdir => :rb) { i += 1 }
17460 checker = new_checker([], tmpdir => []) { i += 1 }
17461 checker = new_checker([], tmpdir => [:rb, :txt]) { i += 1 }
17462 checker = new_checker([], tmpdir => :txt) { i += 1 }
17463 checker = new_checker([non_existing]) { i += 1 }
17464 checker = new_checker([], tmpdir => :rb, subdir => :txt) { i += 1 }
17465 new_checker([])
17466 executor.to_run { called << :run }
17467 called << :body
17468 executor.to_run { @foo = true }
17469 executor.to_run { called << :run_1 }
17470 executor.to_run { called << :run_2 }
17471 executor.wrap { called << :body }
17472 called << :early
17473 called << :late
17474 assert_equal [:run, :early, :body, :late, :complete], called
17475 invoked = []
17476 supplied_state = []
17477 invoked << :"run_#{letter}"
17478 :"state_#{letter}"
17479 invoked << :"complete_#{letter}"
17480 assert_equal [:run_c, :run_a, :run_b, :run_d, :complete_a, :complete_b, :complete_d, :complete_c], invoked
17481 assert_equal [:state_a, :state_b, :state_d, :state_c], supplied_state
17482 other_executor.to_run { called << :other_run }
17483 test "#[]= coerce keys to symbol" do
17484 context[:foo] = 43
17485 checker = new_checker([], linked_dir => ".rb") { }
17486 touch(File.join(actual_dir, "a.rb"))
17487 checker = new_checker([], watched_dir => ".rb", not_exist_watched_dir => ".rb") { }
17488 dir1 = File.join(tmpdir, "app")
17489 dir2 = File.join(tmpdir, "test")
17490 checker1 = new_checker([], dir1 => ".rb") { }
17491 checker2 = new_checker([], dir2 => ".rb") { }
17492 touch(File.join(dir1, "a.rb"))
17493 touch(File.join(dir2, "a.rb"))
17494 assert_equal [[error, true, :warning, "application", { section: "admin" }]], @subscriber.events
17495 assert_equal [[error, true, :warning, "application", { section: "public" }]], @subscriber.events
17496 assert_equal [[error, true, :warning, "my_gem", {}]], @subscriber.events
17497 2 + 2
17498 result = @reporter.handle(fallback: -> { 2 + 2 }) do
17499 assert_equal [[error, false, :error, "application", {}]], @subscriber.events
17500 @key_path = File.join(@tmpdir, "content.txt.key")
17501 encrypted_file(@content_path, key_path: "", env_key: "").read
17502 @tmpdir = Dir.mktmpdir("config-")
17503 @credentials.write({ something: { good: true, bad: false } }.to_yaml)
17504 @credentials.write({ something: { good: true, bad: false, nested: { foo: "bar" } } }.to_yaml)
17505 assert_equal ({ good: true, bad: false, nested: { foo: "bar" } }), @credentials.something
17506 @credentials.write({ something: { good: true } }.to_yaml)
17507 @original_state.each { |k, v| @original_state[k] = v.dup }
17508 def zero() 0 end
17509 def one(a) a end
17510 def multi(a, b, c) [a, b, c] end
17511 BAR = "foo bar"
17512 assert_equal [1, 2, 3], klass.new.multi(1, 2, 3)
17513 hash = { k: 1 }
17514 behavior.call("Some error!", ["call stack!"], @deprecator)
17515 instance.foo_bar = "foo bar!"
17516 legacy = Module.new { def self.name; "Legacy"; end }
17517 assert_deprecated(@deprecator) { 1 + 1 }
17518 assert_equal [1, 2, 3], klass.new.multi!(1, 2, 3)
17519 @deprecator.warn("message", [])
17520 @deprecator.allow(["foo bar", "baz qux"]) do
17521 @deprecator.allow([:"foo bar", :"baz qux"]) do
17522 @deprecator.allow([/(foo|baz) (bar|qux)/]) do
17523 @deprecator.allow("fubar", if: -> { true }) do
17524 @deprecator.allow("fubar", if: -> { false }) do
17525 @deprecator.behavior = ->(_, callstack, *) { @callstack = callstack }
17526 @messages ||= []
17527 disallowed = []
17528 bindings = []
17529 callbacks = [
17530 klass = Class.new { extend mod }
17531 @deprecator_names = [:fubar, :foo, :bar]
17532 gem_names = []
17533 callback = proc { }
17534 File.write("#{@root_dir}/x.rb", "X = :X")
17535 def x.to_path; "x"; end
17536 File.write("#{dir}/y.rb", "Y = :Y")
17537 $loaded_service_one ||= 0
17538 Person = Struct.new(:id, :name, :time_zone)
17539 self.person = Person.new(1, "#{account}'s person")
17540 hash[:world] = world
17541 Current.person = Person.new(42, "David", "Central Time (US & Canada)")
17542 @utc = Time.utc(2000, 1, 1, 0)
17543 assert_equal Time.utc(1999, 12, 31, 19), @twz.time
17544 assert_equal Time.utc(2014, 10, 25, 22, 0, 0), Time.local(2014, 10, 26, 1, 0, 0).in_time_zone("Moscow")
17545 assert_equal "1999-12-31 19:00:00 EST -0500", @twz.strftime("%Y-%m-%d %H:%M:%S %Z %z")
17546 assert_equal "%Z %z", @twz.strftime("%%Z %%z")
17547 assert_equal "%EST %-0500", @twz.strftime("%%%Z %%%z")
17548 one_third_sec = Time.utc(1986, 12, 12, 6, 23, 00, Rational(1000000, 3))
17549 assert_equal "1999-12-31 19:00:00 -0500", @twz.to_s
17550 assert_equal "1999-12-31 19:00:00 -0500", @twz.to_fs
17551 assert_equal "2000-01-01 00:00:00", @twz.to_fs(:db)
17552 assert_equal "2000-01-01 00:00:00", @twz.to_formatted_s(:db)
17553 @twz += Rational(1, 8)
17554 assert_equal(yaml, { "twz" => @twz }.to_yaml)
17555 assert_equal({ "twz" => @twz }, loaded)
17556 assert_equal 1, @twz <=> Time.utc(1999, 12, 31, 23, 59, 59)
17557 assert_equal 0, @twz <=> Time.utc(2000, 1, 1, 0, 0, 0)
17558 assert_equal(-1, @twz <=> Time.utc(2000, 1, 1, 0, 0, 1))
17559 assert_equal 1, @twz <=> DateTime.civil(1999, 12, 31, 23, 59, 59)
17560 assert_equal 0, @twz <=> DateTime.civil(2000, 1, 1, 0, 0, 0)
17561 assert_equal(-1, @twz <=> DateTime.civil(2000, 1, 1, 0, 0, 1))
17562 assert_equal 0, @twz <=> ActiveSupport::TimeWithZone.new(Time.utc(2000, 1, 1, 0, 0, 0), ActiveSupport::TimeZone["UTC"])
17563 assert_equal(-1, @twz <=> ActiveSupport::TimeWithZone.new(Time.utc(2000, 1, 1, 0, 0, 1), ActiveSupport::TimeZone["UTC"]))
17564 assert @twz.between?(Time.utc(1999, 12, 31, 23, 59, 59), Time.utc(2000, 1, 1, 0, 0, 1))
17565 assert_equal false, @twz.between?(Time.utc(2000, 1, 1, 0, 0, 1), Time.utc(2000, 1, 1, 0, 0, 2))
17566 Date.stub(:current, Date.new(2000, 1, 1)) do
17567 Time.stub(:current, Time.local(2005, 2, 10, 15, 30, 45)) do
17568 twz = ActiveSupport::TimeWithZone.new(Time.utc(2017, 3, 6, 12, 0, 0), @time_zone)
17569 assert_equal false, @twz.eql?(Time.utc(2000, 1, 1, 0, 0, 1))
17570 assert_equal false, @twz.eql?(DateTime.civil(1999, 12, 31, 23, 59, 59))
17571 assert_equal Time.utc(1999, 12, 31, 19, 0, 5), (@twz + 5).time
17572 datetime = DateTime.civil(2000, 1, 1, 0)
17573 assert_equal DateTime.civil(1999, 12, 31, 19, 0, 5), (twz + 5).time
17574 assert_equal [0, 0, 19, 19, 1, 2038], (twz + 86_400).to_a[0, 6]
17575 assert_equal Time.utc(2000, 1, 5, 19, 0, 0), (@twz + 5.days).time
17576 assert_equal Time.utc(1999, 12, 31, 18, 59, 55), (@twz - 5).time
17577 assert_equal DateTime.civil(1999, 12, 31, 18, 59, 55), (twz - 5).time
17578 assert_equal Time.utc(1999, 12, 26, 19, 0, 0), (@twz - 5.days).time
17579 utc = Time.utc(2006, 4, 2, 6, 59, 59) # == Apr 2 2006 01:59:59 EST; i.e., 1 second before daylight savings start
17580 twz = twz + 1
17581 utc = Time.utc(2006, 10, 29, 5, 59, 59) # == Oct 29 2006 01:59:59 EST; i.e., 1 second before daylight savings end
17582 assert_equal Time.utc(2006, 10, 29, 1, 59, 59), twz.time
17583 twz = twz - 1
17584 assert_equal [45, 30, 5, 1, 2, 2000, 2, 32, false, "HST"], ActiveSupport::TimeWithZone.new(Time.utc(2000, 2, 1, 15, 30, 45), ActiveSupport::TimeZone["Hawaii"]).to_a
17585 time = @twz.to_time
17586 assert_equal Time.utc(2000, 1, 31, 19, 0, 0), @twz.months_since(1).time
17587 time = @twz.time
17588 def time.foo; "bar"; end
17589 utc = Time.utc(2000, 1, 1, 0, 30)
17590 utc = Time.utc(2000, 1, 1, 0, 30, 10)
17591 twz = ActiveSupport::TimeWithZone.new(nil, @time_zone, Time.utc(2006, 4, 2, 1, 59, 59))
17592 assert_equal "Sun, 02 Apr 2006 03:00:00.000000000 EDT -04:00", (twz + 1).inspect
17593 assert_equal "Sun, 02 Apr 2006 10:30:01.000000000 EDT -04:00", (twz + 1.days + 1.second).inspect
17594 assert_equal "Sun, 29 Oct 2006 10:30:01.000000000 EST -05:00", (twz + 1.days + 1.second).inspect
17595 @t, @dt, @zone = Time.utc(2000), DateTime.civil(2000), Time.zone
17596 time = Time.local(1999, 12, 31, 19) # == Time.utc(2000)
17597 Time.zone = "Alaska"
17598 time = "2019-01-01 00:00:00Z".to_time.end_of_month
17599 Time.zone = -9.hours
17600 t1 = Thread.new { Time.zone = "Alaska"; Time.zone }
17601 t2 = Thread.new { Time.zone = "Hawaii"; Time.zone }
17602 time = Time.local(2000, 7, 1)
17603 assert_equal Time.utc(2000, 6, 30, 23, 0, 0), time_with_zone
17604 @d = Date.civil(2000)
17605 @s = "Sat, 01 Jan 2000 00:00:00"
17606 @u = "Sat, 01 Jan 2000 00:00:00 UTC +00:00"
17607 @z = "Fri, 31 Dec 1999 19:00:00 EST -05:00"
17608 assert_equal Time.utc(2014, 10, 25, 22, 0, 0), "2014-10-26 01:00:00".in_time_zone
17609 assert_equal 2 * 3600 - 1, Time.local(2005, 4, 3, 1, 59, 59).seconds_since_midnight, "just before DST start"
17610 assert_equal 2 * 3600 + 1, Time.local(2005, 4, 3, 3, 0, 1).seconds_since_midnight, "just after DST start"
17611 with_env_tz "NZ" do
17612 assert_equal 2 * 3600 - 1, Time.local(2006, 10, 1, 1, 59, 59).seconds_since_midnight, "just before DST start"
17613 assert_equal 2 * 3600 + 1, Time.local(2006, 10, 1, 3, 0, 1).seconds_since_midnight, "just after DST start"
17614 assert_equal 1 * 3600 - 1, Time.local(2005, 10, 30, 0, 59, 59).seconds_since_midnight, "just before DST end"
17615 assert_equal 3 * 3600 + 1, Time.local(2005, 10, 30, 2, 0, 1).seconds_since_midnight, "just after DST end"
17616 assert_equal 1 * 3600 + 30 * 60, Time.local(0, 30, 1, 30, 10, 2005, 0, 0, true, ENV["TZ"]).seconds_since_midnight, "before DST end"
17617 assert_equal 2 * 3600 + 30 * 60, Time.local(0, 30, 1, 30, 10, 2005, 0, 0, false, ENV["TZ"]).seconds_since_midnight, "after DST end"
17618 assert_equal 2 * 3600 - 1, Time.local(2006, 3, 19, 1, 59, 59).seconds_since_midnight, "just before DST end"
17619 assert_equal 4 * 3600 + 1, Time.local(2006, 3, 19, 3, 0, 1).seconds_since_midnight, "just after DST end"
17620 assert_equal 2 * 3600 + 30 * 60, Time.local(0, 30, 2, 19, 3, 2006, 0, 0, true, ENV["TZ"]).seconds_since_midnight, "before DST end"
17621 assert_equal 3 * 3600 + 30 * 60, Time.local(0, 30, 2, 19, 3, 2006, 0, 0, false, ENV["TZ"]).seconds_since_midnight, "after DST end"
17622 assert_equal 21 * 3600 - 2, Time.local(2005, 4, 3, 3, 0, 1).seconds_until_end_of_day, "just after DST start"
17623 assert_equal 21 * 3600 - 2, Time.local(2006, 10, 1, 3, 0, 1).seconds_until_end_of_day, "just after DST start"
17624 assert_equal 22 * 3600 - 2, Time.local(2005, 10, 30, 2, 0, 1).seconds_until_end_of_day, "just after DST end"
17625 assert_equal 24 * 3600 - 30 * 60 - 1, Time.local(0, 30, 1, 30, 10, 2005, 0, 0, true, ENV["TZ"]).seconds_until_end_of_day, "before DST end"
17626 assert_equal 23 * 3600 - 30 * 60 - 1, Time.local(0, 30, 1, 30, 10, 2005, 0, 0, false, ENV["TZ"]).seconds_until_end_of_day, "after DST end"
17627 assert_equal 23 * 3600, Time.local(2006, 3, 19, 1, 59, 59).seconds_until_end_of_day, "just before DST end"
17628 assert_equal 21 * 3600 - 2, Time.local(2006, 3, 19, 3, 0, 1).seconds_until_end_of_day, "just after DST end"
17629 assert_equal 23 * 3600 - 30 * 60 - 1, Time.local(0, 30, 2, 19, 3, 2006, 0, 0, true, ENV["TZ"]).seconds_until_end_of_day, "before DST end"
17630 assert_equal 22 * 3600 - 30 * 60 - 1, Time.local(0, 30, 2, 19, 3, 2006, 0, 0, false, ENV["TZ"]).seconds_until_end_of_day, "after DST end"
17631 time = Time.utc(2016, 4, 23, 0, 0, Rational(1, 1_000_000_000))
17632 time = Time.utc(2016, 4, 23, 0, 0, 0.000_000_001)
17633 time = Time.utc(2016, 4, 23, 0, 0, 0, Rational(1, 1_000))
17634 time = Time.utc(2016, 4, 23, 0, 0, 0, 0.001)
17635 time = Time.utc(2016, 4, 23, 0, 0, "0.123456789".to_r)
17636 time = Time.utc(2016, 4, 30, 23, 59, "59.123456789".to_r)
17637 assert_equal Time.utc(2016, 5, 1, 0, 0), time.ceil
17638 assert_equal Time.local(2005, 2, 4, 0, 0, 0), Time.local(2005, 2, 4, 10, 10, 10).beginning_of_day
17639 assert_equal Time.local(2006, 4, 2, 0, 0, 0), Time.local(2006, 4, 2, 10, 10, 10).beginning_of_day, "start DST"
17640 assert_equal Time.local(2006, 10, 29, 0, 0, 0), Time.local(2006, 10, 29, 10, 10, 10).beginning_of_day, "ends DST"
17641 assert_equal Time.local(2006, 3, 19, 0, 0, 0), Time.local(2006, 3, 19, 10, 10, 10).beginning_of_day, "ends DST"
17642 assert_equal Time.local(2006, 10, 1, 0, 0, 0), Time.local(2006, 10, 1, 10, 10, 10).beginning_of_day, "start DST"
17643 assert_equal Time.local(2005, 2, 4, 12, 0, 0), Time.local(2005, 2, 4, 10, 10, 10).middle_of_day
17644 assert_equal Time.local(2006, 4, 2, 12, 0, 0), Time.local(2006, 4, 2, 10, 10, 10).middle_of_day, "start DST"
17645 assert_equal Time.local(2006, 10, 29, 12, 0, 0), Time.local(2006, 10, 29, 10, 10, 10).middle_of_day, "ends DST"
17646 assert_equal Time.local(2006, 3, 19, 12, 0, 0), Time.local(2006, 3, 19, 10, 10, 10).middle_of_day, "ends DST"
17647 assert_equal Time.local(2006, 10, 1, 12, 0, 0), Time.local(2006, 10, 1, 10, 10, 10).middle_of_day, "start DST"
17648 assert_equal Time.local(2005, 2, 4, 19, 0, 0), Time.local(2005, 2, 4, 19, 30, 10).beginning_of_hour
17649 assert_equal Time.local(2005, 2, 4, 19, 30, 0), Time.local(2005, 2, 4, 19, 30, 10).beginning_of_minute
17650 assert_equal Time.local(2007, 8, 12, 23, 59, 59, Rational(999999999, 1000)), Time.local(2007, 8, 12, 10, 10, 10).end_of_day
17651 assert_equal Time.local(2007, 4, 2, 23, 59, 59, Rational(999999999, 1000)), Time.local(2007, 4, 2, 10, 10, 10).end_of_day, "start DST"
17652 assert_equal Time.local(2007, 10, 29, 23, 59, 59, Rational(999999999, 1000)), Time.local(2007, 10, 29, 10, 10, 10).end_of_day, "ends DST"
17653 assert_equal Time.local(2006, 3, 19, 23, 59, 59, Rational(999999999, 1000)), Time.local(2006, 3, 19, 10, 10, 10).end_of_day, "ends DST"
17654 assert_equal Time.local(2006, 10, 1, 23, 59, 59, Rational(999999999, 1000)), Time.local(2006, 10, 1, 10, 10, 10).end_of_day, "start DST"
17655 assert_equal Time.local(2015, 2, 8, 23, 59, 59, Rational(999999999, 1000)), Time.new(2015, 2, 8, 8, 0, 0, "+05:00").end_of_day
17656 assert_equal Time.local(2005, 2, 4, 19, 59, 59, Rational(999999999, 1000)), Time.local(2005, 2, 4, 19, 30, 10).end_of_hour
17657 assert_equal Time.local(2005, 2, 4, 19, 30, 59, Rational(999999999, 1000)), Time.local(2005, 2, 4, 19, 30, 10).end_of_minute
17658 assert_equal Time.local(2005, 2, 20, 10, 10, 10), Time.local(2005, 2, 22, 10, 10, 10).ago(86400 * 2)
17659 assert_equal Time.local(2005, 4, 2, 3, 18, 0), Time.local(2005, 4, 3, 4, 18, 0).ago(24.hours), "dt-24.hours=>st"
17660 assert_equal Time.local(2005, 4, 2, 3, 18, 0), Time.local(2005, 4, 3, 4, 18, 0).ago(86400), "dt-86400=>st"
17661 assert_equal Time.local(2005, 4, 2, 3, 18, 0), Time.local(2005, 4, 3, 4, 18, 0).ago(86400.seconds), "dt-86400.seconds=>st"
17662 assert_equal Time.local(2005, 4, 1, 4, 18, 0), Time.local(2005, 4, 2, 4, 18, 0).ago(24.hours), "st-24.hours=>st"
17663 assert_equal Time.local(2005, 4, 1, 4, 18, 0), Time.local(2005, 4, 2, 4, 18, 0).ago(86400), "st-86400=>st"
17664 assert_equal Time.local(2005, 4, 1, 4, 18, 0), Time.local(2005, 4, 2, 4, 18, 0).ago(86400.seconds), "st-86400.seconds=>st"
17665 assert_equal Time.local(2006, 9, 30, 3, 18, 0), Time.local(2006, 10, 1, 4, 18, 0).ago(24.hours), "dt-24.hours=>st"
17666 assert_equal Time.local(2006, 9, 30, 3, 18, 0), Time.local(2006, 10, 1, 4, 18, 0).ago(86400), "dt-86400=>st"
17667 assert_equal Time.local(2006, 9, 30, 3, 18, 0), Time.local(2006, 10, 1, 4, 18, 0).ago(86400.seconds), "dt-86400.seconds=>st"
17668 assert_equal Time.local(2006, 9, 29, 4, 18, 0), Time.local(2006, 9, 30, 4, 18, 0).ago(24.hours), "st-24.hours=>st"
17669 assert_equal Time.local(2006, 9, 29, 4, 18, 0), Time.local(2006, 9, 30, 4, 18, 0).ago(86400), "st-86400=>st"
17670 assert_equal Time.local(2006, 9, 29, 4, 18, 0), Time.local(2006, 9, 30, 4, 18, 0).ago(86400.seconds), "st-86400.seconds=>st"
17671 assert_equal Time.local(2005, 10, 29, 5, 3), Time.local(2005, 10, 30, 4, 3, 0).ago(24.hours), "st-24.hours=>dt"
17672 assert_equal Time.local(2005, 10, 29, 5, 3), Time.local(2005, 10, 30, 4, 3, 0).ago(86400), "st-86400=>dt"
17673 assert_equal Time.local(2005, 10, 29, 5, 3), Time.local(2005, 10, 30, 4, 3, 0).ago(86400.seconds), "st-86400.seconds=>dt"
17674 assert_equal Time.local(2005, 10, 28, 4, 3), Time.local(2005, 10, 29, 4, 3, 0).ago(24.hours), "dt-24.hours=>dt"
17675 assert_equal Time.local(2005, 10, 28, 4, 3), Time.local(2005, 10, 29, 4, 3, 0).ago(86400), "dt-86400=>dt"
17676 assert_equal Time.local(2005, 10, 28, 4, 3), Time.local(2005, 10, 29, 4, 3, 0).ago(86400.seconds), "dt-86400.seconds=>dt"
17677 assert_equal Time.local(2006, 3, 18, 5, 3), Time.local(2006, 3, 19, 4, 3, 0).ago(24.hours), "st-24.hours=>dt"
17678 assert_equal Time.local(2006, 3, 18, 5, 3), Time.local(2006, 3, 19, 4, 3, 0).ago(86400), "st-86400=>dt"
17679 assert_equal Time.local(2006, 3, 18, 5, 3), Time.local(2006, 3, 19, 4, 3, 0).ago(86400.seconds), "st-86400.seconds=>dt"
17680 assert_equal Time.local(2006, 3, 17, 4, 3), Time.local(2006, 3, 18, 4, 3, 0).ago(24.hours), "dt-24.hours=>dt"
17681 assert_equal Time.local(2006, 3, 17, 4, 3), Time.local(2006, 3, 18, 4, 3, 0).ago(86400), "dt-86400=>dt"
17682 assert_equal Time.local(2006, 3, 17, 4, 3), Time.local(2006, 3, 18, 4, 3, 0).ago(86400.seconds), "dt-86400.seconds=>dt"
17683 assert_equal Time.local(2005, 4, 2, 4, 18, 0), Time.local(2005, 4, 3, 4, 18, 0).ago(1.day), "dt-1.day=>st"
17684 assert_equal Time.local(2005, 4, 1, 4, 18, 0), Time.local(2005, 4, 2, 4, 18, 0).ago(1.day), "st-1.day=>st"
17685 assert_equal Time.local(2006, 9, 30, 4, 18, 0), Time.local(2006, 10, 1, 4, 18, 0).ago(1.day), "dt-1.day=>st"
17686 assert_equal Time.local(2006, 9, 29, 4, 18, 0), Time.local(2006, 9, 30, 4, 18, 0).ago(1.day), "st-1.day=>st"
17687 assert_equal Time.local(2005, 10, 29, 4, 3), Time.local(2005, 10, 30, 4, 3, 0).ago(1.day), "st-1.day=>dt"
17688 assert_equal Time.local(2005, 10, 28, 4, 3), Time.local(2005, 10, 29, 4, 3, 0).ago(1.day), "dt-1.day=>dt"
17689 assert_equal Time.local(2006, 3, 18, 4, 3), Time.local(2006, 3, 19, 4, 3, 0).ago(1.day), "st-1.day=>dt"
17690 assert_equal Time.local(2006, 3, 17, 4, 3), Time.local(2006, 3, 18, 4, 3, 0).ago(1.day), "dt-1.day=>dt"
17691 assert_equal Time.local(2005, 2, 22, 10, 10, 11), Time.local(2005, 2, 22, 10, 10, 10).since(1)
17692 assert_equal Time.local(2005, 2, 22, 11, 10, 10), Time.local(2005, 2, 22, 10, 10, 10).since(3600)
17693 assert_equal Time.local(2005, 2, 24, 10, 10, 10), Time.local(2005, 2, 22, 10, 10, 10).since(86400 * 2)
17694 assert_equal Time.local(2005, 2, 24, 11, 10, 35), Time.local(2005, 2, 22, 10, 10, 10).since(86400 * 2 + 3600 + 25)
17695 assert_equal DateTime.civil(2038, 1, 20, 11, 59, 59), Time.utc(2038, 1, 18, 11, 59, 59).since(86400 * 2)
17696 assert_equal Time.local(2005, 4, 3, 20, 27, 0), Time.local(2005, 4, 2, 19, 27, 0).since(24.hours), "st+24.hours=>dt"
17697 assert_equal Time.local(2005, 4, 3, 20, 27, 0), Time.local(2005, 4, 2, 19, 27, 0).since(86400), "st+86400=>dt"
17698 assert_equal Time.local(2005, 4, 3, 20, 27, 0), Time.local(2005, 4, 2, 19, 27, 0).since(86400.seconds), "st+86400.seconds=>dt"
17699 assert_equal Time.local(2005, 4, 4, 19, 27, 0), Time.local(2005, 4, 3, 19, 27, 0).since(24.hours), "dt+24.hours=>dt"
17700 assert_equal Time.local(2005, 4, 4, 19, 27, 0), Time.local(2005, 4, 3, 19, 27, 0).since(86400), "dt+86400=>dt"
17701 assert_equal Time.local(2005, 4, 4, 19, 27, 0), Time.local(2005, 4, 3, 19, 27, 0).since(86400.seconds), "dt+86400.seconds=>dt"
17702 assert_equal Time.local(2006, 10, 1, 20, 27, 0), Time.local(2006, 9, 30, 19, 27, 0).since(24.hours), "st+24.hours=>dt"
17703 assert_equal Time.local(2006, 10, 1, 20, 27, 0), Time.local(2006, 9, 30, 19, 27, 0).since(86400), "st+86400=>dt"
17704 assert_equal Time.local(2006, 10, 1, 20, 27, 0), Time.local(2006, 9, 30, 19, 27, 0).since(86400.seconds), "st+86400.seconds=>dt"
17705 assert_equal Time.local(2006, 10, 2, 19, 27, 0), Time.local(2006, 10, 1, 19, 27, 0).since(24.hours), "dt+24.hours=>dt"
17706 assert_equal Time.local(2006, 10, 2, 19, 27, 0), Time.local(2006, 10, 1, 19, 27, 0).since(86400), "dt+86400=>dt"
17707 assert_equal Time.local(2006, 10, 2, 19, 27, 0), Time.local(2006, 10, 1, 19, 27, 0).since(86400.seconds), "dt+86400.seconds=>dt"
17708 assert_equal Time.local(2005, 4, 3, 19, 27, 0), Time.local(2005, 4, 2, 19, 27, 0).since(1.day), "st+1.day=>dt"
17709 assert_equal Time.local(2005, 4, 4, 19, 27, 0), Time.local(2005, 4, 3, 19, 27, 0).since(1.day), "dt+1.day=>dt"
17710 assert_equal Time.local(2006, 10, 1, 19, 27, 0), Time.local(2006, 9, 30, 19, 27, 0).since(1.day), "st+1.day=>dt"
17711 assert_equal Time.local(2006, 10, 2, 19, 27, 0), Time.local(2006, 10, 1, 19, 27, 0).since(1.day), "dt+1.day=>dt"
17712 assert_equal Time.local(2005, 4, 3, 19, 27, 0), Time.local(2005, 4, 2, 19, 27, 0).tomorrow, "st+1.day=>dt"
17713 assert_equal Time.local(2005, 4, 4, 19, 27, 0), Time.local(2005, 4, 3, 19, 27, 0).tomorrow, "dt+1.day=>dt"
17714 assert_equal Time.local(2006, 10, 1, 19, 27, 0), Time.local(2006, 9, 30, 19, 27, 0).tomorrow, "st+1.day=>dt"
17715 assert_equal Time.local(2006, 10, 2, 19, 27, 0), Time.local(2006, 10, 1, 19, 27, 0).tomorrow, "dt+1.day=>dt"
17716 assert_equal Time.local(2005, 4, 2, 19, 27, 0), Time.local(2005, 4, 3, 19, 27, 0).yesterday, "dt-1.day=>st"
17717 assert_equal Time.local(2005, 4, 3, 19, 27, 0), Time.local(2005, 4, 4, 19, 27, 0).yesterday, "dt-1.day=>dt"
17718 assert_equal Time.local(2006, 9, 30, 19, 27, 0), Time.local(2006, 10, 1, 19, 27, 0).yesterday, "dt-1.day=>st"
17719 assert_equal Time.local(2006, 10, 1, 19, 27, 0), Time.local(2006, 10, 2, 19, 27, 0).yesterday, "dt-1.day=>dt"
17720 assert_equal Time.local(2005, 10, 30, 23, 45, 0), Time.local(2005, 10, 30, 0, 45, 0).since(24.hours), "dt+24.hours=>st"
17721 assert_equal Time.local(2005, 10, 30, 23, 45, 0), Time.local(2005, 10, 30, 0, 45, 0).since(86400), "dt+86400=>st"
17722 assert_equal Time.local(2005, 10, 30, 23, 45, 0), Time.local(2005, 10, 30, 0, 45, 0).since(86400.seconds), "dt+86400.seconds=>st"
17723 assert_equal Time.local(2005, 11, 1, 0, 45, 0), Time.local(2005, 10, 31, 0, 45, 0).since(24.hours), "st+24.hours=>st"
17724 assert_equal Time.local(2005, 11, 1, 0, 45, 0), Time.local(2005, 10, 31, 0, 45, 0).since(86400), "st+86400=>st"
17725 assert_equal Time.local(2005, 11, 1, 0, 45, 0), Time.local(2005, 10, 31, 0, 45, 0).since(86400.seconds), "st+86400.seconds=>st"
17726 assert_equal Time.local(2006, 3, 20, 0, 45, 0), Time.local(2006, 3, 19, 1, 45, 0).since(24.hours), "dt+24.hours=>st"
17727 assert_equal Time.local(2006, 3, 20, 0, 45, 0), Time.local(2006, 3, 19, 1, 45, 0).since(86400), "dt+86400=>st"
17728 assert_equal Time.local(2006, 3, 20, 0, 45, 0), Time.local(2006, 3, 19, 1, 45, 0).since(86400.seconds), "dt+86400.seconds=>st"
17729 assert_equal Time.local(2006, 3, 21, 1, 45, 0), Time.local(2006, 3, 20, 1, 45, 0).since(24.hours), "st+24.hours=>st"
17730 assert_equal Time.local(2006, 3, 21, 1, 45, 0), Time.local(2006, 3, 20, 1, 45, 0).since(86400), "st+86400=>st"
17731 assert_equal Time.local(2006, 3, 21, 1, 45, 0), Time.local(2006, 3, 20, 1, 45, 0).since(86400.seconds), "st+86400.seconds=>st"
17732 assert_equal Time.local(2005, 10, 31, 0, 45, 0), Time.local(2005, 10, 30, 0, 45, 0).since(1.day), "dt+1.day=>st"
17733 assert_equal Time.local(2005, 11, 1, 0, 45, 0), Time.local(2005, 10, 31, 0, 45, 0).since(1.day), "st+1.day=>st"
17734 assert_equal Time.local(2006, 3, 20, 1, 45, 0), Time.local(2006, 3, 19, 1, 45, 0).since(1.day), "dt+1.day=>st"
17735 assert_equal Time.local(2006, 3, 21, 1, 45, 0), Time.local(2006, 3, 20, 1, 45, 0).since(1.day), "st+1.day=>st"
17736 assert_equal Time.local(2005, 10, 31, 0, 45, 0), Time.local(2005, 10, 30, 0, 45, 0).tomorrow, "dt+1.day=>st"
17737 assert_equal Time.local(2005, 11, 1, 0, 45, 0), Time.local(2005, 10, 31, 0, 45, 0).tomorrow, "st+1.day=>st"
17738 assert_equal Time.local(2006, 3, 20, 1, 45, 0), Time.local(2006, 3, 19, 1, 45, 0).tomorrow, "dt+1.day=>st"
17739 assert_equal Time.local(2006, 3, 21, 1, 45, 0), Time.local(2006, 3, 20, 1, 45, 0).tomorrow, "st+1.day=>st"
17740 assert_equal Time.local(2005, 10, 30, 0, 45, 0), Time.local(2005, 10, 31, 0, 45, 0).yesterday, "st-1.day=>dt"
17741 assert_equal Time.local(2005, 10, 31, 0, 45, 0), Time.local(2005, 11, 1, 0, 45, 0).yesterday, "st-1.day=>st"
17742 assert_equal Time.local(2006, 3, 19, 1, 45, 0), Time.local(2006, 3, 20, 1, 45, 0).yesterday, "st-1.day=>dt"
17743 assert_equal Time.local(2006, 3, 20, 1, 45, 0), Time.local(2006, 3, 21, 1, 45, 0).yesterday, "st-1.day=>st"
17744 assert_equal Time.local(2006, 2, 22, 15, 15, 10), Time.local(2005, 2, 22, 15, 15, 10).change(year: 2006)
17745 assert_equal Time.local(2005, 6, 22, 15, 15, 10), Time.local(2005, 2, 22, 15, 15, 10).change(month: 6)
17746 assert_equal Time.local(2012, 9, 22, 15, 15, 10), Time.local(2005, 2, 22, 15, 15, 10).change(year: 2012, month: 9)
17747 assert_equal Time.local(2005, 1, 2, 5, 0, 0, 0), Time.local(2005, 1, 2, 11, 22, 33, 44).change(hour: 5)
17748 assert_equal Time.local(2005, 1, 2, 11, 6, 0, 0), Time.local(2005, 1, 2, 11, 22, 33, 44).change(min: 6)
17749 assert_equal Time.local(2005, 1, 2, 11, 22, 7, 0), Time.local(2005, 1, 2, 11, 22, 33, 44).change(sec: 7)
17750 assert_equal Time.local(2005, 1, 2, 11, 22, 33, 8), Time.local(2005, 1, 2, 11, 22, 33, 44).change(usec: 8)
17751 assert_equal Time.local(2005, 1, 2, 11, 22, 33, 8), Time.local(2005, 1, 2, 11, 22, 33, 2).change(nsec: 8000)
17752 assert_raise(ArgumentError) { Time.local(2005, 1, 2, 11, 22, 33, 8).change(usec: 1, nsec: 1) }
17753 assert_nothing_raised { Time.new(2015, 5, 9, 10, 00, 00, "+03:00").change(nsec: 999999999) }
17754 assert_equal Time.utc(2006, 2, 22, 15, 15, 10), Time.utc(2005, 2, 22, 15, 15, 10).change(year: 2006)
17755 assert_equal Time.utc(2005, 6, 22, 15, 15, 10), Time.utc(2005, 2, 22, 15, 15, 10).change(month: 6)
17756 assert_equal Time.utc(2012, 9, 22, 15, 15, 10), Time.utc(2005, 2, 22, 15, 15, 10).change(year: 2012, month: 9)
17757 assert_equal Time.utc(2005, 1, 2, 11, 22, 33, 8), Time.utc(2005, 1, 2, 11, 22, 33, 2).change(nsec: 8000)
17758 assert_equal Time.new(2006, 2, 22, 15, 15, 10, "-08:00"), Time.new(2005, 2, 22, 15, 15, 10, "-08:00").change(year: 2006)
17759 assert_equal Time.new(2005, 6, 22, 15, 15, 10, "-08:00"), Time.new(2005, 2, 22, 15, 15, 10, "-08:00").change(month: 6)
17760 assert_equal Time.new(2012, 9, 22, 15, 15, 10, "-08:00"), Time.new(2005, 2, 22, 15, 15, 10, "-08:00").change(year: 2012, month: 9)
17761 assert_equal 10, Time.new(2005, 2, 22, 15, 15, 0, "-08:00").change(usec: 10).usec
17762 assert_equal 10, Time.new(2005, 2, 22, 15, 15, 0, "-08:00").change(nsec: 10).nsec
17763 assert_raise(ArgumentError) { Time.new(2005, 2, 22, 15, 15, 45, "-08:00").change(usec: 1000000) }
17764 assert_raise(ArgumentError) { Time.new(2005, 2, 22, 15, 15, 45, "-08:00").change(nsec: 1000000000) }
17765 assert_equal Time.new(2006, 2, 22, 15, 15, 10, "-08:00"), Time.new(2006, 2, 22, 15, 15, 10, "+01:00").change(offset: "-08:00")
17766 assert_equal Time.new(2006, 2, 22, 15, 15, 10, -28800), Time.new(2006, 2, 22, 15, 15, 10, 3600).change(offset: -28800)
17767 assert_raise(ArgumentError) { Time.new(2005, 2, 22, 15, 15, 45, "+01:00").change(usec: 1000000, offset: "-08:00") }
17768 assert_raise(ArgumentError) { Time.new(2005, 2, 22, 15, 15, 45, "+01:00").change(nsec: 1000000000, offset: -28800) }
17769 one_am_1 = Time.local(2005, 10, 30, 00, 59, 59) + 1 # 2005-10-30 01:00:00 -0400
17770 assert_operator one_am_1, :<, one_am_2
17771 assert_equal one_am_1 + 1, one_am_1.change(sec: 1)
17772 assert_equal one_am_2 + 1, one_am_2.change(sec: 1)
17773 one_am_2 = Time.new(2005, 10, 30, 02, 00, 00, Time.zone) - 3600 # 2005-10-30 01:00:00 -0500
17774 one30_am_1 = Time.local(2005, 03, 27, 01, 29, 59) + 1 # 2005-03-27 01:30:00 +1100
17775 assert_equal one30_am_1 + 1, one30_am_1.change(min: 30, sec: 1)
17776 assert_equal one30_am_2 + 1, one30_am_2.change(min: 30, sec: 1)
17777 one30_am_2 = Time.new(2005, 03, 27, 02, 00, 00, Time.zone) - 1800 # 2005-03-27 01:30:00 +1030
17778 assert_equal Time.local(2006, 2, 28, 15, 15, 10), Time.local(2005, 2, 28, 15, 15, 10).advance(years: 1)
17779 assert_equal Time.local(2005, 6, 28, 15, 15, 10), Time.local(2005, 2, 28, 15, 15, 10).advance(months: 4)
17780 assert_equal Time.local(2005, 3, 21, 15, 15, 10), Time.local(2005, 2, 28, 15, 15, 10).advance(weeks: 3)
17781 assert_equal Time.local(2005, 3, 25, 3, 15, 10), Time.local(2005, 2, 28, 15, 15, 10).advance(weeks: 3.5)
17782 assert_in_delta Time.local(2005, 3, 26, 12, 51, 10), Time.local(2005, 2, 28, 15, 15, 10).advance(weeks: 3.7), 1
17783 assert_equal Time.local(2005, 3, 5, 15, 15, 10), Time.local(2005, 2, 28, 15, 15, 10).advance(days: 5)
17784 assert_equal Time.local(2005, 3, 6, 3, 15, 10), Time.local(2005, 2, 28, 15, 15, 10).advance(days: 5.5)
17785 assert_in_delta Time.local(2005, 3, 6, 8, 3, 10), Time.local(2005, 2, 28, 15, 15, 10).advance(days: 5.7), 1
17786 assert_equal Time.local(2012, 9, 28, 15, 15, 10), Time.local(2005, 2, 28, 15, 15, 10).advance(years: 7, months: 7)
17787 assert_equal Time.local(2013, 10, 3, 15, 15, 10), Time.local(2005, 2, 28, 15, 15, 10).advance(years: 7, months: 19, days: 5)
17788 assert_equal Time.local(2013, 10, 17, 15, 15, 10), Time.local(2005, 2, 28, 15, 15, 10).advance(years: 7, months: 19, weeks: 2, days: 5)
17789 assert_equal Time.local(2001, 12, 27, 15, 15, 10), Time.local(2005, 2, 28, 15, 15, 10).advance(years: -3, months: -2, days: -1)
17790 assert_equal Time.local(2005, 2, 28, 15, 15, 10), Time.local(2004, 2, 29, 15, 15, 10).advance(years: 1) # leap day plus one year
17791 assert_equal Time.local(2005, 2, 28, 20, 15, 10), Time.local(2005, 2, 28, 15, 15, 10).advance(hours: 5)
17792 assert_equal Time.local(2005, 2, 28, 15, 22, 10), Time.local(2005, 2, 28, 15, 15, 10).advance(minutes: 7)
17793 assert_equal Time.local(2005, 2, 28, 15, 15, 19), Time.local(2005, 2, 28, 15, 15, 10).advance(seconds: 9)
17794 assert_equal Time.local(2005, 2, 28, 20, 22, 19), Time.local(2005, 2, 28, 15, 15, 10).advance(hours: 5, minutes: 7, seconds: 9)
17795 assert_equal Time.local(2005, 2, 28, 10, 8, 1), Time.local(2005, 2, 28, 15, 15, 10).advance(hours: -5, minutes: -7, seconds: -9)
17796 assert_equal Time.local(2013, 10, 17, 20, 22, 19), Time.local(2005, 2, 28, 15, 15, 10).advance(years: 7, months: 19, weeks: 2, days: 5, hours: 5, minutes: 7, seconds: 9)
17797 assert_equal Time.new(2021, 5, 29, 0, 0, 0, "+03:00"), Time.new(2021, 5, 29, 0, 0, 0, ActiveSupport::TimeZone["Moscow"])
17798 assert_equal Time.new(2021, 5, 29, 0, 0, 0, "+03:00").advance(seconds: 60), Time.new(2021, 5, 29, 0, 0, 0, ActiveSupport::TimeZone["Moscow"]).advance(seconds: 60)
17799 assert_equal Time.new(2021, 5, 29, 0, 0, 0, "+03:00").advance(days: 3), Time.new(2021, 5, 29, 0, 0, 0, ActiveSupport::TimeZone["Moscow"]).advance(days: 3)
17800 assert_equal Time.new(2021, 5, 29, 0, 0, 0, "+03:00"), ActiveSupport::TimeZone["Moscow"].local(2021, 5, 29, 0, 0, 0)
17801 assert_equal Time.new(2021, 5, 29, 0, 0, 0, "+03:00").advance(seconds: 60), ActiveSupport::TimeZone["Moscow"].local(2021, 5, 29, 0, 0, 0).advance(seconds: 60)
17802 assert_equal Time.new(2021, 5, 29, 0, 0, 0, "+03:00").advance(days: 3), ActiveSupport::TimeZone["Moscow"].local(2021, 5, 29, 0, 0, 0).advance(days: 3)
17803 assert_equal Time.utc(2006, 2, 22, 15, 15, 10), Time.utc(2005, 2, 22, 15, 15, 10).advance(years: 1)
17804 assert_equal Time.utc(2005, 6, 22, 15, 15, 10), Time.utc(2005, 2, 22, 15, 15, 10).advance(months: 4)
17805 assert_equal Time.utc(2005, 3, 21, 15, 15, 10), Time.utc(2005, 2, 28, 15, 15, 10).advance(weeks: 3)
17806 assert_equal Time.utc(2005, 3, 25, 3, 15, 10), Time.utc(2005, 2, 28, 15, 15, 10).advance(weeks: 3.5)
17807 assert_in_delta Time.utc(2005, 3, 26, 12, 51, 10), Time.utc(2005, 2, 28, 15, 15, 10).advance(weeks: 3.7), 1
17808 assert_equal Time.utc(2005, 3, 5, 15, 15, 10), Time.utc(2005, 2, 28, 15, 15, 10).advance(days: 5)
17809 assert_equal Time.utc(2005, 3, 6, 3, 15, 10), Time.utc(2005, 2, 28, 15, 15, 10).advance(days: 5.5)
17810 assert_in_delta Time.utc(2005, 3, 6, 8, 3, 10), Time.utc(2005, 2, 28, 15, 15, 10).advance(days: 5.7), 1
17811 assert_equal Time.utc(2012, 9, 22, 15, 15, 10), Time.utc(2005, 2, 22, 15, 15, 10).advance(years: 7, months: 7)
17812 assert_equal Time.utc(2013, 10, 3, 15, 15, 10), Time.utc(2005, 2, 22, 15, 15, 10).advance(years: 7, months: 19, days: 11)
17813 assert_equal Time.utc(2013, 10, 17, 15, 15, 10), Time.utc(2005, 2, 28, 15, 15, 10).advance(years: 7, months: 19, weeks: 2, days: 5)
17814 assert_equal Time.utc(2001, 12, 27, 15, 15, 10), Time.utc(2005, 2, 28, 15, 15, 10).advance(years: -3, months: -2, days: -1)
17815 assert_equal Time.utc(2005, 2, 28, 15, 15, 10), Time.utc(2004, 2, 29, 15, 15, 10).advance(years: 1) # leap day plus one year
17816 assert_equal Time.utc(2005, 2, 28, 20, 15, 10), Time.utc(2005, 2, 28, 15, 15, 10).advance(hours: 5)
17817 assert_equal Time.utc(2005, 2, 28, 15, 22, 10), Time.utc(2005, 2, 28, 15, 15, 10).advance(minutes: 7)
17818 assert_equal Time.utc(2005, 2, 28, 15, 15, 19), Time.utc(2005, 2, 28, 15, 15, 10).advance(seconds: 9)
17819 assert_equal Time.utc(2005, 2, 28, 20, 22, 19), Time.utc(2005, 2, 28, 15, 15, 10).advance(hours: 5, minutes: 7, seconds: 9)
17820 assert_equal Time.utc(2005, 2, 28, 10, 8, 1), Time.utc(2005, 2, 28, 15, 15, 10).advance(hours: -5, minutes: -7, seconds: -9)
17821 assert_equal Time.utc(2013, 10, 17, 20, 22, 19), Time.utc(2005, 2, 28, 15, 15, 10).advance(years: 7, months: 19, weeks: 2, days: 5, hours: 5, minutes: 7, seconds: 9)
17822 assert_equal Time.new(2006, 2, 22, 15, 15, 10, "-08:00"), Time.new(2005, 2, 22, 15, 15, 10, "-08:00").advance(years: 1)
17823 assert_equal Time.new(2005, 6, 22, 15, 15, 10, "-08:00"), Time.new(2005, 2, 22, 15, 15, 10, "-08:00").advance(months: 4)
17824 assert_equal Time.new(2005, 3, 21, 15, 15, 10, "-08:00"), Time.new(2005, 2, 28, 15, 15, 10, "-08:00").advance(weeks: 3)
17825 assert_equal Time.new(2005, 3, 25, 3, 15, 10, "-08:00"), Time.new(2005, 2, 28, 15, 15, 10, "-08:00").advance(weeks: 3.5)
17826 assert_in_delta Time.new(2005, 3, 26, 12, 51, 10, "-08:00"), Time.new(2005, 2, 28, 15, 15, 10, "-08:00").advance(weeks: 3.7), 1
17827 assert_equal Time.new(2005, 3, 5, 15, 15, 10, "-08:00"), Time.new(2005, 2, 28, 15, 15, 10, "-08:00").advance(days: 5)
17828 assert_equal Time.new(2005, 3, 6, 3, 15, 10, "-08:00"), Time.new(2005, 2, 28, 15, 15, 10, "-08:00").advance(days: 5.5)
17829 assert_in_delta Time.new(2005, 3, 6, 8, 3, 10, "-08:00"), Time.new(2005, 2, 28, 15, 15, 10, "-08:00").advance(days: 5.7), 1
17830 assert_equal Time.new(2012, 9, 22, 15, 15, 10, "-08:00"), Time.new(2005, 2, 22, 15, 15, 10, "-08:00").advance(years: 7, months: 7)
17831 assert_equal Time.new(2013, 10, 3, 15, 15, 10, "-08:00"), Time.new(2005, 2, 22, 15, 15, 10, "-08:00").advance(years: 7, months: 19, days: 11)
17832 assert_equal Time.new(2013, 10, 17, 15, 15, 10, "-08:00"), Time.new(2005, 2, 28, 15, 15, 10, "-08:00").advance(years: 7, months: 19, weeks: 2, days: 5)
17833 assert_equal Time.new(2001, 12, 27, 15, 15, 10, "-08:00"), Time.new(2005, 2, 28, 15, 15, 10, "-08:00").advance(years: -3, months: -2, days: -1)
17834 assert_equal Time.new(2005, 2, 28, 15, 15, 10, "-08:00"), Time.new(2004, 2, 29, 15, 15, 10, "-08:00").advance(years: 1) # leap day plus one year
17835 assert_equal Time.new(2005, 2, 28, 20, 15, 10, "-08:00"), Time.new(2005, 2, 28, 15, 15, 10, "-08:00").advance(hours: 5)
17836 assert_equal Time.new(2005, 2, 28, 15, 22, 10, "-08:00"), Time.new(2005, 2, 28, 15, 15, 10, "-08:00").advance(minutes: 7)
17837 assert_equal Time.new(2005, 2, 28, 15, 15, 19, "-08:00"), Time.new(2005, 2, 28, 15, 15, 10, "-08:00").advance(seconds: 9)
17838 assert_equal Time.new(2005, 2, 28, 20, 22, 19, "-08:00"), Time.new(2005, 2, 28, 15, 15, 10, "-08:00").advance(hours: 5, minutes: 7, seconds: 9)
17839 assert_equal Time.new(2005, 2, 28, 10, 8, 1, "-08:00"), Time.new(2005, 2, 28, 15, 15, 10, "-08:00").advance(hours: -5, minutes: -7, seconds: -9)
17840 assert_equal Time.local(1582, 10, 14, 15, 15, 10), Time.local(1582, 10, 15, 15, 15, 10).advance(days: -1)
17841 assert_equal Time.local(1582, 10, 15, 15, 15, 10), Time.local(1582, 10, 14, 15, 15, 10).advance(days: 1)
17842 assert_equal Time.local(1582, 10, 5, 15, 15, 10), Time.local(1582, 10, 4, 15, 15, 10).advance(days: 1)
17843 assert_equal Time.local(1582, 10, 4, 15, 15, 10), Time.local(1582, 10, 5, 15, 15, 10).advance(days: -1)
17844 assert_equal Time.local(999, 10, 4, 15, 15, 10), Time.local(1000, 10, 4, 15, 15, 10).advance(years: -1)
17845 assert_equal Time.local(1000, 10, 4, 15, 15, 10), Time.local(999, 10, 4, 15, 15, 10).advance(years: 1)
17846 assert_equal Time.local(2005, 2, 21), Time.local(2005, 3, 1, 15, 15, 10).last_week
17847 assert_equal Time.local(2005, 2, 22), Time.local(2005, 3, 1, 15, 15, 10).last_week(:tuesday)
17848 assert_equal Time.local(2005, 2, 25), Time.local(2005, 3, 1, 15, 15, 10).last_week(:friday)
17849 assert_equal Time.local(2006, 10, 30), Time.local(2006, 11, 6, 0, 0, 0).last_week
17850 assert_equal Time.local(2006, 11, 15), Time.local(2006, 11, 23, 0, 0, 0).last_week(:wednesday)
17851 assert_equal Time.local(2006, 4, 3), Time.local(2006, 4, 2, 23, 1, 0).next_week, "just crossed standard => daylight"
17852 assert_equal Time.local(2006, 10, 2), Time.local(2006, 10, 1, 23, 1, 0).next_week, "just crossed standard => daylight"
17853 assert_equal Time.local(2006, 10, 30), Time.local(2006, 10, 29, 23, 1, 0).next_week, "just crossed daylight => standard"
17854 assert_equal Time.local(2006, 3, 20), Time.local(2006, 3, 19, 23, 1, 0).next_week, "just crossed daylight => standard"
17855 time = Time.utc(2005, 2, 21, 17, 44, 30.12345678901)
17856 with_env_tz "UTC" do
17857 assert_equal "Thu, 05 Feb 2009 14:30:05 -0600", Time.local(2009, 2, 5, 14, 30, 5).to_fs(:rfc822)
17858 assert_equal "Mon, 09 Jun 2008 04:05:01 -0500", Time.local(2008, 6, 9, 4, 5, 1).to_fs(:rfc822)
17859 assert_equal "2009-02-05T14:30:05-06:00", Time.local(2009, 2, 5, 14, 30, 5).to_fs(:iso8601)
17860 assert_equal "2008-06-09T04:05:01-05:00", Time.local(2008, 6, 9, 4, 5, 1).to_fs(:iso8601)
17861 assert_equal "2009-02-05T14:30:05Z", Time.utc(2009, 2, 5, 14, 30, 5).to_fs(:iso8601)
17862 assert_equal "2009-02-05 14:30:05.000000000 -0600", Time.local(2009, 2, 5, 14, 30, 5).to_fs(:inspect)
17863 assert_equal "2008-06-09 04:05:01.000000000 -0500", Time.local(2008, 6, 9, 4, 5, 1).to_fs(:inspect)
17864 assert_equal "20050221143000", Time.local(2005, 2, 21, 14, 30, 0).to_fs(:custom)
17865 time = Time.new(1999, 12, 31, 19, 0, Rational(1, 8), -18000)
17866 assert_equal Date.new(2005, 2, 21), Time.local(2005, 2, 21, 17, 44, 30).to_date
17867 assert_equal Time.utc(2005, 2, 21, 17, 44, 30).to_datetime, DateTime.civil(2005, 2, 21, 17, 44, 30, 0)
17868 assert_equal Time.local(2005, 2, 21, 17, 44, 30).to_datetime, DateTime.civil(2005, 2, 21, 17, 44, 30, Rational(Time.local(2005, 2, 21, 17, 44, 30).utc_offset, 86400))
17869 assert_equal Time.local(2005, 2, 21, 17, 44, 30), Time.local(2005, 2, 21, 17, 44, 30).to_time
17870 assert_equal Time.local(2005, 2, 21, 17, 44, 30).utc_offset, Time.local(2005, 2, 21, 17, 44, 30).to_time.utc_offset
17871 midnight = Time.local(2005, 2, 21, 0, 0, 0)
17872 assert_equal false, Time.local(1999, 12, 31, 23, 59, 59).today?
17873 assert_equal false, Time.utc(1999, 12, 31, 23, 59, 59).today?
17874 assert_equal false, Time.utc(2000, 1, 2, 0).today?
17875 assert_equal false, Time.utc(2000, 1, 1, 0).prev_day?
17876 assert_equal false, Time.utc(2000, 1, 2, 0).prev_day?
17877 assert_equal false, Time.local(1999, 12, 31, 23, 59, 59).next_day?
17878 assert_equal false, Time.utc(1999, 12, 31, 23, 59, 59).next_day?
17879 assert_equal false, Time.utc(2000, 1, 1, 0).next_day?
17880 twz = Time.utc(2005, 2, 10, 15, 30, 45).in_time_zone("Central Time (US & Canada)")
17881 assert_equal 1, Time.utc(2000) <=> Time.utc(1999, 12, 31, 23, 59, 59, 999)
17882 assert_equal 0, Time.utc(2000) <=> Time.utc(2000, 1, 1, 0, 0, 0)
17883 assert_equal(-1, Time.utc(2000) <=> Time.utc(2000, 1, 1, 0, 0, 0, 001))
17884 assert_equal 1, Time.utc(2000) <=> DateTime.civil(1999, 12, 31, 23, 59, 59)
17885 assert_equal 0, Time.utc(2000) <=> DateTime.civil(2000, 1, 1, 0, 0, 0)
17886 assert_equal(-1, Time.utc(2000) <=> DateTime.civil(2000, 1, 1, 0, 0, 1))
17887 assert_equal(-1, Time.utc(2000) <=> ActiveSupport::TimeWithZone.new(Time.utc(2000, 1, 1, 0, 0, 1), ActiveSupport::TimeZone["UTC"]))
17888 assert_equal 1, Time.utc(2000) <=> Time.utc(1999, 12, 31, 23, 59, 59, 999).to_s
17889 assert_equal 0, Time.utc(2000) <=> Time.utc(2000, 1, 1, 0, 0, 0).to_s
17890 assert_equal(-1, Time.utc(2000) <=> Time.utc(2000, 1, 1, 0, 0, 1, 0).to_s)
17891 assert_equal Time.utc(2000, 1, 1, 0, 0, 0), Time.at(DateTime.civil(2000, 1, 1, 0, 0, 0))
17892 assert_raise(TypeError) { assert_equal(Time.utc(2000, 1, 1, 0, 0, 0), Time.at(DateTime.civil(2000, 1, 1, 0, 0, 0), 0)) }
17893 dt = DateTime.civil(2000, 1, 1, 0, 0, 0, "+0")
17894 assert_equal Time.local(1999, 12, 31, 19, 0, 0), Time.at(dt)
17895 dt = DateTime.civil(2000, 7, 1, 1, 0, 0, "+1")
17896 assert_equal Time.local(2000, 6, 30, 20, 0, 0), Time.at(dt)
17897 assert_equal Time.utc(2000, 1, 1, 0, 0, 0), Time.at(ActiveSupport::TimeWithZone.new(Time.utc(2000, 1, 1, 0, 0, 0), ActiveSupport::TimeZone["UTC"]))
17898 assert_raise(TypeError) { assert_equal(Time.utc(2000, 1, 1, 0, 0, 0), Time.at(ActiveSupport::TimeWithZone.new(Time.utc(2000, 1, 1, 0, 0, 0), ActiveSupport::TimeZone["UTC"]), 0)) }
17899 assert_equal Time.new(1970, 1, 1, 0, 42, 17, "-08:00"), Time.at(31337, in: -28800)
17900 assert_equal Time.local(1999, 12, 31, 19, 0, 0), Time.at(twz)
17901 assert_equal Time.local(2000, 6, 30, 20, 0, 0), Time.at(twz)
17902 assert_equal Time.at(Time.utc(2000, 1, 1, 0, 0, 0, 111)).to_f, Time.utc(2000, 1, 1, 0, 0, 0, 111).to_f
17903 assert_equal Time.local(2000, 7, 1), Time.at(Time.local(2000, 7, 1))
17904 assert_equal "EDT", Time.at(Time.local(2000, 7, 1)).zone
17905 assert_equal 86_400.0, Time.utc(2000, 1, 2) - DateTime.civil(2000, 1, 1)
17906 assert_equal Time.local(2006, 4, 2, 3), Time.local(2006, 4, 2, 2)
17907 assert_predicate Time.local(2006, 4, 2, 2), :dst?
17908 assert Time === Time.utc(2000)
17909 assert_equal Time.local(2011, 6, 7, 0, 0, 0)..Time.local(2011, 6, 7, 23, 59, 59, Rational(999999999, 1000)), Time.local(2011, 6, 7, 10, 10, 10).all_day
17910 assert_equal Time.local(2011, 6, 6, 0, 0, 0)..Time.local(2011, 6, 12, 23, 59, 59, Rational(999999999, 1000)), Time.local(2011, 6, 7, 10, 10, 10).all_week
17911 assert_equal Time.local(2011, 6, 5, 0, 0, 0)..Time.local(2011, 6, 11, 23, 59, 59, Rational(999999999, 1000)), Time.local(2011, 6, 7, 10, 10, 10).all_week(:sunday)
17912 assert_equal Time.local(2011, 6, 1, 0, 0, 0)..Time.local(2011, 6, 30, 23, 59, 59, Rational(999999999, 1000)), Time.local(2011, 6, 7, 10, 10, 10).all_month
17913 assert_equal Time.local(2011, 4, 1, 0, 0, 0)..Time.local(2011, 6, 30, 23, 59, 59, Rational(999999999, 1000)), Time.local(2011, 6, 7, 10, 10, 10).all_quarter
17914 assert_equal Time.local(2011, 1, 1, 0, 0, 0)..Time.local(2011, 12, 31, 23, 59, 59, Rational(999999999, 1000)), Time.local(2011, 6, 7, 10, 10, 10).all_year
17915 assert_equal date_time_init(2005, 2, 24, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_day(-2)
17916 assert_equal date_time_init(2005, 2, 23, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_day(-1)
17917 assert_equal date_time_init(2005, 2, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_day(0)
17918 assert_equal date_time_init(2005, 2, 21, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_day(1)
17919 assert_equal date_time_init(2005, 2, 20, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_day(2)
17920 assert_equal date_time_init(2005, 2, 21, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_day
17921 assert_equal date_time_init(2005, 2, 28, 10, 10, 10), date_time_init(2005, 3, 2, 10, 10, 10).prev_day.prev_day
17922 assert_equal date_time_init(2005, 2, 20, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_day(-2)
17923 assert_equal date_time_init(2005, 2, 21, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_day(-1)
17924 assert_equal date_time_init(2005, 2, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_day(0)
17925 assert_equal date_time_init(2005, 2, 23, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_day(1)
17926 assert_equal date_time_init(2005, 2, 24, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_day(2)
17927 assert_equal date_time_init(2005, 2, 23, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_day
17928 assert_equal date_time_init(2005, 4, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_month(-2)
17929 assert_equal date_time_init(2005, 3, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_month(-1)
17930 assert_equal date_time_init(2005, 2, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_month(0)
17931 assert_equal date_time_init(2005, 1, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_month(1)
17932 assert_equal date_time_init(2004, 12, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_month(2)
17933 assert_equal date_time_init(2005, 1, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_month
17934 assert_equal date_time_init(2004, 12, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_month.prev_month
17935 assert_equal date_time_init(2004, 12, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_month(-2)
17936 assert_equal date_time_init(2005, 1, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_month(-1)
17937 assert_equal date_time_init(2005, 2, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_month(0)
17938 assert_equal date_time_init(2005, 3, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_month(1)
17939 assert_equal date_time_init(2005, 4, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_month(2)
17940 assert_equal date_time_init(2005, 3, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_month
17941 assert_equal date_time_init(2005, 4, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_month.next_month
17942 assert_equal date_time_init(2003, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).next_year(-2)
17943 assert_equal date_time_init(2004, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).next_year(-1)
17944 assert_equal date_time_init(2005, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).next_year(0)
17945 assert_equal date_time_init(2006, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).next_year(1)
17946 assert_equal date_time_init(2007, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).next_year(2)
17947 assert_equal date_time_init(2006, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).next_year
17948 assert_equal date_time_init(2007, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).next_year.next_year
17949 t = Time.utc(2000)
17950 t = Time.local(2000)
17951 t = Time.parse("00:00:00.500")
17952 s = :hello
17953 assert s.starts_with?("h")
17954 assert s.starts_with?("he", "lo")
17955 assert_not s.starts_with?("el", "lo")
17956 assert s.ends_with?("o")
17957 assert s.ends_with?("lo")
17958 assert_not s.ends_with?("el")
17959 assert s.ends_with?("he", "lo")
17960 assert_not s.ends_with?("he", "ll")
17961 assert_equal "", "".strip_heredoc
17962 name = "Kuldeep"
17963 assert_equal "", "".upcase_first
17964 s = "hello"
17965 assert_equal "Hello Wor...", "Hello World!!".truncate(12)
17966 assert_equal "Hello[...]", "Hello World!".truncate(10, omission: "[...]")
17967 assert_equal "Hello[...]", "Hello Big World!".truncate(13, omission: "[...]", separator: " ")
17968 assert_equal "Hello Big[...]", "Hello Big World!".truncate(14, omission: "[...]", separator: " ")
17969 assert_equal "Hello Big[...]", "Hello Big World!".truncate(15, omission: "[...]", separator: " ")
17970 assert_equal "Hello[...]", "Hello Big World!".truncate(13, omission: "[...]", separator: /\s/)
17971 assert_equal "Hello Big[...]", "Hello Big World!".truncate(14, omission: "[...]", separator: /\s/)
17972 assert_equal "Hello Big[...]", "Hello Big World!".truncate(15, omission: "[...]", separator: /\s/)
17973 assert_equal "Hello Big World!", "Hello Big World!".truncate_words(3, omission: "[...]")
17974 assert_equal "Hello Big[...]", "Hello Big World!".truncate_words(2, omission: "[...]")
17975 assert_equal "Hello<br>Big<br>World!...", "Hello<br>Big<br>World!<br>".truncate_words(3, separator: "<br>")
17976 assert_equal "Hello<br>Big<br>World!", "Hello<br>Big<br>World!".truncate_words(3, separator: "<br>")
17977 assert_equal "Hello
<br>Big...", "Hello
<br>Big<br>Wide<br>World!".truncate_words(2, separator: "<br>")
17978 assert_equal "Hello<br>Big<br>World![...]", "Hello<br>Big<br>World!<br>".truncate_words(3, omission: "[...]", separator: "<br>")
17979 assert_equal "Hello<br>Big<br>World!", "Hello<br>Big<br>World!".truncate_words(3, omission: "[...]", separator: "<br>")
17980 assert_equal (+"\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 ...").force_encoding(Encoding::UTF_8),
17981 assert_equal "This is a good day", original.remove(" to ", /die/)
17982 assert_equal "This is a good day", original.remove!(" to ", /die/)
17983 assert_equal "h", "hello".at(0)
17984 assert_equal "lo", "hello".at(-2..-1)
17985 assert_equal "lo", "hello".at(/lo/)
17986 assert_equal "llo", "hello".from(2)
17987 assert_equal "lo", "hello".from(-2)
17988 assert_equal "hel", "hello".to(2)
17989 assert_equal "hell", "hello".to(-2)
17990 assert_equal "h", "hello".to(-5)
17991 assert_equal "", "hello".to(-7)
17992 assert_equal "hello", "hello".from(0).to(-1)
17993 assert_equal "ell", "hello".from(1).to(-2)
17994 assert_equal "x", "x".first
17995 assert_equal "he", "hello".first(2)
17996 assert_equal "", "hello".first(0)
17997 assert_equal "x", "x".first(4)
17998 string = "hello"
17999 string = "he"
18000 (0..string.length + 1).each do |limit|
18001 assert_equal "o", "hello".last
18002 assert_equal "x", "x".last
18003 assert_equal "llo", "hello".last(3)
18004 assert_equal "", "hello".last(0)
18005 assert_equal "x", "x".last(4)
18006 hash["h"] = true
18007 hash["hello123".at(0)] = true
18008 hash["llo"] = true
18009 hash["hello".from(2)] = true
18010 hash["hel"] = true
18011 hash["hello".to(2)] = true
18012 hash["hello"] = true
18013 hash["123hello".last(5)] = true
18014 hash["hello123".first(5)] = true
18015 assert_equal Time.utc(2005, 2, 27, 23, 50), "2005-02-27 23:50".to_time(:utc)
18016 assert_equal Time.local(2005, 2, 27, 23, 50), "2005-02-27 23:50".to_time
18017 assert_equal Time.utc(2005, 2, 27, 23, 50, 19, 275038), "2005-02-27T23:50:19.275038".to_time(:utc)
18018 assert_equal Time.utc(2039, 2, 27, 23, 50), "2039-02-27 23:50".to_time(:utc)
18019 assert_equal Time.local(2039, 2, 27, 23, 50), "2039-02-27 23:50".to_time
18020 assert_equal Time.local(2011, 2, 27, 17, 50), "2011-02-27 13:50 -0100".to_time
18021 assert_equal Time.utc(2011, 2, 27, 23, 50), "2011-02-27 22:50 -0100".to_time(:utc)
18022 assert_equal Time.local(2005, 2, 27, 22, 50), "2005-02-27 14:50 -0500".to_time
18023 assert_equal Time.utc(now.year, now.month, now.day, 23, 50), "23:50".to_time(:utc)
18024 assert_equal Time.utc(now.year, now.month, now.day, 23, 50), "22:50 -0100".to_time(:utc)
18025 Time.stub(:now, Time.local(2012, 1, 1)) do
18026 assert_equal Time.local(2012, 1, 1, 10, 0), "2012-01-01 10:00".to_time
18027 assert_equal Time.utc(2012, 1, 1, 10, 0), "2012-01-01 10:00".to_time(:utc)
18028 assert_equal Time.local(2012, 1, 1, 13, 0), "2012-01-01 10:00 -0800".to_time
18029 assert_equal Time.utc(2012, 1, 1, 18, 0), "2012-01-01 10:00 -0800".to_time(:utc)
18030 assert_equal Time.local(2012, 1, 1, 10, 0), "2012-01-01 10:00 -0500".to_time
18031 assert_equal Time.utc(2012, 1, 1, 15, 0), "2012-01-01 10:00 -0500".to_time(:utc)
18032 assert_equal Time.local(2012, 1, 1, 5, 0), "2012-01-01 10:00 UTC".to_time
18033 assert_equal Time.utc(2012, 1, 1, 10, 0), "2012-01-01 10:00 UTC".to_time(:utc)
18034 assert_equal Time.local(2012, 1, 1, 13, 0), "2012-01-01 10:00 PST".to_time
18035 assert_equal Time.utc(2012, 1, 1, 18, 0), "2012-01-01 10:00 PST".to_time(:utc)
18036 assert_equal Time.local(2012, 1, 1, 10, 0), "2012-01-01 10:00 EST".to_time
18037 assert_equal Time.utc(2012, 1, 1, 15, 0), "2012-01-01 10:00 EST".to_time(:utc)
18038 Time.stub(:now, Time.local(2012, 7, 1)) do
18039 assert_equal Time.local(2012, 7, 1, 10, 0), "2012-07-01 10:00".to_time
18040 assert_equal Time.utc(2012, 7, 1, 10, 0), "2012-07-01 10:00".to_time(:utc)
18041 assert_equal Time.local(2012, 7, 1, 13, 0), "2012-07-01 10:00 -0700".to_time
18042 assert_equal Time.utc(2012, 7, 1, 17, 0), "2012-07-01 10:00 -0700".to_time(:utc)
18043 assert_equal Time.local(2012, 7, 1, 10, 0), "2012-07-01 10:00 -0400".to_time
18044 assert_equal Time.utc(2012, 7, 1, 14, 0), "2012-07-01 10:00 -0400".to_time(:utc)
18045 assert_equal Time.local(2012, 7, 1, 6, 0), "2012-07-01 10:00 UTC".to_time
18046 assert_equal Time.utc(2012, 7, 1, 10, 0), "2012-07-01 10:00 UTC".to_time(:utc)
18047 assert_equal Time.local(2012, 7, 1, 13, 0), "2012-07-01 10:00 PDT".to_time
18048 assert_equal Time.utc(2012, 7, 1, 17, 0), "2012-07-01 10:00 PDT".to_time(:utc)
18049 assert_equal Time.local(2012, 7, 1, 10, 0), "2012-07-01 10:00 EDT".to_time
18050 assert_equal Time.utc(2012, 7, 1, 14, 0), "2012-07-01 10:00 EDT".to_time(:utc)
18051 assert_equal Time.local(2012, 1, 1, 10, 0), "10:00".to_time
18052 assert_equal Time.local(2012, 1, 1, 6, 0), "10:00 -0100".to_time
18053 assert_equal Time.utc(2012, 1, 1, 11, 0), "10:00 -0100".to_time(:utc)
18054 assert_equal Time.local(2012, 1, 1, 10, 0), "10:00 -0500".to_time
18055 assert_equal Time.utc(2012, 1, 1, 15, 0), "10:00 -0500".to_time(:utc)
18056 assert_equal Time.local(2012, 1, 1, 5, 0), "10:00 UTC".to_time
18057 assert_equal Time.utc(2012, 1, 1, 10, 0), "10:00 UTC".to_time(:utc)
18058 assert_equal Time.local(2012, 1, 1, 13, 0), "10:00 PST".to_time
18059 assert_equal Time.utc(2012, 1, 1, 18, 0), "10:00 PST".to_time(:utc)
18060 assert_equal Time.local(2012, 1, 1, 12, 0), "10:00 PDT".to_time
18061 assert_equal Time.utc(2012, 1, 1, 17, 0), "10:00 PDT".to_time(:utc)
18062 assert_equal Time.local(2012, 1, 1, 10, 0), "10:00 EST".to_time
18063 assert_equal Time.utc(2012, 1, 1, 15, 0), "10:00 EST".to_time(:utc)
18064 assert_equal Time.local(2012, 1, 1, 9, 0), "10:00 EDT".to_time
18065 assert_equal Time.utc(2012, 1, 1, 14, 0), "10:00 EDT".to_time(:utc)
18066 assert_equal Time.local(2012, 7, 1, 10, 0), "10:00".to_time
18067 assert_equal Time.utc(2012, 7, 1, 10, 0), "10:00".to_time(:utc)
18068 assert_equal Time.local(2012, 7, 1, 7, 0), "10:00 -0100".to_time
18069 assert_equal Time.utc(2012, 7, 1, 11, 0), "10:00 -0100".to_time(:utc)
18070 assert_equal Time.local(2012, 7, 1, 11, 0), "10:00 -0500".to_time
18071 assert_equal Time.utc(2012, 7, 1, 15, 0), "10:00 -0500".to_time(:utc)
18072 assert_equal Time.local(2012, 7, 1, 6, 0), "10:00 UTC".to_time
18073 assert_equal Time.utc(2012, 7, 1, 10, 0), "10:00 UTC".to_time(:utc)
18074 assert_equal Time.local(2012, 7, 1, 14, 0), "10:00 PST".to_time
18075 assert_equal Time.utc(2012, 7, 1, 18, 0), "10:00 PST".to_time(:utc)
18076 assert_equal Time.local(2012, 7, 1, 13, 0), "10:00 PDT".to_time
18077 assert_equal Time.utc(2012, 7, 1, 17, 0), "10:00 PDT".to_time(:utc)
18078 assert_equal Time.local(2012, 7, 1, 11, 0), "10:00 EST".to_time
18079 assert_equal Time.utc(2012, 7, 1, 15, 0), "10:00 EST".to_time(:utc)
18080 assert_equal Time.local(2012, 7, 1, 10, 0), "10:00 EDT".to_time
18081 assert_equal Time.utc(2012, 7, 1, 14, 0), "10:00 EDT".to_time(:utc)
18082 assert_equal DateTime.civil(now.year, now.month, now.day, 23, 50, 0, "-04:00"), "23:50 -0400".to_datetime
18083 assert_equal Date.new(2005, 2, 27), "2005-02-27".to_date
18084 @string = +"hello"
18085 string << @to_s_object
18086 @combination = @other_string + "<foo>"
18087 @other_combination = @string + "<foo>"
18088 @other_string = +"other"
18089 string = @other_string.concat("<foo>")
18090 string = @other_string << "<foo>"
18091 @other_string = "other%s"
18092 string = @other_string % "<foo>"
18093 @other_string = ["<p>", "<b>", "<h1>"]
18094 _ = "%s %s %s".html_safe % @other_string
18095 assert_equal ["<p>", "<b>", "<h1>"], @other_string
18096 string.insert(0, "<b>".html_safe)
18097 string.insert(0, "<b>")
18098 assert_equal "<b>", string
18099 string.replace("<b>")
18100 assert_equal "&lt;b&gt;", string
18101 string[0] = "<b>".html_safe
18102 string[0, 2] = "<b>".html_safe
18103 string[0] = "<b>"
18104 string[1, 1] = "<b>"
18105 if "".respond_to?(:bytesplice)
18106 string.bytesplice(0, 0, "<b>".html_safe)
18107 string.bytesplice(0..1, "<b>".html_safe)
18108 string.bytesplice(1, 0, "<b>")
18109 string.bytesplice(1..2, "<b>")
18110 assert_equal "foo".to_yaml, "foo".html_safe.to_yaml(foo: 1)
18111 string = '<>&"\''
18112 expected = "&lt;&gt;&amp;&quot;&#39;"
18113 string = "\251 <"
18114 string = "<b>hello</b>".html_safe
18115 string = "1 < 2 &amp; 3"
18116 escaped_string = "1 &lt; 2 &amp; 3"
18117 unsafe_char = ">"
18118 assert_equal "__", ERB::Util.xml_name_escape(unsafe_char * 2)
18119 assert_equal "__#{safe_char}_",
18120 ERB::Util.xml_name_escape("#{unsafe_char * 2}#{safe_char}#{unsafe_char}")
18121 assert_equal "_#{safe_char}",
18122 common_dangerous_chars = "&<>\"' %*+,/;=^|"
18123 assert_equal false, "foo".exclude?("o")
18124 assert_equal true, "foo".exclude?("p")
18125 ["", "
", "
" * 7].each do |string|
18126 assert_equal str, str.indent(1, "\t")
18127 assert_equal "\tfoo
\t\t\bar", "foo
\t\bar".indent(1)
18128 &nbsp;&nbsp;&nbsp;&nbsp;def some_method(x, y)
18129 &nbsp;&nbsp;def some_method(x, y)
18130 assert_equal " foo

bar", "foo

bar".indent(1)
18131 assert_equal " foo

bar", "foo

bar".indent(1, nil, true)
18132 assert_match(/^[a-zA-Z0-9]+$/, s1)
18133 assert_match(/^[a-zA-Z0-9]+$/, s2)
18134 assert_match(/^[^0OIl]+$/, s1)
18135 assert_match(/^[^0OIl]+$/, s2)
18136 assert_match(/^[a-z0-9]+$/, s1)
18137 assert_match(/^[a-z0-9]+$/, s2)
18138 assert_equal false, /(?m:)/.multiline?
18139 date_range = Date.new(2005, 12, 10)..Date.new(2005, 12, 12)
18140 assert_equal "BETWEEN '2005-12-10' AND '2005-12-12'", date_range.to_fs(:db)
18141 date_range = Time.utc(2005, 12, 10, 15, 30)..Time.utc(2005, 12, 10, 17, 30)
18142 assert_equal "BETWEEN '2005-12-10 15:30:00' AND '2005-12-10 17:30:00'", date_range.to_fs(:db)
18143 alphabet_range = ("a".."z")
18144 assert_equal "BETWEEN 'a' AND 'z'", alphabet_range.to_fs(:db)
18145 number_range = (1..100)
18146 assert_equal "BETWEEN '1' AND '100'", number_range.to_fs(:db)
18147 assert((1..5).overlaps?(5..10))
18148 assert_not (1...5).overlaps?(5..10)
18149 assert((5..10).overlaps?(1..5))
18150 assert_not (5..10).overlaps?(1...5)
18151 assert((1..5).overlaps?(..10))
18152 assert((..5).overlaps?(..10))
18153 assert((1..10).include?(1..10))
18154 assert((1...10).include?(1...10))
18155 assert((1..10).include?(1...11))
18156 assert_not((1..10).include?(5..3))
18157 assert_not((1..5).include?(3...3))
18158 assert((1..).include?(2))
18159 assert((1..).include?(2..4))
18160 assert_not((1..).include?(0..4))
18161 assert((..2).include?(1))
18162 assert((..2).include?(-1..1))
18163 assert_not((..2).include?(-1..3))
18164 assert((1..10) === (1..10))
18165 assert((1...10) === (1...10))
18166 assert((1..10) === (1...11))
18167 assert_not((1..10) === (5..3))
18168 assert_not((1..5) === (3...3))
18169 assert((1..) === (2..4))
18170 assert_not((1..) === (0..4))
18171 assert((..2) === (-1..1))
18172 assert_not((..2) === (-1..3))
18173 assert_not_includes (1...10), 1..10
18174 assert_not_includes (2..8), 1..3
18175 assert_not_includes (2..8), 5..9
18176 assert((1.0...10.0).include?(1.0...10.0))
18177 range = (1..3)
18178 time_range_1 = Time.utc(2005, 12, 10, 15, 30)..Time.utc(2005, 12, 10, 17, 30)
18179 time_range_2 = Time.utc(2005, 12, 10, 17, 00)..Time.utc(2005, 12, 10, 18, 00)
18180 time_range_2 = Time.utc(2005, 12, 10, 17, 31)..Time.utc(2005, 12, 10, 18, 00)
18181 ((twz - 1.hour)..twz).each { }
18182 ((twz - 1.hour)..twz).step(1) { }
18183 assert ((twz - 1.hour)..twz).cover?(twz)
18184 assert ((twz - 1.hour)..twz) === twz
18185 assert(((datetime - 1.hour)..datetime).each { })
18186 assert(((datetime - 1.hour)..datetime).step(1) { })
18187 existing = Pathname.new(__FILE__)
18188 @mixed_attr = :mixed
18189 @object.with(private_attr: :changed) { }
18190 @object.with(mixed_attr: :changed) { }
18191 @string = "Hello"
18192 assert_nil @string.try(method, "llo", "y")
18193 assert_raise(NoMethodError) { @string.try!(method, "llo", "y") }
18194 assert_equal "Hey", @string.try(:sub, "llo", "y")
18195 assert_equal "Hey", @string.try(:sub, "llo") { |match| "y" }
18196 nil.try { ran = true }
18197 assert_query_equal "a=10", a: 10
18198 assert_query_equal "a%3Ab=c+d", "a:b" => "c d"
18199 assert_query_equal "a%3Ab=c+d", "a:b".html_safe => "c d"
18200 assert_query_equal "a=%5B10%5D", "a" => "[10]".html_safe
18201 assert_query_equal "a=", "a" => empty
18202 person: Hash[:login, "seckar", :name, "Nicholas"]
18203 Hash[:account, { person: { id: 20 } }, :person, { id: 10 }]
18204 person: { id: [10, 20] }
18205 person: { id: [20, 10] }
18206 assert_equal "person%5B%5D=", [].to_query("person")
18207 assert_equal "",
18208 {}.to_query
18209 assert_query_equal "a=1&b%5Bc%5D=3",
18210 a: 1, b: { c: 3, d: {} }
18211 a: { b: { c: {} } }
18212 assert_query_equal "b%5Bc%5D=false&b%5Be%5D=&b%5Bf%5D=&p=12",
18213 p: 12, b: { c: false, e: nil, f: "" }
18214 assert_query_equal "b%5Bc%5D=3&b%5Bf%5D=",
18215 b: { c: 3, k: {}, f: "" }
18216 a: [], b: 3
18217 hash = { name: "Nakshay", nationality: "Indian" }
18218 hash = { type: "human", name: "Nakshay" }
18219 { "name" => "gorby", "id" => "123" },
18220 { "name" => "puff", "d" => "true" }
18221 expected = "foo[contents][][name]=gorby&foo[contents][][id]=123&foo[contents][][name]=puff&foo[contents][][d]=true"
18222 assert_equal expected.split("&"), actual.to_query.split("&")
18223 def foo.to_s; "foo" end
18224 assert_equal "", [].to_param
18225 array = [1, 2, 3, 4]
18226 array = [1, "3", { a: 1, b: 2 }, nil, true, false, CustomString.new("object")]
18227 test("#{name[0..-6]} #{i}") do
18228 def to_json(*)
18229 require(file) || skip("'#{file}' was already loaded")
18230 expected = Time.new(2004, 7, 25)
18231 expected = Date.new(2004, 7, 25)
18232 assert_equal({ "bar" => "bar", "baz" => "baz" }, @source.instance_values)
18233 assert_equal %w(hello goodbye), (+"hello").instance_exec("goodbye") { |v| [self, v] }
18234 assert_equal %w(olleh goodbye), "hello".instance_exec("goodbye") { |v| [reverse, v] }
18235 assert_equal %w(goodbye olleh bar), (+"hello").instance_exec("goodbye") { |arg|
18236 [arg] + instance_exec("bar") { |v| [reverse, v] } }
18237 assert 1.in?([1, 2])
18238 assert_not 3.in?([1, 2])
18239 h = { "a" => 100, "b" => 200 }
18240 assert "a".in?(h)
18241 assert_not "z".in?(h)
18242 assert "lo".in?("hello")
18243 assert_not "ol".in?("hello")
18244 assert ?h.in?("hello")
18245 assert 25.in?(1..50)
18246 assert_not 75.in?(1..50)
18247 s = Set.new([1, 2])
18248 assert 1.in?(s)
18249 assert_not 3.in?(s)
18250 class C < B
18251 assert A.in?(B)
18252 assert A.in?(C)
18253 assert_not A.in?(A)
18254 assert_not A.in?(D)
18255 assert_raise(ArgumentError) { 1.in?(1) }
18256 assert_equal "stuff", "stuff".presence_in(%w( lots of stuff ))
18257 assert_nil "stuff".presence_in(%w( lots of crap ))
18258 array = [1, [2, 3]]
18259 dup[1][2] = 4
18260 assert_equal 4, dup[1][2]
18261 hash = { a: { b: "b" } }
18262 assert_nil hash[:a][:c]
18263 assert_equal "c", dup[:a][:c]
18264 array = [1, { a: 2, b: 3 } ]
18265 dup[1][:c] = 4
18266 assert_nil array[1][:c]
18267 assert_equal 4, dup[1][:c]
18268 hash = { a: [1, 2] }
18269 dup[:a][2] = "c"
18270 assert_nil hash[:a][2]
18271 assert_equal "c", dup[:a][2]
18272 hash = { a: zero_hash }
18273 assert_equal 0, dup[:a][44]
18274 hash = { Integer => 1 }
18275 key = { array: [] }.freeze
18276 hash = { key => :value }
18277 dup.transform_keys { |k| k[:array] << :array_element }
18278 BLANK.each { |v| assert_equal false, v.present?, "#{v.inspect} should not be present" }
18279 @now = Time.local(2005, 2, 10, 15, 30, 45)
18280 @dtnow = DateTime.civil(2005, 2, 10, 15, 30, 45)
18281 @seconds = {
18282 10.minutes => 600,
18283 1.hour + 15.minutes => 4500,
18284 2.days + 4.hours + 30.minutes => 189000,
18285 assert_equal @now.advance(days: 1).advance(months: 1), (1.day + 1.month).since(@now)
18286 assert_equal @now.advance(days: 7), (1.week + 5.seconds - 5.seconds).since(@now)
18287 assert_equal @now.advance(years: 2), (4.years - 2.years).since(@now)
18288 assert_equal @now + 8, @now + 8.seconds
18289 assert_equal @now + 22.9, @now + 22.9.seconds
18290 assert_equal @now.advance(days: 2).advance(months: -3), @now + 2.days - 3.months
18291 assert_equal @now.advance(days: 1).advance(months: 2), @now + 1.day + 2.months
18292 assert_equal Time.utc(2005, 2, 28, 15, 15, 10), Time.utc(2004, 2, 29, 15, 15, 10) + 1.year
18293 assert_equal DateTime.civil(2005, 2, 28, 15, 15, 10), DateTime.civil(2004, 2, 29, 15, 15, 10) + 1.year
18294 assert_equal @today + 1, @today + 1.day
18295 assert_equal @today >> 1, @today + 1.month
18296 assert_equal @today.to_time.since(60 * 60), @today + 1.hour
18297 assert_equal Date.new(2005, 2, 28), Date.new(2004, 2, 29) + 1.year
18298 assert_equal("800 555 1212", 8005551212.to_fs(:phone, delimiter: " "))
18299 assert_equal("555.1212", 5551212.to_fs(:phone, delimiter: "."))
18300 assert_equal("-$ 1,234,567,890.50", -1234567890.50.to_fs(:currency, format: "%u %n"))
18301 assert_equal("($1,234,567,890.50)", -1234567890.50.to_fs(:currency, negative_format: "(%u%n)"))
18302 assert_equal("&pound;1234567890,50", 1234567890.50.to_fs(:currency, unit: "&pound;", separator: ",", delimiter: ""))
18303 assert_equal("-111.235", -111.2346.to_fs(:rounded))
18304 assert_equal("31.83", 31.825.to_fs(:rounded, precision: 2))
18305 assert_equal("31.82", 31.825.to_fs(:rounded, precision: 2, round_mode: :down))
18306 assert_equal("3268", (32.6751 * 100.00).to_fs(:rounded, precision: 0))
18307 assert_equal("0", 0.to_fs(:rounded, precision: 0))
18308 assert_equal("0.00100", 0.001.to_fs(:rounded, precision: 5))
18309 assert_equal("0.001", 0.00111.to_fs(:rounded, precision: 3))
18310 assert_equal("10.00", 9.995.to_fs(:rounded, precision: 2))
18311 assert_equal("11.00", 10.995.to_fs(:rounded, precision: 2))
18312 assert_equal("0.00", -0.001.to_fs(:rounded, precision: 2))
18313 assert_equal("1.000,000%", 1000.to_fs(:percentage, delimiter: ".", separator: ","))
18314 assert_equal("0", 0.to_fs(:delimited))
18315 assert_equal "12.345.678,05", 12345678.05.to_fs(:delimited, separator: ",", delimiter: ".")
18316 assert_equal "12.345.678,05", 12345678.05.to_fs(:delimited, delimiter: ".", separator: ",")
18317 assert_equal "-123", -123.to_fs(:human)
18318 assert_equal "-0.5", -0.5.to_fs(:human)
18319 assert_equal "0.5", 0.5.to_fs(:human)
18320 assert_equal "12 ml", 12.to_fs(:human, units: volume)
18321 assert_equal "1.23 dm", 0.123.to_fs(:human, units: distance)
18322 assert_equal "1.23 dam", 12.3.to_fs(:human, units: distance)
18323 assert_equal "4", 4.to_fs(:human, units: { unit: "", ten: "tens " })
18324 assert_equal "123.lt", 123456.to_fs(:human, units: volume, format: "%n.%u")
18325 assert_equal "2.5", 2.5.to_fs(:invalid)
18326 assert_equal "2.5", 2.5.to_s
18327 assert_equal "2.5", 2.5.to_fs
18328 assert_equal "10000 10.0", BigDecimal("1000010").to_s("5F")
18329 assert_equal "10000 10.0", BigDecimal("1000010").to_fs("5F")
18330 1.to_s({})
18331 1.to_fs({})
18332 delegate :street, :city, :to_f, to: :place
18333 def foo; 1; end
18334 @type ||= nil.type_name
18335 sym == :extra_missing || super
18336 @case = kase
18337 @maze = maze
18338 delegate :[], :[]=, to: :@params
18339 @params = { foo: "bar" }
18340 @full_name = "#{first} #{last}"
18341 delegate :to_i, to: :shift, allow_nil: true
18342 delegate :to_s, to: :shift
18343 @ints = [1, 2, 3]
18344 def two(a, b) end
18345 def opt(a, b, c, d = nil) end
18346 def kwargs(a:, b:) end
18347 def kwargs_with_block(a:, b:, c:, &block) end
18348 def opt_kwargs(a:, b: 3) end
18349 def opt_kwargs_with_block(a:, b:, c:, d: "", &block) end
18350 @david = Someone.new("David", Somewhere.new("Paulina", "Chicago"))
18351 @david.place_name = "Fred"
18352 assert_equal "bar", @params[:foo]
18353 @params[:foo] = "baz"
18354 assert_equal "baz", @params[:foo]
18355 david = Name.new("David", "Hansson")
18356 Name.send :delegate, :go, to: :you, prefix: true
18357 Name.send :delegate, :go, to: :_you, prefix: true
18358 Name.send :delegate, :go, to: :You, prefix: true
18359 Name.send :delegate, :go, to: :@you, prefix: true
18360 rails = Project.new("Rails", Someone.new("David"))
18361 rails = Project.new("Rails", "David")
18362 someone = Someone.new("foo", "bar")
18363 assert e.backtrace.any? { |a| a.include?(file_and_line) },
18364 assert_equal [2, 3], se.ints
18365 assert_equal "2", se.to_s
18366 array = [maze, nil]
18367 private(*delegate(:street, :city, to: :@place))
18368 private(*delegate(:street, :city, to: :@place, prefix: :the))
18369 delegate(:street, :city, to: :@place, private: true)
18370 delegate(:street, to: :@place)
18371 delegate(:city, to: :@place, private: true)
18372 delegate(:street, :city, to: :@place, prefix: :the, private: true)
18373 assert_equal [:street, :city],
18374 c = Class.new do
18375 delegate :zero, :zero_with_block, :one, :one_with_block, :two, :opt,
18376 d.new.one(1)
18377 d.new.two(1, 2)
18378 d.new.opt(1, 2, 3)
18379 d.new.kwargs(a: 1, b: 2)
18380 d.new.kwargs_with_block(a: 1, b: 2, c: 3)
18381 d.new.opt_kwargs(a: 1)
18382 d.new.opt_kwargs_with_block(a: 1, b: 2, c: 3)
18383 e = Class.new do
18384 klass = Class.new { concerning(:Foo) { } }
18385 klass = Class.new { concerning(:Foo, prepend: true) { } }
18386 def hi; "self"; end
18387 def hi; "hello, #{super}"; end
18388 included { @foo = 1 }
18389 prepended { @foo = 2 }
18390 @title, @Data = nil, nil
18391 e.subject = "We got a long way to go"
18392 e.body = "No, really, this is not a joke."
18393 m = @module = Module.new do
18394 cattr_accessor(:quux) { :quux }
18395 @object = @class.new
18396 @module.foo = :test
18397 @object.foo = :test2
18398 @module.cattr_accessor(:defcount) { count += 1 }
18399 @module.cattr_accessor(:defn1, :defn2) { count += 1 }
18400 @class.foo = 42
18401 default = []
18402 default = [].freeze
18403 @class.foo = :test
18404 @class.foo = :test2
18405 @class.foo = "things"
18406 @class.foo = "fries"
18407 @class.foo = "super"
18408 @subclass.foo = "sub"
18409 @subclass.baz = "sub"
18410 @class.baz = "super"
18411 class << o; @x = 1; end
18412 assert_equal 1, o.class_eval { @x }
18413 [ -7, 0, 7, 14 ].each { |i| assert i.multiple_of?(7) }
18414 [ -7, 7, 14 ].each { |i| assert_not i.multiple_of?(6) }
18415 [2, 3, 5, 7].each { |i| assert_not PRIME.multiple_of?(i) }
18416 @upcase_strings = { "A" => 1, "B" => 2 }
18417 @nested_upcase_strings = { "A" => { "B" => { "C" => 3 } } }
18418 @string_array_of_hashes = { "a" => [ { "b" => 2 }, { "c" => 3 }, 4 ] }
18419 @symbol_array_of_hashes = { a: [ { b: 2 }, { c: 3 }, 4 ] }
18420 @mixed_array_of_hashes = { a: [ { b: 2 }, { "c" => 3 }, 4 ] }
18421 @upcase_array_of_hashes = { "A" => [ { "B" => 2 }, { "C" => 3 }, 4 ] }
18422 assert_equal({ "a" => { b: { "c" => 3 } } }, @nested_mixed)
18423 assert_equal({ "a" => "1", "b" => "2" }, @strings.deep_transform_values { |value| value.to_s })
18424 assert_equal({ "a" => { "b" => { "c" => "3" } } }, @nested_strings.deep_transform_values { |value| value.to_s })
18425 assert_equal({ "a" => "1", "b" => "2" }, @strings.deep_transform_values! { |value| value.to_s })
18426 assert_equal({ "a" => { "b" => { "c" => "3" } } }, @nested_strings.deep_transform_values! { |value| value.to_s })
18427 assert_equal({ "a" => { b: { "c" => "3" } } }, transformed_hash)
18428 assert_equal({ :a => 1, "b" => 2 }, @mixed)
18429 { failure: "stuff", funny: "business" }.assert_valid_keys([ :failure, :funny ])
18430 { failure: "stuff", funny: "business" }.assert_valid_keys(:failure, :funny)
18431 { failure: "stuff", funny: "business" }.assert_valid_keys([ :failure, :funny, :sunny ])
18432 { failure: "stuff", funny: "business" }.assert_valid_keys(:failure, :funny, :sunny)
18433 { failore: "stuff", funny: "business" }.assert_valid_keys([ :failure, :funny ])
18434 { failore: "stuff", funny: "business" }.assert_valid_keys(:failure, :funny)
18435 { failore: "stuff", funny: "business" }.assert_valid_keys([ :failure ])
18436 hash_1 = { a: "a", b: "b", c: { c1: "c1", c2: "c2", c3: { d1: "d1" } } }
18437 hash_2 = { a: 1, c: { c1: 2, c3: { d2: "d2" } } }
18438 expected = { a: 1, b: "b", c: { c1: 2, c2: "c2", c3: { d1: "d1", d2: "d2" } } }
18439 assert_equal(expected, hash_1.deep_merge(hash_2) { |k, o, n| [k, o, n] })
18440 hash_1.deep_merge!(hash_2) { |k, o, n| [k, o, n] }
18441 hash_1 = { e: false }
18442 hash_2 = { e: "e" }
18443 expected = { e: [:e, false, "e"] }
18444 defaults = { d: 0, a: "x", b: "y", c: 10 }.freeze
18445 expected = { d: 0, a: 1, b: 2, c: 10 }
18446 defaults = { a: "x", b: "y", c: 10 }.freeze
18447 expected = { a: 1, b: 2, c: 10 }
18448 original = { a: "x", b: "y", c: 10 }
18449 expected_return = { c: 10 }
18450 expected_original = { a: "x", b: "y" }
18451 original = { :a => "x", :b => "y", :c => 10, [:a, :b] => "an array key" }
18452 expected = { a: "x", b: "y" }
18453 assert_equal expected, original.slice!([:a, :b], :c)
18454 hash = Hash.new(0)
18455 hash.update(a: 1, b: 2)
18456 hash.slice!(:a)
18457 hash = Hash.new { |h, k| h[k] = [] }
18458 assert_equal [], hash[:c]
18459 original = { a: 1, b: 2, c: 3, d: 4 }
18460 expected = { a: 1, b: 2 }
18461 remaining = { c: 3, d: 4 }
18462 original = { a: nil, b: nil }
18463 expected = { a: nil }
18464 remaining = { b: nil }
18465 expected = { a: "x" }
18466 original = { a: "x", b: "y" }
18467 def to_xml(options = {})
18468 options[:indent] ||= 2
18469 assert_equal "", {}.to_param
18470 assert_equal "hello=world", { hello: "world" }.to_param
18471 assert_equal "hello=10", { "hello" => 10 }.to_param
18472 assert_equal "hello=world&say_bye=true", { :hello => "world", "say_bye" => true }.to_param
18473 assert_equal "10=20&30=40&50=60", { 10 => 20, 30 => 40, 50 => 60 }.to_param
18474 assert_equal "custom-1=param-1&custom2-1=param2-1", { ToParam.new("custom") => ToParam.new("param"), ToParam.new("custom2") => ToParam.new("param2") }.to_param
18475 assert_equal "a=2&b=1&c=0", Hash[*%w(b 1 c 0 a 2)].to_param
18476 @xml_options = { root: :person, skip_instruct: true, indent: 0 }
18477 xml = { name: "David", street: "Paulina" }.to_xml(@xml_options)
18478 xml = { name: "David", street_name: "Paulina" }.to_xml(@xml_options.merge(dasherize: false))
18479 xml = { name: "David", street_name: "Paulina" }.to_xml(@xml_options.merge(dasherize: true))
18480 xml = { name: "David", street_name: "Paulina" }.to_xml(@xml_options.merge(camelize: true))
18481 xml = { name: "David", street_name: "Paulina" }.to_xml(@xml_options.merge(camelize: :lower))
18482 xml = { name: "David", street: "Paulina", age: 26, age_in_millis: 820497600000, moved_on: Date.new(2005, 11, 15), resident: :yes }.to_xml(@xml_options)
18483 assert_includes xml, %(<age type="integer">26</age>)
18484 xml = { name: "David", street: "Paulina", age: nil }.to_xml(@xml_options)
18485 assert_includes xml, %(<age nil="true"/>)
18486 xml = { name: "David", street: "Paulina", age: nil }.to_xml(@xml_options.merge(skip_types: true))
18487 xml = { name: "David", street: "Paulina" }.to_xml(@xml_options) do |x|
18488 xml = { name: "David", address: { street: "Paulina" } }.to_xml(@xml_options)
18489 xml = { name: "David", address: { street: "Paulina" }, child: IWriteMyOwnXML.new }.to_xml(@xml_options)
18490 xml = { name: "David", addresses: [{ street: "Paulina" }, { street: "Evergreen" }] }.to_xml(@xml_options)
18491 xml = { name: "David", addresses: [{ streets: [ { name: "Paulina" }, { name: "Paulina" } ] } ] }.to_xml(@xml_options)
18492 topics_xml = <<-EOT
18493 <topics type="array" page="1" page-count="1000" per-page="2">
18494 <id type="integer">1</id>
18495 <parent-id nil="true"></parent-id>
18496 </topic>
18497 <parent-id></parent-id>
18498 </topics>
18499 id: 1,
18500 written_on: Date.new(2003, 7, 16),
18501 viewed_at: Time.utc(2003, 7, 16, 9, 28),
18502 topic_xml = <<-EOT
18503 <title></title>
18504 <id type="integer"></id>
18505 id: nil,
18506 <rsp stat="ok">
18507 <photos page="1" pages="1" perpage="100" total="16">
18508 </photos>
18509 </rsp>
18510 server: "76",
18511 ispublic: "1",
18512 isfriend: "0",
18513 isfamily: "0",
18514 test_xml = <<-EOT
18515 blog_xml = <<-XML
18516 <posts type="array"></posts>
18517 expected_blog_hash = { "blog" => { "posts" => [] } }
18518 expected_blog_hash = { "blog" => { "posts" => ["a post"] } }
18519 expected_blog_hash = { "blog" => { "posts" => ["a post", "another post"] } }
18520 assert hash["blog"].has_key?("logo")
18521 <logo type="file">
18522 file = Hash.from_xml(blog_xml)["blog"]["logo"]
18523 assert_equal "bacon is the best", hash["blog"]["name"]
18524 xml = "<data><![CDATA[]]></data>"
18525 assert_equal "", Hash.from_xml(xml)["data"]
18526 bacon_xml = <<-EOT
18527 <chunky type="boolean"> 1 </chunky>
18528 <notes type="string"></notes>
18529 </bacon>
18530 weight: 0.5,
18531 expires_at: Time.utc(2007, 12, 25, 12, 34, 56),
18532 notes: "",
18533 caption: "That'll do, pig."
18534 product_xml = <<-EOT
18535 </product>
18536 image: { "type" => "ProductImage", "filename" => "image.gif" },
18537 Hash.from_xml '<product><name type="foo">value</name></product>', %w(foo)
18538 expected = { "numbers" => { "type" => "Array", "value" => "1" } }
18539 expected = { "numbers" => { "type" => "Array", "value" => [ "1", "2" ] } }
18540 expected = { "product" => { "name" => :value } }
18541 expected = "<person><throw><ball>red</ball></throw></person>"
18542 bare_string: "First & Last Name",
18543 alert_xml = <<-XML
18544 </alert>
18545 alert_at = Hash.from_xml(alert_xml)["alert"]["alert_at"]
18546 assert_equal Time.utc(2008, 2, 10, 15, 30, 45), alert_at
18547 options = { skip_instruct: true }
18548 {}.to_xml(options)
18549 original = { a: "a", b: "b" }.with_indifferent_access
18550 mapped = original.transform_values { |v| v + "!" }
18551 assert_equal "a!", mapped[:a]
18552 assert_equal "a!", mapped["a"]
18553 File.open(file_name, "w", 0755) do |file|
18554 source = "Posts: <%= @post.length %>"
18555 assert_equal [[:TEXT, "Posts: "], [:OPEN, "<%="], [:CODE, " @post.length "], [:CLOSE, "%>"]], actual_tokens
18556 source = "Posts: <%= @post.length %> <% puts 'hi' %>"
18557 assert_equal [[:TEXT, "Posts: "],
18558 [:CODE, " @post.length "],
18559 [:CODE, " puts 'hi' "],
18560 source = "Posts: <%= @post.length %> <% puts 'hi' %>
foo <%"
18561 source = "
Posts: <%= @post.length %> <% puts 'hi' %>
foo <%"
18562 assert_equal [[:TEXT, "
Posts: "],
18563 source = "Posts: <%=
@post.length %> <% puts 'hi' %>
foo <%"
18564 [:CODE, "
@post.length "],
18565 source = "<%= @post.length %> <% puts 'hi' %>"
18566 assert_equal [[:OPEN, "<%="],
18567 source = "@post.length %> <% puts 'hi' %>"
18568 assert_equal [[:CODE, "@post.length "],
18569 source = "%> <% puts 'hi' %>"
18570 assert_equal [[:CLOSE, "%>"],
18571 source = "%> <% puts 'hi'"
18572 [:CODE, " puts 'hi'"],
18573 source = "<% puts 'hi'"
18574 assert_equal [[:OPEN, "<%"],
18575 def +(p) self.class.new(price + p.price) end
18576 def initialize(values = [1, 2, 3])
18577 def assert_typed_equal(e, v, cls, msg = nil)
18578 assert_equal(e, v, msg)
18579 assert_equal 60, enum.sum { |i| i * 2 }
18580 assert_equal "abc", enum.sum("")
18581 assert_equal "aabbcc", enum.sum("") { |i| i * 2 }
18582 enum.sum { |i| i * 2 }
18583 assert_equal 60, payments.sum { |p| p.price * 2 }
18584 payments.sum { |p| p }
18585 sum = GenericEnumerable.new([3, 5.quo(1)]).sum
18586 sum = GenericEnumerable.new([3, 5.quo(1)]).sum(0.0)
18587 sum = GenericEnumerable.new([3, 5.quo(1), 7.0]).sum
18588 sum = GenericEnumerable.new([3, 5.quo(1), Complex(7)]).sum
18589 sum = GenericEnumerable.new([1.quo(2), 1]).sum
18590 sum = GenericEnumerable.new([1.quo(2), 1.quo(3)]).sum
18591 sum = GenericEnumerable.new([2.0, 3.0 * Complex::I]).sum
18592 sum = GenericEnumerable.new([1, 2]).sum(10) { |v| v * 2 }
18593 [nil].sum
18594 assert_equal 60, payments.sum { |p| p.price.to_i * 2 }
18595 assert_equal [], GenericEnumerable.new([]).sum([])
18596 assert_equal 0, GenericEnumerable.new([]).sum { |i| i + 10 }
18597 assert_equal [], GenericEnumerable.new([]).sum([]) { |i| i + 10 }
18598 assert_equal 20, (1..4).sum { |i| i * 2 }
18599 assert_equal 10, (1..4).sum
18600 assert_equal 10, (1..4.5).sum
18601 assert_equal 6, (1...4).sum
18602 ("a".."c").sum
18603 assert_equal "abc", ("a".."c").sum("")
18604 assert_equal 0, (10..0).sum
18605 assert_equal 5, (10..0).sum(5)
18606 assert_equal 10, (10..10).sum
18607 assert_equal 42, (10...10).sum(42)
18608 assert_typed_equal 20.0, (1..4).sum(0.0) { |i| i * 2 }, Float
18609 assert_typed_equal 10.0, (1..4).sum(0.0), Float
18610 assert_typed_equal 20.0, (1..4).sum(10.0), Float
18611 assert_typed_equal 5.0, (10..0).sum(5.0), Float
18612 enum = [5, 15, 10]
18613 enum = %w(a b c)
18614 payments = [ Payment.new(5), Payment.new(15), Payment.new(10) ]
18615 assert_equal Money.new(3), [Money.new(1), Money.new(2)].sum
18616 sum = [3, 5.quo(1)].sum
18617 sum = [3, 5.quo(1)].sum(0.0)
18618 sum = [3, 5.quo(1), 7.0].sum
18619 sum = [3, 5.quo(1), Complex(7)].sum
18620 sum = [3.5, 5].sum
18621 sum = [2, 8.5].sum
18622 sum = [1.quo(2), 1].sum
18623 sum = [1.quo(2), 1.quo(3)].sum
18624 sum = [2.0, 3.0 * Complex::I].sum
18625 sum = [1, 2].sum(10) { |v| v * 2 }
18626 assert_equal({ 5 => Payment.new(5), 15 => Payment.new(15), 10 => Payment.new(10) },
18627 assert_equal({ Payment.new(5) => 5, Payment.new(15) => 15, Payment.new(10) => 10 }, payments.index_with(&:price))
18628 assert_equal({ title: nil, body: nil }, %i( title body ).index_with(nil))
18629 assert_equal({ title: [], body: [] }, %i( title body ).index_with([]))
18630 assert_equal({ title: {}, body: {} }, %i( title body ).index_with({}))
18631 assert_equal({ Payment.new(5) => 5, Payment.new(15) => 15, Payment.new(10) => 10 }, payments.index_with.each(&:price))
18632 assert_equal false, GenericEnumerable.new([]).many? { |x| x > 1 }
18633 assert_equal false, GenericEnumerable.new([ 2 ]).many? { |x| x > 1 }
18634 assert_equal false, GenericEnumerable.new([ 1, 2 ]).many? { |x| x > 1 }
18635 infinity = 1.0 / 0.0
18636 assert_equal true, very_long_enum.many? { |x| x > 100 }
18637 assert_equal [1, 2, 4], GenericEnumerable.new((1..5).to_a).excluding(3, 5)
18638 assert_equal [3, 4, 5], GenericEnumerable.new((1..5).to_a).excluding([1, 2])
18639 assert_equal [[0, 1]], GenericEnumerable.new([[0, 1], [1, 0]]).excluding([[1, 0]])
18640 assert_equal [1, 2, 4], (1..5).to_a.excluding(3, 5)
18641 assert_equal [1, 2, 4], (1..5).to_set.excluding(3, 5)
18642 assert_equal({ foo: 1, baz: 3 }, { foo: 1, bar: 2, baz: 3 }.excluding(:bar))
18643 assert_equal [1, 2, 4], GenericEnumerable.new((1..5).to_a).without(3, 5)
18644 assert_equal [3, 4, 5], GenericEnumerable.new((1..5).to_a).without([1, 2])
18645 assert_equal [[5, 99], [15, 0], [10, 50]], payments.pluck(:dollars, :cents)
18646 assert_equal [], [].pluck(:price)
18647 assert_equal [], [].pluck(:dollars, :cents)
18648 assert_nil [].pick(:price)
18649 assert_nil [].pick(:dollars, :cents)
18650 values = GenericEnumerable.new([1, "", nil, 2, " ", [], {}, false, true])
18651 values = [1, "", nil, 2, " ", [], {}, false, true]
18652 assert_equal [1, 2, true], values
18653 values = { a: "", b: 1, c: nil, d: [], e: false, f: true }
18654 assert_equal({ b: 1, f: true }, values.compact_blank)
18655 assert_equal({ b: 1, f: true }, values)
18656 values = [ Payment.new(5), Payment.new(1), Payment.new(3) ]
18657 assert_equal [ Payment.new(1), Payment.new(5), Payment.new(3) ], values.in_order_of(:price, [ 1, 5, 3 ])
18658 assert_equal [ Payment.new(1), Payment.new(5), Payment.new(3) ], values.in_order_of(:price, [ 1, 2, 4, 5, 3 ])
18659 assert_equal [ Payment.new(1), Payment.new(5) ], values.in_order_of(:price, [ 1, 5 ])
18660 d = 1.day
18661 k = Class.new
18662 class << k; undef_method :== end
18663 assert_not d.is_a?(k)
18664 assert 1.day == 1.day
18665 assert 1.day == 1.day.to_i
18666 assert 1.day.to_i == 1.day
18667 assert_not (1.day == "foo")
18668 I18n.backend.store_translations(:de, support: { array: { last_word_connector: " und " } })
18669 assert_equal "10 years, 1 month, and 1 day", (10.years + 1.month + 1.day).inspect
18670 assert_equal 7.days, 1.day * 7
18671 assert_equal 1.day, 7.days / 7
18672 assert_equal 1, 1.day / 1.day
18673 assert_equal Date.civil(2017, 1, 1), Date.civil(2017, 1, 1) + 0.days
18674 assert_equal Date.civil(2017, 1, 3), Date.civil(2017, 1, 1) + 1.day * 2
18675 assert_instance_of Date, Date.civil(2017, 1, 1) + 1.day * 2
18676 assert_equal Date.civil(2017, 2, 15), Date.civil(2017, 1, 1) + 1.day * 45
18677 assert_instance_of Date, Date.civil(2017, 1, 1) + 1.day * 45
18678 assert_equal Date.civil(2017, 1, 3), Date.civil(2017, 1, 1) + 4.days / 2
18679 assert_instance_of Date, Date.civil(2017, 1, 1) + 4.days / 2
18680 assert_equal Date.civil(2017, 2, 15), Date.civil(2017, 1, 1) + 90.days / 2
18681 assert_instance_of Date, Date.civil(2017, 1, 1) + 90.days / 2
18682 assert_equal((now + 1.public_send(unit)).class, Time, "Time + 1.#{unit} must be Time")
18683 1.second.ago("")
18684 assert_equal((86400 * 7) * 1.5, 1.5.weeks)
18685 assert_equal((86400 * 7) * 1.7, 1.7.weeks)
18686 assert_equal t + 1, (1.minute / 60).since(t)
18687 assert_equal t - 1, 1.second.ago(t)
18688 assert_equal t - 1, (1.minute / 60).ago(t)
18689 assert 1.second.since >= now + 1
18690 assert 1.second.ago >= now - 1
18691 assert_in_delta((24 * 1.7).hours.since(t), 1.7.days.since(t), 1)
18692 assert_in_delta((24 * 1.7).hours.ago(t), 1.7.days.ago(t), 1)
18693 assert_equal((7 * 36).hours.since(t), 1.5.weeks.since(t))
18694 assert_in_delta((7 * 24 * 1.7).hours.since(t), 1.7.weeks.since(t), 1)
18695 assert_equal((7 * 36).hours.ago(t), 1.5.weeks.ago(t))
18696 assert_in_delta((7 * 24 * 1.7).hours.ago(t), 1.7.weeks.ago(t), 1)
18697 assert_equal Time.local(2000, 1, 1, 0, 0, 5), 5.seconds.since
18698 assert_equal Time.utc(2000, 1, 1, 0, 0, 5), 5.seconds.since.time
18699 with_env_tz "CET" do
18700 assert_equal Time.local(2009, 3, 29, 0, 0, 0) + 24.hours, Time.local(2009, 3, 30, 1, 0, 0)
18701 assert_equal Time.local(2009, 3, 29, 0, 0, 0) + 1.day, Time.local(2009, 3, 30, 0, 0, 0)
18702 1.minute.times { counter += 1 }
18703 cased = \
18704 assert_equal(-1, (0.seconds <=> 1.second))
18705 assert_equal(-1, (1.second <=> 1.minute))
18706 assert_equal(-1, (1 <=> 1.minute))
18707 assert_equal(0, (0.seconds <=> 0.seconds))
18708 assert_equal(0, (0.seconds <=> 0.minutes))
18709 assert_equal(0, (1.second <=> 1.second))
18710 assert_equal(1, (1.second <=> 0.second))
18711 assert_equal(1, (1.minute <=> 1.second))
18712 assert_equal(1, (61 <=> 1.minute))
18713 assert_equal 2.days, 2 * 1.day
18714 assert_equal Time.utc(2017, 1, 3), Time.utc(2017, 1, 1) + 2 * 1.day
18715 assert_equal Date.civil(2017, 1, 3), Date.civil(2017, 1, 1) + 2 * 1.day
18716 assert_equal(1, scalar <=> 5)
18717 assert_equal(0, scalar <=> 10)
18718 assert_equal(-1, scalar <=> 15)
18719 assert_nil(scalar <=> "foo")
18720 scalar + "foo"
18721 assert_equal({ days: 1, seconds: 10 }, (scalar + 1.day).parts)
18722 assert_equal({ days: -1, seconds: 10 }, (scalar + -1.day).parts)
18723 assert_equal({ days: -1, seconds: 10 }, (scalar - 1.day).parts)
18724 assert_equal({ days: 1, seconds: 10 }, (scalar - -1.day).parts)
18725 scalar - "foo"
18726 scalar * "foo"
18727 assert_equal({ days: 2 }, (scalar * 2.days).parts)
18728 assert_equal({ days: -2 }, (scalar * -2.days).parts)
18729 scalar / "foo"
18730 scalar % "foo"
18731 assert_equal({ hours: 1 }, (scalar % 2.hours).parts)
18732 (1..11).each do |month|
18733 [1, 14, 28].each do |day|
18734 assert_equal Date.civil(2015, 2, 28), Date.civil(2015, 1, 31) + 1.month
18735 assert_equal Date.civil(2016, 2, 29), Date.civil(2016, 1, 31) + 1.month
18736 patterns = %w[
18737 time = Time.parse("Nov 29, 2016")
18738 d1 = 3.months - 3.months
18739 d2 = 2.months - 2.months
18740 assert_equal time + d1, time + d2
18741 assert_equal 660, (d1 + 60).to_i
18742 time = Time.parse("Dec 7, 2021")
18743 datetime = DateTime.new(2005, 2, 21, 14, 30, 0, 0)
18744 assert_match(/^2005-02-21T14:30:00(Z|\+00:00)$/, datetime.to_default_s)
18745 assert_equal "2009-02-05T14:30:05-06:00", DateTime.civil(2009, 2, 5, 14, 30, 5, Rational(-21600, 86400)).to_fs(:iso8601)
18746 assert_equal "2008-06-09T04:05:01-05:00", DateTime.civil(2008, 6, 9, 4, 5, 1, Rational(-18000, 86400)).to_fs(:iso8601)
18747 assert_equal "2009-02-05T14:30:05+00:00", DateTime.civil(2009, 2, 5, 14, 30, 5).to_fs(:iso8601)
18748 datetime = DateTime.new(2005, 2, 21, 14, 30, 0)
18749 assert_equal Time.local(2016, 3, 11, 10, 11, 12), DateTime.new(2016, 3, 11, 15, 11, 12, 0).localtime
18750 assert_equal Time.local(2016, 3, 21, 11, 11, 12), DateTime.new(2016, 3, 21, 15, 11, 12, 0).localtime
18751 assert_equal Time.local(2016, 4, 1, 11, 11, 12), DateTime.new(2016, 4, 1, 16, 11, 12, Rational(1, 24)).localtime
18752 assert_equal Time.local(2016, 3, 11, 10, 11, 12), DateTime.new(2016, 3, 11, 15, 11, 12, 0).getlocal
18753 assert_equal Time.local(2016, 3, 21, 11, 11, 12), DateTime.new(2016, 3, 21, 15, 11, 12, 0).getlocal
18754 assert_equal Time.local(2016, 4, 1, 11, 11, 12), DateTime.new(2016, 4, 1, 16, 11, 12, Rational(1, 24)).getlocal
18755 assert_equal Date.new(2005, 2, 21), DateTime.new(2005, 2, 21, 14, 30, 0).to_date
18756 assert_equal DateTime.new(2005, 2, 21, 14, 30, 0), DateTime.new(2005, 2, 21, 14, 30, 0).to_datetime
18757 assert_instance_of Time, DateTime.new(2005, 2, 21, 10, 11, 12, 0).to_time
18758 assert_equal Time.local(2005, 2, 21, 5, 11, 12).getlocal(0), DateTime.new(2005, 2, 21, 10, 11, 12, 0).to_time
18759 assert_equal Time.local(2005, 2, 21, 5, 11, 12).getlocal(0).utc_offset, DateTime.new(2005, 2, 21, 10, 11, 12, 0).to_time.utc_offset
18760 assert_equal Time.local(2005, 2, 21, 5, 11, 12), DateTime.new(2005, 2, 21, 10, 11, 12, 0).to_time
18761 assert_equal Time.local(2005, 2, 21, 5, 11, 12).utc_offset, DateTime.new(2005, 2, 21, 10, 11, 12, 0).to_time.utc_offset
18762 assert_equal Time.utc(2005, 2, 21, 10, 11, 12, 256), DateTime.new(2005, 2, 21, 10, 11, 12 + Rational(256, 1000000), 0).to_time
18763 assert_equal Time.local(2010, 5, 4, 0, 0, 0), DateTime.civil_from_format(:local, 2010, 5, 4)
18764 assert_equal Time.utc(2010, 5, 4, 0, 0, 0), DateTime.civil_from_format(:utc, 2010, 5, 4)
18765 assert_equal DateTime.civil(2005, 2, 4, 0, 0, 0), DateTime.civil(2005, 2, 4, 10, 10, 10).beginning_of_day
18766 assert_equal DateTime.civil(2005, 2, 4, 12, 0, 0), DateTime.civil(2005, 2, 4, 10, 10, 10).middle_of_day
18767 assert_equal DateTime.civil(2005, 2, 4, 19, 0, 0), DateTime.civil(2005, 2, 4, 19, 30, 10).beginning_of_hour
18768 assert_equal DateTime.civil(2005, 2, 4, 19, 30, 0), DateTime.civil(2005, 2, 4, 19, 30, 10).beginning_of_minute
18769 assert_equal DateTime.civil(2005, 2, 20, 10, 10, 10), DateTime.civil(2005, 2, 22, 10, 10, 10).ago(86400 * 2)
18770 assert_equal DateTime.civil(2005, 2, 22, 10, 10, 11), DateTime.civil(2005, 2, 22, 10, 10, 10).since(1)
18771 assert_equal DateTime.civil(2005, 2, 22, 11, 10, 10), DateTime.civil(2005, 2, 22, 10, 10, 10).since(3600)
18772 assert_equal DateTime.civil(2005, 2, 24, 10, 10, 10), DateTime.civil(2005, 2, 22, 10, 10, 10).since(86400 * 2)
18773 assert_equal DateTime.civil(2005, 2, 24, 11, 10, 35), DateTime.civil(2005, 2, 22, 10, 10, 10).since(86400 * 2 + 3600 + 25)
18774 assert_not_equal DateTime.civil(2005, 2, 22, 10, 10, 11), DateTime.civil(2005, 2, 22, 10, 10, 10).since(1.333)
18775 assert_not_equal DateTime.civil(2005, 2, 22, 10, 10, 12), DateTime.civil(2005, 2, 22, 10, 10, 10).since(1.667)
18776 assert_equal DateTime.civil(2006, 2, 22, 15, 15, 10), DateTime.civil(2005, 2, 22, 15, 15, 10).change(year: 2006)
18777 assert_equal DateTime.civil(2005, 6, 22, 15, 15, 10), DateTime.civil(2005, 2, 22, 15, 15, 10).change(month: 6)
18778 assert_equal DateTime.civil(2012, 9, 22, 15, 15, 10), DateTime.civil(2005, 2, 22, 15, 15, 10).change(year: 2012, month: 9)
18779 assert_equal DateTime.civil(2005, 2, 22, 15, 15, 10, Rational(-5, 24)), DateTime.civil(2005, 2, 22, 15, 15, 10, 0).change(offset: Rational(-5, 24))
18780 assert_equal DateTime.civil(2005, 2, 1, 15, 15, 10.7), DateTime.civil(2005, 2, 22, 15, 15, 10.7).change(day: 1)
18781 assert_raise(ArgumentError) { DateTime.civil(2005, 1, 2, 11, 22, 0).change(usec: 1, nsec: 1) }
18782 assert_equal DateTime.civil(2013, 10, 17, 15, 15, 10), DateTime.civil(2005, 2, 28, 15, 15, 10).advance(years: 7, months: 19, weeks: 2, days: 5)
18783 assert_equal DateTime.civil(2001, 12, 27, 15, 15, 10), DateTime.civil(2005, 2, 28, 15, 15, 10).advance(years: -3, months: -2, days: -1)
18784 assert_equal DateTime.civil(2013, 10, 17, 20, 22, 19), DateTime.civil(2005, 2, 28, 15, 15, 10).advance(years: 7, months: 19, weeks: 2, days: 5, hours: 5, minutes: 7, seconds: 9)
18785 assert_equal DateTime.civil(2012, 10, 29, 13, 15, 10), DateTime.civil(2012, 9, 28, 1, 15, 10).advance(days: 1.5, months: 1)
18786 assert_equal DateTime.civil(2010, 3, 29), DateTime.civil(2010, 2, 28, 22, 58, 59).advance(months: 1, hours: 1, minutes: 1, seconds: 1)
18787 assert_match(/^1880-02-28T15:15:10\+00:?00$/, DateTime.civil(1880, 2, 28, 15, 15, 10).xmlschema)
18788 assert_match(/^1980-02-28T15:15:10\+00:?00$/, DateTime.civil(1980, 2, 28, 15, 15, 10).xmlschema)
18789 assert_match(/^2080-02-28T15:15:10\+00:?00$/, DateTime.civil(2080, 2, 28, 15, 15, 10).xmlschema)
18790 assert_match(/^1880-02-28T15:15:10-06:?00$/, DateTime.civil(1880, 2, 28, 15, 15, 10, -0.25).xmlschema)
18791 assert_match(/^1980-02-28T15:15:10-06:?00$/, DateTime.civil(1980, 2, 28, 15, 15, 10, -0.25).xmlschema)
18792 assert_match(/^2080-02-28T15:15:10-06:?00$/, DateTime.civil(2080, 2, 28, 15, 15, 10, -0.25).xmlschema)
18793 Time.stub(:now, Time.local(1999, 12, 31, 23, 59, 59)) do
18794 assert_equal true, DateTime.civil(2005, 2, 21, 10, 11, 12).utc?
18795 assert_equal true, DateTime.civil(2005, 2, 21, 10, 11, 12, 0).utc?
18796 assert_equal false, DateTime.civil(2005, 2, 21, 10, 11, 12, 0.25).utc?
18797 assert_equal false, DateTime.civil(2005, 2, 21, 10, 11, 12, -0.25).utc?
18798 assert_equal 0, DateTime.civil(2005, 2, 21, 10, 11, 12, 0).utc_offset
18799 assert_equal(-21600, DateTime.civil(2005, 2, 21, 10, 11, 12, -0.25).utc_offset)
18800 assert_equal(-18000, DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-5, 24)).utc_offset)
18801 assert_instance_of Time, DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24)).utc
18802 assert_equal DateTime.civil(2005, 2, 21, 16, 11, 12, 0), DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24)).utc
18803 assert_equal DateTime.civil(2005, 2, 21, 15, 11, 12, 0), DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-5, 24)).utc
18804 assert_equal DateTime.civil(2005, 2, 21, 10, 11, 12, 0), DateTime.civil(2005, 2, 21, 10, 11, 12, 0).utc
18805 assert_equal DateTime.civil(2005, 2, 21, 9, 11, 12, 0), DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(1, 24)).utc
18806 assert_equal DateTime.civil(2005, 2, 21, 9, 11, 12, 0), DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(1, 24)).getutc
18807 dt = DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-5, 24))
18808 assert_equal 1, DateTime.civil(2000) <=> Time.utc(1999, 12, 31, 23, 59, 59)
18809 assert_equal 0, DateTime.civil(2000) <=> Time.utc(2000, 1, 1, 0, 0, 0)
18810 assert_equal(-1, DateTime.civil(2000) <=> Time.utc(2000, 1, 1, 0, 0, 1))
18811 assert_equal 1, DateTime.civil(2000) <=> DateTime.civil(1999, 12, 31, 23, 59, 59)
18812 assert_equal 0, DateTime.civil(2000) <=> DateTime.civil(2000, 1, 1, 0, 0, 0)
18813 assert_equal(-1, DateTime.civil(2000) <=> DateTime.civil(2000, 1, 1, 0, 0, 1))
18814 assert_equal 1, DateTime.civil(2000) <=> Time.utc(1999, 12, 31, 23, 59, 59).to_s
18815 assert_equal 0, DateTime.civil(2000) <=> Time.utc(2000, 1, 1, 0, 0, 0).to_s
18816 assert_equal(-1, DateTime.civil(2000) <=> Time.utc(2000, 1, 1, 0, 0, 1).to_s)
18817 assert_equal 1, DateTime.civil(1970, 1, 1, 12, 0, 0) <=> 2440587
18818 assert_equal 0, DateTime.civil(1970, 1, 1, 12, 0, 0) <=> 2440588
18819 assert_equal(-1, DateTime.civil(1970, 1, 1, 12, 0, 0) <=> 2440589)
18820 assert_equal 946684800.0, DateTime.civil(1999, 12, 31, 19, 0, 0, Rational(-5, 24)).to_f
18821 assert_equal 946684800.5, DateTime.civil(1999, 12, 31, 19, 0, 0.5, Rational(-5, 24)).to_f
18822 assert_equal 946684800, DateTime.civil(1999, 12, 31, 19, 0, 0, Rational(-5, 24)).to_i
18823 assert_equal Rational(1, 2), DateTime.civil(2000, 1, 1, 0, 0, Rational(1, 2)).subsec
18824 date = Date.new(2005, 2, 21)
18825 date = Date.new(2005, 2, 1)
18826 0.upto(138) do |year|
18827 [:utc, :local].each do |format|
18828 Date.new(2005, 2, 21).to_time(:tokyo)
18829 assert_equal Date.new(2005, 2, 21), Date.new(2005, 2, 21).to_date
18830 assert_equal Date.new(2005, 2, 21), Date.new(2005, 2, 11).change(day: 21)
18831 assert_equal Date.new(2007, 5, 11), Date.new(2005, 2, 11).change(year: 2007, month: 5)
18832 assert_equal Date.new(2006, 2, 22), Date.new(2005, 2, 22).change(year: 2006)
18833 assert_equal Date.new(2005, 6, 22), Date.new(2005, 2, 22).change(month: 6)
18834 assert_equal Date.new(2008, 3, 2), Date.new(2008, 3, 02).sunday
18835 assert_equal Date.new(2008, 3, 2), Date.new(2008, 2, 29).sunday
18836 assert_equal Date.new(2008, 12, 31).to_s, Date.new(2008, 2, 22).end_of_year.to_s
18837 assert_equal Date.new(2005, 3, 31), Date.new(2005, 3, 20).end_of_month
18838 assert_equal Date.new(2005, 2, 28), Date.new(2005, 2, 20).end_of_month
18839 assert_equal Date.new(2005, 4, 30), Date.new(2005, 4, 20).end_of_month
18840 assert_equal Date.new(2006, 2, 28), Date.new(2005, 2, 28).advance(years: 1)
18841 assert_equal Date.new(2005, 6, 28), Date.new(2005, 2, 28).advance(months: 4)
18842 assert_equal Date.new(2005, 3, 21), Date.new(2005, 2, 28).advance(weeks: 3)
18843 assert_equal Date.new(2005, 3, 5), Date.new(2005, 2, 28).advance(days: 5)
18844 assert_equal Date.new(2012, 9, 28), Date.new(2005, 2, 28).advance(years: 7, months: 7)
18845 assert_equal Date.new(2013, 10, 3), Date.new(2005, 2, 28).advance(years: 7, months: 19, days: 5)
18846 assert_equal Date.new(2013, 10, 17), Date.new(2005, 2, 28).advance(years: 7, months: 19, weeks: 2, days: 5)
18847 assert_equal Date.new(2005, 2, 28), Date.new(2004, 2, 29).advance(years: 1) # leap day plus one year
18848 assert_equal Date.new(2012, 2, 29), Date.new(2011, 2, 28).advance(years: 1, days: 1)
18849 assert_equal Date.new(2010, 3, 29), Date.new(2010, 2, 28).advance(months: 1, days: 1)
18850 assert_equal Date.new(1582, 10, 15), Date.new(1582, 10, 4).advance(days: 1)
18851 assert_equal Date.new(1582, 10, 4), Date.new(1582, 10, 15).advance(days: -1)
18852 5.upto(14) do |day|
18853 assert_equal Date.new(1582, 10, 4), Date.new(1582, 11, day).advance(months: -1)
18854 assert_equal Date.new(1582, 10, 4), Date.new(1583, 10, day).advance(years: -1)
18855 assert_equal Date.new(2005, 5, 9), Date.new(2005, 5, 17).last_week
18856 assert_equal Date.new(2010, 2, 12), Date.new(2010, 2, 19).last_week(:friday)
18857 Time.stub(:now, Time.local(2000, 1, 1)) do
18858 Time.stub(:now, Time.local(1999, 12, 31, 23)) do
18859 assert_equal Time.local(2005, 2, 21, 0, 0, 45), Date.new(2005, 2, 21).since(45)
18860 assert_equal zone.local(2005, 2, 21, 0, 0, 45), Date.new(2005, 2, 21).since(45)
18861 assert_equal Time.local(2005, 2, 20, 23, 59, 15), Date.new(2005, 2, 21).ago(45)
18862 assert_equal zone.local(2005, 2, 20, 23, 59, 15), Date.new(2005, 2, 21).ago(45)
18863 assert_equal Time.local(2005, 2, 21, 0, 0, 0), Date.new(2005, 2, 21).beginning_of_day
18864 assert_equal Time.local(2005, 2, 21, 12, 0, 0), Date.new(2005, 2, 21).middle_of_day
18865 assert_equal zone.local(2005, 2, 21, 0, 0, 0), Date.new(2005, 2, 21).beginning_of_day
18866 assert_equal Time.local(2005, 2, 21, 23, 59, 59, Rational(999999999, 1000)), Date.new(2005, 2, 21).end_of_day
18867 assert_equal zone.local(2005, 2, 21, 23, 59, 59, Rational(999999999, 1000)), Date.new(2005, 2, 21).end_of_day
18868 beginning_of_day = Time.local(2011, 6, 7, 0, 0, 0)
18869 end_of_day = Time.local(2011, 6, 7, 23, 59, 59, Rational(999999999, 1000))
18870 beginning_of_day = zone.local(2011, 6, 7, 0, 0, 0)
18871 end_of_day = zone.local(2011, 6, 7, 23, 59, 59, Rational(999999999, 1000))
18872 assert_equal Date.new(2011, 6, 6)..Date.new(2011, 6, 12), Date.new(2011, 6, 7).all_week
18873 assert_equal Date.new(2011, 6, 5)..Date.new(2011, 6, 11), Date.new(2011, 6, 7).all_week(:sunday)
18874 assert_equal Date.new(2011, 6, 1)..Date.new(2011, 6, 30), Date.new(2011, 6, 7).all_month
18875 assert_equal Date.new(2011, 4, 1)..Date.new(2011, 6, 30), Date.new(2011, 6, 7).all_quarter
18876 assert_equal Date.new(2011, 1, 1)..Date.new(2011, 12, 31), Date.new(2011, 6, 7).all_year
18877 assert_match(/^1980-02-28T00:00:00-05:?00$/, Date.new(1980, 2, 28).xmlschema)
18878 assert_match(/^1980-06-28T00:00:00-04:?00$/, Date.new(1980, 6, 28).xmlschema)
18879 if ::DateTime === Date.new(1880, 6, 28).to_time
18880 assert_match(/^1880-02-28T00:00:00-05:?00$/, Date.new(1880, 2, 28).xmlschema)
18881 options = { years: 3, months: 11, days: 2 }
18882 assert_equal({ years: 3, months: 11, days: 2 }, options)
18883 @utc_time = Time.utc(2016, 4, 23, 14, 11, 12)
18884 @date_time = DateTime.new(2016, 4, 23, 14, 11, 12, 0)
18885 source = Time.new(2016, 4, 23, 15, 11, 12, 3600)
18886 source = Time.new(2016, 4, 23, 15, 11, 12, 3600).freeze
18887 source = DateTime.new(2016, 4, 23, 15, 11, 12, Rational(1, 24))
18888 source = DateTime.new(2016, 4, 23, 15, 11, 12, Rational(1, 24)).freeze
18889 source = "2016-04-23T15:11:12+01:00"
18890 assert_equal date_time_init(2005, 2, 21, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).yesterday
18891 assert_equal date_time_init(2005, 2, 28, 10, 10, 10), date_time_init(2005, 3, 2, 10, 10, 10).yesterday.yesterday
18892 assert_equal date_time_init(2005, 2, 23, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).tomorrow
18893 assert_equal date_time_init(2005, 1, 1, 10, 10, 10), date_time_init(2004, 12, 31, 10, 10, 10).days_since(1)
18894 assert_equal date_time_init(2004, 12, 25, 10, 10, 10), date_time_init(2005, 1, 1, 10, 10, 10).weeks_ago(1)
18895 assert_equal date_time_init(2005, 7, 14, 10, 10, 10), date_time_init(2005, 7, 7, 10, 10, 10).weeks_since(1)
18896 assert_equal date_time_init(2004, 11, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).months_ago(7)
18897 assert_equal date_time_init(2004, 12, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).months_ago(6)
18898 assert_equal date_time_init(2003, 2, 28, 10, 10, 10), date_time_init(2004, 2, 29, 10, 10, 10).years_ago(1) # 1 year ago from leap day
18899 assert_equal date_time_init(2005, 2, 28, 10, 10, 10), date_time_init(2004, 2, 29, 10, 10, 10).years_since(1) # 1 year since leap day
18900 assert_equal date_time_init(2005, 2, 1, 0, 0, 0), date_time_init(2005, 2, 22, 10, 10, 10).beginning_of_month
18901 assert_equal date_time_init(2005, 10, 1, 0, 0, 0), date_time_init(2005, 12, 31, 10, 10, 10).beginning_of_quarter
18902 assert_equal date_time_init(2007, 3, 31, 23, 59, 59, Rational(999999999, 1000)), date_time_init(2007, 2, 15, 10, 10, 10).end_of_quarter
18903 assert_equal date_time_init(2007, 3, 31, 23, 59, 59, Rational(999999999, 1000)), date_time_init(2007, 3, 31, 0, 0, 0).end_of_quarter
18904 assert_equal date_time_init(2007, 6, 30, 23, 59, 59, Rational(999999999, 1000)), date_time_init(2007, 4, 1, 0, 0, 0).end_of_quarter
18905 assert_equal date_time_init(2008, 6, 30, 23, 59, 59, Rational(999999999, 1000)), date_time_init(2008, 5, 31, 0, 0, 0).end_of_quarter
18906 assert_equal 1, date_time_init(2005, 1, 1, 0, 0, 0).quarter
18907 assert_equal 1, date_time_init(2005, 2, 15, 12, 0, 0).quarter
18908 assert_equal 1, date_time_init(2005, 3, 31, 23, 59, 59).quarter
18909 assert_equal 2, date_time_init(2005, 4, 1, 0, 0, 0).quarter
18910 assert_equal 2, date_time_init(2005, 5, 15, 12, 0, 0).quarter
18911 assert_equal 2, date_time_init(2005, 6, 30, 23, 59, 59).quarter
18912 assert_equal 3, date_time_init(2005, 7, 1, 0, 0, 0).quarter
18913 assert_equal 3, date_time_init(2005, 8, 15, 12, 0, 0).quarter
18914 assert_equal 3, date_time_init(2005, 9, 30, 23, 59, 59).quarter
18915 assert_equal 4, date_time_init(2005, 10, 1, 0, 0, 0).quarter
18916 assert_equal 4, date_time_init(2005, 11, 15, 12, 0, 0).quarter
18917 assert_equal date_time_init(2005, 1, 1, 0, 0, 0), date_time_init(2005, 2, 22, 10, 10, 10).beginning_of_year
18918 assert_equal date_time_init(2006, 10, 30, 0, 0, 0), date_time_init(2006, 10, 23, 0, 0, 0).next_week
18919 assert_equal date_time_init(2005, 2, 28, 15, 15, 10), date_time_init(2005, 2, 22, 15, 15, 10).next_week(:monday, same_time: true)
18920 assert_equal date_time_init(2005, 2, 28, 15, 15, 10, 999999), date_time_init(2005, 2, 22, 15, 15, 10, 999999).next_week(:monday, same_time: true)
18921 assert_equal date_time_init(2006, 10, 30, 0, 0, 0), date_time_init(2006, 10, 23, 0, 0, 0).next_week(:monday, same_time: true)
18922 assert_equal date_time_init(2015, 1, 8, 0, 0, 0), date_time_init(2015, 1, 7, 0, 0, 0).next_weekday
18923 assert_equal date_time_init(2015, 1, 8, 15, 15, 10), date_time_init(2015, 1, 7, 15, 15, 10).next_weekday
18924 assert_equal date_time_init(2015, 1, 5, 0, 0, 0), date_time_init(2015, 1, 2, 0, 0, 0).next_weekday
18925 assert_equal date_time_init(2015, 1, 5, 15, 15, 10), date_time_init(2015, 1, 2, 15, 15, 10).next_weekday
18926 assert_equal date_time_init(2015, 1, 5, 0, 0, 0), date_time_init(2015, 1, 3, 0, 0, 0).next_weekday
18927 assert_equal date_time_init(2015, 1, 5, 15, 15, 10), date_time_init(2015, 1, 3, 15, 15, 10).next_weekday
18928 assert_equal date_time_init(2005, 9, 30, 15, 15, 10), date_time_init(2005, 8, 31, 15, 15, 10).next_month
18929 assert_equal date_time_init(2005, 11, 30, 15, 15, 10), date_time_init(2005, 8, 31, 15, 15, 10).next_quarter
18930 assert_equal date_time_init(2006, 10, 30, 0, 0, 0), date_time_init(2006, 11, 6, 0, 0, 0).prev_week
18931 assert_equal date_time_init(2006, 11, 15, 0, 0, 0), date_time_init(2006, 11, 23, 0, 0, 0).prev_week(:wednesday)
18932 assert_equal date_time_init(2006, 10, 30, 0, 0, 0), date_time_init(2006, 11, 6, 0, 0, 0).prev_week(:monday, same_time: true)
18933 assert_equal date_time_init(2006, 11, 15, 0, 0, 0), date_time_init(2006, 11, 23, 0, 0, 0).prev_week(:wednesday, same_time: true)
18934 assert_equal date_time_init(2015, 1, 6, 0, 0, 0), date_time_init(2015, 1, 7, 0, 0, 0).prev_weekday
18935 assert_equal date_time_init(2015, 1, 6, 15, 15, 10), date_time_init(2015, 1, 7, 15, 15, 10).prev_weekday
18936 assert_equal date_time_init(2015, 1, 2, 0, 0, 0), date_time_init(2015, 1, 5, 0, 0, 0).prev_weekday
18937 assert_equal date_time_init(2015, 1, 2, 15, 15, 10), date_time_init(2015, 1, 5, 15, 15, 10).prev_weekday
18938 assert_equal date_time_init(2015, 1, 2, 0, 0, 0), date_time_init(2015, 1, 4, 0, 0, 0).prev_weekday
18939 assert_equal date_time_init(2015, 1, 2, 15, 15, 10), date_time_init(2015, 1, 4, 15, 15, 10).prev_weekday
18940 assert_equal date_time_init(2004, 2, 29, 10, 10, 10), date_time_init(2004, 3, 31, 10, 10, 10).prev_month
18941 assert_equal date_time_init(2004, 2, 29, 10, 10, 10), date_time_init(2004, 5, 31, 10, 10, 10).prev_quarter
18942 assert_equal date_time_init(2004, 2, 29, 0, 0, 0), date_time_init(2004, 3, 31, 0, 0, 0).last_month
18943 assert_equal date_time_init(2004, 6, 5, 10, 0, 0), date_time_init(2005, 6, 5, 10, 0, 0).last_year
18944 assert_equal 0, date_time_init(2011, 11, 01, 0, 0, 0).days_to_week_start(:tuesday)
18945 assert_equal 1, date_time_init(2011, 11, 02, 0, 0, 0).days_to_week_start(:tuesday)
18946 assert_equal 2, date_time_init(2011, 11, 03, 0, 0, 0).days_to_week_start(:tuesday)
18947 assert_equal 3, date_time_init(2011, 11, 04, 0, 0, 0).days_to_week_start(:tuesday)
18948 assert_equal 4, date_time_init(2011, 11, 05, 0, 0, 0).days_to_week_start(:tuesday)
18949 assert_equal 5, date_time_init(2011, 11, 06, 0, 0, 0).days_to_week_start(:tuesday)
18950 assert_equal 6, date_time_init(2011, 11, 07, 0, 0, 0).days_to_week_start(:tuesday)
18951 assert_equal 3, date_time_init(2011, 11, 03, 0, 0, 0).days_to_week_start(:monday)
18952 assert_equal 3, date_time_init(2011, 11, 06, 0, 0, 0).days_to_week_start(:thursday)
18953 assert_equal 3, date_time_init(2011, 11, 07, 0, 0, 0).days_to_week_start(:friday)
18954 assert_equal 3, date_time_init(2011, 11, 8, 0, 0, 0).days_to_week_start(:saturday)
18955 assert_equal 3, date_time_init(2011, 11, 9, 0, 0, 0).days_to_week_start(:sunday)
18956 assert_equal 6, Time.local(2012, 03, 8, 0, 0, 0).days_to_week_start
18957 assert_equal 5, Time.local(2012, 03, 7, 0, 0, 0).days_to_week_start
18958 assert_equal 4, Time.local(2012, 03, 6, 0, 0, 0).days_to_week_start
18959 assert_equal 3, Time.local(2012, 03, 5, 0, 0, 0).days_to_week_start
18960 assert_equal 2, Time.local(2012, 03, 4, 0, 0, 0).days_to_week_start
18961 assert_equal 1, Time.local(2012, 03, 3, 0, 0, 0).days_to_week_start
18962 assert_equal 0, Time.local(2012, 03, 2, 0, 0, 0).days_to_week_start
18963 assert_equal date_time_init(2005, 11, 28, 0, 0, 0), date_time_init(2005, 11, 28, 0, 0, 0).beginning_of_week # monday
18964 assert_equal date_time_init(2005, 11, 28, 0, 0, 0), date_time_init(2005, 11, 29, 0, 0, 0).beginning_of_week # tuesday
18965 assert_equal date_time_init(2005, 11, 28, 0, 0, 0), date_time_init(2005, 11, 30, 0, 0, 0).beginning_of_week # wednesday
18966 assert_equal date_time_init(2005, 11, 28, 0, 0, 0), date_time_init(2005, 12, 01, 0, 0, 0).beginning_of_week # thursday
18967 assert_equal date_time_init(2005, 11, 28, 0, 0, 0), date_time_init(2005, 12, 02, 0, 0, 0).beginning_of_week # friday
18968 assert_equal date_time_init(2005, 11, 28, 0, 0, 0), date_time_init(2005, 12, 03, 0, 0, 0).beginning_of_week # saturday
18969 assert_equal date_time_init(2005, 11, 28, 0, 0, 0), date_time_init(2005, 12, 04, 0, 0, 0).beginning_of_week # sunday
18970 assert_equal date_time_init(2008, 1, 6, 23, 59, 59, Rational(999999999, 1000)), date_time_init(2007, 12, 31, 10, 10, 10).end_of_week
18971 assert_equal date_time_init(2007, 9, 2, 23, 59, 59, Rational(999999999, 1000)), date_time_init(2007, 8, 27, 0, 0, 0).end_of_week # monday
18972 assert_equal date_time_init(2007, 9, 2, 23, 59, 59, Rational(999999999, 1000)), date_time_init(2007, 8, 28, 0, 0, 0).end_of_week # tuesday
18973 assert_equal date_time_init(2007, 9, 2, 23, 59, 59, Rational(999999999, 1000)), date_time_init(2007, 8, 29, 0, 0, 0).end_of_week # wednesday
18974 assert_equal date_time_init(2007, 9, 2, 23, 59, 59, Rational(999999999, 1000)), date_time_init(2007, 8, 30, 0, 0, 0).end_of_week # thursday
18975 assert_equal date_time_init(2007, 9, 2, 23, 59, 59, Rational(999999999, 1000)), date_time_init(2007, 8, 31, 0, 0, 0).end_of_week # friday
18976 assert_equal date_time_init(2007, 9, 2, 23, 59, 59, Rational(999999999, 1000)), date_time_init(2007, 9, 01, 0, 0, 0).end_of_week # saturday
18977 assert_equal date_time_init(2007, 9, 2, 23, 59, 59, Rational(999999999, 1000)), date_time_init(2007, 9, 02, 0, 0, 0).end_of_week # sunday
18978 assert_equal date_time_init(2005, 3, 31, 23, 59, 59, Rational(999999999, 1000)), date_time_init(2005, 3, 20, 10, 10, 10).end_of_month
18979 assert_equal date_time_init(2005, 2, 28, 23, 59, 59, Rational(999999999, 1000)), date_time_init(2005, 2, 20, 10, 10, 10).end_of_month
18980 assert_equal date_time_init(2005, 4, 30, 23, 59, 59, Rational(999999999, 1000)), date_time_init(2005, 4, 20, 10, 10, 10).end_of_month
18981 assert_equal date_time_init(2007, 12, 31, 23, 59, 59, Rational(999999999, 1000)), date_time_init(2007, 2, 22, 10, 10, 10).end_of_year
18982 assert_equal date_time_init(2007, 12, 31, 23, 59, 59, Rational(999999999, 1000)), date_time_init(2007, 12, 31, 10, 10, 10).end_of_year
18983 assert_equal date_time_init(2017, 12, 18, 3, 14, 15), date_time_init(2017, 12, 14, 3, 14, 15).next_occurring(:monday)
18984 assert_equal date_time_init(2017, 12, 19, 3, 14, 15), date_time_init(2017, 12, 14, 3, 14, 15).next_occurring(:tuesday)
18985 assert_equal date_time_init(2017, 12, 20, 3, 14, 15), date_time_init(2017, 12, 14, 3, 14, 15).next_occurring(:wednesday)
18986 assert_equal date_time_init(2017, 12, 21, 3, 14, 15), date_time_init(2017, 12, 14, 3, 14, 15).next_occurring(:thursday)
18987 assert_equal date_time_init(2017, 12, 15, 3, 14, 15), date_time_init(2017, 12, 14, 3, 14, 15).next_occurring(:friday)
18988 assert_equal date_time_init(2017, 12, 16, 3, 14, 15), date_time_init(2017, 12, 14, 3, 14, 15).next_occurring(:saturday)
18989 assert_equal date_time_init(2017, 12, 17, 3, 14, 15), date_time_init(2017, 12, 14, 3, 14, 15).next_occurring(:sunday)
18990 assert_equal date_time_init(2017, 12, 11, 3, 14, 15), date_time_init(2017, 12, 14, 3, 14, 15).prev_occurring(:monday)
18991 assert_equal date_time_init(2017, 12, 12, 3, 14, 15), date_time_init(2017, 12, 14, 3, 14, 15).prev_occurring(:tuesday)
18992 assert_equal date_time_init(2017, 12, 13, 3, 14, 15), date_time_init(2017, 12, 14, 3, 14, 15).prev_occurring(:wednesday)
18993 assert_equal date_time_init(2017, 12, 10, 3, 14, 15), date_time_init(2017, 12, 14, 3, 14, 15).prev_occurring(:sunday)
18994 assert_equal date_time_init(2012, 9, 17, 0, 0, 0), date_time_init(2012, 9, 18, 0, 0, 0).monday
18995 assert_equal date_time_init(2012, 9, 23, 23, 59, 59, Rational(999999999, 1000)), date_time_init(2012, 9, 19, 0, 0, 0).sunday
18996 assert_predicate date_time_init(2015, 1, 3, 0, 0, 0), :on_weekend?
18997 assert_predicate date_time_init(2015, 1, 3, 15, 15, 10), :on_weekend?
18998 assert_predicate date_time_init(2015, 1, 4, 0, 0, 0), :on_weekend?
18999 assert_predicate date_time_init(2015, 1, 4, 15, 15, 10), :on_weekend?
19000 assert_not_predicate date_time_init(2015, 1, 5, 0, 0, 0), :on_weekend?
19001 assert_not_predicate date_time_init(2015, 1, 5, 15, 15, 10), :on_weekend?
19002 assert_not_predicate date_time_init(2015, 1, 4, 0, 0, 0), :on_weekday?
19003 assert_not_predicate date_time_init(2015, 1, 4, 15, 15, 10), :on_weekday?
19004 assert_predicate date_time_init(2015, 1, 5, 0, 0, 0), :on_weekday?
19005 assert_predicate date_time_init(2015, 1, 5, 15, 15, 10), :on_weekday?
19006 assert_equal false, date_time_init(2017, 3, 6, 12, 0, 0).before?(date_time_init(2017, 3, 5, 12, 0, 0))
19007 assert_equal false, date_time_init(2017, 3, 6, 12, 0, 0).before?(date_time_init(2017, 3, 6, 12, 0, 0))
19008 assert_equal true, date_time_init(2017, 3, 6, 12, 0, 0).before?(date_time_init(2017, 3, 7, 12, 0, 0))
19009 assert_equal true, date_time_init(2017, 3, 6, 12, 0, 0).after?(date_time_init(2017, 3, 5, 12, 0, 0))
19010 assert_equal false, date_time_init(2017, 3, 6, 12, 0, 0).after?(date_time_init(2017, 3, 6, 12, 0, 0))
19011 assert_equal false, date_time_init(2017, 3, 6, 12, 0, 0).after?(date_time_init(2017, 3, 7, 12, 0, 0))
19012 class Bar < Foo; end
19013 class Baz < Bar; end
19014 class B < A; end
19015 class C < B; end
19016 @sub = Class.new(@klass)
19017 @sub.setting = 1
19018 val = @klass.public_send(:setting=, 1)
19019 bd = BigDecimal "0.01"
19020 assert_equal "0.01", bd.to_s
19021 assert_equal "+0.01", bd.to_s("+F")
19022 assert_equal "+0.0 1", bd.to_s("+1F")
19023 ["foo", "bar"]
19024 ary = %w(foo bar)
19025 assert_equal ["foo"], Array.wrap("foo")
19026 assert_equal ["foo
bar"], Array.wrap("foo
bar")
19027 o = Struct.new(:foo).new(123)
19028 groups = []
19029 ("a".."i").to_a.in_groups_of(3) do |group|
19030 assert_equal [%w(a b c), %w(d e f), %w(g h i)], groups
19031 assert_equal [%w(a b c), %w(d e f), %w(g h i)], ("a".."i").to_a.in_groups_of(3)
19032 ("a".."g").to_a.in_groups_of(3) do |group|
19033 assert_equal [%w(a b c), %w(d e f), ["g", nil, nil]], groups
19034 ("a".."g").to_a.in_groups_of(3, "foo") do |group|
19035 assert_equal [%w(a b c), %w(d e f), %w(g foo foo)], groups
19036 ("a".."g").to_a.in_groups_of(3, false) do |group|
19037 assert_equal [%w(a b c), %w(d e f), %w(g)], groups
19038 array = (1..7).to_a
19039 1.upto(array.size + 1) do |number|
19040 assert_equal [[], [], []], [].in_groups(3)
19041 array = (1..9).to_a
19042 assert_equal [[1, 2, 3], [4, 5, 6], [7, 8, 9]],
19043 (1..9).to_a.in_groups(3)
19044 assert_equal [[1, 2, 3], [4, 5, nil], [6, 7, nil]],
19045 assert_equal [[1, 2, 3], [4, 5, "foo"], [6, 7, "foo"]],
19046 array.in_groups(3, "foo")
19047 assert_equal [[1, 2, 3], [4, 5], [6, 7]],
19048 (1..7).to_a.in_groups(3, false)
19049 assert_raises(ArgumentError) { [].in_groups_of(-1) }
19050 assert_equal [[]], [].split(0)
19051 a = [1, 2, 3, 4, 5]
19052 assert_equal [[1, 2, 3, 4, 5]], a.split(0)
19053 assert_equal [1, 2, 3, 4, 5], a
19054 a = (1..10).to_a
19055 assert_equal [[1, 2], [4, 5], [7, 8], [10]], a.split { |i| i % 3 == 0 }
19056 assert_equal [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], a
19057 assert_equal [[], [2, 3, 4], []], a.split { |i| i == 1 || i == 5 }
19058 a = [1, 2, 3, 5, 5, 3, 4, 6, 2, 1, 3]
19059 assert_equal [[1, 2], [5, 5], [4, 6, 2, 1], []], a.split(3)
19060 assert_equal [[1, 2, 3], [], [3, 4, 6, 2, 1, 3]], a.split(5)
19061 assert_equal [[1, 2], [], [], [], [4, 6, 2, 1], []], a.split { |i| i == 3 || i == 5 }
19062 assert_equal [1, 2, 3, 5, 5, 3, 4, 6, 2, 1, 3], a
19063 numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
19064 assert_equal [1, 3, 5, 7, 9], odd_numbers
19065 assert_equal [0, 2, 4, 6, 8], numbers
19066 empty_array = []
19067 assert_equal({}, [].extract_options!)
19068 assert_equal({}, [1].extract_options!)
19069 assert_equal({ a: :b }, [{ a: :b }].extract_options!)
19070 assert_equal({ a: :b }, [1, { a: :b }].extract_options!)
19071 hash[:foo] = 1
19072 array = [hash]
19073 assert_equal({ foo: 1 }, options)
19074 assert_equal([], array)
19075 array = [{ foo: 1 }.with_indifferent_access]
19076 hash.foo = 1
19077 assert_equal "", [].to_sentence
19078 assert_equal "one", ["one"].to_sentence
19079 assert_equal "one and two", ["one", "two"].to_sentence
19080 assert_equal "one, two, and three", ["one", "two", "three"].to_sentence
19081 assert_equal "one two, and three", ["one", "two", "three"].to_sentence(words_connector: " ")
19082 assert_equal "one & two, and three", ["one", "two", "three"].to_sentence(words_connector: " & ")
19083 assert_equal "onetwo, and three", ["one", "two", "three"].to_sentence(words_connector: nil)
19084 assert_equal "one, two, and also three", ["one", "two", "three"].to_sentence(last_word_connector: ", and also ")
19085 assert_equal "one, twothree", ["one", "two", "three"].to_sentence(last_word_connector: nil)
19086 assert_equal "one, two three", ["one", "two", "three"].to_sentence(last_word_connector: " ")
19087 assert_equal "one, two and three", ["one", "two", "three"].to_sentence(last_word_connector: " and ")
19088 assert_equal "one two", ["one", "two"].to_sentence(two_words_connector: " ")
19089 elements = ["one"]
19090 assert_equal "1", [1].to_sentence
19091 options = { words_connector: " " }
19092 assert_equal "one two, and three", ["one", "two", "three"].to_sentence(options)
19093 assert_equal({ words_connector: " " }, options)
19094 assert_equal ", one, , two, and three", [nil, "one", "", "two", "three"].to_sentence
19095 ["one", "two"].to_sentence(passing: "invalid option")
19096 assert_not ["one", "two"].to_sentence.frozen?
19097 assert_not ["one", "two", "three"].to_sentence.frozen?
19098 @@counter = 0
19099 @@counter += 1
19100 assert_equal "null", [].to_fs(:db)
19101 assert_equal "1,2,3", collection.to_fs(:db)
19102 assert_equal "null", [].to_formatted_s(:db)
19103 xml = [
19104 { name: "David", age: 26, age_in_millis: 820497600000 },
19105 { name: "Jason", age: 31, age_in_millis: BigDecimal("1.0") }
19106 ].to_xml(skip_instruct: true, indent: 0)
19107 assert_includes xml, %(<age type="integer">26</age>), xml
19108 assert_includes xml, %(<age type="integer">31</age>), xml
19109 xml = %w[1 2 3].to_xml(skip_instruct: true, indent: 0)
19110 xml = [1, 2.0, "3"].to_xml(skip_instruct: true, indent: 0)
19111 assert_includes xml, %(<object type="float">2.0</object>), xml
19112 { name: "David", age: 26, age_in_millis: 820497600000 }, { name: "Jason", age: 31 }
19113 ].to_xml(skip_instruct: true, indent: 0, root: "people")
19114 { name: "David", street_address: "Paulina" }, { name: "Jason", street_address: "Evergreen" }
19115 assert_match(/^<\?xml [^>]*/, xml)
19116 assert_equal 0, xml.rindex(/<\?xml /)
19117 ].to_xml(skip_instruct: true, indent: 0) do |builder|
19118 assert_includes xml, %(<count>2</count>), xml
19119 xml = [].to_xml
19120 assert_match(/type="array"\/>/, xml)
19121 [].to_xml(options)
19122 assert_equal %w( a b c d ), %w( a b c d ).from(0)
19123 assert_equal %w( c d ), %w( a b c d ).from(2)
19124 assert_equal %w(), %w( a b c d ).from(10)
19125 assert_equal %w( d e ), %w( a b c d e ).from(-2)
19126 assert_equal %w(), %w( a b c d e ).from(-10)
19127 assert_equal %w( a ), %w( a b c d ).to(0)
19128 assert_equal %w( a b c ), %w( a b c d ).to(2)
19129 assert_equal %w( a b c d ), %w( a b c d ).to(10)
19130 assert_equal %w( a b c ), %w( a b c d ).to(-2)
19131 assert_equal %w(), %w( a b c ).to(-10)
19132 array = (1..42).to_a
19133 assert_equal [1, 2, 3, 4, 5], [1, 2, 4].including(3, 5).sort
19134 assert_equal [1, 2, 3, 4, 5], [1, 2, 4].including([3, 5]).sort
19135 assert_equal [[0, 1], [1, 0]], [[0, 1]].including([[1, 0]])
19136 assert_equal [1, 2, 4], [1, 2, 3, 4, 5].excluding(3, 5)
19137 assert_equal [1, 2, 4], [1, 2, 3, 4, 5].excluding([3, 5])
19138 assert_equal [[0, 1]], [[0, 1], [1, 0]].excluding([[1, 0]])
19139 assert_equal [1, 2, 4], [1, 2, 3, 4, 5].without(3, 5)
19140 assert_equal Ace::Base::Case, yield("::Ace::Base::Case")
19141 assert_equal Ace::Base::Case::Dice, yield("Ace::Base::Case::Dice")
19142 assert_equal Ace::Base::Case::Dice, yield("Ace::Base::Fase::Dice")
19143 assert_equal Ace::Base::Fase::Dice, yield("Ace::Base::Fase::Dice")
19144 assert_equal Ace::Gas::Case, yield("Ace::Gas::Case")
19145 assert_equal Ace::Gas::Case::Dice, yield("Ace::Gas::Case::Dice")
19146 assert_equal Ace::Base::Case::Dice, yield("Ace::Gas::Case::Dice")
19147 assert_raises(NameError) { yield("Ace::Gas::Base") }
19148 assert_raises(NameError) { yield("") }
19149 assert_raises(NameError) { yield("::") }
19150 assert_raises(NameError) { yield("Ace::gas") }
19151 assert_nil yield("")
19152 assert_nil yield("::")
19153 assert_nil yield("A::Object::B")
19154 file.write("wrong: <%= foo %>")
19155 assert_equal({ foo: :bar }, Parent.config)
19156 assert_equal({ foo: :bar }, mixin.config)
19157 [:black, :blue, :white]
19158 assert_equal "bar's baz + baz", @klass.baz
19159 @klass.class_eval { def initialize; @foo = []; end }
19160 included.module_eval { def foo; @foo << :included; end }
19161 @klass.class_eval { def foo; super; @foo << :class; end }
19162 prepended.module_eval { def foo; super; @foo << :prepended; end }
19163 @klass.class_eval { @foo = [] }
19164 included.class_methods { def foo; @foo << :included; end }
19165 @klass.class_eval { def self.foo; super; @foo << :class; end }
19166 @logger.formatter.datetime_format = "%Y-%m-%d"
19167 assert_match(/D, \[\d\d\d\d-\d\d-\d\d[ ]?#\d+\] DEBUG -- : debug/, @out.string)
19168 an_object = [1, 2, 3, 4, 5]
19169 @bc.add_filter { |line| line.gsub("/my/prefix", "") }
19170 ["/my/class.rb", "/my/module.rb"],
19171 @bc.clean(["/my/prefix/my/class.rb", "/my/prefix/my/module.rb"])
19172 assert_equal "/my/prefix/my/class.rb", @bc.clean(["/my/prefix/my/class.rb"]).first
19173 assert_equal "/my/other_prefix/my/class.rb", @bc.clean([ "/my/other_prefix/my/class.rb" ]).first
19174 @bc.add_silencer { |line| line.include?("mongrel") }
19175 [ "/other/class.rb" ],
19176 @bc.clean([ "/mongrel/class.rb", "/other/class.rb", "/mongrel/stuff.rb" ])
19177 assert_equal ["/mongrel/stuff.rb"], @bc.clean(["/mongrel/stuff.rb"])
19178 @bc.add_silencer { |line| line.include?("yolo") }
19179 @bc.clean([ "/mongrel/class.rb", "/other/class.rb", "/mongrel/stuff.rb", "/other/yolo.rb" ])
19180 [ "/mongrel/class.rb", "/mongrel/stuff.rb", "/other/yolo.rb" ],
19181 @bc.clean([ "/mongrel/class.rb", "/other/class.rb", "/mongrel/stuff.rb", "/other/yolo.rb" ],
19182 assert_equal [ "/class.rb" ], @bc.clean([ "/mongrel/class.rb" ])
19183 backtrace = [ "#{Gem.default_dir}/gems/nosuchgem-1.2.3/lib/foo.rb" ]
19184 target_dir = Gem.path.detect { |p| p != Gem.default_dir }
19185 backtrace = [ "#{target_dir}/gems/nosuchgem-1.2.3/lib/foo.rb" ]
19186 backtrace = [ "#{Gem.default_dir}/bundler/gems/nosuchgem-1.2.3/lib/foo.rb" ]
19187 backtrace = [ "#{Gem.path[0]}/gems/nosuchgem-1.2.3/lib/foo.rb" ]
19188 backtrace = ["#{RbConfig::CONFIG["rubylibdir"]}/lib/foo.rb"]
19189 backtrace = [Gem.default_dir, *Gem.path].map { |path| "/parent#{path}/gems/nosuchgem-1.2.3/lib/foo.rb" }
19190 set_callback(:save, :after, *filters, &blk)
19191 Proc.new { |model| model.history << [callback_method, :proc] }
19192 model.history << [:"#{callback_method}_save", :object]
19193 @history ||= []
19194 model.history << [:before_save, :class]
19195 model.history << [:after_save, :class]
19196 set_callback :dispatch, :before, :log, unless: proc { |c| c.action_name == :index || c.action_name == :show }
19197 @action_name, @logger = action_name, []
19198 @logger << "Done"
19199 skip_callback :dispatch, :before, :log, if: proc { |c| c.action_name == :update }
19200 @@starts_true, @@starts_false = true, false
19201 before_save Proc.new { |r| r.history << [:before_save, :starts_true, :if] }, if: :starts_true
19202 before_save Proc.new { |r| r.history << [:before_save, :starts_false, :if] }, if: :starts_false
19203 before_save Proc.new { |r| r.history << [:before_save, :starts_true, :unless] }, unless: :starts_true
19204 before_save Proc.new { |r| r.history << [:before_save, :starts_false, :unless] }, unless: :starts_false
19205 [:before_save, :starts_true, :if],
19206 after_save Proc.new { |r| r.history << [:after_save, :string1] }
19207 after_save Proc.new { |r| r.history << [:after_save, :string2] }
19208 [:after_save, :string2],
19209 [:after_save, :string1]
19210 before_save Proc.new { |r| r.history << [:before_save, :proc] }, if: Proc.new { |r| true }
19211 before_save Proc.new { |r| r.history << "b00m" }, if: Proc.new { |r| false }
19212 before_save Proc.new { |r| r.history << [:before_save, :proc] }, unless: Proc.new { |r| false }
19213 before_save Proc.new { |r| r.history << "b00m" }, unless: Proc.new { |r| true }
19214 before_save Proc.new { |r| r.history << [:before_save, :symbol] }, if: :yes
19215 before_save Proc.new { |r| r.history << "b00m" }, if: :no
19216 before_save Proc.new { |r| r.history << [:before_save, :symbol] }, unless: :no
19217 before_save Proc.new { |r| r.history << "b00m" }, unless: :yes
19218 before_save Proc.new { |r| r.history << [:before_save, :combined_symbol] }, if: :yes, unless: :no
19219 before_save Proc.new { |r| r.history << "b00m" }, if: :yes, unless: :yes
19220 @history = []
19221 @history << "running"
19222 when /^log_(.*)/
19223 @history << $1
19224 when /^wrap_(.*)/
19225 @history << "wrap_#$1"
19226 @history << "unwrap_#$1"
19227 when /^double_(.*)/
19228 @history << "first_#$1"
19229 @history << "second_#$1"
19230 @history << "third_#$1"
19231 sym.match?(/^(log|wrap)_/) || super
19232 set_callback :save, :before, proc { |m| m.history << "yup" }
19233 @history << "boom"
19234 @history << "yup"
19235 @history << "w0tyes after"
19236 @history << "tweedle dum pre"
19237 @history << "tweedle dum post"
19238 @history << "tweedle"
19239 set_callback :save, :before, :action, if: :yes
19240 @recorder << 3
19241 @recorder << 2
19242 @recorder = []
19243 @recorder << 1
19244 ], call_stack.map(&:label)
19245 [:before_save, :proc],
19246 [:before_save, :object],
19247 [:before_save, :block],
19248 [:after_save, :block],
19249 [:after_save, :class],
19250 [:after_save, :object],
19251 [:after_save, :proc],
19252 [:after_save, :symbol]
19253 [:before_save, :symbol],
19254 [:before_save, :class],
19255 @history << "around1"
19256 @history << "around2"
19257 @history << "first"
19258 @history << "second"
19259 @history << "third"
19260 @saved = true
19261 define_callbacks :save, terminator: ->(_, result_lambda) { result_lambda.call == :halt }
19262 define_callbacks :save, terminator: ->(_, result_lambda) { result_lambda.call == :halt },
19263 @record = []
19264 @record << "yielded"
19265 @record << "one"
19266 @record << "two"
19267 @record << "three"
19268 set_callback :save, :before, :first, :second, :first, :third
19269 assert_equal ["first", "second", "third", "first"], terminator.history
19270 skip_callback :save, :before, :before_save_method, if: -> { age > 21 }
19271 assert_equal ["two", "one", "three", "yielded"], model.record
19272 klass = build_class(->() { calls << :foo })
19273 klass = build_class(->(o) { calls << o })
19274 klass = build_class(->(x, y) { })
19275 klass = build_class(->(*args) { calls << args })
19276 assert_equal [[]], calls
19277 z = []
19278 define_singleton_method(:foo) { |o| z << o }
19279 klass = Class.new {
19280 define_singleton_method(:before) { |o| z << o }
19281 object = build_class(->(*args) { z << args }).new
19282 object = build_class(->() { z << 0 }).new
19283 assert_equal [0], z
19284 object = build_class(->(x) { z << x }).new
19285 object = build_class(->(a, b) { }).new
19286 define_method(:hello) { memo << :hi }
19287 subclass = Class.new(klass) { set_callback :foo, :before, :world }
19288 subclass.class_eval { define_method(:world) { events << :world } }
19289 define_singleton_method(:before) { |o| calls << o }
19290 build_class(->(o) { calls << o }).new.run
19291 klass.class_eval { define_method(:bar) { calls << klass } }
19292 9.downto(0) { |i|
19293 @history << __method__.to_s
19294 @action_name, @log = action_name, []
19295 set_callback :dispatch, :before, :before1, :before2, if: proc { |c| c.action_name == "index" || c.action_name == "update" }
19296 set_callback :dispatch, :after, :after1, :after2, if: proc { |c| c.action_name == "update" || c.action_name == "delete" }
19297 @log << "before1"
19298 @log << "before2"
19299 @log << "after1"
19300 @log << "after2"
19301 @log << action_name
19302 skip_callback :dispatch, :before, :before2, unless: proc { |c| c.action_name == "update" }
19303 skip_callback :dispatch, :after, :after2, unless: proc { |c| c.action_name == "delete" }
19304 skip_callback :dispatch, :before, :before2, unless: proc { |c| c.action_name == "update" }, if: :state_open?
19305 @state == :open
19306 @performed ||= false
19307 @count = 0
19308 @count += 1
19309 parent = Parent.new("foo")
19310 ] do
19311 build url: []
19312 default_args = {
19313 block = -> { :custom_redis_client }
19314 @cache = nil
19315 def lookup_store(options = {})
19316 assert_called(@cache.redis, :mget, returns: []) do
19317 @cache.fetch_multi("a", "b", "c") do |key|
19318 key * 2
19319 @cache.fetch_multi("a", "b", "c", namespace: "custom-namespace") do |key|
19320 @cache.fetch_multi() { }
19321 assert @cache.redis.ttl("#{@namespace}:foo") > 0
19322 @cache.redis.setex "#{@namespace}:bar", 120, 1
19323 assert @cache.redis.ttl("#{@namespace}:bar") > 60
19324 @cache.redis.set "#{@namespace}:dar", 10
19325 assert @cache.redis.ttl("#{@namespace}:dar") > 0
19326 @cache.write("foo", nil)
19327 assert_nil @cache.fetch("foo") { "baz" }
19328 assert_nil @cache.fetch("foo") { nil }
19329 error_handler: -> (method:, returning:, exception:) { raise exception })
19330 key = "#{prefix}#{SecureRandom.uuid}"
19331 @cache.write(key, "bar")
19332 @cache.delete_matched("#{prefix}*")
19333 cache.write("foo", "bar")
19334 cache.write("fu", "baz")
19335 @cache.write("foo", "bar", raw: true)
19336 @cache.read("foo", raw: true)
19337 @cache.write("name", "value")
19338 @cache.write("name", 1, raw: true)
19339 @cache.read("foo")
19340 @cache.read_multi("foo", "bar")
19341 assert_equal({ "foo" => nil, "bar" => nil }, @cache.read_multi("foo", "bar"))
19342 Time.stub(:now, Time.now + 1.minute) do
19343 @cache.write(1, "aaaaaaaaaa") && sleep(0.001)
19344 @cache.write(2, "bbbbbbbbbb") && sleep(0.001)
19345 @cache.write(3, "cccccccccc") && sleep(0.001)
19346 @cache.write(4, "dddddddddd") && sleep(0.001)
19347 @cache.write(5, "eeeeeeeeee") && sleep(0.001)
19348 @cache.read(2) && sleep(0.001)
19349 @cache.prune(@record_size * 3)
19350 assert_not @cache.exist?(3), "no entry"
19351 assert_not @cache.exist?(1), "no entry"
19352 @cache.write(6, "ffffffffff") && sleep(0.001)
19353 @cache.write(7, "gggggggggg") && sleep(0.001)
19354 @cache.write(8, "hhhhhhhhhh") && sleep(0.001)
19355 @cache.write(9, "iiiiiiiiii") && sleep(0.001)
19356 @cache.write(10, "kkkkkkkkkk") && sleep(0.001)
19357 @cache.read(4) && sleep(0.001)
19358 assert_not @cache.exist?(6), "no entry"
19359 assert_not @cache.exist?(5), "no entry"
19360 long_key = "*" * 2 * @record_size
19361 assert_not @cache.exist?(4), "no entry"
19362 assert_not @cache.exist?(2), "no entry"
19363 @cache.prune(30, 0.001)
19364 item = { "foo" => "bar" }
19365 key = "test_key"
19366 read_item["foo"] = "xyz"
19367 item = "my_string"
19368 @cache.write(1, nil)
19369 def get(key, options = {})
19370 (@_stores ||= []) << cache
19371 @namespace = "test-#{Random.rand(16**32).to_s(16)}"
19372 stores, @_stores = @_stores, []
19373 client(cache).stub(:flush_all, -> { stub_called = true; client.delete("#{@namespace}:#{key}") }) do
19374 short_key = "a" * 250
19375 long_key = "b" * 251
19376 normalized_key = @cache.send(:normalize_key, short_key, { namespace: "ns" })
19377 multibyte_key = "c" * 100 + ["01F60F".to_i(16)].pack("U*") + "c" * 149
19378 assert_match(/^c{100}%F0%9F%98%8Fc+:hash:[[:print:]]+$/, normalized_key)
19379 key_one = "d" * 1000 + "a"
19380 key_two = "d" * 1000 + "b"
19381 cache.write("foo", 2)
19382 assert_equal "2", cache.read("foo")
19383 cache.write("foo", Marshal.dump([]))
19384 assert_equal "1", @cache.read("foo", raw: true)
19385 assert_called_with client(cache), :incr, [ "foo", 1, 60, 1 ] do
19386 assert_equal "0", @cache.read("foo", raw: true)
19387 assert_called_with client(cache), :decr, [ "foo", 1, 60, 0 ] do
19388 cache.fetch("nil_foo") { nil }
19389 assert_equal "bar", cache.fetch("nil_foo") { "bar" }
19390 cache1.fetch("not_nil_foo") { nil }
19391 assert_nil cache.fetch("not_nil_foo") { "bar" }
19392 @cache.write("foo", "bar")
19393 value = @cache.read("foo")
19394 value << "bingo"
19395 times: 0,
19396 ) do
19397 cache.write("foo", val)
19398 times: 1,
19399 cache.write("foo", "bar", expires_in: 1, unless_exist: true)
19400 host = "custom_host"
19401 expected_addresses = ["first", "second"]
19402 @cache.instance_variable_get(:@data).with { |c| c.set(@cache.send(:normalize_key, key, nil), "value", 0, compress: false) }
19403 assert_equal "value", @cache.fetch(key) { "value" }
19404 @cache.instance_variable_get(:@data).with { |c| c.set(@cache.send(:normalize_key, key, nil), false, 0, compress: false) }
19405 @cache.instance_variable_get(:@data).with { |c| c.set(@cache.send(:normalize_key, key, nil), nil, 0, compress: false) }
19406 assert_equal({}, @cache.send(:read_multi_entries, [key]))
19407 (0...length).map { (65 + rand(26)).chr }.join
19408 @old_store.write("foo", "bar")
19409 assert_equal "bar", @cache.read("foo")
19410 assert_equal "bar", @old_store.read("foo")
19411 cache_dir = options.delete(:cache_dir) { @cache_dir }
19412 @cache_dir = Dir.mktmpdir("file-store-")
19413 keep = File.join(cache_dir, ".keep")
19414 @cache.write("%" * 870, 1)
19415 assert_equal 1, @cache.read("%" * 870)
19416 key = @cache.send(:normalize_key, "views/index?id=1", {})
19417 key = @cache_with_pathname.send(:normalize_key, "views/index?id=1", {})
19418 path = @cache.send(:normalize_key, key, {})
19419 assert File.basename(tmpname + ".lock").length <= 255, "Temp filename too long: #{File.basename(tmpname + '.lock').length}"
19420 File.stub(:exist?, -> { raise StandardError.new("failed") }) do
19421 @cache.send(:read_entry, "winston", **{})
19422 @cache.write("foo", "bar", expires_in: 10)
19423 @cache.write("baz", "qux")
19424 @cache.write("quux", "corge", expires_in: 20)
19425 Time.stub(:now, time + 15) do
19426 assert_equal 2, Dir.glob(File.join(cache_dir, "**")).size
19427 File.atomic_write(cache_file_path, cache_dir) { |f| Marshal.dump({ "foo": "bar" }, f) }
19428 assert_equal 1, Dir.glob(File.join(cache_dir, "**")).size
19429 middleware = Middleware.new("<3", key).new(->(env) {
19430 [200, {}, []]
19431 _, _, body = middleware.call({})
19432 body.each { }
19433 assert_throws(:warden) { middleware.call({}) }
19434 assert_called_with(Dalli::Client, :new, [%w[localhost], { compress: false }]) do
19435 assert_called_with(Dalli::Client, :new, [%w[localhost 192.168.1.1], { compress: false }]) do
19436 assert_called_with(Dalli::Client, :new, [%w[localhost 192.168.1.1], { timeout: 10, compress: false }]) do
19437 test_val = "tester"
19438 proc = lambda { test_val }
19439 @cache.fetch("foo") { "bar" }
19440 @cache.fetch("foo", namespace: "string_namespace") { "bar" }
19441 @cache.fetch("foo", namespace: proc) { "bar" }
19442 @cache.mute { @cache.fetch("foo") { "bar" } }
19443 key = +"foo"
19444 old_values = {}
19445 kv.each { |key, value| old_values[key], ENV[key] = ENV[key], value }
19446 old_values.each { |key, value| ENV[key] = value }
19447 Time.stub(:now, Time.at(entry.expires_at + 1)) do
19448 assert_equal({ type: value }, @cache.read(key))
19449 @cache.delete_matched("*")
19450 other_key = "#{prefix}#{SecureRandom.uuid}"
19451 @cache.write(key, 1, raw: true)
19452 @peek.write(key, 2, raw: true)
19453 @peek.write(key, 3, raw: true)
19454 @cache.fetch_multi(key, other_key) { |_key| true }
19455 initial = +"bar"
19456 initial << "baz"
19457 @cache.fetch(key) { initial }
19458 app = lambda { |env|
19459 app.call({})
19460 Time.stub(:now, time + 61) do
19461 val = cache.fetch(key) { "1" }
19462 fetched = cache.fetch_multi(key, other_key) { |k| "unavailable" }
19463 cache.fetch_multi(key, other_key) { |k| "unavailable" }
19464 assert @cache.write(key, "1", raw: true)
19465 assert_equal "1", @cache.read(key, raw: true)
19466 assert_equal "1", @cache.fetch(key, raw: true)
19467 assert_equal "2", @cache.fetch(key, raw: true) { "2" }
19468 key = (+"\xC3\xBCmlaut").force_encoding(Encoding::UTF_8)
19469 cache = ActiveSupport::Cache.lookup_store(*store, { pool: { size: 2, timeout: 1 } }.merge(store_options))
19470 def store_options; {}; end
19471 @cache.fetch(key, version: 1) { value }
19472 @cache.write([ "something", m1v1 ], value)
19473 assert_nil @cache.read([ "something", m1v2 ])
19474 @cache.fetch(m1v1) { value }
19475 second_fetch_values = @cache.fetch_multi(m1v1, m2v2) { |m| m.cache_key + " 2nd" }
19476 assert_equal({ m1v1 => "#{model_name}/1", m2v1 => "#{model_name}/2" }, first_fetch_values)
19477 assert_equal({ m1v1 => "#{model_name}/1", m2v2 => "#{model_name}/2 2nd" }, second_fetch_values)
19478 @dumped_entries = []
19479 @loaded_entries = []
19480 @store.write("foo", "bar")
19481 @store.read("foo")
19482 @store.write_multi({ "foo" => "bar", "egg" => "spam" })
19483 @store.read_multi("foo", "egg")
19484 @cache.write(key, "baz")
19485 assert_equal "bar", @cache.fetch(key) { "baz" }
19486 assert_called_with(@cache, :write, [key, "baz", @cache.options]) do
19487 assert_equal "baz", @cache.fetch(key) { "baz" }
19488 assert_equal 10, @cache.fetch(key) { |key| cache_miss = true; key.length }
19489 version: "v42",
19490 assert_called_with(@cache, :write, [key, "bar", @cache.options.merge(force: true)]) do
19491 @cache.fetch(key, force: true) { "bar" }
19492 assert_nil @cache.fetch(key) { "baz" }
19493 assert_nil @cache.fetch(key, skip_nil: true) { nil }
19494 assert_equal "foo_bar", @cache.fetch(key, force: true) { "foo_bar" }
19495 assert @cache.write(key, a: "b")
19496 assert_equal({ a: "b" }, @cache.read(key))
19497 @cache.write(other_key, "baz")
19498 assert_equal({ key => "bar", other_key => "baz" }, @cache.read_multi(key, other_key))
19499 @cache.write(key, "bar", expires_in: 10)
19500 Time.stub(:now, time + 11) do
19501 @cache.write(other_key, "biz")
19502 values = @cache.fetch_multi(key, other_key, third_key) { |value| value * 2 }
19503 assert_equal({ key => "bar", other_key => "biz", third_key => (third_key * 2) }, values)
19504 assert_equal((third_key * 2), @cache.read(third_key))
19505 values = @cache.fetch_multi(key, third_key, other_key, expires_in: nil) { |value| value * 2 }
19506 assert_equal({ key => "bar", third_key => (third_key * 2), other_key => "biz" }, values)
19507 foo = cache_struct.new(key, "FOO!")
19508 @cache.write(other_key, "BAM!")
19509 values = @cache.fetch_multi(foo, bar) { |object| object.title }
19510 assert_equal({ foo => "FOO!", bar => "BAM!" }, values)
19511 @cache.write(key, "BAM")
19512 values = @cache.fetch_multi(other_key, third_key, key) { |key| key.upcase }
19513 values = @cache.fetch_multi(key, other_key, force: true) { |value| value * 2 }
19514 assert_equal({ key => (key * 2), other_key => (other_key * 2) }, values)
19515 assert_equal(key * 2, @cache.read(key))
19516 values = @cache.fetch_multi(key, other_key, skip_nil: true) { |k| k == key ? k : nil }
19517 assert_equal({ key => key, other_key => nil }, values)
19518 @cache.write(klass.new(key), "bar")
19519 @cache.write([key, "foo"], "bar")
19520 assert_equal "bar", @cache.read("#{key}/foo")
19521 @cache.write([test_instance_one], "one")
19522 @cache.write([test_instance_two], "two")
19523 @cache.write({ key => 1, other_key => 2 }, "bar")
19524 assert_equal "bar", @cache.read({ key => 1, other_key => 2 })
19525 bar = +"bar"
19526 assert_nothing_raised { bar.gsub!(/.*/, "baz") }
19527 time = Time.local(2008, 4, 24)
19528 @cache.write(key, "bar", expires_in: 1.minute)
19529 Time.stub(:now, time + 30) do
19530 Time.stub(:now, time + 1.minute + 1.second) do
19531 Time.stub(:now, time + 2.minute + 1.second) do
19532 @cache.write(key, "bar", expires_at: time + 15.seconds)
19533 Time.stub(:now, time + 10) do
19534 @cache.write(key, "bar", expire_in: 20)
19535 Time.stub(:now, time + 21) do
19536 @cache.write(key, "bar", expired_in: 20)
19537 @cache.write(key, "bar", expire_in: 60, expires_at: 1.minute.from_now)
19538 @cache.write(key, "bar", expires_in: -60)
19539 time = @cache.send(:read_entry, @cache.send(:normalize_key, key, {}), **{}).expires_at
19540 Time.stub(:now, Time.at(time)) do
19541 @cache.write(key, "bar", expires_in: 60)
19542 Time.stub(:now, time + 71) do
19543 Time.stub(:now, time + 91) do
19544 @cache.write(key, "foo", expires_in: 60)
19545 assert_equal({ key => "baz", other_key => "bar" }, result)
19546 absurd_key = "#/:*(<+=> )&$%@?;'\"\'`~-"
19547 assert_equal "2", @cache.fetch(absurd_key, raw: true) { "2" }
19548 assert_nil @cache.read("#{key}x")
19549 assert_equal({ key => "bar" }, @cache.read_multi(key))
19550 assert @cache.fetch(key, raw: true) { }
19551 actual_entry = @cache.send(:read_entry, @cache.send(:normalize_key, actual, {}), **{})
19552 uncompressed_entry = @cache.send(:read_entry, @cache.send(:normalize_key, uncompressed, {}), **{})
19553 @cache.fetch_multi "a", "b", "c" do |key|
19554 writes = { key_1 => value_1, key_2 => value_2 }
19555 assert_equal({ key_1 => value_1, key_2 => value_2 }, events[0].payload[:key])
19556 @cache.fetch_multi(key_2, key_1) { |key| key * 2 }
19557 assert_equal [key_2, key_1], events[0].payload[:key]
19558 @cache.fetch_multi() { |key| key * 2 }
19559 assert_equal [], events[0].payload[:key]
19560 [].tap do |events|
19561 @cache.write(key, 3, raw: true)
19562 @cache.write("fu", "baz")
19563 @cache.write("foo/bar", "baz")
19564 @cache.write("fu/baz", "bar")
19565 assert @cache.exist?("fu")
19566 assert @cache.exist?("fu/baz")
19567 @logger = @log1
19568 logger << "foo"
19569 assert_equal [[::Logger::ERROR, "from error", nil], [::Logger::UNKNOWN, "from unknown", nil]], custom_logger.adds
19570 assert_equal [[::Logger::ERROR, "from error", nil], [::Logger::UNKNOWN, "from unknown", nil]], new_logger.adds
19571 assert_equal [[::Logger::ERROR, "from error", nil], [::Logger::UNKNOWN, "from unknown", nil]], log1.adds
19572 assert_equal [[::Logger::ERROR, "from error", nil], [::Logger::UNKNOWN, "from unknown", nil]], log2.adds
19573 assert_equal [[::Logger::FATAL, "seen", nil]], log1.adds
19574 assert_equal [[::Logger::FATAL, "seen", nil]], log2.adds
19575 @local_level = ::Logger::DEBUG
19576 add(::Logger::INFO, message, &block)
19577 add(::Logger::WARN, message, &block)
19578 def <<(x)
19579 @chevrons << x
19580 def initialize; @lines = []; end
19581 def each(&block); @lines.each(&block); end
19582 def write(x); @lines << x; end
19583 def empty?; @lines.empty?; end
19584 benchmark { i_was_run = true }
19585 benchmark("test_run") { i_was_run = true }
19586 benchmark("included_debug_run", level: :debug) { }
19587 benchmark("skipped_debug_run", level: :debug) { }
19588 assert_match(/^#{message} \(.*\)$/, buffer.last)
19589 assert @array_inquirer.any? { |v| v == :mobile }
19590 assert_not @array_inquirer.any? { |v| v == :desktop }
19591 result = [:mobile, :tablet, "api"].inquiry
19592 (name == :foo) || super
19593 data = StringIO.new(data || "")
19594 texts = +""
19595 element.texts.each { |t| texts << t.value }
19596 hash[key] << value
19597 hash[key] = [hash[key], value]
19598 hash[key] = [value]
19599 attributes = {}
19600 element.attributes.each { |n, v| attributes[n] = v }
19601 @hash = {}
19602 @hash_stack = [@hash]
19603 def start_element(name, attrs = [])
19604 def to_hash(hash = {})
19605 node_hash = {}
19606 elsif c.text? || c.cdata?
19607 attribute_nodes.each { |a| node_hash[a.node_name] = a.value }
19608 @hash = @hash_stack.pop
19609 def on_start_element(name, attrs = {})
19610 each_attr { |a| node_hash[a.name] = a.value }
19611 raise "Document too deep!" if depth == 0
19612 (0...child_nodes.length).each do |i|
19613 attribute_hash = {}
19614 (0...attributes.length).each do |i|
19615 texts = []
19616 text = +""
19617 if String === number
19618 if value.is_a?(::Method) || value.is_a?(::Proc)
19619 if value.arity == 1
19620 type_name ||= value.class.name if value && !value.respond_to?(:to_str)
19621 attributes = options[:skip_types] || type_name.nil? ? {} : { type: type_name }
19622 def rename_key(key, options = {})
19623 left, middle, right = /\A(_*)(.*?)(_*)\Z/.match(key.strip)[1, 3]
19624 sign = (seconds < 0 ? "-" : "+")
19625 minutes = (seconds.abs % 3600) / 60
19626 def [](arg)
19627 @lazy_zones_map[arg] ||= create(arg)
19628 @lazy_zones_map[arg.name] ||= create(arg.name, nil, arg)
19629 arg *= 3600 if arg.abs <= 13
19630 all.find { |z| z.utc_offset == arg.to_i }
19631 def clear # :nodoc:
19632 @zones = nil
19633 @zones_map = nil
19634 MAPPING.inject([]) do |memo, (key, value)|
19635 memo << self[key] if value == tz_id
19636 @zones_map ||= MAPPING.each_with_object({}) do |(name, _), zones|
19637 def <=>(zone)
19638 result = (utc_offset <=> zone.utc_offset)
19639 result = (name <=> zone.name) if result == 0
19640 def =~(re)
19641 re === name || re === MAPPING[name]
19642 (re == name) || (re == MAPPING[name]) ||
19643 ((Regexp === re) && (re.match?(name) || re.match?(MAPPING[name])))
19644 time = Time.utc(*args)
19645 def at(*args)
19646 if parts.key?(:yday)
19647 time = Time.new(
19648 parts.fetch(:hour, 0),
19649 parts.fetch(:min, 0),
19650 parts.fetch(:sec, 0) + parts.fetch(:sec_fraction, 0),
19651 def parse(str, now = now())
19652 parts.fetch(:sec) + parts.fetch(:sec_fraction, 0),
19653 def strptime(str, format, now = now())
19654 today + 1
19655 today - 1
19656 t : Time.utc(t.year, t.month, t.day, t.hour, t.min, t.sec, t.sec_fraction * 1_000_000)
19657 def init_with(coder) # :nodoc:
19658 coder.tag = "!ruby/object:#{self.class}"
19659 coder.map = { "name" => tzinfo.name }
19660 parts.fetch(:mday, parts[:year] || parts[:mon] ? 1 : now.day),
19661 if parts[:offset] || parts[:seconds]
19662 @period ||= time_zone.period_for_utc(@utc)
19663 def in_time_zone(new_zone = ::Time.zone)
19664 zone == "UTC" || zone == "UCT"
19665 alias_method :gmt?, :utc?
19666 %(#{time.strftime("%Y/%m/%d %H:%M:%S")} #{formatted_offset(false)})
19667 initialize(coder["utc"], coder["zone"], coder["time"])
19668 coder.map = { "utc" => utc, "zone" => time_zone, "time" => time }
19669 if format == :db
19670 format = format.gsub(/((?:\A|[^%])(?:%%)*)%Z/, "\\1#{zone}")
19671 utc <=> other
19672 alias_method :before?, :<
19673 alias_method :after?, :>
19674 alias_method :since, :+
19675 alias_method :in, :+
19676 def -(other)
19677 result = utc.acts_like?(:date) ? utc.ago(other) : utc - other rescue utc.ago(other)
19678 new_zone = ::Time.find_zone(options[:zone])
19679 new_zone ||= time_zone
19680 [time.sec, time.min, time.hour, time.day, time.mon, time.year, time.wday, time.yday, dst?, zone]
19681 klass == ::Time || super
19682 alias_method :kind_of?, :is_a?
19683 def method_missing(...)
19684 wrap_with_time_zone time.__send__(...)
19685 @time += 1.hour
19686 return time if time.instance_of?(::Time) && time.utc?
19687 @stubs = Hash.new { |h, k| h[k] = {} }
19688 new_name = "__simple_stub__#{method_name}"
19689 if date_or_time.is_a?(Date) && !date_or_time.is_a?(DateTime)
19690 stubs.stub_object(Time, :now) { at(now) }
19691 stubs.stub_object(Time, :new) do |*args, **options|
19692 stubs.stub_object(Date, :today) { jd(now.to_date.jd) }
19693 heading = "#{self.class}: #{name}"
19694 divider = "-" * heading.size
19695 @tagged_logger ||= (defined?(Rails.logger) && Rails.logger)
19696 def warn(message, *)
19697 stream_io = eval("$#{stream}", binding, __FILE__, __LINE__)
19698 @size = size
19699 def <<(work)
19700 set_process_title("#{klass}##{method}")
19701 def <<(o)
19702 o[2] = DRbObject.new(o[2]) if o
19703 @queue << o
19704 if test = @queue.pop
19705 @in_flight[[test[0].to_s, test[1]]] = test
19706 error.set_backtrace([""])
19707 @@after_fork_hooks = []
19708 @@after_fork_hooks << blk
19709 @@run_cleanup_hooks = []
19710 @@run_cleanup_hooks << blk
19711 @worker_pool = []
19712 object.stub(method_name, proc { times_called += 1; returns }, &block)
19713 error = "Expected #{method_name} to be called #{times} times, " \
19714 error = "#{message}.
#{error}" if message
19715 klass.define_method("stubbed_#{method_name}") do |*|
19716 failures.map! { |e|
19717 write.puts [result].pack("m")
19718 test_opts = "-n#{self.class.name}##{name}"
19719 load_path_args = []
19720 $-I.each do |p|
19721 load_path_args << "-I"
19722 child = IO.popen([env, Gem.ruby, *load_path_args, $0, *ORIG_ARGV, test_opts])
19723 msg = "the directory '%s' does not contain a file named '%s'"
19724 reports = []
19725 recorders.delete_if { |r| reports.equal?(r) }
19726 elsif (report = reports.find { |r| error_class === r.error })
19727 assert warnings.any? { |w| match.match?(w) }, "No deprecation warning matched #{match}: #{warnings.join(', ')}"
19728 test_name = "test_#{name.gsub(/\s+/, '_')}".to_sym
19729 names = test_name.split "::"
19730 names.last.sub!(/Test$/, "")
19731 message ||= "Expected #{mu_pp(object)} to be nil or false"
19732 error = super(*exp, &block)
19733 yield.tap { assert(true) }
19734 difference = args[0] || 1
19735 exps = expressions.keys.map { |e|
19736 e.respond_to?(:call) ? e : lambda { eval(e, block.binding) }
19737 before = exps.map(&:call)
19738 exp = expression.respond_to?(:call) ? expression : -> { eval(expression.to_s, block.binding) }
19739 error = "#{error}. It was already #{to}" if before == to
19740 error = "Expected change to #{to}, got #{after}
"
19741 assert to === after, error
19742 warning = <<~MSG
19743 def pop_tags(count = 1)
19744 @tags = []
19745 tags.reject!(&:blank?)
19746 elsif @tags.size == 1
19747 @tags_string ||= "[#{@tags.join("] [")}] "
19748 def spot(_)
19749 @ex = ex
19750 super(@ex.__getobj__)
19751 file, line = trace.match(/^(.+?):(\d+).*$/, &:captures) || trace
19752 __getobj__.to_s.split("
")
19753 @@subscribers ||= []
19754 method = event.name[0, event.name.index(".")]
19755 method_name.end_with?("?") || super
19756 if method_name.end_with?("?")
19757 self == method_name[0..-2]
19758 l = a.unpack "C#{a.bytesize}"
19759 res = 0
19760 b.each_byte { |byte| res |= byte ^ l.shift }
19761 res == 0
19762 @rotate_values = []
19763 key = if klass.is_a?(Module) && klass.respond_to?(:===)
19764 self.rescue_handlers += [[key, with]]
19765 if method.arity == 0
19766 -> e { method.call }
19767 -> e { object.instance_exec(&rescuer) }
19768 -> e { object.instance_exec(e, &rescuer) }
19769 to_run(:after) { self.class.prepare! }
19770 def self.run!(reset: false) # :nodoc:
19771 def self.check! # :nodoc:
19772 def run! # :nodoc:
19773 def class_unload!(&block) # :nodoc:
19774 def complete! # :nodoc:
19775 if k == "disable_to_s_conversion"
19776 k = "#{k}="
19777 undef_method :==
19778 ::Object.send(:raise, *args)
19779 pattern.is_a?(Regexp) ? pattern : "(?i:#{Regexp.escape pattern.to_s})"
19780 deep_patterns = patterns.extract! { |pattern| pattern.to_s.include?("\\.") }
19781 @mask = mask
19782 @regexps, strings = [], []
19783 @blocks = nil
19784 (@blocks ||= []) << item
19785 if item.to_s.include?("\\.")
19786 (@deep_regexps ||= []) << item
19787 @regexps << item
19788 if s.include?("\\.")
19789 (deep_strings ||= []) << s
19790 strings << s
19791 (@deep_regexps ||= []) << Regexp.new(deep_strings.join("|"), true) if deep_strings
19792 full_key = full_parent_key ? "#{full_parent_key}.#{key}" : key.to_s
19793 if @regexps.any? { |r| r.match?(key.to_s) }
19794 value = @mask
19795 elsif @deep_regexps&.any? { |r| r.match?(full_key) }
19796 value = value.map { |v| value_for_key(key, v, full_parent_key, original_params) }
19797 @blocks.each { |b| b.arity == 2 ? b.call(key, value) : b.call(key, value, original_params) }
19798 alias_method :_get, :[] # preserve the original #[] method
19799 if name_string.chomp!("=")
19800 bangs = name_string.chomp!("!")
19801 super() { |h, k| parent._get(k) }
19802 super() { |h, k| parent[k] }
19803 class OrderedHash < ::Hash # :nodoc:
19804 coder.represent_seq "!omap", map { |k, v| { k => v } }
19805 dup.tap { |hash| hash.select!(*args, &block) }
19806 dup.tap { |hash| hash.reject!(*args, &block) }
19807 undef_method(method) unless method.start_with?("__", "instance_eval", "class", "object_id")
19808 if arguments.size == 1 && arguments.first.is_a?(Proc)
19809 arguments << lambda { |*args| @options.deep_merge(proc.call(*args)) }
19810 @context.__send__(method, *arguments, **options, &block)
19811 @context.__send__(method, *arguments, &block)
19812 s = rounded_number.to_s("F")
19813 a, b = s.split(".", 2)
19814 b << "0" * precision
19815 a << "."
19816 a << b[0, precision]
19817 number.sub(/(#{escaped_separator})(\d*[1-9])?0+\z/, '\1\2').sub(/#{escaped_separator}\z/, "")
19818 default_pattern = /(\d{1,3})(\d{3})(\d{4}$)/
19819 default_pattern = /(\d{0,3})(\d{3})(\d{4})$/
19820 opts[:delimiter] || "-"
19821 code.blank? ? "" : "+#{code}#{delimiter}"
19822 ext.blank? ? "" : " x #{ext}"
19823 conversion_format.gsub("%n", number_to_format).gsub("%u", unit)
19824 exp = (Math.log(number) / Math.log(base)).to_i
19825 -1 => :deci, -2 => :centi, -3 => :mili, -6 => :micro, -9 => :nano, -12 => :pico, -15 => :femto }
19826 units = opts[:units]
19827 @number = number / (10**exponent)
19828 format.gsub("%n", rounded_number).gsub("%u", unit).strip
19829 units[exp] || ""
19830 I18n.translate("#{units}.#{exp}", locale: options[:locale], count: number.to_i)
19831 exponent = number != 0 ? Math.log10(number.abs).floor : 0
19832 unit_exponents(units).find { |e| exponent >= e } || 0
19833 left, right = number.to_s.split(".")
19834 format = options[:negative_format] if (number_f * 10**options[:precision]) >= 0.5
19835 format = options[:negative_format] if number_s.sub!(/^-/, "")
19836 format.gsub("%n", number_s).gsub("%u", options[:unit])
19837 @options ||= begin
19838 defaults[:negative_format] = "-#{opts[:format]}" if opts[:format]
19839 i18n[:negative_format] ||= "-#{i18n[:format]}" if i18n[:format]
19840 separator: ".",
19841 delimiter: ",",
19842 format: "%u%n",
19843 negative_format: "-%u%n",
19844 unit: "$",
19845 delimiter: "",
19846 format: "%n%"
19847 delimiter: ""
19848 byte: "Bytes",
19849 unit: "",
19850 key.split(".").reduce(DEFAULTS) { |defaults, k| defaults[k.to_sym] }
19851 @id = id
19852 def new_event(name, payload = {}) # :nodoc:
19853 Event.new(name, nil, nil, @id, payload)
19854 @cpu_time_start = 0.0
19855 @cpu_time_finish = 0.0
19856 @time = now
19857 @end = now
19858 diff > 0.0 ? diff : 0.0
19859 def parent_of?(event) # :nodoc:
19860 start = (time - event.time) * 1000
19861 start <= 0 && (start + duration >= event.duration)
19862 exceptions ||= []
19863 @string_subscribers = Hash.new { |h, k| h[k] = [] }
19864 @other_subscribers = []
19865 def clear_cache(key = nil) # :nodoc:
19866 each do |s|
19867 def groups_for(name) # :nodoc:
19868 group.start(@name, @id, @payload)
19869 @all_listeners_for[name] ||=
19870 all_listeners_for(name).reject { |s| s.silenced?(name) }
19871 all_listeners_for(name).any? { |s| !s.silenced?(name) }
19872 exclusions << -name if pattern === name
19873 def ===(name)
19874 pattern === name && !exclusions.include?(name)
19875 pattern === name
19876 delegate :<=>, :=~, :match?, :acts_like_string?, to: :wrapped_string
19877 result = @wrapped_string.__send__(method, *args, &block)
19878 if method.end_with?("!")
19879 @wrapped_string.split(*args).map { |i| self.class.new(i) }
19880 chars(downcase.to_s.gsub(/\b('?\S)/u) { $1.upcase })
19881 def as_json(options = nil) # :nodoc:
19882 define_method("#{method}!") do |*args|
19883 super(*args, **options)
19884 @args = args
19885 @rotations = []
19886 self.class.new(*args, *@args.drop(args.length), **@options, **options)
19887 @rotate_options = []
19888 @codecs = {}
19889 def [](salt)
19890 def []=(salt, codec)
19891 @rotate_options << (block || options)
19892 filter_map { |type, name| name if type == :key || type == :keyreq }
19893 rotate_options.map { |options| build(salt.to_s, **options) }.reduce(&:fall_back_to)
19894 @signed, @encrypted = [], []
19895 @signed << args
19896 has_metadata = metadata.any? { |k, v| v }
19897 data = wrap_in_metadata_envelope({ "data" => data }, **metadata) if has_metadata
19898 elsif expected_metadata.none? { |k, v| v }
19899 hash["exp"] = expiry if expiry
19900 { "_rails" => hash }
19901 hash = envelope["_rails"]
19902 if hash["exp"] && Time.now.utc >= parse_expiry(hash["exp"])
19903 if hash["pur"] != purpose&.to_s
19904 object.is_a?(Hash) && object.key?("_rails")
19905 string.start_with?('{"_rails":{"message":')
19906 @url_safe = url_safe
19907 error = as.new(error.to_s) if as
19908 @digest = digest&.to_s || "SHA1"
19909 @verifier = if !@aead_mode
19910 cipher.auth_data = "" if aead_mode?
19911 cipher.auth_data = ""
19912 parts.map! { |part| encode(part) }.join(SEPARATOR)
19913 parts.reverse!.map! { |part| decode(part) }
19914 @local_level_key ||= :"logger_thread_safe_level_#{object_id}"
19915 silencer ? log_at(severity) { yield self } : yield(self)
19916 sources.any? { |source| source == logger_source }
19917 define_method(:add) do |*args, &block|
19918 define_method(:<<) do |x|
19919 logger << x
19920 @flush_count = 0
19921 @logged = Hash.new { |h, k| h[k] = [] }
19922 @logged[level] << yield
19923 @logged[level].compact.map { |l| l.to_s.strip }
19924 @flush_count += 1
19925 @logger ||= if defined?(Rails) && Rails.respond_to?(:logger)
19926 def attach_to(...) # :nodoc:
19927 subscriber.event_levels = log_levels.transform_keys { |k| "#{k}.#{namespace}" }
19928 @event_levels = {}
19929 def #{level}(progname = nil, &block)
19930 def color(text, color, mode_options = {}) # :doc:
19931 clear = "\e[#{MODES[:clear]}m"
19932 in Rails 7.2. Use an option hash instead (eg. `color("my text", :red, bold: true)`).
19933 options = { bold: options }
19934 logger.error "Could not log #{name.inspect} event. #{e.class}: #{e.message} #{e.backtrace}"
19935 en: {
19936 nth: {
19937 when 1; "st"
19938 when 2; "nd"
19939 when 3; "rd"
19940 when 4, 5, 6, 7, 8, 9, 10, 11, 12, 13; "th"
19941 num_modulo %= 10 if num_modulo > 13
19942 @load_hooks = Hash.new { |h, k| h[k] = [] }
19943 def on_load(name, options = {}, &block)
19944 @load_hooks[name] << [block, options]
19945 @loaded[name] << base
19946 @run_once[name] << block if once
19947 @iterations = options[:iterations] || 2**16
19948 @cache_keys[args.join("|")] ||= @key_generator.generate_key(*args)
19949 @options = options || {}
19950 s = super
19951 value.each do |k, v|
19952 value.map { |v| jsonify(v) }
19953 data.map! { |d| convert_dates_from(d) }
19954 @scope =
19955 self[:__id__] ||= Object.new
19956 parameterized_string.gsub!(/[^a-z0-9\-_]+/i, separator)
19957 if separator == "-"
19958 re_leading_trailing_separator = /^-|-$/i
19959 re_leading_trailing_separator = /^#{re_sep}|#{re_sep}$/i
19960 elsif string.match?(/\A[a-z\d]*\z/)
19961 string = string.sub(/^[a-z\d]*/) { |match| inflections.acronyms[match] || match.capitalize! || match }
19962 string.gsub!(/(?:_|(\/))([a-z\d]*)/i) do
19963 word = $2
19964 $1 ? "::#{substituted}" : substituted
19965 return camel_cased_word.to_s unless /[A-Z-]|::/.match?(camel_cased_word)
19966 word = camel_cased_word.to_s.gsub("::", "/")
19967 word.gsub!(inflections.acronyms_underscore_regex) { "#{$1 && '_' }#{$2.downcase}" }
19968 word.gsub!(/([A-Z])(?=[A-Z][a-z])|([a-z\d])(?=[A-Z])/) { ($1 || $2) << "_" }
19969 word.tr!("-", "_")
19970 result.tr!("_", " ")
19971 result.gsub!(/([a-z\d]+)/i) do |match|
19972 result.sub!(/\A\w/) do |match|
19973 string.length > 0 ? string[0].upcase.concat(string[1..-1]) : ""
19974 string.length > 0 ? string[0].downcase.concat(string[1..-1]) : ""
19975 camelize(singularize(table_name.to_s.sub(/.*\./, "")))
19976 underscored_word.tr("_", "-")
19977 path = path.to_s
19978 if i = path.rindex("::")
19979 path[(i + 2), path.length]
19980 raise if e.name && !(camel_cased_word.to_s.split("::").include?(e.name.to_s) ||
19981 e.name.to_s == camel_cased_word.to_s)
19982 parts = camel_cased_word.split("::")
19983 part.empty? ? acc : "#{part}(::#{acc})?"
19984 @__instance__ = Concurrent::Map.new
19985 @regex_array = []
19986 def <<(*word)
19987 @regex_array += words.map { |word| to_regex(word) }
19988 @regex_array.any? { |regex| regex.match? str }
19989 /\b#{::Regexp.escape(string)}\Z/i
19990 @__instance__[locale] ||= new
19991 return @__instance__[k] if @__instance__.key?(k)
19992 @plurals, @singulars, @uncountables, @humans, @acronyms = [], [], Uncountables.new, [], {}
19993 s0 = singular[0]
19994 srest = singular[1..-1]
19995 p0 = plural[0]
19996 prest = plural[1..-1]
19997 plural(/(#{s0})#{srest}$/i, '\1' + prest)
19998 plural(/(#{p0})#{prest}$/i, '\1' + prest)
19999 singular(/(#{s0})#{srest}$/i, '\1' + srest)
20000 singular(/(#{p0})#{prest}$/i, '\1' + srest)
20001 plural(/#{s0.downcase}(?i)#{srest}$/, p0.downcase + prest)
20002 plural(/#{p0.downcase}(?i)#{prest}$/, p0.downcase + prest)
20003 singular(/#{s0.downcase}(?i)#{srest}$/, s0.downcase + srest)
20004 singular(/#{p0.downcase}(?i)#{prest}$/, s0.downcase + srest)
20005 def clear(scope = :all)
20006 @acronyms = {}
20007 instance_variable_set "@#{scope}", []
20008 @acronyms_underscore_regex = /(?:(?<=([A-Za-z\d]))|\b)(#{@acronym_regex})(?=\b|[^a-z])/
20009 inflect.plural(/s$/i, "s")
20010 inflect.plural(/^(ax|test)is$/i, '\1es')
20011 inflect.plural(/(octop|vir)us$/i, '\1i')
20012 inflect.plural(/(octop|vir)i$/i, '\1i')
20013 inflect.plural(/(alias|status)$/i, '\1es')
20014 inflect.plural(/(bu)s$/i, '\1ses')
20015 inflect.plural(/(buffal|tomat)o$/i, '\1oes')
20016 inflect.plural(/([ti])um$/i, '\1a')
20017 inflect.plural(/([ti])a$/i, '\1a')
20018 inflect.plural(/sis$/i, "ses")
20019 inflect.plural(/(?:([^f])fe|([lr])f)$/i, '\1\2ves')
20020 inflect.plural(/(hive)$/i, '\1s')
20021 inflect.plural(/([^aeiouy]|qu)y$/i, '\1ies')
20022 inflect.plural(/(x|ch|ss|sh)$/i, '\1es')
20023 inflect.plural(/(matr|vert|ind)(?:ix|ex)$/i, '\1ices')
20024 inflect.plural(/^(m|l)ouse$/i, '\1ice')
20025 inflect.plural(/^(m|l)ice$/i, '\1ice')
20026 inflect.plural(/^(ox)$/i, '\1en')
20027 inflect.plural(/^(oxen)$/i, '\1')
20028 inflect.singular(/s$/i, "")
20029 inflect.singular(/(ss)$/i, '\1')
20030 inflect.singular(/(n)ews$/i, '\1ews')
20031 inflect.singular(/([ti])a$/i, '\1um')
20032 inflect.singular(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)(sis|ses)$/i, '\1sis')
20033 inflect.singular(/(^analy)(sis|ses)$/i, '\1sis')
20034 inflect.singular(/([^f])ves$/i, '\1fe')
20035 inflect.singular(/(hive)s$/i, '\1')
20036 inflect.singular(/(tive)s$/i, '\1')
20037 inflect.singular(/([lr])ves$/i, '\1f')
20038 inflect.singular(/([^aeiouy]|qu)ies$/i, '\1y')
20039 inflect.singular(/(s)eries$/i, '\1eries')
20040 inflect.singular(/(m)ovies$/i, '\1ovie')
20041 inflect.singular(/(x|ch|ss|sh)es$/i, '\1')
20042 inflect.singular(/^(m|l)ice$/i, '\1ouse')
20043 inflect.singular(/(bus)(es)?$/i, '\1')
20044 inflect.singular(/(o)es$/i, '\1')
20045 inflect.singular(/(shoe)s$/i, '\1')
20046 inflect.singular(/(cris|test)(is|es)$/i, '\1is')
20047 inflect.singular(/^(a)x[ie]s$/i, '\1xis')
20048 inflect.singular(/(octop|vir)(us|i)$/i, '\1us')
20049 inflect.singular(/(alias|status)(es)?$/i, '\1')
20050 inflect.singular(/^(ox)en/i, '\1')
20051 inflect.singular(/(vert|ind)ices$/i, '\1ex')
20052 inflect.singular(/(matr)ices$/i, '\1ix')
20053 inflect.singular(/(quiz)zes$/i, '\1')
20054 config.i18n.load_path = []
20055 I18n.public_send("#{setting}=", value)
20056 I18n.load_path.keep_if { |p| File.exist?(p) }
20057 args = \
20058 [*(fallbacks[:defaults] || []) << fallbacks[:map]].compact
20059 I18n.load_path << File.expand_path("locale/en.yml", __dir__)
20060 I18n.load_path << File.expand_path("locale/en.rb", __dir__)
20061 /(?:_|\b)html\z/.match?(key)
20062 unless i18n_option?(name) || (name == :count && value.is_a?(Numeric))
20063 def self.[](*args)
20064 new.merge!(Hash[*args])
20065 alias_method :store, :[]=
20066 args[0] = convert_key(args[0]) if args.size > 0
20067 def default(key = (no_key = true))
20068 keys.map! { |key| convert_key(key) }
20069 indices.map! { |key| convert_key(key) }
20070 dup.tap { |hash| hash.transform_values!(&block) }
20071 dup.tap { |h| h.transform_keys!(hash, &block) }
20072 keys.each { |key| self[yield(key)] = delete(key) }
20073 keys.each { |key| self[hash[key] || yield(key)] = delete(key) }
20074 keys.each { |key| self[hash[key] || key] = delete(key) }
20075 dup.tap(&:compact!)
20076 _new_hash = Hash.new
20077 each do |key, value|
20078 key.kind_of?(Symbol) ? key.name : key
20079 key.kind_of?(Symbol) ? key.to_s : key
20080 if block && key?(key)
20081 if pid == 0
20082 def fork(...)
20083 @callbacks = []
20084 if @pid != new_pid
20085 @pid = new_pid
20086 if Process.respond_to?(:_fork) # Ruby 3.1+
20087 def initialize(files, dirs = {}, &block)
20088 all = @files.select { |f| File.exist?(f) }
20089 @updated_at || max_mtime(paths) || Time.at(0)
20090 globs = hash.map do |key, value|
20091 key.gsub(",", '\,')
20092 def run(...)
20093 Null = Object.new # :nodoc:
20094 def self.to_run(*args, &block)
20095 set_callback(:run, *args, &block)
20096 RunHook = Struct.new(:hook) do # :nodoc:
20097 @active_key ||= :"active_execution_wrapper_#{object_id}"
20098 def self.active? # :nodoc:
20099 def run # :nodoc:
20100 @_hook_state ||= {}
20101 @core = Core.new(files, dirs)
20102 @files = files.map { |file| Pathname(file).expand_path }.to_set
20103 @dirs = dirs.each_with_object({}) do |(dir, exts), hash|
20104 hash[Pathname(dir).expand_path] = Array(exts).map { |ext| ext.to_s.sub(/\A\.?/, ".") }.to_set
20105 @missing = []
20106 @dtw, @missing = [*@dtw, *@missing].partition(&:exist?)
20107 @listener = @dtw.any? ? Listen.to(*@dtw, &method(:changed)) : nil
20108 @missing.any?(&:exist?)
20109 @updated.make_true if (modified + added + removed).any? { |f| watching?(f) }
20110 elsif dir == @common_path || dir.root?
20111 dtw = @dirs.keys | @files.map(&:dirname)
20112 accounted_for = dtw.to_set + Gem.path.map { |path| Pathname(path) }
20113 dtw.reject { |dir| dir.ascend.drop(1).any? { |parent| accounted_for.include?(parent) } }
20114 paths.map { |path| path.ascend.to_a }.reduce(&:&)&.first
20115 @subscribers.delete_if { |s| subscriber === s }
20116 def set_context(...)
20117 unless disabled_subscribers&.any? { |s| s === subscriber }
20118 instance_variable_set :"@#{default}", env == default
20119 def #{env}?
20120 @#{env}
20121 if !key.nil? && content_path.exist?
20122 tmp_file = "#{Process.pid}.#{content_path.basename.to_s.chomp('.enc')}"
20123 super "Invalid YAML in '#{content_path}'."
20124 delegate :[], :fetch, to: :config
20125 @config = nil
20126 def validate! # :nodoc:
20127 hash.each do |k, v|
20128 h[k] = deep_transform(v)
20129 config.presence || {}
20130 output = +"P"
20131 time = +""
20132 time << "#{format_seconds(parts[:seconds])}S"
20133 output << "T#{time}" unless time.empty?
20134 parts = @duration.parts.each_with_object(Hash.new(0)) do |(k, v), p|
20135 sprintf("%0.0#{@precision}f", seconds)
20136 DATE_TO_PART = { "Y" => :years, "M" => :months, "W" => :weeks, "D" => :days }
20137 TIME_TO_PART = { "H" => :hours, "M" => :minutes, "S" => :seconds }
20138 @parts = {}
20139 @mode = :start
20140 @sign = 1
20141 self.sign = (scanner.matched == "-") ? -1 : 1
20142 fractions = parts.values.reject(&:zero?).select { |a| (a % 1) != 0 }
20143 unless fractions.empty? || (fractions.size == 1 && fractions.last == @parts.values.reject(&:zero?).last)
20144 delegate :to_i, :to_f, :to_s, to: :value
20145 def -@
20146 if Scalar === other || Duration === other
20147 value <=> other
20148 calculate(:+, other)
20149 calculate(:-, other)
20150 calculate(:*, other)
20151 def /(other)
20152 calculate(:/, other)
20153 def %(other)
20154 calculate(:%, other)
20155 def variable? # :nodoc:
20156 if Scalar === other
20157 PARTS = [:years, :months, :weeks, :days, :hours, :minutes, :seconds].freeze
20158 def ===(other) # :nodoc:
20159 new(value, { seconds: value }, false)
20160 def hours(value) # :nodoc:
20161 def days(value) # :nodoc:
20162 def weeks(value) # :nodoc:
20163 def years(value) # :nodoc:
20164 parts = {}
20165 remainder_sign = value <=> 0
20166 parts.inject(0) do |total, (part, value)|
20167 @value, @parts = value, parts
20168 @parts.reject! { |k, v| v.zero? } unless value == 0
20169 @variable = @parts.any? { |part, _| VARIABLE_PARTS.include?(part) }
20170 [other, self]
20171 seconds = @parts.fetch(:seconds, 0) + other
20172 self + (-other)
20173 if Duration === other || Scalar === other
20174 def -@ # :nodoc:
20175 def +@ # :nodoc:
20176 def is_a?(klass) # :nodoc:
20177 Duration == klass || value.is_a?(klass)
20178 alias :kind_of? :is_a?
20179 def instance_of?(klass) # :nodoc:
20180 Duration === other && other.value.eql?(value)
20181 sum(1, time)
20182 def ago(time = ::Time.current)
20183 sum(-1, time)
20184 coder.map = { "value" => @value, "parts" => @parts }
20185 def _parts # :nodoc:
20186 def sum(sign, time = ::Time.current)
20187 unless time.acts_like?(:time) || time.acts_like?(:date)
20188 @parts.inject(time) do |t, (type, number)|
20189 if type == :seconds
20190 t.since(sign * number * 60)
20191 elsif type == :hours
20192 t.since(sign * number * 3600)
20193 t.advance(type => sign * number)
20194 def <<(object)
20195 def [](object)
20196 alias_method :include?, :[]
20197 def []=(object, _present)
20198 def reject!(classes) # :nodoc:
20199 @refs = []
20200 def <<(klass)
20201 @refs.reject! do |ref|
20202 yield ref.__getobj__
20203 @refs.delete_if { |ref| !ref.weakref_alive? }
20204 when String then "#{warning} (#{message})"
20205 } || callstack.first
20206 if md = offending_line.match(/^(.+?):(\d+)(?::in `(.*?)')?/)
20207 instance_methods.each { |m| undef_method m unless /^__|^object_id$/.match?(m) }
20208 target.__send__(called, *args, &block)
20209 @var = var
20210 @instance.__send__(@method)
20211 @deprecator.warn("#{@var} is deprecated! Call #{@method}.#{called} instead of #{@var}.#{called}. Args: #{args.inspect}", callstack)
20212 def self.new(*args, **options, &block)
20213 mod = nil
20214 mod ||= Module.new
20215 @disallowed_warnings ||= []
20216 @options = {}
20217 @deprecators = {}
20218 def [](name)
20219 def []=(name, deprecator)
20220 each { |deprecator| deprecator.public_send("#{name}=", value) }
20221 silence: ->(message, callstack, deprecator) { },
20222 when -2..3
20223 def raw_state(&block) # :nodoc:
20224 @_under_path = nil
20225 @_at_path = nil
20226 full = [name, @_under_path, const_name.to_s].compact.join("::")
20227 @_eagerloaded_constants ||= []
20228 @_under_path, old_path = path, @_under_path
20229 @_under_path = old_path
20230 @_at_path, old_path = path, @_at_path
20231 @_at_path = old_path
20232 relpath += ".rb" unless relpath.end_with?(".rb")
20233 INVALID_ATTRIBUTE_NAMES = [:set, :reset, :resets, :instance, :before_reset, :after_reset, :reset_all, :clear_all] # :nodoc:
20234 batch <<
20235 def reset_all # :nodoc:
20236 def clear_all # :nodoc:
20237 send(name, *args, &block)
20238 @attributes = {}
20239 self.attributes = {}
20240 new_attributes.each { |key, value| public_send("#{key}=", value) }
20241 keys.index_with { |key| public_send(key) }
20242 old_zone, ::Time.zone = ::Time.zone, new_zone
20243 ::Time.zone = old_zone
20244 db: "%Y-%m-%d %H:%M:%S",
20245 inspect: "%Y-%m-%d %H:%M:%S.%9N %z",
20246 number: "%Y%m%d%H%M%S",
20247 time: "%H:%M",
20248 short: "%d %b %H:%M",
20249 long: "%B %d, %Y %H:%M",
20250 time.strftime("%B #{day_format}, %Y %H:%M")
20251 rfc822: lambda { |time|
20252 time.strftime("%a, %d %b %Y %H:%M:%S #{offset_format}")
20253 def ===(other)
20254 super || (self == Time && other.is_a?(ActiveSupport::TimeWithZone))
20255 if month == 2 && ::Date.gregorian_leap?(year)
20256 days_in_month(2, year) + 337
20257 ::Time.zone ? ::Time.zone.now : ::Time.now
20258 return at_without_coercion(*args, **kwargs) if args.size != 1 || !kwargs.empty?
20259 to_i - change(hour: 0).to_i + (usec / 1.0e+6)
20260 end_of_day.to_i - to_i
20261 new_usec = options.fetch(:usec, (options[:hour] || options[:min] || options[:sec]) ? 0 : Rational(nsec, 1000))
20262 ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec, new_offset)
20263 ::Time.utc(new_year, new_month, new_day, new_hour, new_min, new_sec)
20264 new_time = ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec, zone)
20265 ::Time.local(new_sec, new_min, new_hour, new_day, new_month, new_year, nil, nil, isdst, nil)
20266 ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec, utc_offset)
20267 options[:days] = options.fetch(:days, 0) + 7 * partial_weeks
20268 options[:hours] = options.fetch(:hours, 0) + 24 * partial_days
20269 options.fetch(:minutes, 0) * 60 +
20270 hour: 23,
20271 min: 59,
20272 sec: 59,
20273 def prev_day(days = 1)
20274 def next_day(days = 1)
20275 def in_time_zone(zone = ::Time.zone)
20276 gsub(/^#{scan(/^[ \t]*(?=\S)/).min}/, "").tap do |stripped|
20277 to_str[*args]
20278 alias_method :slice, :[]
20279 self[0, 0]
20280 def []=(arg1, arg2, arg3 = nil)
20281 def *(_)
20282 def %(args)
20283 (!html_safe? || arg.html_safe?) ? arg : CGI.escapeHTML(arg.to_s)
20284 if !html_safe? || arg.html_safe?
20285 block.binding.eval("proc { |m| $~ = m }").call(match_data)
20286 def pluralize(count = nil, locale = :en)
20287 if count == 1
20288 indent_string = indent_string || self[/^[ \t]/] || " "
20289 re = indent_empty_lines ? /^/ : /^(?!$)/
20290 dup.tap { |_| _.indent!(amount, indent_string, indent_empty_lines) }
20291 gsub!(/[[:space:]]+/, " ")
20292 gsub! pattern, ""
20293 omission = options[:omission] || "..."
20294 stop = \
20295 +"#{self[0, stop]}#{omission}"
20296 omission ||= ""
20297 sep = options[:separator] || /\s+/
20298 if self =~ /\A((?>.+?#{sep}){#{words_count - 1}}.+?)#{sep}.*/m
20299 $1 + (options[:omission] || "...")
20300 def to_time(form = :local)
20301 parts.fetch(:offset, form == :utc ? 0 : nil)
20302 form == :utc ? time.utc : time.to_time
20303 self[0, position + 1] || +""
20304 def first(limit = 1)
20305 def last(limit = 1)
20306 BASE58_ALPHABET = ("0".."9").to_a + ("A".."Z").to_a + ("a".."z").to_a - ["0", "O", "I", "l"]
20307 def self.base58(n = 16)
20308 idx = byte % 64
20309 def self.base36(n = 16)
20310 other.begin == self.begin || cover?(other.begin) || other.cover?(self.begin)
20311 def step(n = 1, &block)
20312 db: -> (start, stop) do
20313 def ===(value)
20314 if value.is_a?(::Range)
20315 is_backwards_op = value.exclude_end? ? :>= : :>
20316 operator = exclude_end? && !value.exclude_end? ? :< : :<=
20317 value_max = !exclude_end? && value.exclude_end? ? value.max : value.last
20318 public_send("#{key}=", value)
20319 public_send("#{key}=", old_value)
20320 def try(*args, &block)
20321 if args.empty? && block_given?
20322 if block.arity == 0
20323 def try!(*args, &block)
20324 def try(*)
20325 def try!(*)
20326 collect(&:to_param).join "/"
20327 prefix = "#{key}[]"
20328 collect { |value| value.to_query(prefix) }.join "&"
20329 unless (value.is_a?(Hash) || value.is_a?(Array)) && value.empty?
20330 value.to_query(namespace ? "#{namespace}[#{key}]" : key)
20331 query.join("&")
20332 if options.is_a?(::JSON::State)
20333 class Data # :nodoc:
20334 finite? ? self : nil
20335 finite? ? to_s : nil
20336 map { |v| options ? v.as_json(options.dup) : v.as_json }
20337 subset.each do |k, v|
20338 result[k.to_s] = options ? v.as_json(options.dup) : v.as_json
20339 %(#{strftime("%Y/%m/%d %H:%M:%S")} #{formatted_offset(false)})
20340 strftime("%Y-%m-%d")
20341 strftime("%Y/%m/%d")
20342 strftime("%Y/%m/%d %H:%M:%S %z")
20343 variables.map! { |s| s.to_s.freeze }
20344 in?(another_object) ? self : nil
20345 map(&:deep_dup)
20346 hash = dup
20347 if ::String === key || ::Symbol === key
20348 respond_to?(:empty?) ? !!empty? : !self
20349 empty? ||
20350 class Time # :nodoc:
20351 respond_to? :"acts_like_#{duck}?"
20352 def to_fs(format = nil, options = nil)
20353 if match = message.match(/((::)?([A-Z]\w*)(::[A-Z]\w*)*)$/)
20354 parent_name = name =~ /::[^:]+\z/ ? -$` : nil
20355 parents = []
20356 parts = module_parent_name.split("::")
20357 if prefix == true && /^[^a-z_]/.match?(to)
20358 method_def = []
20359 method_names = []
20360 method_name = prefix ? "#{method_prefix}#{method}" : method
20361 if /[^\]]=\z/.match?(method)
20362 if to.is_a?(Module)
20363 if (parameters.map(&:first) & [:opt, :rest, :keyreq, :key, :keyrest]).any?
20364 defn = parameters.filter_map { |type, arg| arg if type == :req }
20365 defn << "&block" if parameters.last&.first == :block
20366 defn.join(", ")
20367 method_def <<
20368 module_eval(method_def.join(";"), file, line)
20369 return false if name == :marshal_dump || name == :_dump
20370 if #{target}.nil?
20371 if #{allow_nil == true}
20372 __send__(method, concern(topic, &block))
20373 raise NameError.new("invalid attribute name: #{sym}") unless /^[_A-Za-z]\w*$/.match?(sym)
20374 def self.#{sym}
20375 @__thread_mattr_#{sym} ||= "attr_#{sym}_\#{object_id}"
20376 def #{sym}
20377 def self.#{sym}=(obj)
20378 def #{sym}=(obj)
20379 self.class.#{sym} = obj
20380 definition = []
20381 raise NameError.new("invalid attribute name: #{sym}") unless /\A[_A-Za-z]\w*\z/.match?(sym)
20382 definition << "def self.#{sym}; @@#{sym}; end"
20383 definition << "def #{sym}; @@#{sym}; end"
20384 sym_default_value = (block_given? && default.nil?) ? yield : default
20385 class_variable_set("@@#{sym}", sym_default_value) unless sym_default_value.nil? && class_variable_defined?("@@#{sym}")
20386 definition << "def self.#{sym}=(val); @@#{sym} = val; end"
20387 definition << "def #{sym}=(val); @@#{sym} = val; end"
20388 attr_name, internal_name = "#{attr_name}=", "#{internal_name}=" if type == :writer
20389 location.delete_suffix(".rb") == path.to_s.delete_suffix(".rb")
20390 number == 0 ? self == 0 : self % number == 0
20391 omit = slice(*self.keys - keys)
20392 hash = slice(*keys)
20393 keys.each_with_object(self.class.new) { |key, result| result[key] = delete(key) if has_key?(key) }
20394 transform_keys!(&:to_s)
20395 each_key do |k|
20396 raise ArgumentError.new("Unknown key: #{k.inspect}. Valid keys are: #{valid_keys.map(&:inspect).join(', ')}")
20397 object.map { |e| _deep_transform_keys_in_object(e, &block) }
20398 object.map! { |e| _deep_transform_keys_in_object!(e, &block) }
20399 keys.each { |key| delete(key) }
20400 object.map { |e| _deep_transform_values_in_object(e, &block) }
20401 object.map! { |e| _deep_transform_values_in_object!(e, &block) }
20402 if this_val.is_a?(Hash) && other_val.is_a?(Hash)
20403 from_xml xml, []
20404 deep_to_h(@xml)
20405 Hash[params.map { |k, v| [k.to_s.tr("-", "_"), normalize_keys(v)] } ]
20406 params.map { |v| normalize_keys(v) }
20407 if value.include?("type") && !value["type"].is_a?(Hash) && @disallowed_types.include?(value["type"])
20408 _, entries = Array.wrap(value.detect { |k, v| not v.is_a?(String) })
20409 if entries.nil? || value["__content__"].try(:empty?)
20410 entries.collect { |v| deep_to_h(v) }
20411 [deep_to_h(entries)]
20412 xml_value = value.transform_values { |v| deep_to_h(v) }
20413 xml_value["file"].is_a?(StringIO) ? xml_value["file"] : xml_value
20414 value["type"] == "file" || (value["__content__"] && (value.keys.size == 1 || value["__content__"].present?))
20415 value["type"] == "array"
20416 value["type"] == "string" && value["nil"] != "true"
20417 !nothing?(value) && !garbage?(value)
20418 value.blank? || value["nil"] == "true"
20419 value["type"] && !value["type"].is_a?(::Hash) && value.size == 1
20420 content = value["__content__"]
20421 value.map! { |i| deep_to_h(i) }
20422 Tempfile.open(".#{basename(file_name)}", temp_dir) do |temp_file|
20423 basename = [
20424 ].join(".")
20425 def html_escape(s) # :nodoc:
20426 s = s.to_s
20427 name = name.to_s
20428 following_chars = name[1..-1]
20429 tokens = []
20430 start_re = /<%(?:={1,2}|-|\#|%)?/m
20431 finish_re = /(?:[-=])?%>/m
20432 source.scan_until(/(?:#{start_re}|#{finish_re})/)
20433 tokens << [:TEXT, source.string[pos, len]] if len > 0
20434 tokens << [:OPEN, source.matched]
20435 if source.scan(/(.*?)(?=#{finish_re}|\z)/m)
20436 tokens << [:CODE, source.string[pos, len]] if len > 0
20437 map(&key).min
20438 map(&key).max
20439 each { |elem| result[yield(elem)] = elem }
20440 to_enum(:index_by) { size if respond_to?(:size) }
20441 each { |elem| result[elem] = yield(elem) }
20442 to_enum(:index_with) { size if respond_to?(:size) }
20443 each { |elem| result[elem] = default }
20444 cnt = 0
20445 any? do |element, *args|
20446 cnt += 1 if yield element, *args
20447 cnt > 1
20448 any? { (cnt += 1) > 1 }
20449 map { |element| keys.map { |key| element[key] } }
20450 map { |element| element[key] }
20451 keys.map { |key| first[key] }
20452 reject(&:blank?)
20453 reject { |_k, v| v.blank? }
20454 delete_if { |_k, v| v.blank? }
20455 if block_given? || !(first.is_a?(Integer) && last.is_a?(Integer))
20456 actual_last = exclude_end? ? (last - 1) : last
20457 sum = initial_value || 0
20458 sum + (actual_last - first + 1) * (actual_last + first) / 2
20459 delete_if(&:blank?)
20460 if hash_class == Digest::MD5 || hash_class == OpenSSL::Digest::MD5
20461 ary[2] = (ary[2] & 0x0FFF) | (version << 12)
20462 ary[3] = (ary[3] & 0x3FFF) | 0x8000
20463 match_data = namespace.match(/\A(\h{8})-(\h{4})-(\h{4})-(\h{4})-(\h{4})(\h{8})\z/)
20464 match_data.captures.map { |s| s.to_i(16) }.pack("NnnnnN")
20465 def self.civil_from_format(utc_or_local, year, month = 1, day = 1, hour = 0, min = 0, sec = 0)
20466 if utc_or_local.to_sym == :local
20467 offset = ::Time.local(year, month, day).utc_offset.to_r / 86400
20468 (sec_fraction * 1_000_000).to_i
20469 (sec_fraction * 1_000_000_000).to_i
20470 (offset * 86400).to_i
20471 ::Time.zone ? ::Time.zone.now.to_datetime : ::Time.now.to_datetime
20472 sec + (min * 60) + (hour * 3600)
20473 options.fetch(:min, options[:hour] ? 0 : min),
20474 options.fetch(:sec, (options[:hour] || options[:min]) ? 0 : sec) + new_fraction,
20475 utc = new_offset(0)
20476 offset == 0
20477 time = acts_like?(:time) ? self : nil
20478 time || to_time
20479 sunday: 0,
20480 monday: 1,
20481 friday: 5,
20482 to_date == ::Date.current
20483 first_quarter_month = month - (2 + month) % 3
20484 last_quarter_month = month + (12 - month) % 3
20485 (month / 3.0).ceil
20486 (wday - start_day_number) % 7
20487 from_now += 7 unless from_now > 0
20488 ago += 7 unless ago > 0
20489 other.change(hour: hour, min: min, sec: sec, nsec: try(:nsec))
20490 short: "%d %b",
20491 long: "%B %d, %Y",
20492 db: "%Y-%m-%d",
20493 inspect: "%Y-%m-%d",
20494 number: "%Y%m%d",
20495 date.strftime("%B #{day_format}, %Y") # => "April 25th, 2007"
20496 rfc822: "%d %b %Y",
20497 strftime("%a, %d %b %Y")
20498 ::Time.zone ? ::Time.zone.today : ::Date.today
20499 d = self
20500 d = d >> options[:years] * 12 if options[:years]
20501 d = d >> options[:months] if options[:months]
20502 d = d + options[:weeks] * 7 if options[:weeks]
20503 d = d + options[:days] if options[:days]
20504 ::Date.new(
20505 if other.is_a?(Time)
20506 class Date # :nodoc:
20507 k.singleton_class? || k == self
20508 class_methods, methods = [], []
20509 unless name.is_a?(Symbol) || name.is_a?(String)
20510 defined?(@#{name}) ? @#{name} : self.class.#{name}
20511 class_methods << <<~RUBY
20512 attr_writer :#{name}
20513 class_methods << "silence_redefinition_of_method def #{name}?; !!self.#{name}; end"
20514 methods << "silence_redefinition_of_method def #{name}?; !!self.#{name}; end"
20515 class_eval(["class << self", *class_methods, "end", *methods].join(";").tr("
", ";"), location.path, location.lineno)
20516 attrs.each { |name| public_send("#{name}=", default) }
20517 def to_s(format = "F")
20518 object.to_ary || [object]
20519 if number.to_i <= 0
20520 padding = (number - size % number) % number
20521 start = 0
20522 length = division + (modulo > 0 && modulo > index ? 1 : 0)
20523 last_group << fill_with if fill_with != false &&
20524 modulo > 0 && length == division
20525 def split(value = nil, &block)
20526 arr = dup
20527 while (idx = arr.index(&block))
20528 while (idx = arr.index(value))
20529 result << arr
20530 def to_sentence(options = {})
20531 words_connector: ", ",
20532 two_words_connector: " and ",
20533 last_word_connector: ", and "
20534 if options[:locale] != false && defined?(I18n)
20535 +""
20536 +"#{self[0]}"
20537 +"#{self[0]}#{options[:two_words_connector]}#{self[1]}"
20538 +"#{self[0...-1].join(options[:words_connector])}#{options[:last_word_connector]}#{self[-1]}"
20539 collect(&:id).join(",")
20540 if first.class != Hash && all?(first.class)
20541 attributes = options[:skip_types] ? {} : { type: "array" }
20542 self[position, length] || []
20543 if position >= 0
20544 self[-3]
20545 self[-2]
20546 Dir.glob(File.expand_path("core_ext/*.rb", __dir__)).sort.each do |path|
20547 YAML.unsafe_load(source, **options) || {}
20548 YAML.load(source, **options) || {}
20549 erb = ERB.new(@content).tap { |e| e.filename = @content_path }
20550 keys.reject { |m| method_defined?(m) }.each do |key|
20551 def #{key}; _get(#{key.inspect}); end
20552 @_config ||= if respond_to?(:superclass) && superclass.respond_to?(:config)
20553 reader, reader_line = "def #{name}; config.#{name}; end", __LINE__
20554 writer, writer_line = "def #{name}=(value); config.#{name} = value; end", __LINE__
20555 send("#{name}=", block_given? ? yield : default)
20556 @_config = nil
20557 def raw_state # :nodoc:
20558 data[thread] = {
20559 @cv = new_cond
20560 @sharing = Hash.new(0)
20561 @waiting = {}
20562 @sleeping = {}
20563 @sharing.size > (@sharing[Thread.current] > 0 ? 1 : 0)
20564 @waiting.any? { |t, (_, c)| t != Thread.current && !c.include?(purpose) }
20565 @waiting.any? { |t, (p, _)| compatible.include?(p) && @waiting.all? { |t2, (_, c2)| t == t2 || c2.include?(p) } }
20566 mon_try_enter ||
20567 @owner = nil
20568 @count -= 1
20569 @sources = []
20570 @methods = {}
20571 as = as.to_sym
20572 @methods[name] = as
20573 @cache.module_eval("# frozen_string_literal: true
" + @sources.join(";"), path, line)
20574 @line = line
20575 @namespaces = Hash.new { |h, k| h[k] = MethodSet.new(k) }
20576 method_set.apply(@owner, @path, @line - 1)
20577 env.value = !env.halted && (!block_given? || yield)
20578 (skipped ||= []) << current
20579 if !halted && user_conditions.all? { |c| c.call(target, value) }
20580 if user_conditions.all? { |c| c.call(target, value) }
20581 if: @if.dup,
20582 @kind == _kind && filter == _filter
20583 Array(chain_config[:scope]).map { |s| public_send(s) }
20584 @if.map { |c| CallTemplate.build(c, self).make_lambda } +
20585 @before = []
20586 @after = []
20587 arg.halted || !@user_conditions.all? { |c| c.call(arg.target, arg.value) }
20588 @before.each { |b| b.call(arg) }
20589 @after.each { |a| a.call(arg) }
20590 scope: [:kind],
20591 }.merge!(config)
20592 @chain = []
20593 @single_callbacks = {}
20594 def each(&block); @chain.each(&block); end
20595 callbacks.each { |c| append_one(c) }
20596 callbacks.each { |c| prepend_one(c) }
20597 @chain.delete_if { |c| callback.duplicates?(c) }
20598 callback = chain.find { |c| c.matches?(type, filter) }
20599 if callback && (options.key?(:if) || options.key?(:unless))
20600 callbacks.each { |c| chain.delete(c) }
20601 @app = nil
20602 [400, {}, []]
20603 @data = {}
20604 @data[key]
20605 @data[key] = entry
20606 !!@data.delete(key)
20607 def fetch_entry(key) # :nodoc:
20608 @data.fetch(key) { @data[key] = yield }
20609 def clear(options = nil) # :nodoc:
20610 def cleanup(options = nil) # :nodoc:
20611 def increment(name, amount = 1, options = nil) # :nodoc:
20612 def decrement(name, amount = 1, options = nil) # :nodoc:
20613 hit = true
20614 def delete_entry(key, **)
20615 @local_cache_key ||= "#{self.class.name.underscore}_local_cache_#{object_id}".gsub(/[\/-]/, "_").to_sym
20616 gem "redis", ">= 4.0.1"
20617 warn "The Redis cache store requires the redis gem, version 4.0.1 or later. Please add it to your Gemfile: `gem \"redis\", \">= 4.0.1\"`"
20618 def build_redis(redis: nil, url: nil, **redis_options) # :nodoc:
20619 if redis.is_a?(Proc)
20620 urls.each { |u| dist.add_node url: u }
20621 @redis ||= begin
20622 cursor = "0"
20623 nodes = c.respond_to?(:nodes) ? c.nodes : [c]
20624 end until cursor == "0"
20625 redis.then { |c| c.flushdb }
20626 redis.then { |c| c.info }
20627 redis.then { |c| c.pipelined(&block) }
20628 redis.then { |c| c.get(key) }
20629 return {} if names == []
20630 raw = options&.fetch(:raw, false)
20631 keys = names.map { |name| normalize_key(name, options) }
20632 redis.then { |c| c.mget(*keys) }
20633 names.zip(values).each_with_object({}) do |(name, value), results|
20634 if race_condition_ttl && expires_in && expires_in > 0 && !raw
20635 modifiers = {}
20636 modifiers[:px] = (1000 * expires_in.to_f).ceil if expires_in
20637 redis.then { |c| c.set key, payload, **modifiers }
20638 redis.then { |c| c.del key }
20639 redis.then { |c| c.del(entries) }
20640 if raw && !payload.nil?
20641 super(entry, raw: raw, **options)
20642 c = c.node_for(key) if c.is_a?(Redis::Distributed)
20643 pipeline.call(:expire, key, options[:expires_in].to_i, "NX")
20644 if count != amount && options[:expires_in] && c.ttl(key) < 0
20645 redis_version = redis.then { |c| c.info("server").fetch("redis_version") }
20646 @supports_expire_nx = Gem::Version.new(redis_version) >= Gem::Version.new("7.0.0")
20647 def read_entry(key, **s)
20648 def write_entry(key, entry, **)
20649 @max_size = options[:size] || 32.megabytes
20650 @max_prune_time = options[:max_prune_time] || 2
20651 @cache_size = 0
20652 keys = synchronize { @data.keys }
20653 entry = @data[key]
20654 @data[key] = payload
20655 prune(@max_size * 0.75, @max_prune_time) if @cache_size > @max_size
20656 @data.with { |c| c.incr(normalize_key(name, options), amount, options[:expires_in], amount) }
20657 @data.with { |c| c.decr(normalize_key(name, options), amount, options[:expires_in], 0) }
20658 rescue_error_with(nil) { @data.with { |c| c.flush_all } }
20659 @data.with { |c| c.stats }
20660 def [](version)
20661 @data.with { |c| c.get(key, options) }
20662 method = options[:unless_exist] ? :add : :set
20663 if options[:race_condition_ttl] && expires_in > 0 && !options[:raw]
20664 @data.with { |c| c.send(method, key, payload, expires_in, **options) }
20665 raw_values = @data.with { |c| c.get_multi(keys_to_names.keys) }
20666 rescue_error_with(false) { @data.with { |c| c.delete(key) } }
20667 key = key.gsub(ESCAPE_KEY_CHARS) { |match| "%#{match.getbyte(0).to_s(16).upcase}" }
20668 key_separator = ":hash:"
20669 key = "#{key[0, key_trim_size]}#{key_separator}#{key_hash}"
20670 FileUtils.rm_r(root_dirs.collect { |f| File.join(cache_path, f) })
20671 File.atomic_write(key, cache_path) { |f| f.write(payload) }
20672 File.open(file_name, "r+") do |f|
20673 fname_paths = []
20674 Dir.each_child(dir) do |d|
20675 name = File.join(dir, d)
20676 num = num.to_i + amount
20677 expanded_cache_key = namespace ? +"#{namespace}/" : +""
20678 expanded_cache_key << "#{prefix}/"
20679 raise "Could not find cache store adapter for #{store} (#{e})"
20680 unless options.key?(:pool) || options.key?(:pool_size) || options.key?(:pool_timeout)
20681 {}.tap do |pool_options|
20682 Use `pool: { size: #{options[:pool_size].inspect} }` instead.
20683 Use `pool: { timeout: #{options[:pool_timeout].inspect} }` instead.
20684 @coder = @options.delete(:coder) { default_coder } || NullCoder
20685 entries = hash.each_with_object({}) do |(name, value), memo|
20686 reads = {}
20687 reads.fetch(name) { writes[name] = yield(name) }
20688 names.map! { |key| normalize_key(key, options) }
20689 def new_entry(value, options = nil) # :nodoc:
20690 if source.start_with?("^")
20691 source = ".*#{source[0, source.length]}"
20692 entries.count { |key| delete_entry(key, **options) }
20693 alias_key = aliases.detect { |key| options.key?(key) }
20694 if key && key.encoding != Encoding::UTF_8
20695 if key.size > 1
20696 key.collect { |k, v| "#{k}=#{v}" }.sort!
20697 (options && options[:version].try(:to_param)) || expanded_version(key)
20698 if logger && logger.debug? && !silence?
20699 logger.debug "Cache #{operation}: #{normalize_key(key, options)}#{options.blank? ? "" : " (#{options.inspect})"}"
20700 payload = { key: key, store: self.class.name }
20701 if (race_ttl > 0) && (Time.now.to_f - entry.expires_at <= race_ttl)
20702 @created_at = 0.0
20703 @expires_in = expires_at&.to_f || expires_in && (expires_in.to_f + Time.now.to_f)
20704 @version && version && @version != version
20705 @expires_in && @created_at + @expires_in <= Time.now.to_f
20706 @expires_in ? @created_at + @expires_in : nil
20707 @expires_in = value.to_f - @created_at
20708 @s ||= Marshal.dump(@value).bytesize
20709 if @value && !compressed? && !(@value.is_a?(Numeric) || @value == true || @value == false)
20710 if @value.is_a?(String)
20711 @value = @value.dup
20712 options[:level] ||= :info
20713 ms = Benchmark.ms { result = options[:silence] ? logger.silence(&block) : yield }
20714 logger.public_send(options[:level], "%s (%.1fms)" % [ message, ms ])
20715 @filters, @silencers = [], []
20716 @silencers = []
20717 @filters = []
20718 gems_paths = (Gem.path | [Gem.default_dir]).map { |p| Regexp.escape(p) }
20719 gems_regexp = %r{\A(#{gems_paths.join('|')})/(bundler/)?gems/([^/]+)-([\w.]+)/(.*)}
20720 gems_result = '\3 (\4) \5'
20721 @filters.each do |f|
20722 backtrace = backtrace.map { |line| f.call(line.to_s) }
20723 @silencers.any? do |s|
20724 name.end_with?("?") || super
20725 if name.end_with?("?")
20726 any?(name[0..-2])
20727 when ActionableError, -> it { Class === it && it < ActionableError }
20728 ActiveStorage::Current.url_options = { protocol: "https://", host: "example.com", port: nil }
20729 queries = []
20730 queries << payload[:sql] if %w[ SCHEMA TRANSACTION ].exclude?(payload[:name]) && (matcher.nil? || payload[:sql].match(matcher))
20731 assert_dom_equal %(<video src="#{polymorphic_url @blob}" />), video_tag(@blob)
20732 @user = User.create!(name: "DHH")
20733 assert_dom_equal %(<img src="#{polymorphic_url @blob}" />), image_tag(@blob)
20734 assert_dom_equal %(<img src="#{polymorphic_url variant}" />), image_tag(variant)
20735 assert_dom_equal %(<img src="#{polymorphic_url preview}" />), image_tag(preview)
20736 assert_dom_equal %(<audio src="#{polymorphic_url @blob}" />), audio_tag(@blob)
20737 expected_chunks = [ "a" * 5.megabytes, "b" ]
20738 actual_chunks = []
20739 @service.delete_prefixed("#{key}/a/a/")
20740 assert_not @service.exist?("#{key}/a/a/a")
20741 assert_not @service.exist?("#{key}/a/a/b")
20742 assert @service.exist?("#{key}/a/b/a")
20743 @service.delete("#{key}/a/a/a")
20744 @service.delete("#{key}/a/a/b")
20745 @service.delete("#{key}/a/b/a")
20746 data = %w(To get her)
20747 Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
20748 user = User.create! name: "DHH", avatar: blob
20749 custom_metadata: { "foo" => "baz" },
20750 assert_match(/s3(-[-a-z0-9]+)?\.(\S+)?amazonaws\.com\/#{@key}/, url)
20751 assert_match(/#{@service.bucket.name}\/#{@key}/, url)
20752 mirror_config = (1..3).to_h do |i|
20753 [ "mirror_#{i}",
20754 service: "Disk",
20755 headers.each do |k, v|
20756 assert_match(/storage\.googleapis\.com\/.*\/#{@key}/, url)
20757 tmp_config = { tmp: { service: "Disk", root: File.join(Dir.tmpdir, "active_storage") } }
20758 assert_match(/^https:\/\/example.com\/rails\/active_storage\/disk\/.*$/,
20759 assert_match(/^https:\/\/example.com\/rails\/active_storage\/disk\/.*\/avatar\.png$/,
20760 assert_match(/^http:\/\/example.com:3001\/rails\/active_storage\/disk\/.*\/avatar\.png$/,
20761 @service.root = tmp_config.dig(:tmp, :root)
20762 tmp_config = {
20763 assert_match(/^https:\/\/example.com\/rails\/active_storage\/disk\/.*\/avatar\.png/, url)
20764 data = "Foobar"
20765 assert_equal("baz", response["x-ms-meta-foo"])
20766 assert_match(/.*\.blob\.core\.windows\.net\/.*\/#{@key}/, url)
20767 user = User.create!(name: "Josh")
20768 variant_b = blob.variant("resize_to_limit" => [100, 100])
20769 mock_upload = lambda do |_, _, options = {}|
20770 blob.variant(resize: [123, "-write", "/tmp/file.erb"]).processed
20771 blob.variant(resize: [123, ["-write", "/tmp/file.erb"], "/tmp/file.erb"]).processed
20772 blob.variant(resize: [123, { "-write /tmp/file.erb": "something" }, "/tmp/file.erb"]).processed
20773 blob.variant(saver: { "-write": "/tmp/file.erb" }).processed
20774 blob.variant(saver: { "something": { "-write": "/tmp/file.erb" } }).processed
20775 blob.variant(saver: { "something": ["-write", "/tmp/file.erb"] }).processed
20776 a = Admin.new(name: "DHH")
20777 [ create_blob(filename: "funky.jpg"), create_blob(filename: "town.jpg") ].tap do |blobs|
20778 data = "First file"
20779 data = "Hello world!"
20780 assert_match(/^[a-z0-9]{28}$/, create_blob.key)
20781 name: "Nate",
20782 avatar: {
20783 assert_match(/^[a-z0-9]{28}$/, build_blob_after_unfurling.key)
20784 blobs = 3.times.map { create_blob(data: "123", filename: "numbers.txt", content_type: "text/plain", identify: false) }
20785 blobs = 3.times.map { create_blob(data: "123", filename: "numbers.txt", content_type: "text/plain", identify: false).dup }
20786 test "image?" do
20787 test "video?" do
20788 test "text?" do
20789 chunks = []
20790 create_blob(data: "Hello, world!").tap do |blob|
20791 assert_match(/\.jpg\z/, file.path)
20792 arguments = [
20793 kwargs = {
20794 custom_metadata: { "test" => true }
20795 blob.update!(metadata: { custom: { "test" => true } })
20796 includes_values.any? { |values| values[:variant_records] == { image_attachment: :blob } },
20797 @user = User.create!(name: "Josh")
20798 track_transaction_depth = ->(*) do
20799 hash = { io: StringIO.new("STUFF"), filename: "town.jpg", content_type: "image/jpeg" }
20800 @io ||= StringIO.new("")
20801 @user.name = "Tina"
20802 user = User.new(name: "John")
20803 group = Group.create!(users_attributes: [{ name: "John", avatar: { io: StringIO.new("STUFF"), filename: "town.jpg", content_type: "image/jpeg" } }])
20804 new_user = User.find_by(name: "John")
20805 group = Group.create!(users: [@user])
20806 User.new(name: "Jason").tap do |user|
20807 assert_changes -> { @user.updated_at } do
20808 { io: StringIO.new("STUFF"), filename: "funky.jpg", content_type: "image/jpeg" },
20809 { io: StringIO.new("THINGS"), filename: "town.jpg", content_type: "image/jpeg" })
20810 user = User.create!(name: "John") do |user|
20811 [ create_blob(filename: "funky.jpg"), create_blob(filename: "town.jpg") ].tap do |old_blobs|
20812 @user.highlights = []
20813 @user.vlogs = []
20814 @user.highlights = [""]
20815 @user.highlights = [ "", fixture_file_upload("racecar.jpg") ]
20816 [ create_blob(filename: "funky.mp4"), create_blob(filename: "town.mp4") ].tap do |blobs|
20817 @user.update! vlogs: []
20818 user = User.create!(name: "Jason", highlights: [ create_blob(filename: "funky.jpg"), create_blob(filename: "town.jpg") ])
20819 user = User.create!(name: "Jason", highlights: [
20820 ].tap do |blobs|
20821 user.highlights = []
20822 @connection.columns(table).find { |c| c.name == "id" }
20823 setup { @blob = create_blob }
20824 user = users(:first)
20825 :passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn
20826 config.log_tags = [ :request_id ]
20827 $LOAD_PATH.unshift File.expand_path("../../../lib", __dir__)
20828 get blob.url, headers: { "Range" => "bytes=5-9" }
20829 get blob.url, headers: { "Range" => "bytes=1000-1000" }
20830 params: "Something else entirely!", headers: { "Content-Type" => "text/plain" }
20831 assert_match(/s3(-[-a-z0-9]+)?\.(\S+)?amazonaws\.com/, details["direct_upload"]["url"])
20832 assert_match %r{#{@config[:storage_account_name]}\.blob\.core\.windows\.net/#{@config[:container]}}, details["direct_upload"]["url"]
20833 assert_equal({ "Content-Type" => "text/plain" }, details["direct_upload"]["headers"])
20834 get rails_storage_proxy_url(create_file_blob(filename: "racecar.jpg")), headers: { "Range" => "bytes=5-9" }
20835 get rails_storage_proxy_url(create_file_blob(filename: "racecar.jpg")), headers: { "Range" => "bytes=*/1234" }
20836 get rails_storage_proxy_url(create_file_blob(filename: "racecar.jpg")), headers: { "Range" => "bytes=5-9,13-17" }
20837 ].join("\r
"),
20838 blob = create_blob(data: "bad", filename: "bad_file.bad", content_type: "image/bad_type")
20839 def process(file, format:) # :doc:
20840 Please add `gem 'image_processing', '~> 1.2'` to your Gemfile.
20841 loader(page: 0).
20842 if name.to_s == "combine_options"
20843 list << [ name, argument ]
20844 method_name = name.to_s.tr("-", "_")
20845 if arg.is_a?(Integer) || arg.is_a?(Float)
20846 elsif arg.is_a?(String) || arg.is_a?(Symbol)
20847 if value.is_a?(Integer) || value.is_a?(Float)
20848 elsif value.is_a?(String) || value.is_a?(Symbol)
20849 gem "aws-sdk-s3", "~> 1.48"
20850 @client = Aws::S3::Resource.new(**options)
20851 ) do |out|
20852 metadata.transform_keys { |key| "x-amz-meta-#{key}" }
20853 @services = {}
20854 [ primary, *mirrors ].each(&block)
20855 gem "google-cloud-storage", "~> 1.11"
20856 def url_for_direct_upload(key, expires_in:, checksum:, custom_metadata: {}, **)
20857 version = :v2
20858 version = :v4
20859 args = {
20860 if @config[:iam]
20861 query: {
20862 def public_url(key, **)
20863 @client ||= Google::Cloud::Storage.new(**config.except(:bucket, :cache_control, :iam, :gsa_email))
20864 @issuer ||= if @config[:gsa_email]
20865 http = Net::HTTP.new(uri.host, uri.port)
20866 metadata.transform_keys { |key| "x-goog-meta-#{key}" }
20867 def upload(key, io, checksum: nil, **)
20868 File.open(path_for(key), "rb") do |file|
20869 Dir.glob(path_for("#{prefix}*")).each do |path|
20870 key: key,
20871 { "Content-Type" => content_type }
20872 def path_for(key) # :nodoc:
20873 [ key[0..1], key[2..3] ].join("/")
20874 gem "azure-storage-blob", ">= 2.0"
20875 _, io = client.get_blob(container, key)
20876 uri_for(key), false,
20877 service: "b",
20878 ).tap do |blob|
20879 client.generate_uri("#{container}/#{key}")
20880 blob = blob_for(key)
20881 metadata.transform_keys { |key| "x-ms-meta-#{key}" }
20882 def open(*args, **options, &block)
20883 def url(key, **options)
20884 disposition = (type.to_s.presence_in(%w( attachment inline )) || "inline")
20885 @variants ||= {}
20886 @ffmpeg_exists = system(ffmpeg_path, "-version", out: File::NULL, err: File::NULL)
20887 @pdftoppm_exists = system(pdftoppm_path, "-v", out: File::NULL, err: File::NULL)
20888 draw self.class.pdftoppm_path, "-singlefile", "-cropbox", "-r", "72", "-png", file.path, &block
20889 @mutool_exists = $?.exitstatus == 1
20890 draw self.class.mutool_path, "draw", "-F", "png", "-o", "-", file.path, "1", &block
20891 @blob = blob
20892 def draw(*argv) # :doc:
20893 def capture(*argv, to:)
20894 IO.popen(argv, err: err) { |out| IO.copy_stream(out, to) }
20895 raise PreviewError, "#{argv.first} failed (status #{$?.exitstatus}): #{err.read.to_s.chomp}"
20896 def logger # :doc:
20897 def tmpdir # :doc:
20898 message = "Uploaded file to key: #{key_in(event)}"
20899 info event, color("Deleted file from key: #{key_in(event)}", RED)
20900 debug event, color("Checked if file exists at key: #{key_in(event)} (#{event.payload[:exist] ? "yes" : "no"})", BLUE)
20901 debug event, color("Generated URL for file at key: #{key_in(event)} (#{event.payload[:url]})", BLUE)
20902 message = "Mirrored file at key: #{key_in(event)}"
20903 record.public_send("#{name}")
20904 generated_association_methods.class_eval <<-CODE, __FILE__, __LINE__ + 1
20905 def #{name}
20906 @active_storage_attached ||= {}
20907 @active_storage_attached[:#{name}] ||= ActiveStorage::Attached::One.new("#{name}", self)
20908 attachment_changes["#{name}"] =
20909 scope :"with_attached_#{name}", -> { includes("#{name}_attachment": :blob) }
20910 @active_storage_attached[:#{name}] ||= ActiveStorage::Attached::Many.new("#{name}", self)
20911 scope :"with_attached_#{name}", -> {
20912 includes("#{name}_attachments": { blob: { variant_records: { image_attachment: :blob } } })
20913 @attachment_changes ||= {}
20914 def initialize_dup(*) # :nodoc:
20915 def reload(*) # :nodoc:
20916 @name, @record = name, record
20917 record.public_send("#{name}_attachments=", [])
20918 @blob ||= find_or_build_blob
20919 record.public_send("#{name}_blob=", blob)
20920 if record.public_send("#{name}_blob") == blob
20921 elsif side_data && side_data[0] && side_data[0]["rotation"]
20922 if terms = descriptor.split(":", 2)
20923 angle == 90 || angle == 270 || angle == -90 || angle == -270
20924 @tags ||= video_stream["tags"] || {}
20925 @side_data ||= video_stream["side_data_list"] || {}
20926 @video_stream ||= streams.detect { |stream| stream["codec_type"] == "video" } || {}
20927 @audio_stream ||= streams.detect { |stream| stream["codec_type"] == "audio" } || {}
20928 probe["streams"] || []
20929 probe["format"] || {}
20930 @probe ||= download_blob_to_tempfile { |file| probe_from(file) }
20931 ]) do |output|
20932 return {}
20933 rescue ::Vips::Error => error
20934 t.index [ :key ], unique: true
20935 delegate :key, :url, :download, to: :image, allow_nil: true
20936 @record =
20937 def as_json(*)
20938 format || :png
20939 self[:metadata][:custom] || {}
20940 def unfurl(io, identify: true) # :nodoc:
20941 scope :with_all_variant_records, -> { includes(blob: { variant_records: { image_attachment: :blob } }) }
20942 response.headers["Content-Range"] = "bytes #{range.begin}-#{range.end}/#{blob.byte_size}"
20943 data = +""
20944 data << "\r
--#{boundary}\r
"
20945 data << "Content-Type: #{blob.content_type_for_serving}\r
"
20946 data << "Content-Range: bytes #{range.begin}-#{range.end}/#{blob.byte_size}\r
\r
"
20947 data << chunk
20948 data << "\r
--#{boundary}--\r
"
20949 delegate :keys, :key?, :has_key?, :empty?, to: :@parameters
20950 @config ||= read_config
20951 dbs = [["arunit", "activerecord_unittest"], ["arunit2", "activerecord_unittest2"],
20952 connection[name] = { "database" => connection[name] }
20953 types.any? do |type|
20954 !conn.mariadb? && conn.database_version >= "8.0.13"
20955 conn.mariadb? && conn.database_version >= "10.2.1"
20956 %w[
20957 ].each do |method_name|
20958 t.integer :random_number, default: -> { "random()" }
20959 t.column :char1, "char(1)", default: "Y"
20960 t.text :char3, limit: 50, default: "a text field"
20961 create_table :"1_need_quoting", force: true do |t|
20962 t.string :json_data_empty, null: true, default: "", limit: 1024
20963 create_table :books, id: :integer, force: true do |t|
20964 default_zero = { default: 0 }
20965 t.index [:author_id, :name], unique: true
20966 t.column :name, :string, default: "<untitled>"
20967 create_table :bulbs, primary_key: "ID", force: true do |t|
20968 create_table :old_cars, id: :integer, force: true do |t|
20969 create_table :carts, force: true, primary_key: [:shop_id, :id] do |t|
20970 create_table :cpk_books, primary_key: [:author_id, :number], force: true do |t|
20971 create_table :cpk_orders, primary_key: [:shop_id, :id], force: true do |t|
20972 t.index [:name, :rating], order: :desc
20973 t.index [:firm_id, :type, :rating], name: "company_index", length: { type: 10 }, order: { rating: :desc }
20974 t.index [:firm_id, :type], name: "company_partial_index", where: "(rating > 10)"
20975 create_table :edges, force: true, id: false do |t|
20976 t.index [:source_id, :sink_id], unique: true, name: "unique_edge_index"
20977 (1..8).each do |i|
20978 t.integer :"c_int_#{i}", limit: i
20979 create_table :pets, primary_key: :pet_id, force: true do |t|
20980 t.index [:author_name, :title]
20981 create_table :toys, primary_key: :toy_id, force: true do |t|
20982 [:circles, :squares, :triangles, :non_poly_ones, :non_poly_twos].each do |t|
20983 create_table(t, force: true) { }
20984 t.string "a$b"
20985 create_table :fk_test_has_pk, primary_key: "pk_id", force: :cascade do |t|
20986 t.foreign_key :fk_test_has_pk, column: "fk_id", name: "fk_name", primary_key: "pk_id"
20987 uuid_default = connection.supports_pgcrypto_uuid? ? {} : { default: "uuid_generate_v4()" }
20988 create_table :uuid_parents, id: :uuid, force: true, **uuid_default do |t|
20989 t.date :modified_date_function, default: -> { "now()" }
20990 t.datetime :modified_time_function, default: -> { "now()" }
20991 t.bigint :bigint_default, default: -> { "0::bigint" }
20992 t.text :multiline_default, default: "--- []
20993 t.oid :obj_id
20994 execute "SELECT setval('#{seq_name}', 100)"
20995 $$
20996 t.index [:logdate, :city_id], unique: true
20997 add_index(:companies, [:firm_id, :type], name: "company_include_index", include: [:name, :account_id])
20998 fixed_date date default to_date('2004-01-01', 'YYYY-MM-DD'),
20999 t.binary :uuid, limit: 36, default: -> { "(uuid())" }
21000 t.text :tiny_text_2, size: :tiny
21001 t.text :long_text_2, size: :long
21002 default_scope -> { where(published: true) }
21003 class_name: "Vertex", join_table: "edges",
21004 class_name: "Job",
21005 has_one :family_tree, -> { where(token: nil) }, foreign_key: "member_id"
21006 scope :with_pet, -> { joins(:pet) }
21007 scope :base, -> { all }
21008 where "written_on < ?", time
21009 scope :approved, -> { where(approved: true) }
21010 scope :rejected, -> { where(approved: false) }
21011 scope :true, -> { where(approved: true) }
21012 scope :false, -> { where(approved: false) }
21013 scope :children, -> { where.not(parent_id: nil) }
21014 scope :has_children, -> { where(id: Topic.children.select(:parent_id)) }
21015 scope :by_lifo, -> { where(author_name: "lifo") }
21016 scope :replied, -> { where "replies_count > 0" }
21017 scope "approved_as_string", -> { where(approved: true) }
21018 scope :anonymous_extension, -> { } do
21019 scope :scope_stats, -> stats { stats[:count] = count; self }
21020 }.new(self)
21021 has_many :open_replies, -> { open }, class_name: "Reply", foreign_key: "parent_id"
21022 default_scope -> { where(approved: false) }
21023 belongs_to :tag, -> { includes(:tagging) }
21024 belongs_to :blue_tag, -> { where tags: { name: "Blue" } }, class_name: "Tag", foreign_key: :tag_id
21025 has_many :ordered_taggings, -> { order("taggings.id DESC") }, foreign_key: "tag_id", class_name: "Tagging"
21026 validates :name, presence: true, if: -> { true }
21027 scope :ordered, -> { Reply.order(:id) }
21028 if attribute_present?("title") && attribute_present?("content") && content == "Mismatch"
21029 errors.add(:title, "is Wrong Create") if attribute_present?("title") && title == "Wrong Create"
21030 errors.add(:title, "is Wrong Update") if attribute_present?("title") && title == "Wrong Update"
21031 belongs_to :first_post, -> { where(id: [2, 3]) }
21032 default_scope -> { where(skimmer: true) }
21033 scope :skimmers_or_not, -> { unscope(where: :skimmer) }
21034 has_many :taggings_without_tag, -> { left_joins(:tag).where("tags.id": [nil, 0]) }, as: :taggable, class_name: "Tagging"
21035 has_many :taggings_with_no_tag, -> { joins("LEFT OUTER JOIN tags ON tags.id = taggings.tag_id").where("tags.id": nil) }, as: :taggable, class_name: "Tagging"
21036 has_and_belongs_to_many :developers_named_david, -> { where("name = 'David'").distinct }, class_name: "Developer"
21037 has_and_belongs_to_many :salaried_developers, -> { where "salary > 0" }, class_name: "Developer"
21038 has_and_belongs_to_many :developers_with_callbacks, class_name: "Developer", before_add: Proc.new { |o, r| o.developers_log << "before_adding#{r.id || '<new>'}" },
21039 after_add: Proc.new { |o, r| o.developers_log << "after_adding#{r.id || '<new>'}" },
21040 before_remove: Proc.new { |o, r| o.developers_log << "before_removing#{r.id}" },
21041 after_remove: Proc.new { |o, r| o.developers_log << "after_removing#{r.id}" }
21042 @developers_log = []
21043 scope :all_as_scope, -> { all }
21044 super + " :)"
21045 scope :containing_the_letter_a, -> { where("body LIKE '%a%'") }
21046 scope :titled_with_an_apostrophe, -> { where("title LIKE '%''%'") }
21047 scope :ordered_by_post_id, -> { order("posts.post_id ASC") }
21048 scope :limit_by, lambda { |l| limit(l) }
21049 scope :locked, -> { lock }
21050 .group("posts.id")
21051 .having("count(comments.id) >= #{comments_count}")
21052 belongs_to :author_with_posts, -> { includes(:posts) }, class_name: "Author", foreign_key: :author_id
21053 belongs_to :author_with_select, -> { select(:id) }, class_name: "Author", foreign_key: :author_id
21054 belongs_to :author_with_the_letter_a, -> { where("name LIKE '%a%'") }, class_name: "Author", foreign_key: :author_id
21055 has_one :first_comment, -> { order("id ASC") }, class_name: "Comment"
21056 has_one :last_comment, -> { order("id desc") }, class_name: "Comment"
21057 scope :no_comments, -> { left_joins(:comments).where(comments: { id: nil }) }
21058 scope :with_post, ->(post_id) { joins(:comments).where(comments: { post_id: post_id }) }
21059 scope :with_comments, -> { preload(:comments) }
21060 scope :with_tags, -> { preload(:taggings) }
21061 scope :with_tags_cte, -> { with(posts_with_tags: where("tags_count > 0")).from("posts_with_tags AS posts") }
21062 scope :tagged_with, ->(id) { joins(:taggings).where(taggings: { tag_id: id }) }
21063 has_many :nonexistent_comments, -> { where "comments.id < 0" }, class_name: "Comment"
21064 .to_a
21065 has_many :misc_tags, -> { where tags: { name: "Misc" } }, through: :taggings, source: :tag
21066 has_many :first_taggings, -> { where taggings: { comment: "first" } }, as: :taggable, class_name: "Tagging"
21067 has_many :first_blue_tags, -> { where tags: { name: "Blue" } }, through: :first_taggings, source: :tag
21068 has_many :first_blue_tags_2, -> { where taggings: { comment: "first" } }, through: :taggings, source: :blue_tag
21069 has_many :invalid_taggings, -> { where "taggings.id < 0" }, as: :taggable, class_name: "Tagging"
21070 has_many :readers_with_person, -> { includes(:person) }, class_name: "Reader"
21071 has_many :skimmers, -> { where skimmer: true }, class_name: "Reader"
21072 has_many :lazy_readers_skimmers_or_not, -> { where(skimmer: [ true, false ]) }, class_name: "LazyReader"
21073 @log = []
21074 def self.log(message = nil, side = nil, new_record = nil)
21075 @log << [message, side, new_record]
21076 default_scope { where(id: 1) }
21077 has_many :taggings, -> { rewhere(taggable_type: "TaggedPost") }, as: :taggable
21078 default_scope { where(id: [1, 5, 6]) }
21079 scope :unscoped_all, -> { unscoped { all } }
21080 scope :authorless, -> { unscoped { where(author_id: 0) } }
21081 { "name" => nil }
21082 has_and_belongs_to_many :parrots, -> { order("parrots.id ASC") }, validate: true
21083 before_add: proc { |p, pa| p.ship_log << "before_adding_proc_parrot_#{pa.id || '<new>'}" },
21084 after_add: proc { |p, pa| p.ship_log << "after_adding_proc_parrot_#{pa.id || '<new>'}" },
21085 before_remove: proc { |p, pa| p.ship_log << "before_removing_proc_parrot_#{pa.id}" },
21086 after_remove: proc { |p, pa| p.ship_log << "after_removing_proc_parrot_#{pa.id}" }
21087 def build(attributes = {})
21088 has_many :birds, -> { order("birds.id ASC") }
21089 before_add: proc { |p, b| p.ship_log << "before_adding_proc_bird_#{b.id || '<new>'}" },
21090 after_add: proc { |p, b| p.ship_log << "after_adding_proc_bird_#{b.id || '<new>'}" },
21091 before_remove: proc { |p, b| p.ship_log << "before_removing_proc_bird_#{b.id}" },
21092 after_remove: proc { |p, b| p.ship_log << "after_removing_proc_bird_#{b.id}" }
21093 has_one :foo_bulb, -> { where name: "foo" }, foreign_key: :car_id, class_name: "Bulb"
21094 @ship_log ||= []
21095 ship_log << "#{callback}_#{record.class.name.downcase}_#{record.id || '<new>'}"
21096 has_one :ship_with_annotation, -> { annotate("that is a rocket") }, class_name: :Ship, foreign_key: :pirate_id
21097 has_many :first_posts, -> { where(id: [1, 2]) }, through: :readers
21098 (1 << INSURES.index(insure)) & mask.to_i > 0
21099 numbers.inject(0) { |sum, n| sum + (1 << n) }
21100 enum breed: { african: 0, australian: 1 }
21101 has_many :pets, -> { order "pets.name desc" }
21102 scope :including_last_pet, -> {
21103 owners.*, (
21104 ) as last_pet_id
21105 @blocks ||= []
21106 @blocks = []
21107 scope :clubs, -> { from("clubs") }
21108 belongs_to :member, -> { order("members.id DESC") }
21109 select("'1' as foo")
21110 default_scope -> {
21111 has_one :favorite_club, -> { where "memberships.favorite = ?", true }, through: :membership, source: :club
21112 has_one :hairy_club, -> { where clubs: { name: "Moustache and Eyebrow Fancier Club" } }, through: :membership, source: :club
21113 scope :with_member_type_id, -> (id) { where(member_type_id: id) }
21114 has_many :molecules, -> { distinct }
21115 has_many :shipping_lines, -> { from("shipping_lines") }, autosave: true
21116 class_name: "Human",
21117 has_many :family_trees, -> { where(token: nil) }
21118 (@after_create_callbacks_stack ||= []) << !iris.persisted?
21119 (@after_update_callbacks_stack ||= []) << iris.has_changes_to_save?
21120 (@after_save_callbacks_stack ||= []) << iris.has_changes_to_save?
21121 delegated_type :thing, types: %w[ Post ],
21122 has_many :comments, ->(developer) { where(body: "I'm #{developer.name}") }
21123 scope :jamises, -> { where(name: "Jamis") }
21124 default_scope { select("name") }
21125 default_scope -> { where(mentor_id: 1) }
21126 default_scope -> { where(mentor_id: 1) }, all_queries: true
21127 default_scope -> { where(firm_id: firm_id) if firm_id }, all_queries: true
21128 included { default_scope { where(mentor_id: 1) } }
21129 scope :by_name, -> { order("name DESC") }
21130 default_scope { where("name = 'David'") }
21131 default_scope { where(name: "David") }
21132 where(name: "David")
21133 scope :david, -> { where(name: "David") }
21134 default_scope { where(name: "Jamis") }
21135 scope :poor, -> { where("salary < 150000") }
21136 scope :david, -> { where name: "David" }
21137 scope :david2, -> { unscoped.where name: "David" }
21138 default_scope -> { where(name: "Jamis", salary: 50000) }
21139 default_scope -> { where(salary: 50000) }
21140 default_scope -> { where(name: "Jamis") }
21141 self.ignored_columns += ["name"]
21142 other.is_a?(self.class) && other.street == street && other.city == city && other.country == country
21143 if str.is_a?(Hash)
21144 new(str[:first], str[:last])
21145 new(*str.to_s.split)
21146 @first, @last = first, last
21147 self.primary_key = [:shop_id, :id]
21148 self.primary_key = [:author_id, :number]
21149 @hi_count ||= 0
21150 @hi_count += 1
21151 @bye_count ||= 0
21152 @bye_count += 1
21153 self.metadata = { code: company_id && "%08x" % company_id, company_id: company_id, developer_id: developer_id }
21154 @destroyed_ids ||= []
21155 @destroy_count += 1
21156 if @destroy_count == 1
21157 table_name => "id"
21158 def column(name, sql_type = nil, options = {})
21159 has_many :clients, -> { order("id") }, dependent: :destroy
21160 has_many :clients_sorted_desc, -> { order("id DESC") }, class_name: "Client"
21161 has_many :clients_of_firm, -> { order "id" }, foreign_key: "client_of", class_name: "Client"
21162 has_many :clients_like_ms, -> { where("name = 'Microsoft'").order("id") }, class_name: "Client"
21163 has_many :clients_sorted_desc, -> { order "id DESC" }, class_name: "Client"
21164 has_many :clients_of_firm, -> { order "id" }, foreign_key: "client_of", class_name: "Client", inverse_of: :firm
21165 has_many :clients_ordered_by_name, -> { order "name" }, class_name: "Client"
21166 has_many :dependent_clients_of_firm, -> { order "id" }, foreign_key: "client_of", class_name: "Client", dependent: :destroy
21167 has_many :limited_clients, -> { limit 1 }, class_name: "Client"
21168 has_many :clients_like_ms_with_hash_conditions, -> { where(name: "Microsoft").order("id") }, class_name: "Client"
21169 has_many :clients_grouped_by_firm_id, -> { group("firm_id").select("firm_id") }, class_name: "Client"
21170 has_many :clients_grouped_by_name, -> { group("name").select("name") }, class_name: "Client"
21171 has_one :account_with_select, -> { select("id, firm_id") }, foreign_key: "firm_id", class_name: "Account"
21172 has_one :readonly_account, -> { readonly }, foreign_key: "firm_id", class_name: "Account"
21173 has_one :account_using_primary_key, -> { order("id") }, primary_key: "firm_id", class_name: "Account"
21174 has_many :developers_with_select, -> { select("id, name, first_name") }, class_name: "Developer"
21175 @log ||= []
21176 log << "before_remove#{record.id}"
21177 log << "after_remove#{record.id}"
21178 has_one :account, -> { order(:id) }, foreign_key: "firm_id", dependent: :nullify
21179 has_one :account, -> { order("id") }, foreign_key: "firm_id", dependent: :restrict_with_exception
21180 has_many :companies, -> { order("id") }, foreign_key: "client_of", dependent: :restrict_with_exception
21181 has_one :account, -> { order("id") }, foreign_key: "firm_id", dependent: :restrict_with_error
21182 has_many :companies, -> { order("id") }, foreign_key: "client_of", dependent: :restrict_with_error
21183 belongs_to :firm_with_select, -> { select("id") }, class_name: "Firm", foreign_key: "firm_id"
21184 belongs_to :firm_with_condition, -> { where "1 = ?", 1 }, class_name: "Firm", foreign_key: "client_of"
21185 belongs_to :readonly_firm, -> { readonly }, class_name: "Firm", foreign_key: "firm_id"
21186 belongs_to :bob_firm, -> { where name: "Bob" }, class_name: "Firm", foreign_key: "client_of"
21187 @destroyed_client_ids ||= Hash.new { |h, k| h[k] = [] }
21188 has_many :dependent_conditional_clients_of_firm, -> { order("id").where("name = ?", "BigShot Inc.") }, foreign_key: "client_of", class_name: "Client", dependent: :delete_all
21189 self[:extra_size] = 50
21190 scope :containing_the_letter_e, -> { where("comments.body LIKE '%e%'") }
21191 scope :not_again, -> { where("comments.body NOT LIKE '%again%'") }
21192 scope :for_first_post, -> { where(post_id: 1) }
21193 scope :for_first_author, -> { joins(:post).where("posts.author_id" => 1) }
21194 scope :created, -> { all }
21195 scope :ordered_by_post_id, -> { order("comments.post_id DESC") }
21196 enum label: [:default, :child]
21197 update(body: "bar")
21198 assoc.has_many :students, -> { where(active: true) }
21199 has_many :favorites, -> { where(memberships: { favorite: true }) }, through: :memberships, source: :member
21200 scope :general, -> { left_joins(:category).where(categories: { name: "General" }).unscope(:limit) }
21201 -> { select "posts.*, 1 as correctness_marker" },
21202 class_name: "Post",
21203 -> { where title: "Yet Another Testing Title" },
21204 has_and_belongs_to_many :posts_grouped_by_title, -> { group("title").select("title") }, class_name: "Post"
21205 has_many :ordered_post_comments, -> { order(id: :desc) }, through: :posts, source: :comments
21206 has_many :human_writers_of_typed_essays, -> { where(essays: { type: TypedEssay.name }) }, through: :essays, source: :writer, source_type: "Human", primary_key: :name
21207 scope :general, -> { where(name: "General") }
21208 enum gender: [:female, :male]
21209 has_many :all_bulbs, -> { unscope(where: :name) }, class_name: "Bulb"
21210 has_many :all_bulbs2, -> { unscope(:where) }, class_name: "Bulb"
21211 has_many :other_bulbs, -> { unscope(where: :name).where(name: "other") }, class_name: "Bulb"
21212 has_many :old_bulbs, -> { rewhere(name: "old") }, class_name: "Bulb"
21213 has_many :foo_bulbs, -> { where(name: "foo") }, class_name: "Bulb"
21214 has_many :awesome_bulbs, -> { awesome }, class_name: "Bulb"
21215 scope :incl_tyres, -> { includes(:tyres) }
21216 scope :incl_engines, -> { includes(:engines) }
21217 attribute :wheels_owned_at, :datetime, default: -> { Time.now }
21218 default_scope { order("name desc") }
21219 scope :awesome, -> { where(frickinawesome: true) }
21220 self[:color] = color.upcase + "!"
21221 def self.new(attributes = {}, &block)
21222 bulb_type = (attributes || {}).delete(:bulb_type)
21223 has_many :tags, -> { where name: "Der be rum" }, through: :taggings, dependent: :destroy_async
21224 enum last_read: { unread: 0, reading: 2, read: 3, forgotten: nil }
21225 enum language: [:english, :spanish, :french], _prefix: :in
21226 enum font_size: [:small, :medium, :large], _prefix: :with, _suffix: true
21227 enum difficulty: [:easy, :medium, :hard], _suffix: :to_read
21228 enum cover: { hard: "hard", soft: "soft" }
21229 enum :cover, { hard: "0", soft: "1" }, default: :hard
21230 has_many :posts_with_comments, -> { includes(:comments) }, class_name: "Post"
21231 has_many :popular_grouped_posts, -> { includes(:comments).group("type").having("SUM(legacy_comments_count) > 1").select("type") }, class_name: "Post"
21232 has_many :posts_sorted_by_id, -> { order(:id) }, class_name: "Post"
21233 has_many :posts_sorted_by_id_limited, -> { order("posts.id").limit(1) }, class_name: "Post"
21234 -> { order(id: :desc) },
21235 -> { where("ratings.value > 5").order(:id) },
21236 has_many :comments_with_include, -> { includes(:post).where(posts: { type: "Post" }) }, through: :posts, source: :comments
21237 has_one :comment_on_first_post, -> { order("posts.id desc, comments.id asc") }, through: :first_post, source: :comments
21238 has_many :thinking_posts, -> { where(title: "So I was thinking") }, dependent: :delete_all, class_name: "Post"
21239 has_many :welcome_posts, -> { where(title: "Welcome to the weblog") }, class_name: "Post"
21240 -> { where(title: "Welcome to the weblog").where(comments_count: 1) },
21241 -> { where(title: "Welcome to the weblog").where("legacy_comments_count > 0") },
21242 has_many :comments_desc, -> { order("comments.id DESC") }, through: :posts_sorted_by_id, source: :comments
21243 has_many :hello_posts, -> { where "posts.body = 'hello'" }, class_name: "Post"
21244 has_many :posts_with_no_comments, -> { where("comments.id" => nil).includes(:comments) }, class_name: "Post"
21245 has_many :posts_with_no_comments_2, -> { left_joins(:comments).where("comments.id": nil) }, class_name: "Post"
21246 has_many :hello_posts_with_hash_conditions, -> { where(body: "hello") }, class_name: "Post"
21247 before_add: Proc.new { |o, r| o.post_log << "before_adding#{r.id || '<new>'}" },
21248 after_add: Proc.new { |o, r| o.post_log << "after_adding#{r.id || '<new>'}" },
21249 before_remove: Proc.new { |o, r| o.post_log << "before_removing#{r.id}" },
21250 after_remove: Proc.new { |o, r| o.post_log << "after_removing#{r.id}" }
21251 before_add: [:log_before_adding, Proc.new { |o, r| o.post_log << "before_adding_proc#{r.id || '<new>'}" }],
21252 has_many :categorizations, -> { }
21253 has_many :favorite_authors, -> { order("name") }, through: :author_favorites
21254 has_many :similar_posts, -> { distinct }, through: :tags, source: :tagged_posts
21255 has_many :distinct_tags, -> { select("DISTINCT tags.*").order("tags.name") }, through: :posts, source: :tags
21256 has_many :unpublished_books, -> { where(status: [:proposed, :written]) }, class_name: "Book"
21257 has_many :misc_posts, -> { where(posts: { title: ["misc post by bob", "misc post by mary"] }) }, class_name: "Post"
21258 has_many :misc_post_first_blue_tags_2, -> { where(posts: { title: ["misc post by bob", "misc post by mary"] }) },
21259 has_many :posts_with_signature, ->(record) { where(arel_table[:title].matches("%by #{record.name.downcase}%")) }, class_name: "Post"
21260 has_many :posts_mentioning_author, ->(record = nil) { where(arel_table[:body].matches("%#{record&.name&.downcase}%")) }, class_name: "Post"
21261 has_one :recent_post, -> { order(id: :desc) }, class_name: "Post"
21262 has_many :posts_with_extension, -> { order(:title) }, class_name: "Post" do
21263 has_many :posts_with_extension_and_instance, ->(record) { order(:title) }, class_name: "Post" do
21264 has_many :top_posts, -> { order(id: :asc) }, class_name: "Post"
21265 has_many :other_top_posts, -> { order(id: :asc) }, class_name: "Post"
21266 has_many :topics_without_type, -> { select(:id, :title, :author_name) },
21267 @post_log = []
21268 @post_log << "before_adding#{object.id || '<new>'}"
21269 @post_log << "after_adding#{object.id}"
21270 @post_log << "before_removing#{object.id}"
21271 @post_log << "after_removing#{object.id}"
21272 @destroyed_author_address_ids ||= []
21273 default_scope { order(id: :asc) }
21274 store :params, accessors: [ :token ], coder: JSON
21275 read_store_attribute(:settings, :phone_number).gsub(/(\d{3})(\d{3})(\d{4})/, '(\1) \2-\3')
21276 write_store_attribute(:settings, :phone_number, value && value.gsub(/[^\d]/, ""))
21277 super || "red"
21278 store :params, accessors: [ :token ], coder: YAML
21279 @destroyed_account_ids ||= Hash.new { |h, k| h[k] = [] }
21280 scope :open, -> { where("firm_name = ?", "37signals") }
21281 scope :available, -> { open }
21282 create_table("things") do |t|
21283 topic = Topic.new(content: { "omg" => "lol" })
21284 assert_equal({ "omg" => "lol" }, yaml_load(YAML.dump(topic)).content)
21285 topic = Topic.new(parent_id: "123")
21286 .group("authors.id")
21287 coder = {}
21288 author.name = "Sean"
21289 self.primary_key = "id"
21290 create_view "ebooks'", <<~SQL
21291 assert_equal [books(:rfr).id], books.map(&:id)
21292 assert_equal ["Ruby for Rails"], books.map(&:name)
21293 assert_equal([["id", :integer],
21294 ["name", :string],
21295 ["cover", :string],
21296 ["status", :integer]], Ebook.columns.map { |c| [c.name, c.type] })
21297 assert_equal({ "id" => 2, "name" => "Ruby for Rails", "cover" => "hard", "status" => 0 },
21298 assert_equal([["name", :string],
21299 ["status", :integer]], Paperback.columns.map { |c| [c.name, c.type] })
21300 assert_equal({ "name" => "Agile Web Development with Rails", "status" => 2 },
21301 r.title = "Bad"
21302 r.content = "Good"
21303 r = WrongReply.new(title: "Valid title", author_name: "secret", content: "Good")
21304 WrongReply.create!([ { "title" => "OK" }, { "title" => "Wrong Create" }])
21305 WrongReply.create!("title" => "OK") do |r|
21306 WrongReply.create!([{ "title" => "OK" }, { "title" => "Wrong Create" }]) do |r|
21307 d = Developer.new("name" => "David", "salary" => "100,000")
21308 topic = klass.create("approved" => true)
21309 topic.wibble.gsub!("-", "")
21310 ["97.179", 97.179, BigDecimal("97.179")].each do |raw_value|
21311 ["97.174", 97.174, BigDecimal("97.174")].each do |raw_value|
21312 update!(author_name: "#{title} #{id}")
21313 topic = Topic.new(new_title: "abc")
21314 t = Topic.new("title" => nil)
21315 t2 = Topic.new("title" => nil)
21316 Topic.create!("title" => "abc")
21317 t2 = Topic.new("title" => "abc")
21318 t = Topic.new("title" => "new
line")
21319 t = Topic.create("title" => "I'm unique!")
21320 r1 = t.replies.create "title" => "r1", "content" => "hello world"
21321 r2 = t.replies.create "title" => "r2", "content" => "hello world"
21322 t2 = Topic.create("title" => "I'm unique too!")
21323 r3 = t2.replies.create "title" => "r3", "content" => "hello world"
21324 t = Topic.create(title: "I'm unique!")
21325 r1 = t.replies.create(title: "r1", content: "hello world")
21326 r2 = t.replies.create(title: "r2", content: "hello world")
21327 r3 = t2.replies.create(title: "r3", content: "hello world")
21328 a = Author.create(name: "Sergey")
21329 e1 = a.essays.create(name: "Essay")
21330 e2 = p.essays.create(name: "Essay")
21331 r1 = ReplyWithTitleObject.create "title" => "r1", "content" => "hello world"
21332 r2 = ReplyWithTitleObject.create "title" => "r1", "content" => "hello world"
21333 t = Topic.create("title" => "What, me worry?")
21334 r1 = t.unique_replies.create "title" => "r1", "content" => "a barrel of fun"
21335 r2 = t.silly_unique_replies.create "title" => "r2", "content" => "a barrel of fun"
21336 r3 = t.replies.create "title" => "r2", "content" => "a barrel of fun"
21337 t = Topic.create("title" => "The earth is actually flat!")
21338 r1 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy@rubyonrails.com", "title" => "You're joking!", "content" => "Silly reply"
21339 r2 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy@rubyonrails.com", "title" => "You're joking!", "content" => "Silly reply again..."
21340 r3 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy_alt_email@rubyonrails.com", "title" => "You're wrong", "content" => "It's cubic"
21341 r3.author_name = "jj"
21342 t = Topic.new("title" => "I'm unique!", :parent_id => 2)
21343 t2 = Topic.new("title" => "I'm UNIQUE!", :parent_id => 1)
21344 t2.parent_id = 4
21345 t = Topic.new("title" => "I'm unique!")
21346 t2 = Topic.new("title" => "I'm %")
21347 t3 = Topic.new("title" => "I'm uniqu_!")
21348 t3 = Topic.new("title" => "I'M uNiQUe!")
21349 Topic.create!("title" => 101)
21350 t2 = Topic.new("title" => 101)
21351 t1 = Topic.new("title" => "I'm unique!", "author_name" => "Mary")
21352 t2 = Topic.new("title" => "I'm unique!", "author_name" => "David")
21353 g = Guid.new
21354 g.key = "foo"
21355 w3 = Conjurer.new(name: "Rincewind", city: "Quirm")
21356 Topic.create("title" => "I'm a topic", "approved" => true)
21357 Topic.create("title" => "I'm an unapproved topic", "approved" => false)
21358 t3 = Topic.new("title" => "I'm a topic", "approved" => true)
21359 t4 = Topic.new("title" => "I'm an unapproved topic", "approved" => false)
21360 abc = klass.create!(dashboard_id: "abc")
21361 t = Topic.new("title" => "This is a unique title")
21362 t.id += 1
21363 t = Topic.new(title: "abc")
21364 t = Topic.create!(title: "abc")
21365 t.author_name = "John"
21366 t.title = "abc v2"
21367 t = Topic.create!(title: "abc", author_name: "John")
21368 t.author_name = "Amy"
21369 e1 = Event.create!(title: "abc")
21370 e2 = Event.create!(title: "cde")
21371 t.event = e2
21372 b = Boy.new
21373 b.name = "Alex"
21374 f = Face.new
21375 b.face = f
21376 b.interests << [i1 = Interest.new, i2 = Interest.new]
21377 def dash.to_a; ["(/)", '(\)']; end
21378 if 123.455.to_d(5) == BigDecimal("123.46")
21379 ["99.994", 99.994, BigDecimal("99.994")].each do |raw_value|
21380 ["99.999", 99.999, BigDecimal("99.999")].each do |raw_value|
21381 o = @owner.new("name" => "nopets")
21382 o.pets.build("name" => "apet")
21383 2.times { o.pets.build("name" => "apet") }
21384 assert_not owner.update pets_attributes: [ { _destroy: 1, id: pet.id } ]
21385 pet = Pet.create!(name: "Fancy Pants", nickname: "Fancy")
21386 pet.nickname = ""
21387 I18n.backend.store_translations("en", errors: { messages: { custom: nil } })
21388 @unique ||= Topic.create title: "unique!"
21389 I18n.backend.store_translations "en", activerecord: { errors: { models: { topic: { attributes: { replies: { invalid: "custom message" } } } } } }
21390 I18n.backend.store_translations "en", errors: { attributes: { title: { taken: "Custom taken message" } } }
21391 I18n.backend.store_translations "en", activerecord: { errors: { models: { topic: { taken: "Custom taken message" } } } }
21392 I18n.backend.store_translations "en", activerecord: { errors: { models: { topic: { attributes: { title: { taken: "Custom taken message" } } } } } }
21393 I18n.backend.store_translations "en", activerecord: { errors: { models: { topic: { attributes: { title: { taken: "custom en message" } } } } } }
21394 t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
21395 r.content = r3.content = "non-empty"
21396 r = Reply.new("title" => "A reply", "content" => "with content!")
21397 r.topic = Topic.create("title" => "uhohuhoh")
21398 t = Topic.new
21399 r = Reply.create("title" => "A reply", "content" => "with content!")
21400 human = Human.new(name: "John")
21401 human = Human.create!(name: "John")
21402 boy.interests << [i1 = Interest.new, i2 = Interest.new]
21403 def face_with_to_a.to_a; ["(/)", '(\)']; end
21404 ids = Post.order("title").pluck(:id)
21405 ids = Post.order(:title).pluck(:id)
21406 ids_expected = Post.order(Arel.sql("title") => Arel.sql("asc")).pluck(:id)
21407 ids = Post.order(title: :asc).pluck(:id)
21408 ids_expected = Post.order(Arel.sql("title") => Arel.sql("ASC")).pluck(:id)
21409 ids = Post.order(title: :ASC).pluck(:id)
21410 ids = Post.order(title: "asc").pluck(:id)
21411 ids_expected = Post.order(Arel.sql("author_id"), Arel.sql("title")).pluck(:id)
21412 ids = Post.order(:author_id, :title).pluck(:id)
21413 ids_expected = Post.order(Arel.sql("author_id"), Arel.sql("title") => Arel.sql("asc")).pluck(:id)
21414 ids = Post.order(:author_id, title: :asc).pluck(:id)
21415 ids = Post.order("posts.title").pluck(:id)
21416 ids = Post.order("title desc").pluck(:id)
21417 ["asc", "desc", ""].each do |direction|
21418 ids = Post.order("type::text #{direction} nulls #{position}").pluck(:id)
21419 Post.order("REPLACE(title, 'misc', 'zzzz') asc").pluck(:id)
21420 Post.order("REPLACE(title, 'misc', 'zzzz')" => :asc).pluck(:id)
21421 ids_expected = Post.order(Arel.sql("REPLACE(title, 'misc', 'zzzz'), id")).pluck(:id)
21422 ids = Post.order([Arel.sql("REPLACE(title, ?, ?), id"), "misc", "zzzz"]).pluck(:id)
21423 Post.order(["REPLACE(title, ?, ?), id", "misc", "zzzz"]).pluck(:id)
21424 Post.order(["author_id", "REPLACE(title, 'misc', 'zzzz')"]).pluck(:id)
21425 ids = Post.order(["author_id", "length(title)"]).pluck(:id)
21426 ids = Post.order(["author_id", %Q'title COLLATE "#{collation_name}" DESC']).pluck(:id)
21427 ids = Post.order("author_id, length(trim(title))").pluck(:id)
21428 Post.order("REPLACE(title, 'misc', 'zzzz')")
21429 values_expected = Post.pluck(Arel.sql("title"), Arel.sql("id"))
21430 values = Post.pluck(:title, :id)
21431 Post.pluck("REPLACE(title, 'misc', 'zzzz')")
21432 Post.pluck(:title, "REPLACE(title, 'misc', 'zzzz')")
21433 Post.includes(:comments).pluck(:title, "REPLACE(title, 'misc', 'zzzz')")
21434 model.foo = "foo"
21435 model.foo = "bar"
21436 assert_equal "string", mapping.fetch(1) { "int" }
21437 assert_equal "int", mapping.fetch(2) { "int" }
21438 string = +""
21439 if type.include?("(")
21440 mapping.register_type("foo") { |*args| args.join("-") }
21441 assert_equal "foo-1-2-3", mapping.fetch("foo", 1, 2, 3) { |*args| args.join("-") }
21442 assert_equal "foo-2-3-4", mapping.fetch("foo", 2, 3, 4) { |*args| args.join("-") }
21443 assert_equal "bar-1-2-3", mapping.fetch("bar", 1, 2, 3) { |*args| args.join("-") }
21444 expected_time = ::Time.utc(2000, 1, 1, 10, 30, 0)
21445 topic = Topic.new(bonus_time: { 4 => 10, 5 => 30 })
21446 value = type.cast("1999-12-31T12:34:56.789-10:00")
21447 author = klass.create!(name: "Sean")
21448 author.name << " Griffin"
21449 firm = Firm.create(name: "Apple")
21450 model.foo = 1
21451 p = Task.create!(starting: ::Time.now)
21452 value = type.cast("1999-12-31 12:34:56.789 -1000")
21453 [*args, "block for foo"]
21454 [*args, "block for bar"]
21455 assert_equal [:foo, 1, "block for foo"], registry.lookup(:foo, 1)
21456 assert_equal [:foo, 2, "block for foo"], registry.lookup(:foo, 2)
21457 assert_equal [:bar, 1, 2, 3, "block for bar"], registry.lookup(:bar, 1, 2, 3)
21458 def ==(other) self.args == other.args end
21459 @first, @second = Topic.find(1, 2).sort_by(&:id)
21460 title_change = ["The Fifth Topic of the day", "Ruby on Rails"]
21461 title_change = [nil, "Ruby on Rails"]
21462 author = Author.new(name: "DHH")
21463 num = nil
21464 status = author.update(name: nil, post_ids: [])
21465 author.update!(name: nil, post_ids: [])
21466 topic = Class.new(Topic) {
21467 new_topic = topic.new(title: "A new topic",
21468 author_name: "Ben",
21469 last_read: "2004-04-15",
21470 bonus_time: "2005-01-30t15:28:00.00+01:00",
21471 topic_one = Topic.new(title: "A new topic")
21472 @first.content = "One"
21473 @first.content = "Two"
21474 @first.content = "Four"
21475 Topic.connection.stub(:commit_db_transaction, -> { raise("OH NOES") }) do
21476 topic = Topic.new(title: "test")
21477 topic_1 = Topic.new(title: "test_1")
21478 topic_2 = Topic.new(title: "test_2")
21479 movie = Movie.new(name: "foo")
21480 movie = Movie.create!(name: "foo")
21481 assert_no_difference(-> { klass.count }) do
21482 meta = class << topic; self; end
21483 @first = Topic.find(1)
21484 threads = (1..3).map do
21485 tag = Tag.create(name: "jon")
21486 @before_commit ||= {}
21487 @before_commit[on] ||= []
21488 @after_commit ||= {}
21489 @after_commit[on] ||= []
21490 @after_commit[on] << block
21491 @after_rollback ||= {}
21492 @after_rollback[on] ||= []
21493 blocks.each { |b| b.call(self) } if blocks
21494 @first.after_commit_block { |r| r.history << :after_commit }
21495 def @first.valid?(*)
21496 record.after_commit_block(:save) { |r| r.history << :after_save }
21497 new_record.after_commit_block(:create) { |r| r.save! }
21498 r.content = "bar"
21499 def @first.rollbacks(i = 0); @rollbacks ||= 0; @rollbacks += i if i; end
21500 def @first.commits(i = 0); @commits ||= 0; @commits += i if i; end
21501 @first.after_rollback_block { |r| r.rollbacks(1) }
21502 @first.after_commit_block { |r| r.commits(1) }
21503 def second.rollbacks(i = 0); @rollbacks ||= 0; @rollbacks += i if i; end
21504 def second.commits(i = 0); @commits ||= 0; @commits += i if i; end
21505 second.after_commit_block { |r| r.commits(1) }
21506 first = klass.new(title: "foo")
21507 callbacks = []
21508 define_method(:object_id) { 42 }
21509 record.after_commit_block { |r| r.history << :after_commit }
21510 after_commit(if: opts, on: :create) { }
21511 record.after_commit_block(:create) { |r| r.history << :commit_on_create }
21512 record.after_commit_block(:update) { |r| r.history << :commit_on_update }
21513 after_commit(on: [:create, :destroy]) { |record| record.history << :create_and_destroy }
21514 after_commit(on: [:create, :update]) { |record| record.history << :create_and_update }
21515 after_commit(on: [:update, :destroy]) { |record| record.history << :update_and_destroy }
21516 @@history = []
21517 @@history ||= []
21518 after_commit(on: [:create, :update], if: :run_callback?) { |record| record.history << :create_or_update }
21519 if model != ActiveRecord::Base && !old
21520 time = Time.now.utc - 25.days
21521 time = (Time.now.utc - 25.days).change(nsec: 0)
21522 time = Time.now.utc - 2.days
21523 owner.update pets_attributes: { "0" => { id: "1", name: "Alfred" } }
21524 class User < ::User
21525 { updated_at: updated_at }
21526 @user = User.create!(password_digest: "$2a$4$#{"x" * 22}#{"y" * 31}")
21527 User.find_by_token_for!(:lookup, "bad")
21528 new_time = Time.utc(2015, 2, 16, 0, 0, 0)
21529 now = Time.now.change(usec: 0)
21530 new_time = Time.utc(2015, 2, 16, 4, 54, 0)
21531 validate { errors.add(:base, :invalid) }
21532 def self.name; "Pet"; end
21533 pet.name = "I'm a parrot"
21534 def self.name; "Toy"; end
21535 pet = toy.pet
21536 toy1 = klass.find(1)
21537 toy2 = klass.find(2)
21538 def self.name; "Car"; end
21539 car = car_class.find(1)
21540 toy = toy_class.find(3)
21541 toy = klass.find(1)
21542 toy.pet = nil
21543 foo = Foo.new(start: time, finish: time)
21544 time = ::Time.now.change(nsec: 123)
21545 time = ::Time.utc(2000, 1, 1, 12, 30, 0, 999999)
21546 assert_match %r{t\.time\s+"start",\s+precision: 4$}, output
21547 assert_match %r{t\.time\s+"finish",\s+precision: 6$}, output
21548 assert_match %r{t\.time\s+"start",\s+precision: 0$}, output
21549 assert_match %r{t\.time\s+"finish",\s+precision: 0$}, output
21550 File.write(File.join(tmp_dir, "zines.yml"), <<~YML)
21551 idx = 42
21552 failed_patterns = []
21553 def assert_queries(num = 1, options = {}, &block)
21554 ignore_none = options.fetch(:ignore_none) { num == :any }
21555 if num == :any
21556 mesg = "#{the_log.size} instead of #{num} queries were executed.#{the_log.size == 0 ? '' : "
Queries:
#{the_log.join("
")}"}"
21557 def assert_no_queries(options = {}, &block)
21558 old_callbacks = {}
21559 if cfg.has_key?(:zone)
21560 Time.zone = cfg[:zone]
21561 $stderr.puts <<-MSG
21562
#{self}
21563 Got: #{Time.zone}
21564 def clear_log; self.log = []; self.log_all = []; end
21565 sql = values[:sql]
21566 3,
21567 times: 6,
21568 env => {
21569 primary: {
21570 [:primary, :secondary].each do |db|
21571 define_method("test_#{k}_create") do
21572 assert_called(eval("@#{v}"), :create) do
21573 f.puts "This is a cache."
21574 path = "#{dir}/fake_db_config_schema.rb"
21575 @configurations = { "development" => { "database" => "my-db" } }
21576 @configurations["development"]["host"] = "127.0.0.1"
21577 [config_for("test", "primary")]
21578 [config_for("development", "primary")],
21579 [config_for("test", "primary")],
21580 [config_for("test", "secondary")]
21581 [config_for("production", "primary")],
21582 define_method("test_#{k}_drop") do
21583 assert_called(eval("@#{v}"), :drop) do
21584 @configurations = { development: { "database" => "my-db" } }
21585 @configurations[:development]["host"] = "127.0.0.1"
21586 :drop,
21587 backup = SQLite3::Backup.new(dest_db, "main", source_db, "main")
21588 define_method("test_#{k}_purge") do
21589 assert_called(eval("@#{v}"), :purge) do
21590 configurations = { development: { "database" => "my-db" } }
21591 assert_called(eval("@#{v}"), :charset) do
21592 assert_called(eval("@#{v}"), :collation) do
21593 eval("@#{v}"), :structure_dump,
21594 ["awesome-file.sql", nil]
21595 eval("@#{v}"),
21596 { ruby: "schema.rb", sql: "structure.sql" }.each_pair do |fmt, filename|
21597 user = User.create! token: "asdf"
21598 user.token = "uiop"
21599 firm = Firm.create!(name: "NASA")
21600 proc { dev.ship }
21601 ].each do |block|
21602 @john = Admin::User.create!(
21603 name: "John Doe", color: "black", remember_login: true,
21604 height: "tall", is_a_good_guy: true,
21605 @john.color = "red"
21606 user.color = "red"
21607 @john.settings = { color: @john.color, some: "thing" }
21608 @john.color = "black"
21609 @john.spouse[:name] = "Lena"
21610 @john.phone_number = "(123) 456-7890"
21611 @john.color = "yellow"
21612 @john.height = "low"
21613 user = Admin::User.find_by_name("Jamis")
21614 user.update(settings: { "color" => { "jenny" => "blue" }, homepage: "rails" })
21615 user.height = "low"
21616 assert_equal false, @john.json_data.delete_if { |k, v| k == "height" }.any?
21617 @john.height = "short"
21618 @john.weight = "heavy"
21619 assert_equal({}, @john.params)
21620 sql = Book.where(author_id: 96, cover: "hard").to_sql
21621 b = cache.execute([ "my book" ], Book.connection)
21622 assert_equal "my book", b[0].name
21623 b = cache.execute([ "my other book" ], Book.connection)
21624 b1 = Book.create(name: "my book")
21625 b2 = Book.create(name: "my other book")
21626 b = cache.execute([ b1.id ], Book.connection)
21627 b = cache.execute([ b2.id ], Book.connection)
21628 a = Book.find_or_create_by(name: "my book")
21629 b = Book.find_or_create_by(name: "my other book")
21630 Book.where(name: "my book").where("author_id > 3")
21631 Book.create(name: "my book", author_id: 4)
21632 book = Book.find_by(name: "my book")
21633 @toy = Toy.first
21634 [200, {}, ["body"]]
21635 }, ->(*) { :shard_one })
21636 }, ->(*) { :shard_one }, { lock: false })
21637 }, ->(*) { "shard_one" })
21638 myobj = MyObject.new("value1", "value2")
21639 topic = Topic.create("content" => myobj)
21640 serialize(:content, type: Hash, default: { key: "value" })
21641 t = klass.new
21642 assert_equal({ key: "value" }, t.content)
21643 attribute :content, default: { key: "value" }
21644 hash = { "content1" => "value1", "content2" => "value2" }
21645 t = ImportantTopic.new(content: { foo: :bar })
21646 assert_equal({ foo: :bar }, t.content)
21647 orig = Topic.new(content: { foo: :bar })
21648 t = Topic.find(id)
21649 hash = { "important1" => "value1", "important2" => "value2" }
21650 myobj = Time.local(2008, 1, 1, 1, 0)
21651 myobj = "Yes"
21652 settings = { "color" => "blue" }
21653 settings = [ "color" => "green" ]
21654 settings = { "color" => "green" }
21655 insures = ["life"]
21656 topic = Topic.create!(content: { zomg: true })
21657 expected = "can't load `content`: was supposed to be a Array, but was a Hash. -- {:zomg=>true}"
21658 topic = Topic.create(content: { "things" => "stuff" })
21659 topic = Topic.create!(content: {})
21660 topic = Topic.create!(content: { foo: "bar" })
21661 !new.nil?
21662 topic = klass.create!(content: { trial: true })
21663 assert_equal({ "trial" => true }, topic.content)
21664 value + " encoded"
21665 value.gsub(" encoded", "")
21666 value.gsub(" serialized", "")
21667 topic = model.create!(foo: "bar")
21668 attribute :content, default: { "key" => "value" }
21669 assert_equal({ "key" => "value" }, t.content)
21670 topic = Topic.create!(content: { "foo" => "bar" })
21671 serialize(:content, type: Hash, default: { "key" => "value" })
21672 t = ImportantTopic.new(content: { "foo" => "bar" })
21673 assert_equal({ "foo" => "bar" }, t.content)
21674 myobj = { "somevalue" => "thevalue" }
21675 topic = Topic.create!(content: { "zomg" => true })
21676 expected = "can't load `content`: was supposed to be a Array, but was a Hash. -- {\"zomg\"=>true}"
21677 name: "aaron stack",
21678 age: 25,
21679 created_at: Time.utc(2006, 8, 1),
21680 preferences: { "gem" => "<strong>ruby</strong>" },
21681 @serialized = Contact.new(@contact_attributes).public_send("to_#{format}", only: [ :age, :name ])
21682 @serialized = Contact.new(@contact_attributes).public_send("to_#{format}", except: [ :age, :name ])
21683 @user = User.new
21684 assert_called_with(params, :to_h, [], returns: { token: @user.token, password: @user.password }) do
21685 assert_called_with(params, :to_h, [], returns: { token: "wrong", password: @user.password }) do
21686 assert_equal [1, 5, 6], ids.sort
21687 assert_sql(%r{/\* scoped \*/}) do
21688 assert_predicate log.select { |query| query.match?(%r{/\* scoped \*/}) }, :empty?
21689 where("name = 'David'").
21690 assert_predicate log.select { |query| query.match?(%r{/\* unscope \*/}) }, :empty?
21691 Developer.where("projects.id" => 2).to_a
21692 assert_match "(salary = 80000)", sql
21693 @welcome = Post.find(1)
21694 assert_equal Topic.all.to_a, Topic.base.map { |i| i }
21695 scope :since, Proc.new { where("written_on >= ?", Time.now - 1.day) }
21696 stats = {}
21697 Class.new(Post).class_eval { scope :containing_the_letter_z, where("body LIKE '%z%'") }
21698 conflicts = [
21699 :to_ary,
21700 :to_sql,
21701 Class.new(Post).class_eval { scope name, -> { where(approved: true) } }
21702 scope = Topic.where("content LIKE '%Have%'")
21703 topics.any? { true }
21704 topics.many? { true }
21705 klass.class_eval { scope name, -> { where(approved: true) } }
21706 subklass.class_eval { scope name, -> { where(approved: true) } }
21707 scope :"title containing space", ->(space: " ") { where("title LIKE '%#{space}%'") }
21708 assert_equal klass.where("title LIKE '% %'"), klass.public_send(:"title containing space", space: " ")
21709 assert_sql(/COUNT/i) { topics.size }
21710 relation = Topic.where("1=1")
21711 post = Post.find(1)
21712 group.each { |t| assert t.approved? }
21713 one = assert_queries(1) { post.comments.limit_by(1).to_a }
21714 two = assert_queries(1) { post.comments.limit_by(2).to_a }
21715 [:destroy_all, :reset, :delete_all].each do |method|
21716 assert_sql(%r{/\* from-scope \*/}) do
21717 create_sql = capture_sql { klass.create!(name: "Steve") }.first
21718 update_sql = capture_sql { dev.update!(name: "Not Eileen") }.first
21719 update_sql = capture_sql { dev.update!(name: "Not Nikita") }.first
21720 reload_sql = capture_sql { dev.reload({ unscoped: true }) }.first
21721 expected = Developer.order("name DESC, id DESC").collect { |dev| [dev.name, dev.id] }
21722 received = Developer.order("name ASC").reorder("name DESC").order("id DESC").collect { |dev| [dev.name, dev.id] }
21723 expected = Developer.all.collect { |dev| [dev.name, dev.id] }
21724 expected = Developer.order("id DESC, name DESC").collect { |dev| [dev.name, dev.id] }
21725 expected_2 = Developer.all.collect { |dev| [dev.name, dev.id] }
21726 received_2 = Developer.order("id DESC, name DESC").unscope(:order).collect { |dev| [dev.name, dev.id] }
21727 expected_3 = Developer.all.collect { |dev| [dev.name, dev.id] }
21728 received_3 = Developer.reorder("name DESC").unscope(:order).collect { |dev| [dev.name, dev.id] }
21729 received_2 = DeveloperOrderedBySalary.select("id").where("name" => "Jamis").unscope({ where: :name }, :select).collect(&:name)
21730 scope :by_name, -> name { unscope(where: :name).where(name: name) }
21731 expected = developer_klass.where(name: "Jamis").collect { |dev| [dev.name, dev.id] }
21732 received = developer_klass.where(name: "David").by_name("Jamis").collect { |dev| [dev.name, dev.id] }
21733 Developer.where(name: "Jamis").unscope("where" => :name)
21734 projects_attributes: [{ name: "p1" }]
21735 Post.where(id: [1, 5, 6]).scoping do
21736 assert_equal Developer.where(name: "David").map(&:id), scope.map(&:id)
21737 }.join
21738 Thread.current[:default_scope_delay] = -> { barrier_2.wait }
21739 expected = <<~STR
21740 assert_no_match %r{(?<=, ) do \|t\|}, output
21741 matches = lines.map { |line| line.match(pattern) }
21742 line_matches = lines.map { |line| [line, line.match(pattern)] }.select { |line, match| match }
21743 line[start - 2..start - 1] == ", "
21744 output.scan(/^( *)create_table.*?
(.*?)^\1end/m).map { |m| m.last.split(/
/) }
21745 assert column_set.all? { |column| !column.match(/\bt\.\w+\s{2,}/) }
21746 assert_no_line_up(column_set, /limit: /)
21747 assert_no_line_up(column_set, /null: /)
21748 output = dump_all_table_schema([/^[^r]/])
21749 output = dump_all_table_schema([/^(?!integer_limits)/])
21750 assert_match %r{"c_int_without_limit"(?!.*limit)}, output
21751 assert_match %r{c_int_1.*limit: 2}, output
21752 assert_match %r{c_int_2.*limit: 2}, output
21753 assert_match %r{"c_int_3"(?!.*limit)}, output
21754 assert_match %r{"c_int_4"(?!.*limit)}, output
21755 assert_match %r{c_int_1.*limit: 1}, output
21756 assert_match %r{c_int_3.*limit: 3}, output
21757 assert_match %r{c_int_4.*limit: 4}, output
21758 assert_match %r{c_int_5.*limit: 5}, output
21759 assert_match %r{c_int_6.*limit: 6}, output
21760 assert_match %r{c_int_7.*limit: 7}, output
21761 assert_match %r{c_int_8.*limit: 8}, output
21762 assert_match %r{t\.bigint\s+"c_int_5"$}, output
21763 assert_match %r{t\.bigint\s+"c_int_6"$}, output
21764 assert_match %r{t\.bigint\s+"c_int_7"$}, output
21765 assert_match %r{t\.bigint\s+"c_int_8"$}, output
21766 assert_equal 't.index ["firm_id", "type", "rating"], name: "company_index", length: { type: 10 }, order: { rating: :desc }', index_definition
21767 assert_equal 't.index ["firm_id", "type", "rating"], name: "company_index", length: { type: 10 }', index_definition
21768 assert_equal 't.index ["firm_id", "type", "rating"], name: "company_index", order: { rating: :desc }', index_definition
21769 assert_equal 't.index ["firm_id", "type", "rating"], name: "company_index"', index_definition
21770 assert_equal 't.index ["firm_id", "type"], name: "company_partial_index", where: "(rating > 10)"', index_definition
21771 match = output.match(%r{create_table "movies"(.*)do})
21772 assert_match %r{t\.text\s+"params"$}, output
21773 assert_match %r{t\.binary\s+"data"$}, output
21774 assert_match %r{t\.binary\s+"blob_data"$}, output
21775 index_definition.sub!(/, name: "company_expression_index"\z/, "")
21776 assert_match %r{CASE.+lower\(\(name\)::text\).+END\) DESC"\z}i, index_definition
21777 assert_match %r{CASE.+lower\(`name`\).+END\) DESC"\z}i, index_definition
21778 assert_match %r{CASE.+lower\(name\).+END\) DESC"\z}i, index_definition
21779 assert_match %r{t\.binary\s+"var_binary",\s+limit: 255$}, output
21780 assert_match %r{t\.binary\s+"tiny_blob",\s+size: :tiny$}, output
21781 assert_match %r{t\.binary\s+"medium_blob",\s+size: :medium$}, output
21782 assert_match %r{t\.binary\s+"long_blob",\s+size: :long$}, output
21783 assert_match %r{t\.text\s+"tiny_text",\s+size: :tiny$}, output
21784 assert_match %r{t\.text\s+"normal_text"$}, output
21785 assert_match %r{t\.text\s+"medium_text",\s+size: :medium$}, output
21786 assert_match %r{t\.text\s+"long_text",\s+size: :long$}, output
21787 assert_match %r{t\.binary\s+"tiny_blob_2",\s+size: :tiny$}, output
21788 assert_match %r{t\.binary\s+"medium_blob_2",\s+size: :medium$}, output
21789 assert_match %r{t\.binary\s+"long_blob_2",\s+size: :long$}, output
21790 assert_match %r{t\.text\s+"tiny_text_2",\s+size: :tiny$}, output
21791 assert_match %r{t\.text\s+"medium_text_2",\s+size: :medium$}, output
21792 assert_match %r{t\.text\s+"long_text_2",\s+size: :long$}, output
21793 assert_no_match %r{t\.boolean\s+"has_fun",.+limit: 1}, output
21794 assert_match %r{t\.index \["awesome"\], name: "index_key_tests_on_awesome", type: :fulltext$}, output
21795 assert_match %r{t\.index \["pizza"\], name: "index_key_tests_on_pizza"$}, output
21796 output = dump_all_table_schema([/^[^n]/])
21797 assert_match %r{precision: 3,[[:space:]]+scale: 2,[[:space:]]+default: "2\.78"}, output
21798 assert_match %r{t\.decimal\s+"decimal_array_default",\s+default: \["1.23", "3.45"\],\s+array: true}, output
21799 assert_match %r{t\.oid\s+"obj_id"$}, output
21800 output = dump_all_table_schema(/./)
21801 connection.stub(:extensions, ["hstore", "uuid-ossp", "xml2"]) do
21802 connection.stub(:extensions, ["uuid-ossp", "xml2", "hstore"]) do
21803 match = output.match(%r{create_table "goofy_string_id"(.*)do.*
(.*)
})
21804 assert_match %r{t\.string\s+"id",.*?null: false$}, match[2], "non-primary key id column not preserved"
21805 assert_match(/^\s+add_foreign_key "fk_test_has_fk"[^
]+
\s+add_foreign_key "lessons_students"/, output)
21806 assert_equal ["authors"], output.scan(/^\s*add_foreign_key "([^"]+)".+$/).flatten
21807 assert_no_match(/^\s+add_foreign_key "fk_test_has_fk"[^
]+
\s+add_foreign_key "lessons_students"/, output)
21808 create_table("dog_owners") do |t|
21809 create_table("dogs") do |t|
21810 t.index [:name]
21811 assert_no_match %r{create_table "foo_.+_bar"}, output
21812 assert_no_match %r{add_index "foo_.+_bar"}, output
21813 assert_no_match %r{add_foreign_key "foo_.+_bar"}, output
21814 assert_no_match %r{add_foreign_key "[^"]+", "foo_.+_bar"}, output
21815 assert_no_match %r{create_table "foo\$.+\$bar"}, output
21816 assert_no_match %r{add_index "foo\$.+\$bar"}, output
21817 assert_no_match %r{add_foreign_key "foo\$.+\$bar"}, output
21818 assert_no_match %r{add_foreign_key "[^"]+", "foo\$.+\$bar"}, output
21819 create_table("cats") do |t|
21820 create_table("omg_cats") do |t|
21821 t.text :uuid, default: -> { "gen_random_uuid()" }
21822 t.text :uuid, default: -> { "uuid()" }
21823 assert_match %r{t\.string\s+"string_with_default",.*?default: "Hello!"}, output
21824 assert_match %r{t\.date\s+"date_with_default",\s+default: "2014-06-05"}, output
21825 assert_match %r{t\.time\s+"time_with_default",\s+default: "2000-01-01 07:17:04"}, output
21826 assert_match %r{t\.text\s+"text_with_default",.*?default: "John' Doe"}, output
21827 assert_match %r{t\.text\s+"uuid",.*?default: -> \{ "gen_random_uuid\(\)" \}}, output
21828 assert_match %r{t\.text\s+"uuid",.*?default: -> \{ "uuid\(\)" \}}, output
21829 assert_equal "name='#{quoted_bambi}'", Binary.sanitize_sql_array(["name='%s'", "Bambi"])
21830 assert_equal "name='#{quoted_bambi}'", Binary.sanitize_sql_array(["name='%s'", "Bambi".mb_chars])
21831 assert_equal "name=#{quoted_bambi}", Binary.sanitize_sql_array(["name=?", "Bambi"])
21832 assert_equal "name=#{quoted_bambi}", Binary.sanitize_sql_array(["name=?", "Bambi".mb_chars])
21833 assert_equal "name=#{quoted_bambi}", Binary.sanitize_sql_array(["name=:name", name: "Bambi"])
21834 assert_equal "name=#{quoted_bambi} AND id='1'", Binary.sanitize_sql_array(["name=:name AND id=:id", name: "Bambi", id: 1])
21835 assert_equal "name=#{quoted_bambi} AND id=1", Binary.sanitize_sql_array(["name=:name AND id=:id", name: "Bambi", id: 1])
21836 sub_query_pattern = /\(\bselect\b.*?\bwhere\b.*?\)/i
21837 select_author_sql = Post.sanitize_sql_array(["id in (?)", david_posts])
21838 assert_equal "100!%", Binary.sanitize_sql_like("100%", "!")
21839 assert_equal "great!!", Binary.sanitize_sql_like("great!", "!")
21840 assert_equal 'C:\\Programs\\MsPaint', Binary.sanitize_sql_like('C:\\Programs\\MsPaint', "!")
21841 assert_equal "1__000_%", Binary.sanitize_sql_like("1_000%", "_")
21842 assert_equal "1%_000%%", Binary.sanitize_sql_like("1_000%", "%")
21843 where("title LIKE ?", sanitize_sql_like(term, "!"))
21844 scope :search_as_scope, -> (term) {
21845 assert_sql(/LIKE '20!% !_reduction!_!!'/) do
21846 assert_nothing_raised { Binary.disallow_raw_sql!([Arel.sql("field(id, ?)")]) }
21847 assert_equal "'1'", bind(":a", a: 1) # ' ruby-mode
21848 assert_equal "1", bind(":a", a: 1) # ' ruby-mode
21849 assert_nothing_raised { bind("'+00:00'", foo: "bar") }
21850 @ary = ary
21851 def each(&b)
21852 @ary.each(&b)
21853 assert_equal "'1','2','3'", bind("?", [1, 2, 3])
21854 assert_equal "1,2,3", bind("?", [1, 2, 3])
21855 assert_equal quoted_abc, bind("?", %w(a b c))
21856 assert_equal "'1','2','3'", bind(":a", a: [1, 2, 3])
21857 assert_equal "1,2,3", bind(":a", a: [1, 2, 3])
21858 assert_equal quoted_abc, bind(":a", a: %w(a b c)) # '
21859 assert_equal "'1','2','3'", bind("?", SimpleEnumerable.new([1, 2, 3]))
21860 assert_equal "1,2,3", bind("?", SimpleEnumerable.new([1, 2, 3]))
21861 assert_equal "'1','2','3'", bind(":a", a: SimpleEnumerable.new([1, 2, 3]))
21862 assert_equal "1,2,3", bind(":a", a: SimpleEnumerable.new([1, 2, 3]))
21863 assert_equal quoted_abc, bind(":a", a: SimpleEnumerable.new(%w(a b c))) # '
21864 assert_equal quoted_nil, bind("?", [])
21865 assert_equal " in (#{quoted_nil})", bind(" in (?)", [])
21866 assert_equal "foo in (#{quoted_nil})", bind("foo in (?)", [])
21867 assert_equal "'0'", bind("?", 0..0)
21868 assert_equal "'1','2','3'", bind("?", 1..3)
21869 assert_equal "0", bind("?", 0..0)
21870 assert_equal "1,2,3", bind("?", 1..3)
21871 assert_equal quoted_abc, bind("?", "a"..."d")
21872 assert_equal quoted_nil, bind("?", 0...0)
21873 assert_equal quoted_nil, bind("?", "a"..."a")
21874 assert_equal quoted_empty, bind("?", "")
21875 assert_equal "name=#{quoted_bambi}", bind("name=?", "Bambi")
21876 assert_equal "name=#{quoted_bambi}", bind("name=?", "Bambi".mb_chars)
21877 l = Proc.new { bind(":a::integer '2009-01-01'::date", a: "10") }
21878 Result.new(["col_1", "col_2"], [
21879 ["row 1 col 1", "row 1 col 2"],
21880 ["row 2 col 1", "row 2 col 2"],
21881 ["row 3 col 1", "row 3 col 2"],
21882 { "col_1" => "row 1 col 1", "col_2" => "row 1 col 2" },
21883 { "col_1" => "row 2 col 1", "col_2" => "row 2 col 2" },
21884 { "col_1" => "row 3 col 1", "col_2" => "row 3 col 2" },
21885 ], result.to_a
21886 { "col_1" => "row 1 col 1", "col_2" => "row 1 col 2" }, result.first)
21887 ], result.first(1)
21888 ], result.first(2)
21889 ], result.first(3)
21890 { "col_1" => "row 3 col 1", "col_2" => "row 3 col 2" }, result.last)
21891 ], result.last(1)
21892 ], result.last(2)
21893 ], result.last(3)
21894 assert_equal ["col_1", "col_2"], row.keys
21895 values = [["1.1", "2.2"], ["3.3", "4.4"]]
21896 columns = ["col1", "col2"]
21897 types = { "col1" => Type::Integer.new, "col2" => Type::Float.new }
21898 assert_equal [[1, 2.2], [3, 4.4]], result.cast_values
21899 types = { "col1" => Type::Integer.new }
21900 assert_equal [[1, "2.2"], [3, "4.4"]], result.cast_values
21901 values = [["1.1"], ["3.3"]]
21902 columns = ["col1"]
21903 assert_equal [[1.1, 2.2], [3.3, 4.4]], result.cast_values("col1" => Type::Float.new)
21904 assert_equal ["id", "order", "select_id"], @connection.columns(:group).map(&:name).sort
21905 x = Group.new
21906 x.order = "x"
21907 x.order = "y"
21908 assert_equal [2, 3], gs.collect(&:id).sort
21909 assert_equal [1, 2], s.collect(&:id).sort
21910 assert_equal ["id", "order", "select_id"], Group.columns.map(&:name).sort
21911 pet = Pet.find_by_name("parrot")
21912 Kernel.load(File.expand_path("../models/owner.rb", __dir__))
21913 x = Post.where("author_id = ?", 1)
21914 posts = Post.where("author_id = ? AND id = ?", 1, 1)
21915 2.times { topics.to_a }
21916 subquery = Comment.from("#{Comment.table_name} /*! USE INDEX (PRIMARY) */").joins(:post).select(:id).order(:id)
21917 subquery = Comment.from("#{Comment.table_name} /*! USE INDEX (PRIMARY) */").joins(:post).order(:id)
21918 subquery = Comment.from("#{Comment.quoted_table_name} /*! USE INDEX (PRIMARY) */").joins(:post).select(:id).order(:id)
21919 subquery = Comment.from("#{Comment.quoted_table_name} /*! USE INDEX (PRIMARY) */").joins(:post).order(:id)
21920 subquery = Comment.from("(#{relation.to_sql}) #{Comment.table_name}_grouped").select("type", "post_count")
21921 assert_equal ["David"], Author.where(name: "David").map(&:name)
21922 topics = Topic.order("id")
21923 topics = Topic.order(Arel.sql("id") => :desc)
21924 topics = Topic.order(Arel.sql("id") => :asc).reverse_order
21925 Topic.order(Arel.sql("REPLACE(title, '', '')") => :asc).reverse_order
21926 topics = Topic.order(id: "desc")
21927 topics = Topic.order(id: "asc")
21928 e = assert_raise(ArgumentError) { Topic.order(:name, "id DESC", id: :asfsdf) }
21929 assert_equal 'Direction "asfsdf" is invalid. Valid directions are: [:asc, :desc, :ASC, :DESC, "asc", "desc", "ASC", "DESC"]', e.message
21930 topics = Topic.order("author_name").order("title").reorder("id").to_a
21931 topics = Topic.reorder("id desc", "id desc")
21932 limit(1).to_a
21933 query = Tag.order([Arel.sql("field(id, ?)"), [1, 3, 2]]).to_sql
21934 assert_match(/field\(id, '1','3','2'\)/, query)
21935 assert_match(/field\(id, 1,3,2\)/, query)
21936 query = Tag.order([Arel.sql("field(id, ?)"), []]).to_sql
21937 assert_match(/field\(id, NULL\)/, query)
21938 query = Tag.order([Arel.sql("field(id, ?)"), nil]).to_sql
21939 query = Tag.order(Arel.sql("field(id, ?)", [1, 3, 2])).to_sql
21940 assert_match(/field\(id, '1', '3', '2'\)/, query)
21941 assert_match(/field\(id, 1, 3, 2\)/, query)
21942 query = Tag.order(Arel.sql("field(id, ?)", [])).to_sql
21943 query = Tag.order(Arel.sql("field(id, ?)", nil)).to_sql
21944 even_ids = Developer.all.select { |d| d.id % 2 == 0 }.map(&:id)
21945 assert_equal [2, 4, 6, 8, 10], even_ids.sort
21946 where("project_id=1").to_a
21947 ).to_a
21948 authors = Author.eager_load(posts: { special_comments: { post: [ :special_comments, :very_special_comment ] } }).
21949 .where(comments: { id: 1 })
21950 post = Post.create! title: "Uhuu", body: "body"
21951 post = posts.find { |p| p.id == 1 }
21952 authors = Author.all.where(id: [])
21953 relation = [
21954 { name: david.name },
21955 { name: "Santiago" },
21956 { name: "tenderlove" },
21957 ids = Author.pluck(:id)
21958 slugs = ids.map { |id| "#{id}-as-a-slug" }
21959 relation = Author.where("id in (?)", Author.where(id: david).select(:id))
21960 relation = Post.where("id in (?)", david.posts.select(:id))
21961 relation = Post.where("id in (:post_ids)", post_ids: david.posts.select(:id))
21962 expected = { 1 => 4, 2 => 1 }
21963 no_posts = posts.where(title: "")
21964 assert posts.any? { |p| p.id > 0 }
21965 assert_not posts.any? { |p| p.id <= 0 }
21966 assert posts.many? { |p| p.id > 0 }
21967 assert_not posts.many? { |p| p.id < 2 }
21968 assert posts.none? { |p| p.id < 0 }
21969 assert_not posts.none? { |p| p.id == 1 }
21970 assert_not posts.one? { |p| p.id < 3 }
21971 assert posts.one? { |p| p.id == 1 }
21972 posts = Post.where(title: "You told a lie")
21973 hen = birds.where(name: "hen").create!
21974 green_birds = Bird.where(color: "green").new([{ name: "parrot" }, { name: "canary" }])
21975 assert_equal ["parrot", "canary"], green_birds.map(&:name)
21976 assert_equal ["green", "green"], green_birds.map(&:color)
21977 green_birds = Bird.where(color: "green").build([{ name: "parrot" }, { name: "canary" }])
21978 green_birds = Bird.where(color: "green").create([{ name: "parrot" }, { name: "canary" }])
21979 bird.color = "grey"
21980 green_birds = Bird.where(color: "green").create!([{ name: "parrot" }, { name: "canary" }])
21981 canary = Bird.create!(color: "yellow", name: "canary")
21982 bird.name = "parrot"
21983 same_parrot = Bird.where(color: "green").first_or_create { |bird| bird.name = "parakeet" }
21984 several_green_birds = Bird.where(color: "green").first_or_create([{ name: "parrot" }, { name: "parakeet" }])
21985 same_parrot = Bird.where(color: "green").first_or_create([{ name: "hummingbird" }, { name: "macaw" }])
21986 same_parrot = Bird.where(color: "green").first_or_create! { |bird| bird.name = "parakeet" }
21987 Bird.where(color: "green").first_or_create! { |bird| bird.pirate_id = 1 }
21988 several_green_birds = Bird.where(color: "green").first_or_create!([{ name: "parrot" }, { name: "parakeet" }])
21989 same_parrot = Bird.where(color: "green").first_or_create!([{ name: "hummingbird" }, { name: "macaw" }])
21990 assert_raises(ActiveRecord::RecordInvalid) { Bird.where(color: "green").first_or_create!([ { name: "parrot" }, { pirate_id: 1 } ]) }
21991 bird = Bird.find_or_create_by(name: "bob")
21992 results = [nil, bob]
21993 find_by_mock = -> (*) do
21994 bird = Bird.create_with(color: "green").find_or_create_by(name: "bob")
21995 bird = Bird.find_or_create_by(name: "bob") do |record|
21996 Subscriber.create_or_find_by!(nick: "bob", name: "the cat")
21997 hens = Bird.where(name: "hen")
21998 relation = Post.where(author_id: 1).order("id ASC").limit(1)
21999 assert_equal Post.all.sort_by(&:id), all_posts.sort_by(&:id)
22000 assert_equal all_posts.sort_by(&:id), relation.scoping { Post.except(:where, :order, :limit).sort_by(&:id) }
22001 tag1 = Tag.create(name: "Foo")
22002 tag2 = Tag.create(name: "Foo")
22003 query = Tag.select(:name).where(id: [tag1.id, tag2.id])
22004 assert_equal ["Foo", "Foo"], query.map(&:name)
22005 scope = Post.having("")
22006 scope = Post.having([])
22007 scope = Post.includes(:comments).order({ "comments.label": :ASC })
22008 scope = Post.includes(:comments).order({ "posts.title": :ASC })
22009 scope = Post.where(comments: { body: "Bla" })
22010 scope = Post.where("comments.body" => "Bla")
22011 scope = Post.where.not(comments: { body: "Bla" })
22012 scope = Post.where.not("comments.body" => "Bla")
22013 scope = Post.having(comments: { body: "Bla" })
22014 scope = Post.having("comments.body" => "Bla")
22015 post = nil
22016 assert sql_log.any? { |sql| /order by/i.match?(sql) }, "ORDER BY was not used in the query: #{sql_log}"
22017 assert sql_log.all? { |sql| !/order by/i.match?(sql) }, "ORDER BY was used in the query: #{sql_log}"
22018 assert_difference("Post.count", -3) { david.posts.delete_by(body: "hello") }
22019 assert_equal posts(:eager_other), Post.order(:id).find_by("author_id = ?", 2)
22020 assert_nil Post.all.find_by("1 = 0")
22021 assert_sql(/^((?!ORDER).)*$/) { Post.all.find_by(author_id: 2) }
22022 assert_equal posts(:eager_other), Post.order(:id).find_by!("author_id = 2")
22023 assert_equal posts(:eager_other), Post.order(:id).find_by!("author_id = ?", 2)
22024 assert_sql(/^((?!ORDER).)*$/) { Post.all.find_by!(author_id: 2) }
22025 Post.all.find_by!("1 = 0")
22026 assert_equal "#<ActiveRecord::Relation [#{Post.limit(2).map(&:inspect).join(', ')}]>", relation.inspect
22027 assert_equal "#<ActiveRecord::Relation [#{Post.limit(10).map(&:inspect).join(', ')}, ...]>", relation.inspect
22028 assert_sql(%r(/\* loading for inspect \*/)) do
22029 expected = "#<ActiveRecord::Relation [#{Post.limit(2).map(&:inspect).join(', ')}]>"
22030 assert_equal 10, out.string.scan(/#<\w*Post:/).size
22031 assert out.string.end_with?("\"...\"]
"), "Did not end with an ellipsis."
22032 assert_sql(%r(/\* loading for pp \*/)) do
22033 test "#load" do
22034 expected = [[1, nil], [5, "David"], [3, "Mary"], [2, "Bob"]]
22035 assert_equal [1, 2, 4], posts.map(&:id)
22036 assert_equal [1, 1, 1], posts.map(&:author_address_id)
22037 companies = Company.create!([{ name: "test1" }, { name: "test2" }])
22038 p1 = Post.where(id: 1)
22039 p2 = Post.where(id: 2)
22040 p0 = Post.where(author_id: 0)
22041 posts = Post.where(author: authors(:mary), text: "hullo").order(:id)
22042 comments = comments.unscope(where: { posts: :id })
22043 title: ["Welcome to the weblog", "So I was thinking", nil]
22044 5.times do |idx|
22045 Post.create!(title: idx.to_s, body: idx.to_s)
22046 third_post = posts.find_by(title: "3")
22047 authors = Author.where(name: ["David", "Mary"].to_set)
22048 authors = Author.public_send(method, [""])
22049 assert_equal({}, value)
22050 relation.where!(title: ["foo", "bar", "hello"])
22051 assert_equal({ "title" => ["foo", "bar", "hello"] }, relation.where_values_hash)
22052 assert_equal({ "id" => 10 }, relation.where_values_hash)
22053 assert_equal({ "hello" => "world" }, relation.scope_for_create)
22054 assert_equal({ "id" => 10 }, relation.scope_for_create)
22055 assert_equal({ "hello" => "world", "id" => 10 }, relation.scope_for_create)
22056 assert_equal({ "name" => :lol }, relation.where_clause.to_h)
22057 values[:where] = nil
22058 relation = Relation.new(FakeKlass, values: { select: [:foo] })
22059 raise unless args == ["foo = ?", "bar"]
22060 relation.merge!(where: ["foo = ?", "bar"])
22061 nb_inner_join = queries.sum { |sql| sql.scan(/INNER\s+JOIN/i).size }
22062 post = Post.create!(title: "haha", body: "huhu")
22063 selected = Post.select(:join).from(Post.select("id as #{quoted_join}")).map(&:join)
22064 assert_equal({ 2 => 1, 4 => 3, 5 => 1 }, authors(:david).posts.merge(posts_with_special_comments_with_ratings).count)
22065 assert_match %r{= 1 /\* foo \*/}, post_with_annotation.to_sql
22066 assert_sql(%r{/\* foo \*/}) do
22067 assert_sql(%r{/\* foo \*/ /\* bar \*/}) do
22068 post_with_annotation = Post.where(id: 1).annotate("**//foo//**")
22069 assert_includes post_with_annotation.to_sql, "= 1 /* ** //foo// ** */"
22070 assert_predicate log.select { |query| query.match?(%r{/\*}) }, :empty?
22071 post_with_hint = Post.where(id: 1).optimizer_hints("**//BADHINT//**")
22072 assert_includes post_with_hint.to_sql, "/*+ ** //BADHINT// ** */"
22073 post_with_hint = Post.where(id: 1).optimizer_hints("/*+ BADHINT */")
22074 assert_includes post_with_hint.to_sql, "/*+ BADHINT */"
22075 Post.where(id: []).load
22076 Post.where(id: []).unscope(where: :id).load
22077 Post.where(id: []).exists?(123)
22078 Post.all.exists?(id: [])
22079 cte_options = {
22080 .with(posts_with_tags: Post.where("tags_count > 0"))
22081 assert_equal [comment], Comment.joins(post: :author).where(authors: { id: "2-foo" })
22082 posts = Post.where(id: "1-foo")
22083 posts = Post.where(id: ["1-foo", "bar"])
22084 joined.each { |post|
22085 author.id = 1
22086 assert_equal Post.where(author_id: [1, 2]).to_sql, Post.where(author: [1, 2]).to_sql
22087 expected = Post.where(author_id: Author.where(id: [1, 2])).to_sql
22088 parent.id = 1
22089 hidden.id = 2
22090 car = cars(:honda)
22091 thing.id = 1
22092 Post.where(id: { "posts.author_id" => 10 }).first
22093 assert_equal post, Post.where(posts: { "id" => post.id }).first
22094 assert_equal 0, Post.where(id: []).count
22095 [[], {}, nil, ""].each do |blank|
22096 first_clause = WhereClause.new([table["id"].eq(bind_param(1))])
22097 [table["id"].eq(bind_param(1)), table["name"].eq(bind_param("Sean"))],
22098 a = WhereClause.new(["a"])
22099 b = WhereClause.new(["b"])
22100 c = WhereClause.new(["c"])
22101 assert_equal a + (b + c), (a + b) + c
22102 assert_not_equal a + b, b + a
22103 clause = WhereClause.new([table["id"].eq(bind_param(1))])
22104 a = WhereClause.new([table["id"].eq(1)])
22105 b = WhereClause.new([table["name"].eq("Sean")])
22106 expected = WhereClause.new([table["id"].eq(1), table["name"].eq("Sean")])
22107 a = WhereClause.new([table["id"].eq(1), table["name"].eq("Sean")])
22108 b = WhereClause.new([table["name"].eq("Jim")])
22109 expected = WhereClause.new([table["id"].eq(1), table["name"].eq("Jim")])
22110 [table["name"].eq(bind_param("Jim"))],
22111 [table["id"].eq(bind_param(1)), table["name"].eq(bind_param("Jim"))],
22112 [table["id"].eq(bind_param(1)), table2["id"].eq(bind_param(2))],
22113 [table["id"].eq(bind_param(3))],
22114 [table2["id"].eq(bind_param(2)), table["id"].eq(bind_param(3))],
22115 table["id"].in([1, 2, 3]),
22116 table["id"].not_in([1, 2, 3]),
22117 table["id"].eq(1),
22118 table["id"].not_eq(2),
22119 table["id"].gt(1),
22120 table["id"].gteq(2),
22121 table["id"].lt(1),
22122 table["id"].lteq(2),
22123 table["id"].is_not_distinct_from(1),
22124 table["id"].is_distinct_from(2),
22125 Arel::Nodes::And.new([
22126 table["name"].eq(bind_param("Sean")),
22127 table["age"].gteq(bind_param(30)),
22128 wcs = (0..9).map do |i|
22129 WhereClause.new([table["id#{i}"].eq(bind_param(i))])
22130 wc = wcs[0] + wcs[1] + wcs[2].or(wcs[3]) + wcs[4] + wcs[5] + wcs[6].or(wcs[7]) + wcs[8] + wcs[9]
22131 expected = wcs[0] + wcs[2].or(wcs[3]) + wcs[5] + wcs[6].or(wcs[7]) + wcs[9]
22132 actual = wc.except("id1", "id2", "id4", "id7", "id8")
22133 table["name"].eq(bind_param(nil)),
22134 expected = Arel::Nodes::And.new([
22135 Arel::Nodes::Grouping.new(Arel.sql("foo = bar")),
22136 where_clause = WhereClause.new([table["id"].in([1, 2, 3])])
22137 where_clause_with_empty = WhereClause.new([table["id"].in([1, 2, 3]), ""])
22138 where_clause = WhereClause.new([table["id"].eq(bind_param(1))])
22139 other_clause = WhereClause.new([table["name"].eq(bind_param("Sean"))])
22140 Arel::Nodes::Or.new(table["id"].eq(bind_param(1)), table["name"].eq(bind_param("Sean")))
22141 [table["id"].eq(bind_param(1)), table["hair_color"].eq(bind_param("black"))],
22142 [table["id"].eq(bind_param(1))],
22143 or_clause = WhereClause.new([table["name"].eq(bind_param("Sean"))])
22144 .or(WhereClause.new([table["hair_color"].eq(bind_param("black"))]))
22145 common_or = WhereClause.new([table["name"].eq(bind_param("Sean"))])
22146 a = common_or + WhereClause.new([table["id"].eq(bind_param(1))])
22147 b = common_or + WhereClause.new([table["foo"].eq(bind_param("bar"))])
22148 new_or = WhereClause.new([table["id"].eq(bind_param(1))])
22149 .or(WhereClause.new([table["foo"].eq(bind_param("bar"))]))
22150 assert_equal common_or + new_or, a.or(b)
22151 table["id"].eq(bind_param(1)),
22152 table["extra"].eq(bind_param("pluto")),
22153 h = Hash.new(0)
22154 h[WhereClause.new(["a"])] += 1
22155 h[WhereClause.new(["b"])] += 1
22156 WhereClause.new(["a"]) => 2,
22157 WhereClause.new(["b"]) => 1
22158 relation = Post.where.not(author_id: [1, 2]).where.not(title: "ruby on rails")
22159 relation = Post.where(body: "hello").where(body: "world").rewhere(body: "hullo")
22160 relation = Post.where(body: "hello").where(type: "StiPost").rewhere(body: "hullo", type: "Post")
22161 expected = Post.where(body: "hullo", type: "Post")
22162 relation = Post.where(body: "hello").where(type: "Post").rewhere(body: "hullo")
22163 relation = Post.where(text: "hello").where(text: "world").rewhere(text: "hullo")
22164 posts.each { |post| assert_equal "rofl", post.title }
22165 assert_equal 1, WarehouseThing.where(id: 1).update_all(["value = ?", 0])
22166 assert posts.all? { |post| "ig" == post.title }
22167 pets = Pet.joins(:toys).where(toys: { name: "Bone" })
22168 pets = Pet.left_joins(:toys).where(toys: { name: "Bone" })
22169 pets = Pet.includes(:toys).where(toys: { name: "Bone" })
22170 Pet.joins(:toys).where(toys: { name: "Bone" }).update_counters(integer: 1)
22171 [topic1.id, topic2.id],
22172 [{ title: "adequaterecord" }, { title: "adequaterecord" }]
22173 topic = Topic.create!(title: "Foo", author_name: nil)
22174 expected.map! { |version| version + 1 }
22175 Author.order(order).update_all("id = id + 1")
22176 assert_equal 1, limited_posts.update_all([ "body = ?", "bulk update!" ])
22177 left = Post.where(id: 1)
22178 right = Post.where(id: 2)
22179 left = Post.distinct.where("id = 1")
22180 right = Post.where(id: [2, 3])
22181 left = Post.order("body asc").where("id = 1")
22182 right = Post.order("id desc").where(id: [2, 3])
22183 left = Post.order("body asc").where("id = 1").unscope(:order)
22184 right = Post.order("body asc").where("id = 2")
22185 post = Post.select(:title, posts: { title: :post_title }).take
22186 Post.select(posts: { boo: :post_title }).take
22187 Post.select(posts: [:bar, :id]).take
22188 Post.select(posts: { "UPPER(title)" => :post_title }).take
22189 post = Post.select(posts: [:title, :id]).take
22190 post = Post.joins(:comments).select(:title, posts: { title: :post_title }, comments: { body: :comment_body }).take
22191 expected = Post.select(:title, posts: { title: :post_title }).to_sql
22192 actual = Post.select(:title, :body).reselect(:title, posts: { title: :post_title }).to_sql
22193 ].each do |post|
22194 posts = Post.select("posts.id * 1.1 AS foo").eager_load(:comments)
22195 assert_match %r{#{Regexp.escape(topic_title)} ~ 'rails'}i, Topic.where(title: /rails/).to_sql
22196 assert_match %r{#{Regexp.escape(topic_title)} ~ 'rails'}i, Reply.joins(:topic).where(topics: { title: /rails/ }).to_sql
22197 expected = Post.where("id = 1 or id = 2").to_a
22198 assert_equal expected, Post.where("id = 1").or(Post.where("id = 2")).to_a
22199 expected = Post.where("id = 1").to_a
22200 assert_equal expected, Post.where("id = 1").or(Post.where("id = 1")).to_a
22201 assert_equal Post.find([1, 2]).sort_by(&:id), Post.where(id: 1).or(Post.where(id: 2)).sort_by(&:id)
22202 expected = Post.where("id = 1 or id = 2 or id = 3").order("body asc").to_a
22203 assert_equal expected, partial.where("id = 1").or(partial.where(id: [2, 3])).to_a
22204 assert_equal expected, Post.order("body asc").where("id = 1").or(Post.order("body asc").where(id: [2, 3])).to_a
22205 Post.distinct.where("id = 1").or(Post.where(id: [2, 3])).to_a
22206 Post.order("body asc").where("id = 1").or(Post.order("id desc").where(id: [2, 3])).to_a
22207 expected = Post.where("id = 1 or id = 2")
22208 partial = Post.where("id = 1 and id != 2")
22209 partial = Post.where(id: 1).where.not(id: 2)
22210 expected = Post.where("id = 1 or id = 2").sort_by(&:id)
22211 assert_equal expected, Post.order("body asc").where("id = 1").unscope(:order).or(Post.where("id = 2")).sort_by(&:id)
22212 assert_equal expected, Post.order(:id).where("id = 1").or(Post.order(:id).where("id = 2").unscope(:order)).sort_by(&:id)
22213 Post.order("body asc").where("id = 1").unscope(:order).or(Post.order("body asc").where("id = 2")).to_a
22214 groups = Post.where("id < 10").group("body")
22215 expected = groups.having("COUNT(*) > 1 OR body like 'Such%'").count
22216 expected = Post.where("id = 1 or body LIKE '\%a\%'").to_a
22217 expected = Post.where("body LIKE '\%a\%' OR title LIKE ?", "%'%").order("id DESC").to_a
22218 p = Post.where("id = 1")
22219 assert_equal expected, p.or(Post.where("id = 2")).to_a
22220 Post.where(id: [1, 2, 3]).or(title: "Rails")
22221 actual = joined.where(authors: { id: 1 })
22222 assert_match %r{#{quoted_posts} /\* foo \*/\z}, Post.annotate("foo").or(Post.all).to_sql
22223 assert_match %r{#{quoted_posts} /\* foo \*/\z}, Post.annotate("foo").or(Post.annotate("foo")).to_sql
22224 assert_match %r{#{quoted_posts} /\* foo \*/\z}, Post.annotate("foo").or(Post.annotate("bar")).to_sql
22225 assert_match %r{#{quoted_posts} /\* foo \*/ /\* bar \*/\z}, Post.annotate("foo", "bar").or(Post.annotate("foo")).to_sql
22226 Post.from("posts").or(Post.from("posts"))
22227 Paragraph.where(id: i, book_id: i * i)
22228 test "##{method}!" do
22229 test "#_select!" do
22230 test "#order!" do
22231 test "#from!" do
22232 test "#lock!" do
22233 test "#reorder!" do
22234 test "merge!" do
22235 assert_equal [:foo], relation.merge(-> { select(:foo) }).select_values
22236 test "none!" do
22237 test "#regroup!" do
22238 david, mary, bob = authors = authors(:david, :mary, :bob)
22239 david_and_mary = Author.where(id: [david, mary]).order(:id)
22240 david, mary, bob = authors(:david, :mary, :bob)
22241 non_mary_and_bob = Author.where.not(id: [mary, bob])
22242 assert_sql(/WHERE #{Regexp.escape(author_id)} NOT IN \((\?|\W?\w?\d), \g<1>\)\z/) do
22243 only_david = Author.where("#{author_id} IN (?)", david)
22244 assert_sql(/WHERE \(#{Regexp.escape(author_id)} IN \('1'\)\)\z/) do
22245 assert_sql(/WHERE \(#{Regexp.escape(author_id)} IN \(1\)\)\z/) do
22246 devs = Developer.where("salary >= 80000").merge(Developer.limit(2)).merge(Developer.order("id ASC").where("id < 3"))
22247 assert_match(/.?post_id.? = #{post.id}\z/i, sql)
22248 relations = []
22249 right = Post.where(title: "wtf").where(title: "bbq")
22250 right = Post.where(id: 1)
22251 relation = Post.all.merge(Post.order([Arel.sql("title LIKE ?"), "%suffix"]))
22252 relation = Post.all.merge(Post.order(Arel.sql("title LIKE '%?'")))
22253 assert_sql(%r{/\* bar \*/ /\* foo \*/}) do
22254 assert_sql(%r{/\* foo \*/ /\* bar \*/ /\* baz \*/ /\* qux \*/}) do
22255 assert_sql(%r{FROM #{Regexp.escape(Post.quoted_table_name)} /\* foo \*/\z}) do
22256 assert_sql(%r{FROM #{Regexp.escape(Post.quoted_table_name)} /\* foo \*/ /\* bar \*/\z}) do
22257 assert_sql(%r{FROM #{Regexp.escape(Post.quoted_table_name)} /\* bar \*/ /\* foo \*/\z}) do
22258 hello_by_bob = Post.where(body: "hello").joins(:author).
22259 merge(Author.where(name: "Bob")).order("posts.id").pluck("posts.id")
22260 where.not("authors.name": "David").
22261 assert_equal ["Bob", "Bob", "Mary"], posts_by_author_name
22262 assert_equal ["Mary", "Mary", "Mary", "Bob"], posts_by_author_name
22263 assert_equal [1, 2, 7], relation.pluck(:id)
22264 callback = -> (event) do
22265 assert_equal [["Comment Load", true]], events.map { |e| [e.payload[:name], e.payload[:async]] }
22266 assert_equal [["Category Load", true]], events.map { |e| [e.payload[:name], e.payload[:async]] }
22267 if event.payload[:name] == "Post Load"
22268 if event.payload[:name] == "SQL"
22269 assert_equal [], Post.where(id: []).load_async.to_a
22270 dog_status = {}
22271 order = [3, 4, 1]
22272 posts = Post.in_order_of(:id, order)
22273 posts = Post.in_order_of(:id, [])
22274 posts = Post.in_order_of(Arel.sql("id * 2"), order.map { |id| id * 2 })
22275 posts = Post.where(type: "Post").order(:type).in_order_of(:id, order)
22276 posts = Post.where(type: "Post").order(:type).in_order_of("id", order)
22277 order = ["ebook", nil, "paperback"]
22278 bob = Author.create(name: "Bob")
22279 order = ["Bob", "Anna", "John"]
22280 davids = Author.where(name: "David").from("#{Author.quoted_table_name} /*! USE INDEX (PRIMARY) */")
22281 pets = Pet.joins(:toys).where("toys.name = ?", "Bone")
22282 :+, :-, :|, :&, :[], :shuffle,
22283 :all?, :collect, :compact, :detect, :each, :each_cons, :each_with_index,
22284 :exclude?, :find_all, :flat_map, :group_by, :include?, :length,
22285 :map, :none?, :one?, :partition, :reject, :reverse, :rotate,
22286 :sample, :second, :sort, :sort_by, :slice, :third, :index, :rindex,
22287 :to_ary, :to_set, :to_xml, :to_yaml, :join,
22288 :in_groups, :in_groups_of, :to_sentence, :to_formatted_s, :to_fs, :as_json
22289 method.end_with?("=", "!", "?", "value", "values", "clause")
22290 } - [:reverse_order, :arel, :extensions, :construct_join_dependency] + [
22291 :any?, :many?, :none?, :one?,
22292 :create_or_find_by, :create_or_find_by!,
22293 hash = { "id" => 123 }
22294 :has_many,
22295 ].each do |rel|
22296 :address, nil, { mapping: [ %w(address_street street), %w(address_city city), %w(address_country country) ] }, Customer
22297 :balance, nil, { class_name: "Money", mapping: %w(balance amount) }, Customer
22298 :gps_location, nil, {}, Customer
22299 :firm,
22300 class_name: "Firm",
22301 exit!(1)
22302 conn = nil
22303 [conn, child]
22304 dev.name = "Forbidden."
22305 Developer.joins(", projects").each { |d| assert_not d.readonly? }
22306 @quoter = Class.new {
22307 }.new
22308 assert_equal "''", @quoter.quote_string("'")
22309 assert_equal "\\\\", @quoter.quote_string("\\")
22310 assert_equal "hi''i", @quoter.quote_string("hi'i")
22311 assert_equal "hi\\\\i", @quoter.quote_string("hi\\i")
22312 t = Time.now.change(usec: 0)
22313 expected = t.change(year: 2000, month: 1, day: 1)
22314 expected = expected.getlocal.to_fs(:db).sub("2000-01-01 ", "")
22315 t = Time.new(2000, 7, 1, 0, 0, 0, "+04:30")
22316 float = 1.2
22317 bignum = 1 << 100
22318 bigdec = BigDecimal((1 << 100).to_s)
22319 assert_equal "'lo\\\\l'", @quoter.quote('lo\l')
22320 assert_equal "'lo\\\\l'", @quoter.quote(string)
22321 assert_sql(%r{/\*application:active_record\*/}) do
22322 dash.name = "New name"
22323 ActiveRecord::QueryLogs.tags = [ { query_counter: -> { i += 1 } } ]
22324 assert_sql("SELECT 1 /*query_counter:1*/") do
22325 ActiveRecord::QueryLogs.tags = [ empty: -> { nil } ]
22326 assert_sql(%r{/\*application='active_record'\*/}) do
22327 ActiveRecord::QueryLogs.tags = [ :application, { custom_proc: -> { "test content" } } ]
22328 { custom_proc: -> { "test content" }, another_proc: -> { "more test content" } },
22329 { tracestate: "congo=t61rcWkgMzE,rojo=00f067aa0ba902b7", custom_proc: -> { "Joe's Shack" } },
22330 { custom_proc: -> { 1234 } },
22331 assert_sql(%r{custom_proc='1234'\*/}) do
22332 ActiveRecord::QueryLogs.tags = [ :application, { custom_context_proc: ->(context) { context[:foo] } } ]
22333 @logger = ::Logger.new File::NULL
22334 @events << event
22335 mw = middleware { |env|
22336 Post.create!(title: "a new post", body: "and a body")
22337 mw.call({})
22338 assert_raises(RuntimeError) { mw.call({}) }
22339 if Process.respond_to?(:fork) && !in_memory_db?
22340 rd, wr = IO.pipe
22341 pid = fork {
22342 status = 0
22343 status = 1
22344 }.call({})
22345 if !$?.success?
22346 [200, {}, nil]
22347 assert_queries(2) { Task.find(1); Task.find(1) }
22348 assert_queries(1) { Task.find(1); Task.find(1) }
22349 assert_queries(2) { Task.find(1); Task.find(1); Task.find(2) }
22350 assert_queries(2) { Task.find(1); Task.find(2) }
22351 assert_no_queries { Task.find(1); Task.find(1); Task.find(2) }
22352 payload[:sql].downcase! if payload[:name] == "Task Load"
22353 assert_queries(1) { Topic.find(1); Topic.find(1) }
22354 assert_queries(2) { task.lock!; task.lock! }
22355 lambda { |env| executor.wrap { app.call(env) } }
22356 JsonObj.create(payload: { a: 1 })
22357 search.merge!(b: 2)
22358 task = Task.find(1)
22359 Task.cache { Task.insert({ starting: Time.now }) }
22360 Task.cache { Task.insert_all([{ starting: Time.now }]) }
22361 Task.cache { Task.insert!({ starting: Time.now }) }
22362 Task.cache { Task.insert_all!([{ starting: Time.now }]) }
22363 Task.cache { Task.upsert({ starting: Time.now }) }
22364 Task.cache { Task.upsert_all([{ starting: Time.now }]) }
22365 p = Post.find(1)
22366 id = topic.id
22367 k.table_name = "bar"
22368 k.primary_key = "foo"
22369 dashboard.id = "2"
22370 assert_match %r/create_table "barcodes", primary_key: "code", id: { type: :string, limit: 42 }/, schema
22371 assert_no_match %r{t\.index \["code"\]}, schema
22372 @connection.create_table(:uber_barcodes, primary_key: ["region", "code"], force: true) do |t|
22373 @connection.create_table(:travels, primary_key: ["from", "to"], force: true) do |t|
22374 assert_match %r{create_table "uber_barcodes", primary_key: \["region", "code"\]}, schema
22375 assert_equal(["author_id", "number"], Cpk::Book.primary_key)
22376 assert_equal(["shop_id", "id"], Cpk::Order.primary_key)
22377 column = @connection.columns(:widgets).find { |c| c.name == "id" }
22378 assert_match %r{create_table "widgets", id: :#{@pk_type}, }, schema
22379 assert_match %r/create_table "widgets", id: { type: :bigint, unsigned: true }/, schema
22380 @per_test_teardown = []
22381 @timed_out = 0
22382 @timed_out += 1
22383 topic_data = { 1 => { "content" => "1 updated" }, 2 => { "content" => "2 updated" } }
22384 assert_equal [1, 2], updated.map(&:id)
22385 updated = Topic.update([1, 1, 2], [
22386 { "content" => "1 duplicated" }, { "content" => "1 updated" }, { "content" => "2 updated" }
22387 assert_equal [1, 1, 2], updated.map(&:id)
22388 topic_data = { 1 => { "content" => "1 updated" }, 2 => { "content" => "2 updated" }, 99999 => {} }
22389 updated = Topic.update!([1, 1, 2], [
22390 Topic.update!(Topic.first, "content" => "1 updated")
22391 clients = Client.find([2, 3])
22392 Client.destroy([2, 3, 99999])
22393 Topic.delete(deleting = [1, 2])
22394 topics = Topic.build([{ title: "first" }, { title: "second" }])
22395 assert_equal ["first", "second"], topics.map(&:title)
22396 topic = Topic.build("title" => "New Topic") do |t|
22397 t.author_name = "David"
22398 topics = Topic.build([{ "title" => "first" }, { "title" => "second" }]) do |t|
22399 topic.attributes = { "title" => "null", "author_name" => "null" }
22400 topics = Topic.create([ { "title" => "first" }, { "title" => "second" }])
22401 topic = Topic.create("title" => "New Topic") do |t|
22402 topics = Topic.create([ { "title" => "first" }, { "title" => "second" }]) do |t|
22403 topic.written_on = "2003-12-12 23:23:00"
22404 @counter ||= 0
22405 @counter += 1
22406 Topic.where("1=0").scoping { topic.delete }
22407 t = klass.create(title: "New Topic", author_name: "Not David")
22408 topic.update_column("content", "--- Have a nice day
...
")
22409 topic.update_column(:content, "--- You too
...
")
22410 new_name = "sebavan"
22411 t = Topic.order("id").limit(1).first
22412 topic.update("content" => "--- Have a nice day
...
", :author_name => "Jose")
22413 topic.update_columns(content: "--- You too
...
", "author_name" => "Sebastian")
22414 topic.update_columns(content: "--- Have a nice day
...
", author_name: "Jose")
22415 topic.update("approved" => true, "title" => "The First Topic Updated")
22416 topic.update(id: 3, title: "Hm is it possible?")
22417 topic.update({})
22418 reply.update!("title" => "The Second Topic of the day updated", "content" => "Have a nice evening")
22419 should_be_destroyed_reply = Reply.create("title" => "hello", "content" => "world")
22420 should_not_be_destroyed_reply = Reply.create("title" => "hello", "content" => "world")
22421 Topic.where("1=0").scoping { Topic.destroy(1) }
22422 Topic.where("1=0").scoping { Topic.delete(1) }
22423 post = Post.select("posts.*, 1 as wibble").last!
22424 post.id = 1
22425 name: "Bob",
22426 parrot.name = "Barb"
22427 assert_match(/WHERE .*#{column}/, sql)
22428 [:count, :sum].each do |method|
22429 normalizes :name, with: -> name { name.titlecase }
22430 @time = Time.utc(1999, 12, 31, 12, 34, 56)
22431 normalizes :name, with: -> name { name&.titlecase || "Untitled" }, apply_to_nil: true
22432 normalizes :name, with: -> name { name.reverse }
22433 normalizes :name, with: -> name { name.succ }
22434 aircraft.name = "0"
22435 class_name: "Bird",
22436 before_add: proc { |p, b|
22437 @@add_callback_called << b
22438 before_add: proc { |p, b| @@add_callback_called << b })
22439 @@add_callback_called = []
22440 pirate.birds_attributes = [{ name: "Bird1" }, { name: "Bird2" }]
22441 @birds[0]
22442 @birds[1]
22443 @birds.map do |bird|
22444 [{ "name" => "New Bird" }]
22445 [{ "id" => bird_to_destroy.id.to_s, "_destroy" => true }]
22446 [{ "id" => @birds[0].id.to_s, "name" => "New Name" },
22447 { "name" => "New Bird" },
22448 { "id" => bird_to_destroy.id.to_s, "_destroy" => true }]
22449 [:parrots, :birds].each do |name|
22450 pirate.birds_with_reject_all_blank_attributes = [{ name: "", color: "", _destroy: "0" }]
22451 pirate.birds_with_reject_all_blank_attributes = [{ name: "", color: "" }]
22452 pirate.birds_with_reject_all_blank_attributes = [{ name: "Tweetie", color: "" }]
22453 pirate.update(ship_attributes: { "_destroy" => true, :id => ship.id })
22454 pirate.ship_attributes = { name: "Red Pearl", _reject_me_if_new: true }
22455 pirate.update(ship_attributes: { name: "s2", id: ship.id })
22456 pirate.ship_attributes = { name: "Ship 1" }
22457 pirate.ship_attributes = { name: "Ship 1", pirate_id: pirate.id + 1 }
22458 human = Human.create(name: "Jon")
22459 Pirate.accepts_nested_attributes_for :ship, reject_if: ->(a) { a[:name] == "The Golden Hind" }, allow_destroy: false
22460 pirate = Pirate.create!(catchphrase: "Stop wastin' me time", ship_attributes: { name: "White Pearl", _destroy: "1" })
22461 pirate.update!(ship_attributes: { id: pirate.ship.id, name: "The Golden Hind", _destroy: "1" })
22462 pirate.update!(ship_attributes: { id: pirate.ship.id, name: "Black Pearl", _destroy: "1" })
22463 pirate.ship_attributes = { id: "" }
22464 ).find_or_create_by!(
22465 name: "Monkey D. Luffy"
22466 @pirate.reload.ship_attributes = { name: "Davy Jones Gold Dagger", _destroy: "1" }
22467 @pirate.reload.ship_attributes = { "id" => @ship.id, "name" => "Davy Jones Gold Dagger" }
22468 @ship.stub(:id, "ABC1X") do
22469 @pirate.ship_attributes = { id: @ship.id, name: "Davy Jones Gold Dagger" }
22470 [1, "1", true, "true"].each do |truth|
22471 [nil, "0", 0, "false", false].each do |not_truth|
22472 @pirate.update(ship_attributes: { id: @pirate.ship.id, _destroy: "1" })
22473 @pirate.update(catchphrase: "Arr", ship_attributes: { id: @ship.id, name: "Mister Pablo" })
22474 @pirate.attributes = { ship_attributes: { id: @ship.id, _destroy: "1" } }
22475 @ship.reload.pirate_attributes = { catchphrase: "Arr", _destroy: "1" }
22476 @ship.reload.pirate_attributes = { "id" => @pirate.id, "catchphrase" => "Arr" }
22477 @pirate.stub(:id, "ABC1X") do
22478 @ship.pirate_attributes = { id: @pirate.id, catchphrase: "Arr" }
22479 @ship.update(pirate_attributes: { id: @ship.pirate.id, _destroy: "1" })
22480 @ship.attributes = { pirate_attributes: { :id => pirate.id, "_destroy" => true } }
22481 @pirate.parrots_attributes = [{ peg_leg: true }]
22482 :catchphrase => "Arr",
22483 association_getter => { "foo" => { name: "Grace OMalley" } })
22484 @pirate.public_send(association_setter, [{ id: @child_1.id, name: "Grace OMalley" }])
22485 @pirate.public_send(association_setter, [{ id: @child_1.id, _destroy: "1" }])
22486 @child_1.stub(:id, "ABC1X") do
22487 @child_2.stub(:id, "ABC2X") do
22488 { id: @child_1.id, name: "Grace OMalley" },
22489 { id: @child_2.id, name: "Privateers Greed" }
22490 @pirate.attributes = { association_getter => [{ id: 1234567890 }] }
22491 @pirate.attributes = { association_getter => [{ id: other_child.id }] }
22492 association_getter => { "foo" => { name: "Grace OMalley" }, "bar" => { name: "Privateers Greed" } }
22493 @pirate.public_send(association_setter, "foo" => { "_destroy" => "0" })
22494 attributes["123726353"] = { name: "Grace OMalley" }
22495 attributes["2"] = { name: "Privateers Greed" } # 2 is lower then 123726353
22496 association_getter => { "foo" => { id: @child_1.id, name: "Grace OMalley" } })
22497 ["1", 1, "true", true].each do |true_variable|
22498 @alternate_params[association_getter].merge("baz" => { :id => record.id, "_destroy" => true_variable })
22499 [nil, "", "0", 0, "false", false].each do |false_variable|
22500 @pirate.public_send(association_setter, @alternate_params[association_getter].merge("baz" => { :id => @child_1.id, "_destroy" => true }))
22501 human = Human.create!(name: "John",
22502 interests_attributes: [{ topic: "Cars" }, { topic: "Sports" }])
22503 @pirate.attributes = { parrots_attributes: { foo: { name: "Lovely Day" }, bar: { name: "Blown Away" } } }
22504 @child_1, @child_2 = @pirate.birds
22505 @child_1, @child_2 = @pirate.parrots
22506 @pirate.attributes = { parrots_attributes: { "foo" => { name: "Big Big Love" } } }
22507 @pirate.attributes = { parrots_attributes: { "foo" => { name: "Lovely Day" }, "bar" => { name: "Blown Away" } } }
22508 @pirate.attributes = { parrots_attributes: { "foo" => { name: "Lovely Day" },
22509 @pet1, @pet2 = pets(:chew), pets(:mochi)
22510 @params = {
22511 assert_equal ["Foo", "Bar"], @owner.pets.map(&:name)
22512 @pet1 = pets(:chew)
22513 attributes = { pets_attributes: { "1" => { id: @pet1.id,
22514 name: "Foo2",
22515 _destroy: true } } }
22516 @part = @ship.parts.create!(name: "Mast")
22517 @pirate.attributes = { ship_attributes: { id: @ship.id, parts_attributes: [{ id: @part.id, trinkets_attributes: [{ id: @trinket.id, name: "changed" }] }] } }
22518 @pirate.attributes = { ship_attributes: { id: @ship.id, parts_attributes: [{ id: @part.id, trinkets_attributes: [{ id: @trinket.id, _destroy: true }] }] } }
22519 @pirate.attributes = { ship_attributes: { id: @ship.id, parts_attributes: [{ id: @part.id, trinkets_attributes: [{ name: "created" }] }] } }
22520 @ship.parts_attributes = [{ id: @part.id, name: "Deck" }]
22521 @ship.parts_attributes = [{ id: @part.id, trinkets_attributes: [{ id: @trinket.id, name: "Ruby" }] }]
22522 @ship.attributes = { parts_attributes: [{ id: @part.id, trinkets_attributes: [{ id: @trinket.id, name: "changed" }] }] }
22523 @ship.attributes = { parts_attributes: [{ id: @part.id, trinkets_attributes: [{ id: @trinket.id, _destroy: true }] }] }
22524 assert_difference("@part.trinkets.count", -1) { @ship.save }
22525 @ship.attributes = { parts_attributes: [{ id: @part.id, trinkets_attributes: [{ name: "created" }] }] }
22526 ship = Ship.new(name: "The Black Rock")
22527 part = ShipPart.new(name: "Stern", ship_attributes: { name: nil })
22528 pirate.treasures_attributes = [{ id: nil }]
22529 c1 = Course.find(1)
22530 c2 = Course.find(2)
22531 e1 = Entrant.find(1)
22532 e2 = Entrant.find(2)
22533 e3 = Entrant.find(3)
22534 c1.name = "Typo"
22535 e1.name = "Typo"
22536 raise "No I messed up."
22537 attributes = { "last_read(1i)" => "2004", "last_read(2i)" => "6", "last_read(3i)" => "24" }
22538 attributes = { "last_read(1i)" => "", "last_read(2i)" => "6", "last_read(3i)" => "24" }
22539 attributes = { "last_read(1i)" => "2004", "last_read(2i)" => "", "last_read(3i)" => "24" }
22540 attributes = { "last_read(1i)" => "2004", "last_read(2i)" => "6", "last_read(3i)" => "" }
22541 attributes = { "last_read(1i)" => "", "last_read(2i)" => "6", "last_read(3i)" => "" }
22542 attributes = { "last_read(1i)" => "2004", "last_read(2i)" => "", "last_read(3i)" => "" }
22543 attributes = { "last_read(1i)" => "", "last_read(2i)" => "", "last_read(3i)" => "24" }
22544 attributes = { "last_read(1i)" => "", "last_read(2i)" => "", "last_read(3i)" => "" }
22545 assert_equal Time.utc(2004, 6, 24, 16, 24, 0), topic.written_on
22546 assert_equal Time.utc(2004, 6, 24, 23, 24, 0), topic.written_on
22547 topic = Topic.new("bonus_time(4i)" => "01", "bonus_time(5i)" => "05")
22548 topic = Topic.new("written_on(1i)" => "1952", "written_on(2i)" => "3", "written_on(3i)" => "11")
22549 topic = Topic.create_with("written_on(1i)" => "1952", "written_on(2i)" => "3", "written_on(3i)" => "11").new
22550 Topic.new("written_on(4i)" => "13", "written_on(5i)" => "55")
22551 address = Address.new("The Street", "The City", "The Country")
22552 attributes = { "address(1)" => address.street, "address(2)" => address.city, "address(3)" => address.country }
22553 attributes = { "address(3)" => address.country, "address(2)" => address.city, "address(1)" => address.street }
22554 attributes = { "address(2)" => address.city, "address(3)" => address.country }
22555 attributes = { "address(1)" => "", "address(2)" => address.city, "address(3)" => address.country }
22556 attributes = { "address(1)" => "The Street", "address(2)" => address.city, "address(3000)" => address.country }
22557 @went_up = false
22558 def up; @went_up = true; end
22559 def down; @went_down = true; end
22560 def puts(*)
22561 ["down", "001", "Valid people have last names"],
22562 ["down", "003", "Innocent jointable"],
22563 ["down", "001", "People have hobbies"],
22564 ["down", "002", "People have descriptions"],
22565 ["up", "004", "********** NO FILE **********"]
22566 _, migrator_a = migrator_class(3)
22567 _, migrator_b = migrator_class(2)
22568 _, migrator_b = migrator_class(3)
22569 define_method(:up) { yield(:up, x); super() }
22570 define_method(:down) { yield(:down, x); super() }
22571 }) if block_given?
22572 m(nil, i + 1) { |c, migration|
22573 define_method(:migrations) { |*|
22574 @undefined_consts = {}
22575 [:Firm, :Client].each do |const|
22576 clients = []
22577 ["up", "230", "Add people hobby"],
22578 ["up", "231", "Add people last name"],
22579 ["up", "20210716123013", "Add people number of legs"],
22580 ["up", "001", "Valid people have last names"],
22581 ["up", "002", "We need reminders"],
22582 ["up", "003", "Innocent jointable"],
22583 ["down", "20090101010101", "People have hobbies"],
22584 pass_one = [Sensor.new("One", 1)]
22585 pass_two = [Sensor.new("One", 1), Sensor.new("Three", 3)]
22586 assert pass_two.all? { |x| !x.went_down }
22587 pass_three = [Sensor.new("One", 1),
22588 Sensor.new("Two", 2),
22589 Sensor.new("Three", 3)]
22590 migrations = [Sensor.new(nil, 0), Sensor.new(nil, 1), Sensor.new(nil, 2)]
22591 assert migrations.all? { |m| !m.went_down }
22592 assert migrations.all? { |m| !m.went_up }
22593 assert_equal [[:up, 1]], calls
22594 assert_equal [[:up, 2]], calls
22595 assert_equal [[:up, 1], [:up, 2], [:up, 3]], calls
22596 assert_equal [[:down, 3], [:down, 2]], calls
22597 assert_equal [[:down, 1]], calls
22598 _, migrations = sensors(3)
22599 result = migrator.run(:up, 1)
22600 assert_equal [[:up, 2], [:up, 3]], calls
22601 long_name = "a" * (name_limit + 1)
22602 short_name = "a" * name_limit
22603 def create_table; "hi mom!"; end
22604 @went_up = true
22605 @internal_metadata[:foo] = "bar"
22606 assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
22607 data_column = columns.detect { |c| c.name == "data" }
22608 t.column :foo, :bar
22609 AND state = 'idle'
22610 @connection.create_table(:delete_me, force: true) { |t| }
22611 }.fetch(classname) {
22612 [:name, :qualification, :experience].each { |s| assert_equal :string, column(s).type }
22613 [:qualification, :experience].each { |c| assert column(c) }
22614 [:qualification, :experience].each { |c| assert_not column(c) }
22615 [:created_at, :updated_at].each { |c| assert column(c) }
22616 [:created_at, :updated_at].each { |c| assert_not column(c) }
22617 t.index [:name, :age], comment: "This is a comment"
22618 t.string :name, default: -> { "gen_random_uuid()" }
22619 t.string :name, default: -> { "UUID()" }
22620 assert_match(/\A(.+)-(.+)-(.+)-(.+)\Z/, person_data.fetch("name"))
22621 @columns = @indexes = nil
22622 columns.detect { |c| c.name == name.to_s }
22623 indexes.detect { |i| i.name == name.to_s }
22624 def write(text = ""); end
22625 to_delete = Dir[@migrations_path + "/*.rb"] - @existing_migrations
22626 @existing_migrations = Dir[@migrations_path + "/*.rb"]
22627 files_count = Dir[@migrations_path + "/*.rb"].length
22628 sources = {}
22629 travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do
22630 travel_to(Time.utc(2010, 2, 20, 10, 10, 10)) do
22631 skipped = []
22632 on_skip = Proc.new { |name, migration| skipped << "#{name} #{migration.name}" }
22633 columns: ["position_1"]
22634 columns: ["position_2"]
22635 columns: ["position_3"]
22636 id_column = td.columns.find { |col| col.name == "id" }
22637 foo_column = td.columns.find { |col| col.name == "foo" }
22638 assert_equal ["another_col", "comment_id", "post_id"], join_td.columns.map(&:name).sort
22639 assert_equal ["comment_id", "post_id"], join_td.columns.map(&:name).sort
22640 pk = connection.send(:column_for, :users, :id)
22641 t.references :bar, index: { unique: true }
22642 fk = @connection.foreign_keys("testings").find { |k| k.to_table == "testing_parents" }
22643 assert_equal([["testings", "testing_parents", "parent_id"]],
22644 fks.map { |fk| [fk.from_table, fk.to_table, fk.column] })
22645 fk_definitions = fks.map { |fk| [fk.from_table, fk.to_table, fk.column] }
22646 assert_equal([["testings", "testing_parents", "parent1_id"],
22647 ["testings", "testing_parents", "parent2_id"],
22648 ["testings", "testings", "self_join_id"]], fk_definitions)
22649 filename = "#{number}_#{name.underscore}.rb"
22650 assert_nothing_raised { CheckPending.new(proc { }).call({}) }
22651 CheckPending.new(proc { flunk }).call({})
22652 app.expect :call, nil, [{}]
22653 migrations = [Migration.new("a", 1), Migration.new("b", 2), Migration.new("c", 3)]
22654 default_keys = [":limit", ":precision", ":scale", ":default", ":null", ":collation", ":comment", ":primary_key", ":if_exists", ":if_not_exists"]
22655 default_keys.concat([":auto_increment", ":charset", ":as", ":size", ":unsigned", ":first", ":after", ":type", ":stored"])
22656 default_keys.concat([":array", ":using", ":cast_as", ":as", ":type", ":enum_type", ":stored"])
22657 table_keys = [":temporary", ":if_not_exists", ":options", ":as", ":comment", ":charset", ":collation"]
22658 primary_keys = [":limit", ":default", ":precision"]
22659 table_keys.concat([":rename"])
22660 t.string :first_name, index: { nema: "test" }
22661 add_index "test_models", "first_name", nema: "my_index"
22662 too_long_index_name = good_index_name + "x"
22663 connection.add_index(table_name, [:foo], name: "foo")
22664 connection.add_index :testings, [:foo, :bar], name: "my_index"
22665 connection.add_index :testings, [:foo, :bar], length: { foo: 10, bar: nil }
22666 connection.add_index("testings", ["last_name"], length: { last_name: 10 })
22667 connection.add_index("testings", ["last_name", "first_name"], length: 10)
22668 connection.add_index("testings", ["last_name", "first_name"], length: { last_name: 10, first_name: 20 })
22669 connection.add_index("testings", ["key"], name: "key_idx", unique: true)
22670 connection.add_index("testings", ["last_name"], order: { last_name: :desc })
22671 connection.add_index("testings", ["last_name", "first_name"], order: { last_name: :desc })
22672 connection.add_index("testings", ["last_name", "first_name"], order: { last_name: :desc, first_name: :asc })
22673 connection.add_index("testings", ["last_name", "first_name"], order: :desc)
22674 connection.add_index("testings", "last_name", where: "first_name = 'john doe'")
22675 connection.add_index("testings", "last_name", include: [:foo, :bar])
22676 connection.add_index("testings", "last_name", include: :foo, where: "first_name = 'john doe'")
22677 assert foreign_keys.all? { |fk| fk.to_table == "rockets" }
22678 column: "rocket_id", primary_key: "pk", name: "custom_pk")
22679 assert_equal [["astronauts", "rockets", "rocket_id"]],
22680 database: ":memory:",
22681 assert_match %r{\s+add_foreign_key "fk_test_has_fk", "fk_test_has_pk", column: "fk_id", primary_key: "pk_id"$}, output
22682 assert_match %r{\s+add_foreign_key "fk_test_has_fk", "fk_test_has_pk", column: "fk_id", primary_key: "pk_id", name: "fk_name"$}, output
22683 create_table("cities") { |t| }
22684 create_table("houses") do |t|
22685 assert_no_changes -> { column_for(:astronauts, :rocket_id).bigint? }, from: true do
22686 t.index [:artist_id, :music_id]
22687 t.column :foo, :string, limit: 5
22688 column = connection.columns(:more_testings).find { |el| el.name == "testings_id" }
22689 long_table_name = "a" * (connection.table_name_length + 1)
22690 { precision: 0 }
22691 { precision: nil }
22692 class V5_2 < V6_0
22693 class V5_1 < V6_0
22694 class V5_0 < V6_0
22695 class V4_2 < V6_0
22696 assert_match %r{create_table "legacy_primary_keys", id: :(?:integer|serial), (?!default: nil)}, schema
22697 }.new)
22698 def foo(kw:)
22699 assert_equal "bar", recorder.foo(kw: "bar")
22700 tables = @recorder.commands.map { |_cmd, args, _block| args }
22701 assert_equal [[:world], [:hello]], tables
22702 block = Proc.new { |t| t.string :name }
22703 assert_equal [[:create_table, ["apples"], block], [:drop_table, ["elderberries"], nil],
22704 [:create_table, ["clementines"], block], [:create_table, ["dates"], nil],
22705 [:drop_table, ["bananas"], block], [:drop_table, ["grapes"], nil],
22706 [:drop_table, ["figs"], block]], @recorder.commands
22707 [:rename_column, [:fruits, :cultivar, :kind]],
22708 [:remove_column, [:fruits, :name, :string], nil],
22709 [:remove_column, [:fruits, :name, :string, {}], nil],
22710 block = Proc.new do |t|
22711 [:change_table, [:fruits]],
22712 [:change_table, [:fruits]]
22713 ], @recorder.commands.map { |command| command[0...-1] }
22714 assert_equal [:drop_table, [:system_settings, {}], nil], drop_table
22715 block = Proc.new { }
22716 assert_equal [:rename_table, [:new, :old]], rename
22717 remove = @recorder.inverse_of :add_column, [:table, :column, :type, {}]
22718 assert_equal [:remove_column, [:table, :column, :type, {}], nil], remove
22719 @recorder.inverse_of :change_column, [:table, :column, :type, {}]
22720 assert_equal [:change_column_default, [:table, :column, from: "new_value", to: "old_value"]], change
22721 assert_equal [:change_column_comment, [:table, :column, from: "new_value", to: "old_value"]], change
22722 assert_equal [:change_column_comment, [:table, :column, from: "new_value", to: nil]], change
22723 assert_equal [:change_table_comment, [:table, from: "new_value", to: "old_value"]], change
22724 assert_equal [:change_table_comment, [:table, from: "new_value", to: nil]], change
22725 add = @recorder.inverse_of :remove_column, [:table, :column, :type, {}]
22726 assert_equal [:add_column, [:table, :column, :type, {}], nil], add
22727 rename = @recorder.inverse_of :rename_column, [:table, :old, :new]
22728 assert_equal [:rename_column, [:table, :new, :old]], rename
22729 remove = @recorder.inverse_of :add_index, [:table, [:one, :two]]
22730 assert_equal [:remove_index, [:table, [:one, :two]], nil], remove
22731 remove = @recorder.inverse_of :add_index, [:table, [:one, :two], name: "new_index"]
22732 assert_equal [:remove_index, [:table, [:one, :two], name: "new_index"], nil], remove
22733 add = @recorder.inverse_of :remove_index, [:table, :one]
22734 assert_equal [:add_index, [:table, :one]], add
22735 add = @recorder.inverse_of :remove_index, [:table, [:one, :two], { options: true }]
22736 assert_equal [:add_index, [:table, [:one, :two], options: true]], add
22737 add = @recorder.inverse_of :remove_index, [:table, { column: [:one, :two], options: true }]
22738 add = @recorder.inverse_of :remove_index, [:table, { column: [:one, :two], name: "new_index" }]
22739 assert_equal [:add_index, [:table, [:one, :two], name: "new_index"]], add
22740 add = @recorder.inverse_of :remove_index, [:table, { column: [:one, :two] }]
22741 assert_equal [:add_index, [:table, [:one, :two]]], add
22742 rename = @recorder.inverse_of :rename_index, [:table, :old, :new]
22743 assert_equal [:rename_index, [:table, :new, :old]], rename
22744 add = @recorder.inverse_of :remove_timestamps, [:table, { null: true }]
22745 assert_equal [:add_timestamps, [:table, { null: true }], nil], add
22746 assert_equal [:add_reference, [:table, :taggable, { polymorphic: true }], nil], add
22747 assert_equal [:add_reference, [:table, :taggable, { index: true, foreign_key: true }], nil], add
22748 assert_equal [:add_reference, [:table, :user], nil], add
22749 assert_equal [:remove_foreign_key, [:dogs, :people, column: "owner_id"], nil], enable
22750 assert_equal [:add_foreign_key, [:dogs, :people, column: "owner_id"]], enable
22751 enable = @recorder.inverse_of :add_foreign_key, [:dogs, :people, column: "owner_id", name: "fk"]
22752 assert_equal [:remove_foreign_key, [:dogs, :people, column: "owner_id", name: "fk"], nil], enable
22753 enable = @recorder.inverse_of :remove_foreign_key, [:dogs, :people, column: "owner_id", name: "fk"]
22754 assert_equal [:add_foreign_key, [:dogs, :people, column: "owner_id", name: "fk"]], enable
22755 assert_equal [:add_foreign_key, [:dogs, :people, primary_key: "person_id"]], enable
22756 assert_equal [:add_foreign_key, [:dogs, :people, primary_key: "uuid"]], enable
22757 assert_equal [:add_foreign_key, [:dogs, :people, column: :owner_id]], enable
22758 assert_equal [:add_check_constraint, [:dogs, "speed > 0", name: "speed_check"], nil], enable
22759 assert_equal [:add_unique_key, [:dogs, ["speed"], deferrable: :deferred, name: "uniq_speed"], nil], enable
22760 enable = @recorder.inverse_of :remove_unique_key, [:dogs, ["speed"]]
22761 assert_equal [:add_unique_key, [:dogs, ["speed"]], nil], enable
22762 drop = @recorder.inverse_of :create_enum, [:color, ["blue", "green"]]
22763 assert_equal [:drop_enum, [:color, ["blue", "green"]], nil], drop
22764 create = @recorder.inverse_of :drop_enum, [:color, ["blue", "green"]]
22765 assert_equal [:create_enum, [:color, ["blue", "green"]], nil], create
22766 rename_column "test_models", "id", "id_test"
22767 rename_column "test_models", "id_test", "id"
22768 add_index "test_models", ["hat_style", "hat_size"], unique: true
22769 assert old_columns.find { |c| c.name == "age" && c.type == :integer }
22770 assert_not new_columns.find { |c| c.name == "age" && c.type == :integer }
22771 assert new_columns.find { |c| c.name == "age" && c.type == :string }
22772 c.name == "approved" && c.type == :boolean && default == true
22773 c.name == "approved" && c.type == :boolean && default == false
22774 t.string "col_two", limit: 128, null: false
22775 remove_column("my_table", "col_two")
22776 rename_column("my_table", "col_one", "col_three")
22777 assert_equal ["id", "created_at", "updated_at"], columns
22778 string = "foo
bar"
22779 add_column "test_models", "bio", :text
22780 add_column "test_models", "wealth", :decimal, precision: "30", scale: "10"
22781 bio: "I was born ....", age: 18, height: 1.78,
22782 moment_of_truth: "1782-10-10 21:40:18", male: true
22783 assert_equal "I was born ....", bob.bio
22784 expect :add_column, nil, [:delete_me, :id, :primary_key], primary_key: true, first: true
22785 expect :add_column, nil, [:delete_me, :foo, :integer]
22786 expect :add_column, nil, [:delete_me, :bar, :integer]
22787 t.integer :foo, :bar
22788 expect :add_column, nil, [:delete_me, :foo, :bigint]
22789 expect :add_column, nil, [:delete_me, :bar, :bigint]
22790 t.bigint :foo, :bar
22791 expect :add_column, nil, [:delete_me, :foo, :string]
22792 expect :add_column, nil, [:delete_me, :bar, :string]
22793 t.string :foo, :bar
22794 expect :add_column, nil, [:delete_me, :foo, :json]
22795 expect :add_column, nil, [:delete_me, :bar, :json]
22796 t.json :foo, :bar
22797 expect :add_column, nil, [:delete_me, :foo, :xml]
22798 expect :add_column, nil, [:delete_me, :bar, :xml]
22799 t.xml :foo, :bar
22800 expect :add_column, nil, [:delete_me, :bar, :integer], null: false
22801 expect :add_index, nil, [:delete_me, :bar]
22802 expect :add_index, nil, [:delete_me, :bar], unique: true
22803 expect :index_exists?, nil, [:delete_me, :bar]
22804 expect :index_exists?, nil, [:delete_me, :bar], unique: true
22805 expect :rename_index, nil, [:delete_me, :bar, :baz]
22806 expect :change_column, nil, [:delete_me, :bar, :string]
22807 expect :change_column, nil, [:delete_me, :bar, :string], null: true
22808 expect :change_column_null, nil, [:delete_me, :bar, true, nil]
22809 expect :remove_columns, nil, [:delete_me, :bar, :baz]
22810 t.remove :bar, :baz
22811 expect :remove_columns, nil, [:delete_me, :bar, :baz], type: :string, null: false
22812 t.remove :bar, :baz, type: :string, null: false
22813 expect :remove_index, nil, [:delete_me, :bar], unique: true
22814 expect :rename_column, nil, [:delete_me, :bar, :baz]
22815 t.rename :bar, :baz
22816 t.column :one, :string, default: "hello"
22817 one = columns.detect { |c| c.name == "one" }
22818 two = columns.detect { |c| c.name == "two" }
22819 three = columns.detect { |c| c.name == "three" }
22820 four = columns.detect { |c| c.name == "four" }
22821 five = columns.detect { |c| c.name == "five" } unless mysql
22822 array_column = columns.detect { |c| c.name == "foo" }
22823 foo = columns.detect { |c| c.name == "foo" }
22824 default = columns.detect { |c| c.name == "default_int" }
22825 created_at_column = created_columns.detect { |c| c.name == "created_at" }
22826 updated_at_column = created_columns.detect { |c| c.name == "updated_at" }
22827 connection.execute("insert into testings (#{quoted_id}, #{quoted_foo}) values (1, 'hello')")
22828 connection.execute("insert into testings (#{quoted_id}, #{quoted_foo}, #{quoted_bar}) values (2, 'hello', NULL)")
22829 column = connection.columns(:testings).find { |c| c.name == "foo" }
22830 assert_equal false, connection.columns(:testings).find { |c| c.name == "foo" }.null
22831 assert connection.columns(:testings).find { |c| c.name == "foo" }.null
22832 [:wagons, :trains].each do |table|
22833 @debugs = []
22834 logger.sql(Event.new(0.9, sql: "hi mom!"))
22835 logger.sql(Event.new(0.9, sql: "hi mom!", name: "foo"))
22836 logger.sql(Event.new(0.9, sql: "hi mom!", name: "SCHEMA"))
22837 logger.sql(Event.new(0.9, sql: verb.to_s))
22838 logger.sql(Event.new(0.9, sql: verb.to_s, name: "SQL"))
22839 logger.sql(Event.new(0.9, sql: verb.to_s, name: "Model Load"))
22840 logger.sql(Event.new(0.9, sql: verb.to_s, name: "Model Exists"))
22841 logger.sql(Event.new(0.9, sql: "SELECT * from models", name: "Model Load", async: true, lock_wait: 0.01))
22842 logger.sql(Event.new(0.9, sql: sql))
22843 logger.sql(Event.new(0, sql: "hi mom!"))
22844 Developer.where(id: [1, 2, 3, 4, 5]).load
22845 assert_match(%{["id", 1], ["id", 2], ["id", 3], ["id", 4], ["id", 5]}, @logger.logged(:debug).last)
22846 Binary.create(data: { a: 1 })
22847 p1 = Person.find(1)
22848 p2 = Person.find(1)
22849 p1.first_name = "stu"
22850 p2.first_name = "sue"
22851 p2.first_name = "sue2"
22852 p1 = Person.new(first_name: "anika")
22853 p2 = Person.find(p1.id)
22854 p1 = Person.new(first_name: "mira")
22855 p1.first_name = "mira2"
22856 p1.first_name = "mira3"
22857 person.id = 2
22858 t1.title = "new title1"
22859 t2.title = "new title2"
22860 assert_queries(1) { t1.update(title: "title2") }
22861 assert_queries(1) { t2.save! }
22862 p1 = Person.create!(first_name: "anika")
22863 counter_test model, -1 do |id|
22864 p1 = Person.new(first_name: "fjord")
22865 frog = ::Frog.create(name: "Old Frog")
22866 frog.name = "New Frog"
22867 first, second = duel { Person.find 1 }
22868 def duel(zzz = 5, &block)
22869 t0, t1, t2, t3 = nil, nil, nil, nil
22870 t0 = Time.now
22871 t1 = Time.now
22872 t2 = Time.now
22873 t3 = Time.now
22874 assert t1 > t0 + zzz
22875 [t0.to_f..t1.to_f, t2.to_f..t3.to_f]
22876 assert_match(/t\.#{column_type}\s+"settings"/, output)
22877 x = klass.new(payload: { "string" => "foo", :symbol => :bar })
22878 assert_equal({ "string" => "foo", :symbol => :bar }, x.payload_before_type_cast)
22879 assert_equal({ "string" => "foo", "symbol" => "bar" }, x.payload)
22880 assert_equal({ "string" => "foo", "symbol" => "bar" }, x.reload.payload)
22881 data = '{"a_key":"a_value"}'
22882 assert_equal({ "a_key" => "a_value" }, hash)
22883 assert_equal({ "a_key" => "a_value" }, type.deserialize(data))
22884 assert_equal({}, type.deserialize("{}"))
22885 assert_equal({ "key" => nil }, type.deserialize('{"key": null}'))
22886 x.payload = { '"a\'' => "b" }
22887 assert_equal({ "k" => "v" }, x.payload)
22888 @connection.execute(insert_statement_per_database('{"k1":"v1", "k2":"v2", "k3":[1,2,3]}'))
22889 assert_equal({ "k1" => "v1", "k2" => "v2", "k3" => [1, 2, 3] }, x.payload)
22890 json = klass.create!(payload: "foo")
22891 @connection.execute(insert_statement_per_database('["v0",{"k1":"v1"}]'))
22892 assert_equal(["v0", { "k1" => "v1" }], x.payload)
22893 x.payload = ["v1", { "k2" => "v2" }, "v3"]
22894 y = x.dup
22895 json.payload = { "one" => "two" }
22896 json.payload["three"] = "four"
22897 assert_equal({ "one" => "two", "three" => "four" }, json.payload)
22898 json.payload = { "three" => "four", "one" => "two" }
22899 json.payload = [{ "three" => "four", "one" => "two" }, { "seven" => "eight", "five" => "six" }]
22900 new_klass.create!(settings: MySettings.new("one" => "two"))
22901 assert_equal({ "one" => "two" }, record.settings.to_hash)
22902 assert_equal({ "three" => "four" }, record.reload.settings.to_hash)
22903 super + [:password]
22904 x.payload[11] = "foo"
22905 PP.pp(x, io)
22906 assert_match %r(\A#{native_type}\b), sql_type
22907 age: 16,
22908 preferences: { "shows" => "anime" }
22909 assert_match %r{^\{"namespaced_contact":\{}, json
22910 assert_match %r{^\{"contact":\{}, json
22911 assert_match %r{"age":16}, json
22912 assert_match %r{"preferences":\{"shows":"anime"\}}, json
22913 json = @contact.to_json(only: [:name, :age])
22914 assert_no_match %r{"preferences":\{"shows":"anime"\}}, json
22915 json = @contact.to_json(except: [:name, :age])
22916 assert_no_match %r{"age":16}, json
22917 super({ only: %w(name) }.freeze)
22918 super(only: %w(name))
22919 super(except: %w(age))
22920 super({ except: %w(age) }.merge!(options))
22921 options = { only: :name }.freeze
22922 @mary = authors(:mary)
22923 assert_match %r{"posts":\[}, json
22924 assert_match %r{"id":1}, json
22925 assert_match %r{"name":"David"}, json
22926 assert_match %r{"author_id":1}, json
22927 assert_match %r{"body":"Such a lovely day"}, json
22928 assert_match %r{"title":"So I was thinking"}, json
22929 json = @david.to_json(include: { posts: { only: :title } })
22930 assert_no_match %r{"body":"Such a lovely day"}, json
22931 json = @david.to_json(include: { posts: { include: { comments: { only: :body } } } })
22932 assert_match %r{"comments":\[}, json
22933 assert_match %r{\{"body":"Thank you again for the welcome"\}}, json
22934 assert_match %r{\{"body":"Don't think too hard"\}}, json
22935 assert_no_match %r{"post_id":}, json
22936 json = @david.to_json(
22937 include: {
22938 posts: {
22939 tag: { only: :name }
22940 assert_match %r{"taggings":\[}, json
22941 assert_match %r{"tag":\{"name":"General"\}}, json
22942 only: :id,
22943 authors = [@david, @mary]
22944 assert_equal %([{"name":"David"},{"name":"Mary"}]), ActiveSupport::JSON.encode(authors, only: :name)
22945 assert_equal %([{"id":1},{"id":2}]), encoded
22946 only: :name,
22947 posts: { only: :id }
22948 ['"name":"David"', '"posts":[', '{"id":1}', '{"id":2}', '{"id":4}',
22949 authors_hash = {
22950 1 => @david,
22951 2 => @mary
22952 assert_equal %({"1":{"author":{"name":"David"}}}), ActiveSupport::JSON.encode(authors_hash, only: [1, :name])
22953 authors_relation = Author.where(id: [@david.id, @mary.id]).order(:id)
22954 assert_equal '[{"author":{"name":"David"}},{"author":{"name":"Mary"}}]', json
22955 def write(text = "")
22956 create_table("horses") do |t|
22957 change_table("horses") do |t|
22958 create_table("new_horses") do |t|
22959 t.index [:name, :color]
22960 t.index [:color]
22961 t.remove_index [:name, :color]
22962 revert { super }
22963 up_only { execute "update horses set oldie = 1" }
22964 index_definition = ["horses", [:name, :color]]
22965 received = []
22966 migration.test = ->(dir) {
22967 assert_equal [:both, :up, :both, :down], received
22968 [:create_table, ["clementines"], nil], [:create_table, ["dates"], nil],
22969 [:drop_table, ["figs"], nil]], recorder.commands
22970 client.id = 1
22971 firm = Firm.find(4)
22972 firm.name << ", Inc."
22973 firm.name = "Huey, Dewey, & Louie LLC"
22974 firm.name = "a " * 100
22975 assert_equal "4-a-a-a-a-a-a-a-a-a-a", firm.to_param
22976 firm.name = "ab
" * 100
22977 firm.name = " "
22978 assert_match(/\/#{dev.id}$/, dev.cache_key)
22979 id = 1_000_000
22980 Book.insert({ id: id, name: "Rework", author_id: 1 })
22981 Book.upsert({ id: id, name: "Remote", author_id: 1 })
22982 Book.insert!({ name: "Rework", author_id: 1 })
22983 { name: "Rework", author_id: 1 },
22984 { name: "Design of Everyday Things", author_id: 1 },
22985 { name: "Clean Code", author_id: 1 },
22986 { name: "Ruby Under a Microscope", author_id: 1 },
22987 { name: "Peopleware", author_id: 1 },
22988 { name: "About Face", author_id: 1 },
22989 { name: "Eloquent Ruby", author_id: 1 },
22990 { name: "Agile Web Development with Rails", author_id: 1 },
22991 result = Book.insert_all! [{ name: "Rework", author_id: 1 }]
22992 result = Book.insert_all! [{ name: "Rework", author_id: 1 }], returning: []
22993 result = Book.insert_all! [{ name: "Rework", author_id: 1 }], returning: false
22994 result = Book.insert_all! [{ name: "Rework", author_id: 1 }], returning: [:id, :name]
22995 result = Book.insert_all! [{ name: "Rework", author_id: 1 }], returning: Arel.sql("UPPER(name) as name")
22996 Book.insert_all [{ id: 1, name: "Agile Web Development with Rails" }]
22997 { author_id: 8, name: "Refactoring" },
22998 { author_id: 8, name: "Refactoring" }
22999 { id: 200, author_id: 8, name: "Refactoring" },
23000 { id: 201, author_id: 8, name: "Refactoring" }
23001 Book.insert({ author_id: 8, name: "Refactoring", format: "UNEXPECTED" })
23002 Book.insert_all [{ id: 1, name: "Agile Web Development with Rails" }],
23003 Book.insert_all [{ name: "Rework", author_id: 1 }], unique_by: :isbn
23004 Book.insert_all [{ name: "Remote", author_id: 1 }], unique_by: %i( author_id name )
23005 Book.insert_all [{ name: "Renote", author_id: 1 }], unique_by: :index_books_on_isbn
23006 Book.insert_all [{ name: "Recoat", author_id: 1 }], unique_by: :id
23007 Book.upsert_all [{ name: "Rework", author_id: 1 }], unique_by: :isbn
23008 book = Book.create!(external_id: "abc")
23009 [ :cats, %i( author_id isbn ), :author_id ].each do |missing_or_non_unique_by|
23010 Book.insert_all [{ name: "Rework", author_id: 1 }], unique_by: missing_or_non_unique_by
23011 Book.upsert_all [{ name: "Rework", author_id: 1 }], unique_by: missing_or_non_unique_by
23012 Cart.insert_all [{ id: 1, shop_id: 1, title: "My cart" }], unique_by: [:shop_id, :id]
23013 Cart.upsert_all [{ id: 3, shop_id: 2, title: "My other cart" }], unique_by: [:shop_id, :id]
23014 Cart.insert_all! [{ id: 2, shop_id: 1, title: "My cart" }]
23015 Cart.insert_all [{ id: 1, shop_id: 1, title: "My cart" }]
23016 Cart.insert_all! [{ id: 2, shop_id: 1, title: "My cart 2" }]
23017 Cart.upsert_all [{ id: 3, shop_id: 2, title: "My other cart" }]
23018 Book.insert({ name: "Rework", author_id: 1 })
23019 Book.insert_all [{ name: "Remote", author_id: 1 }, { name: "Renote", author_id: 1 }]
23020 result = Book.insert_all [{ title: "Remote", author_id: 1 }], returning: :title
23021 Book.upsert_all [{ id: 101, title: "Perelandra", author_id: 7, isbn: "1974522598" }]
23022 Book.upsert_all [{ id: 101, title: "Perelandra 2", author_id: 6, isbn: "111111" }], update_only: %i[ title isbn ]
23023 SpecialCategory.insert_all [{ name: "First" }, { name: "Second", type: nil }]
23024 SpecialCategory.upsert_all [{ id: 103, name: "First" }, { id: 104, name: "Second", type: nil }]
23025 Book.upsert({ name: "Remote", author_id: 1 })
23026 Book.upsert_all [{ name: "Remote", author_id: 1 }, { name: "Renote", author_id: 1 }]
23027 Book.upsert_all [{ id: 1, name: new_name }]
23028 Book.upsert_all [{ id: 1, name: "New edition" }], unique_by: :id
23029 Book.upsert_all [{ id: 101, name: "Perelandra", author_id: 7 }]
23030 Book.upsert_all [{ id: 103, name: "Perelandra", author_id: 7, isbn: "1974522598" }],
23031 Book.upsert_all [{ id: 101, name: "Perelandra", author_id: 7, isbn: "1974522598" }], on_duplicate: "NAME=values(name)", update_only: :name
23032 Book.upsert_all [{ id: 101, name: "Perelandra", author_id: 7, isbn: "1974522598" }]
23033 Book.upsert_all [{ id: 101, name: "Perelandra 2", author_id: 7, isbn: "111111" }], update_only: :name
23034 Book.upsert_all [{ id: 101, name: "Perelandra 2", author_id: 6, isbn: "111111" }], update_only: %i[ name isbn ]
23035 Book.upsert_all [{ name: "Out of the Silent Planet", author_id: 7, isbn: "1974522598", published_on: Date.new(1938, 4, 1) }]
23036 Book.upsert_all [{ name: "Perelandra", author_id: 7, isbn: "1974522598" }],
23037 Book.insert_all [{ id: 101, name: "Out of the Silent Planet", published_on: Date.new(1938, 4, 1), updated_at: updated_at }]
23038 Book.upsert_all [{ id: 101, name: "Out of the Silent Planet", published_on: Date.new(1938, 4, 1) }]
23039 Book.insert_all [{ id: 101, name: "Out of the Silent Planet", published_on: Date.new(1938, 4, 1), updated_at: 5.years.ago, updated_on: 5.years.ago }]
23040 Book.upsert_all [{ id: 101, name: "Out of the Silent Planet", published_on: Date.new(1938, 4, 8) }]
23041 has_subsecond_precision = (1..100).any? do |i|
23042 Book.upsert_all [{ id: 101, name: "Out of the Silent Planet (Edition #{i})" }]
23043 Book.insert_all [{ id: 101, name: "Out of the Silent Planet", published_on: Date.new(1938, 4, 1), updated_at: 5.years.ago }]
23044 Book.upsert_all [{ id: 101, name: "Out of the Silent Planet", published_on: Date.new(1938, 4, 8), updated_at: updated_at }]
23045 Book.insert_all [{ id: 101, name: "Out of the Silent Planet", published_on: Date.new(1938, 4, 1), updated_on: 5.years.ago }]
23046 Book.upsert_all [{ id: 101, name: "Out of the Silent Planet", published_on: Date.new(1938, 4, 8), updated_on: updated_on }]
23047 Ship.upsert_all [{ id: 101, name: "RSS Boaty McBoatface" }]
23048 Book.upsert_all [{ id: 101 + i, name: "Out of the Silent Planet", published_on: Date.new(1938, 4, 1) }]
23049 Book.find(101 + i).created_at.usec > 0
23050 travel_to(Date.new(2016, 4, 17)) { Ship.create! id: 101, name: "RSS Boaty McBoatface" }
23051 Ship.upsert_all [{ id: 101, name: "RSS Sir David Attenborough" }]
23052 Developer.upsert_all [{ id: 101, name: "Alice" }]
23053 Developer.upsert_all [{ id: alice.id, name: alice.name, salary: alice.salary * 2 }]
23054 Book.insert_all! [{ unknown_attribute: "Test" }]
23055 Measurement.upsert_all([{ city_id: "1", logdate: 1.days.ago, peaktemp: 1, unitsales: 1 },
23056 { city_id: "2", logdate: 2.days.ago, peaktemp: 2, unitsales: 2 },
23057 { city_id: "2", logdate: 3.days.ago, peaktemp: 0, unitsales: 0 }],
23058 assert_equal [[1.day.ago.to_date, 1, 1]],
23059 assert_equal [[2.days.ago.to_date, 2, 2], [3.days.ago.to_date, 0, 0]],
23060 Book.insert_all! [{ status: :published, isbn: "1234566", name: "Rework", author_id: 1 },
23061 { status: :proposed, isbn: "1234567", name: "Remote", author_id: 2 }]
23062 assert_equal ["published", "proposed"], Book.where(isbn: ["1234566", "1234567"]).order(:id).pluck(:status)
23063 author.books.insert_all!([{ name: "My little book", isbn: "1974522598" }])
23064 author.books.insert_all!([{ name: "My little book", isbn: "1974522598", author_id: second_author.id }])
23065 Book.create_with(format: "X").insert_all!([ { name: "A" }, { name: "B" } ])
23066 assert_raise(ArgumentError) { book.subscribers.insert_all!([ { nick: "Jimmy" } ]) }
23067 author.books.upsert_all([{ name: "My little book", isbn: "1974522598" }])
23068 Book.create_with(format: "X").upsert_all([ { name: "A" }, { name: "B" } ])
23069 assert_raise(ArgumentError) { book.subscribers.upsert_all([ { nick: "Jimmy" } ]) }
23070 [{ id: 1, status: 1 }, { id: 2, status: 1 }],
23071 on_duplicate: Arel.sql("status = #{operator}(books.status, 1)")
23072 firm = Company.new(type: "Firm")
23073 firm = Company.where(type: "Firm").create!(name: "Basecamp")
23074 path = File.expand_path("../models/autoloadable", __dir__)
23075 Client.update_all "name = 'I am a client'"
23076 assert_equal 1, Client.all.merge!(where: "name = 'Summit'").to_a.size
23077 assert_sql(/#{Regexp.escape(c.quote_table_name("companies.id"))} = (?:#{Regexp.escape(bind_param.to_sql)}|1)/i) do
23078 assert_nothing_raised { s = SpecialSubscriber.new("name" => "And breaaaaathe!"); s.id = "roger"; s.save }
23079 phone = Shop::Product::Type.new(name: "Phone")
23080 if value =~ /\Aomg_(.+)\z/
23081 record = @klass.create! foo: "foo"
23082 record.foo = "bar"
23083 record = @klass.create! bar: "bar"
23084 @logged = []
23085 @payloads = []
23086 @logged << [payload[:sql].squish, payload[:name], payload[:binds]]
23087 sicp = Lesson.new(name: "SICP")
23088 lesson = Lesson.new(name: "SICP")
23089 person = Person.new(first_name: "Guille", gender: "m")
23090 def call(_, _, _, _, values)
23091 @events << values[:sql] if /INSERT/.match?(values[:sql])
23092 expected_sql = <<~EOS.chop
23093 fixtures = {
23094 { "name" => "working_aircrafts", "wheels_count" => 2 },
23095 { "name" => "broken_aircrafts", "wheels_count" => nil },
23096 { "location" => "US", "state" => ["NY"], "long_state" => ["a"] },
23097 { "location" => "US", "state" => ["NY"], "long_state" => ["a" * bytes_needed_to_have_a_1024_bytes_fixture] },
23098 { "location" => "US", "state" => ["NY"], "long_state" => ["a" * 51] },
23099 { "location" => "US", "state" => ["NY"], "long_state" => ["a" * 450] },
23100 { "post_id" => 1, "body" => "a" * 450 },
23101 { "location" => "US", "state" => ["NY"], "long_state" => ["a" * 200] },
23102 { "post_id" => 1, "body" => "a" * 200 },
23103 fixtures = [
23104 { "name" => "first", "wheels_count" => 2 },
23105 { "name" => "second", "wheels_count" => 3 }
23106 conn.insert_fixtures_set({ "aircraft" => fixtures }, ["aircraft"])
23107 badyaml = Tempfile.new ["foo", ".yml"]
23108 badyaml.write "a: : "
23109 first = Task.find(1)
23110 assert_equal "fixture key is not a hash: #{fixture_path}.yml, keys: [\"two\"]", error.to_s
23111 assert_equal "fixture_no_#{i}", name
23112 assert_equal "Category #{i}", fixture["name"]
23113 assert_equal ["Green", "Red", "Orange"], traffic_lights(:uk).state
23114 fixture_id = fixture["id"].to_i
23115 fixture_id > _max_id ? fixture_id : _max_id
23116 @first = true
23117 topic.title = "omg"
23118 last = nil
23119 last ||= current
23120 :'admin/randomly_named_a9' =>
23121 two: { writing: :default, reading: :readonly }
23122 two: { writing: :default }
23123 { "default" => default_config, "readonly" => readonly_config }
23124 { "adapter" => "sqlite3", "database" => "test/fixtures/fixture_database.sqlite3" }
23125 assert_equal [1, 2, 3, 4, 5, 6].sort, fh.to_a.map(&:last).map { |x|
23126 x["id"]
23127 devs = Array.new(8) { |i| "dev_#{i + 3}" }
23128 assert_equal [], devs - fh.to_a.map(&:first)
23129 tmp_yaml ["empty", "yml"], "" do |t|
23130 assert_equal [], File.open(t.path) { |fh| fh.to_a }
23131 tmp_yaml ["empty", "yml"], "qwerty" do |t|
23132 File.open(t.path) { |fh| fh.to_a }
23133 tmp_yaml ["empty", "yml"], "one: two" do |t|
23134 tmp_yaml ["empty", "yml"], { "_fixture" => { "class_name" => "Foo" } }.to_yaml do |t|
23135 File.open(t.path) { |fh| fh.model_class }
23136 tmp_yaml ["curious", "yml"], yaml do |t|
23137 [["one", { "name" => "Fixture helper" }]]
23138 assert_equal golden, File.open(t.path) { |fh| fh.to_a }
23139 File: <%= File.name %>
23140 golden = [["one", {
23141 }]]
23142 yaml1 = "<% def leaked_method; 'leak'; end %>
"
23143 tmp_yaml ["leaky", "yml"], yaml1 do |t1|
23144 tmp_yaml ["curious", "yml"], yaml2 do |t2|
23145 File.open(t1.path) { |fh| fh.to_a }
23146 File.open(t2.path) { |fh| fh.to_a }
23147 assert_equal(["second_welcome"], fh.each.map { |name, _| name })
23148 Post.find_by_title_and_id("foo", limit: 1)
23149 topics = Topic.select(:title).find([4, 2, 5])
23150 assert_equal [4, 2, 5], topics.map(&:id)
23151 topics = Topic.select(:title).order(:id).find([4, 2, 5])
23152 assert_equal [2, 4, 5], topics.map(&:id)
23153 Topic.all.find(-> { raise "should happen" }) { |e| e.title == "non-existing-title" }
23154 Topic.all.find(-> { raise "should not happen" }) { |e| e.title == topics(:first).title }
23155 records = Topic.find([4, 2, 5])
23156 records = Topic.find(4, 2, 5)
23157 records = Topic.find(["4", "2", "5"])
23158 records = Topic.find("4", "2", "5")
23159 records = Topic.order(:author_name).find([5, 3, 1])
23160 records = Topic.order(:id).find([5, 3, 1])
23161 records = Topic.limit(2).order(:id).find([5, 3, 1])
23162 records = Topic.limit(3).find([3, 2, 5, 1, 4])
23163 records = Topic.where(approved: true).limit(3).find([3, 2, 5, 1, 4])
23164 records = Topic.offset(2).find([3, 2, 5, 1, 4])
23165 Post.where("title" => { "xxxqqqq" => "bar" })
23166 assert_equal true, Topic.exists?(["parent_id = ?", 1])
23167 assert_raise(NoMethodError) { Topic.exists?([1, 2]) }
23168 authors = Author.includes(:posts).where(name: "David", posts: { id: post.id })
23169 assert_equal true, relation.exists?(["title LIKE ?", "Post%"])
23170 bob = authors(:bob)
23171 assert_equal false, Author.select("COUNT(*) as total_posts", "authors.*").joins(:posts).group(:id).having("total_posts > 2").include?(bob)
23172 assert_equal true, Author.select("COUNT(*) as total_posts", "authors.*").joins(:posts).group(:id).having("total_posts > 2").include?(mary)
23173 assert_kind_of(Array, Topic.find([ 1 ]))
23174 assert_equal(1, Topic.find([ 1 ]).length)
23175 assert_equal 2, Entrant.limit(2).find([1, 3, 2]).size
23176 entrants = Entrant.limit(3).offset(2).find([1, 3, 2])
23177 assert_sql(/^((?!ORDER).)*$/) { Topic.find(1) }
23178 Topic.where("author_name = 'Carl'").sole
23179 Topic.find_sole_by("author_name = 'Carl'")
23180 assert Topic.where(["approved = ?", false]).find(1)
23181 assert Topic.where("topics.approved" => false, topics: { author_name: "David" }).find(1)
23182 assert_equal [1, 2, 3, 5, 6, 7, 8, 9, 10, 12, 13], Comment.where(post_id: authors(:david).posts).map(&:id).sort
23183 assert_equal [1, 2], Topic.where(id: 1..2).to_a.map(&:id).sort
23184 assert_equal [1, 2, 3], Topic.where(id: 1..3).to_a.map(&:id).sort
23185 assert_equal [1, 2], Topic.where(id: 1...3).to_a.map(&:id).sort
23186 assert_equal [1, 2, 3], Comment.where(id: 1..3, post_id: 1..2).to_a.map(&:id).sort
23187 assert_equal [1], Comment.where(id: 1..1, post_id: 1..10).to_a.map(&:id).sort
23188 assert_equal [1, 2, 3, 5, 6, 7, 8, 9], Comment.where(id: [1..2, 3, 5, 6..8, 9]).to_a.map(&:id).sort
23189 assert_equal [1, 2, 6, 7, 8], Comment.where(id: [1..2, 6..8]).to_a.map(&:id).sort
23190 assert_equal [1, 2, 3], Comment.where(id: Float::INFINITY..3).to_a.map(&:id).sort
23191 assert_kind_of Firm, Company.where("name = '%s'", "37signals").first
23192 assert_nil Company.where(["name = '%s'", "37signals!"]).first
23193 assert_nil Company.where(["name = '%s'", "37signals!' OR 1=1"]).first
23194 assert_kind_of Time, Topic.where(["id = %d", 1]).first.written_on
23195 assert_kind_of Firm, Company.where(["name = '%s'", "37signals"]).first
23196 Company.create("name" => "Ain't noth'n like' \#stuff")
23197 p1, p2 = Post.limit(2).order("id asc").to_a
23198 assert_equal [p1, p2], Post.where(id: [p1, p2]).order("id asc").to_a
23199 assert_equal [p1, p2], Post.where(id: [p1, p2.id]).order("id asc").to_a
23200 assert_kind_of Firm, Company.where(["name = ?", "37signals"]).first
23201 assert_nil Company.where(["name = ?", "37signals!"]).first
23202 assert_nil Company.where(["name = ?", "37signals!' OR 1=1"]).first
23203 assert_kind_of Time, Topic.where(["id = ?", 1]).first.written_on
23204 Company.where(["id=? AND name = ?", 2]).first
23205 Company.where(["id=?", 2, 3, 4]).first
23206 assert Company.where(["name = ?", "37signals' go'es against"]).first
23207 assert Company.where(["name = :name", { name: "37signals' go'es against" }]).first
23208 assert_kind_of Firm, Company.where(["name = :name", { name: "37signals" }]).first
23209 assert_nil Company.where(["name = :name", { name: "37signals!" }]).first
23210 assert_nil Company.where(["name = :name", { name: "37signals!' OR 1=1" }]).first
23211 assert_kind_of Time, Topic.where(["id = :id", { id: 1 }]).first.written_on
23212 dog_alias = "Dog"
23213 a = Account.where("firm_id = ?", 6).find_by_credit_limit(50)
23214 assert_equal accounts(:unknown), Account.order("id DESC").where("id != ?", 3).find_by_credit_limit(50)
23215 first = Firm.
23216 Post.where("posts.id <= 3 OR posts.#{QUOTED_TYPE} = 'Post'").find([1, 2, 3])
23217 Post.create!(title: "test", body: "it out")
23218 assert_equal [], Post.where(id: nil)
23219 assert_equal [], Post.find([])
23220 assert_equal [], Post.where("id in (?)", [])
23221 assert_equal [p1, p2], Post.where(["id in (?)", [p1, p2]]).order("id asc")
23222 assert_equal [p1, p2], Post.where(["id in (?)", [p1, p2.id]]).order("id asc")
23223 [["1", "1", nil, "37signals"],
23224 ["2", "1", "2", "Summit"],
23225 ["3", "1", "1", "Microsoft"]],
23226 Company.connection.select_rows("SELECT id, firm_id, client_of, name FROM companies WHERE id IN (1,2,3) ORDER BY id").map! { |i| i.map! { |j| j.to_s unless j.nil? } })
23227 assert_equal [["1", "37signals"], ["2", "Summit"], ["3", "Microsoft"]],
23228 Company.connection.select_rows("SELECT id, name FROM companies WHERE id IN (1,2,3) ORDER BY id").map! { |i| i.map! { |j| j.to_s unless j.nil? } }
23229 where.not(author_addresses: { id: nil }).
23230 where(client_of: [2, 1, nil],
23231 name: ["37signals", "Summit", "Microsoft"]).
23232 map(&:client_of)
23233 where(client_of: [nil]).
23234 includes: :author, select: 'posts.*, authors.id as "author_id"',
23235 limit: 3, order: "posts.id"
23236 assert_equal [1, 1, nil], posts.map(&:author_id)
23237 model.find "Hello", "World!"
23238 assert_equal posts(:eager_other), Post.find_by("id = #{posts(:eager_other).id}")
23239 assert_equal posts(:eager_other), Post.find_by("id = ?", posts(:eager_other).id)
23240 assert_nil Post.find_by("1 = 0")
23241 assert_sql(/^((?!ORDER).)*$/) { Post.find_by(id: posts(:eager_other).id) }
23242 assert_equal posts(:eager_other), Post.find_by!("id = #{posts(:eager_other).id}")
23243 assert_equal posts(:eager_other), Post.find_by!("id = ?", posts(:eager_other).id)
23244 assert_sql(/^((?!ORDER).)*$/) { Post.find_by!(id: posts(:eager_other).id) }
23245 Post.find_by!("1 = 0")
23246 honda = cars(:honda)
23247 zyke = cars(:zyke)
23248 ActiveRecord::Base.filter_attributes = [ lambda { |key, value| value.reverse! if key == "name" } ]
23249 actual = "".dup
23250 Car.where(name: "honda").to_a
23251 sql, binds = queries[0]
23252 expected = sqls.map { |sql| "#{expected_explain_clause} #{sql}
query plan #{sql}" }.join("
")
23253 expected = <<~SQL
23254 metaclass.define_method(:explain) do |_arel, _binds = [], _options = {}|
23255 SUBSCRIBER.finish(nil, nil, name: "SQL", sql: "select 1 from users", binds: [1, 2])
23256 binds = [1, 2]
23257 SUBSCRIBER.finish(nil, nil, name: "SQL", sql: "select_db yo_mama")
23258 SUBSCRIBER.finish(nil, nil, name: "SQL", sql: "with s as (values(3)) select 1 from s")
23259 SUBSCRIBER.finish(nil, nil, name: "SQL", sql: "/* comment */ select 1 from users")
23260 setup { @post = posts(:welcome) }
23261 @book = books(:awdr)
23262 @book.cover = :hard
23263 @book.cover = "hard"
23264 Book.where(id: @book.id).update_all("status = NULL")
23265 @book.status = ""
23266 enum(:status, {}, **{})
23267 enum :status, []
23268 enum status: { "" => 1, "active" => 2 }
23269 enum status: ["active", ""]
23270 klass.class_eval { enum name => ["value_#{i}"] }
23271 klass.class_eval { enum "status_#{i}" => [value] }
23272 def self.name; "Book"; end
23273 Book.statuses["bad_enum"] = 40
23274 status: [:value_1],
23275 last_read: [:value_1],
23276 book = books(:tlg)
23277 enum :status, { proposed: 0, written: 1 }, prefix: true
23278 enum :last_read, { unread: 0, reading: 1, read: 2 }, prefix: :being
23279 enum :cover, { hard: 0, soft: 1 }, suffix: true
23280 enum :difficulty, { easy: 0, medium: 1, hard: 2 }, suffix: :to_read
23281 enum :status, default: 0, scopes: 1, prefix: 2, suffix: 3
23282 enum breed: { "American Bobtail" => 0, "Balinese-Javanese" => 1 }
23283 enum timezone: [:"Etc/GMT+1", :"Etc/GMT-1"]
23284 written = Struct.new(:to_s).new("written")
23285 enum status: { proposed => 0, written => 1 }
23286 enum status: [:sent, :not_sent]
23287 enum status: [:not_sent, :sent]
23288 enum status: [:not_sent, :sent], _scopes: false
23289 @properties[:key_1] = "value 1"
23290 @properties[:key_2] = "value 2"
23291 auth_tag = "some auth tag"
23292 @properties.add(key_1: "value 1", key_2: "value 2")
23293 @properties["some_value_#{index}"] = value
23294 baseline = -> { EncryptedBook.where("id > 0").find_by(format: "paperback") } # not encrypted
23295 baseline = -> { encrypted_books(:awdr).created_at }
23296 body: "<p>the Starfleet is here, we are safe now!</p>"
23297 @serializer.load JSON.dump({ some: "other data" })
23298 headers = { key_1: "1" }
23299 @keys = build_keys(3)
23300 target_key = @keys[1]
23301 password = "some secret #{index}"
23302 puts "#{output}#{error}"
23303 test "where(...).first_or_create works" do
23304 test "exists?(...) works" do
23305 @secret_key = "This is my secret 256 bits key!!"
23306 key.public_tags[:key] = "my tag"
23307 key_provider.stub :decryption_keys, ->(message) { [key] } do
23308 text = "The Starfleet is here #{'OMG! ' * 50}!".dup.force_encoding(Encoding::ISO_8859_1)
23309 encrypts :name, encryptor: TestEncryptor.new("1" => "2")
23310 encrypts :name, encryptor: TestEncryptor.new("2" => "3"), previous: { encryptor: TestEncryptor.new("1" => "2") }
23311 post.title = "You sure?"
23312 states = ["green", "red"]
23313 assert_encrypted_attribute(traffic_light, :state, { "color" => "red" })
23314 title: title = "The Starfleet is here!",
23315 body: body = "<p>the Starfleet is here, we are safe now!</p>"
23316 ciphertext = "{\"p\":\"DIohhw==\",\"h\":{\"iv\":\"wEPaDcJP3VNIxaiz\",\"at\":\"X7+2xvvcu1k1if6Dy28Esw==\"}}"
23317 book.update!(name: "Dune II")
23318 book.update!(name: "A new title!")
23319 body = "<p>the Starfleet is here, we are safe now!</p>"
23320 EncryptedPost.insert_all 100.times.collect { |index| { title: "Article #{index} (#{thread_label})", body: "Body #{index} (#{thread_label})" } }
23321 topic = Topic.new("title" => "Literature")
23322 movie = Movie.new(name: "test")
23323 parrot.name = "Sam"
23324 ["", nil].each do |value|
23325 pirate.parrot_id = "0"
23326 pirate.parrot_id = ""
23327 assert_equal({ "catchphrase" => [nil, "arrr"] }, pirate.changes)
23328 params = { topic: { approved: 1 } }
23329 assert_queries(2) { 2.times { pirate.save! } }
23330 assert_no_queries { 2.times { pirate.save! } }
23331 assert_queries(2) { 2.times { person.save! } }
23332 assert_no_queries { 2.times { person.save! } }
23333 assert_queries(1) { person.first_name = "bar"; person.save! }
23334 10.times do |i|
23335 pirate.catchphrase = "*hic*" * i
23336 topic = Topic.create!(content: { "a" => "a" })
23337 topic.content["b"] = "b"
23338 assert_equal "b", topic.content["b"]
23339 topic.content["hello"] = "world"
23340 topic = Topic.create!(author_name: "Bill", content: { "a" => "a" })
23341 topic = Topic.new(author_name: "Bill", content: [{ "a" => "a" }])
23342 assert_equal [{ "a" => "a" }], topic.content
23343 written_on = Time.utc(2012, 12, 1, 12, 0, 0).in_time_zone("Paris")
23344 topic.written_on += 0.3
23345 time_in_paris = Time.utc(2014, 1, 1, 12, 0, 0).in_time_zone("Paris")
23346 jon = nil
23347 binary = klass.create!(data: "\\\\foo")
23348 binary.data << "bar"
23349 define_method(:changed_in_place?) do |*|
23350 model = klass.new(first_name: "Jim")
23351 person = Person.create!(first_name: "Sean", gender: "M")
23352 assert_equal manufactured_at.utc.strftime("%Y-%m-%d %H:%M:%S"), aircraft.manufactured_at.strftime("%Y-%m-%d %H:%M:%S")
23353 %w(id name course_id).each do |name|
23354 assert("--- []

" == record.multiline_default || "--- []\\012\\012" == record.multiline_default)
23355 assert_match %r/t\.date\s+"modified_date",\s+default: -> { "CURRENT_DATE" }/, output
23356 assert_match %r/t\.datetime\s+"modified_time",\s+default: -> { "CURRENT_TIMESTAMP" }/, output
23357 assert_match %r/t\.date\s+"modified_date",\s+default: -> { "\('now'::text\)::date" }/, output
23358 assert_match %r/t\.datetime\s+"modified_time",\s+default: -> { "now\(\)" }/, output
23359 assert_match %r/t\.date\s+"modified_date_function",\s+default: -> { "now\(\)" }/, output
23360 assert_match %r/t\.datetime\s+"modified_time_function",\s+default: -> { "now\(\)" }/, output
23361 assert_match %r/t\.binary\s+"uuid",\s+limit: 36,\s+default: -> { "\(uuid\(\)\)" }/i, output
23362 assert_match %r/t\.datetime\s+"modified_datetime",\s+precision: nil,\s+default: -> { "CURRENT_TIMESTAMP(?:\(\))?" }/i, output
23363 assert_match %r/t\.datetime\s+"precise_datetime",\s+default: -> { "CURRENT_TIMESTAMP\(6\)" }/i, output
23364 assert_match %r/t\.timestamp\s+"modified_timestamp",\s+default: -> { "CURRENT_TIMESTAMP(?:\(\))?" }/i, output
23365 assert_match %r/t\.timestamp\s+"precise_timestamp",.+default: -> { "CURRENT_TIMESTAMP\(6\)" }/i, output
23366 assert_match %r/t\.integer\s+"random_number",\s+default: -> { "random\(\)" }/, output
23367 time_values = [1807, 2, 10, 15, 30, 45]
23368 now = DateTime.civil(*(time_values + [local_offset]))
23369 task.starting = ""
23370 topic.last_read = ""
23371 topic.bonus_time = ""
23372 now = DateTime.civil(2017, 3, 1, 12, 0, 0)
23373 string_value = "2017-07-04 14:19:00.5"
23374 date = ::Time.utc(2014, 8, 17, 12, 30, 0, 999999)
23375 date = ::Date.new(2001, 2, 3)
23376 assert_match %r{t\.datetime\s+"created_at",\s+precision: 0,\s+null: false$}, output
23377 assert_match %r{t\.datetime\s+"updated_at",\s+precision: 0,\s+null: false$}, output
23378 time_value = Time.new(2016, 05, 11, 19, 0, 0)
23379 string_value = "2016-05-11 19:00:00"
23380 valid_dates = [[2007, 11, 30], [1993, 2, 28], [2008, 2, 29]]
23381 invalid_dates = [[2007, 11, 31], [1993, 2, 29], [2007, 2, 29]]
23382 topic = Topic.new("last_read(1i)" => date_src[0].to_s, "last_read(2i)" => date_src[1].to_s, "last_read(3i)" => date_src[2].to_s)
23383 @session_store = {}
23384 sleep(0.1)
23385 }).find_db_config("primary")
23386 pool_config = resolve_db_config :production, "production" => { "url" => "abstract://foo?encoding=utf8" }
23387 hash = { "url" => "abstract://foo?encoding=utf8&", "adapter" => "sqlite3", "host" => "bar", "pool" => "3" }
23388 hash = { "url" => "abstract:///?user=user&password=passwd&dbname=app" }
23389 database: "bar",
23390 password = "am@z1ng_p@ssw0rd#!"
23391 pool_config = resolve_db_config :production, "production" => { "url" => "sqlite3:foo?encoding=utf8" }
23392 database: "foo",
23393 config = HashConfig.new("default_env", "primary", pool: "0")
23394 config = HashConfig.new("default_env", "primary", {})
23395 config = HashConfig.new("default_env", "primary", { schema_dump: "my_schema.rb" })
23396 config = HashConfig.new("default_env", "primary", { schema_dump: nil })
23397 config = HashConfig.new("default_env", "primary", { schema_dump: false })
23398 @topic = Topic.find(1)
23399 t1, t2 = topics(:first, :second)
23400 _ = joanna # squelch a warning
23401 assert_equal %(#<Topic id: 1>), Topic.all.merge!(select: "id", where: "id = 1").first.inspect
23402 assert_equal %(#<Topic id: 1, title: "The First Topic">), Topic.all.merge!(select: "id, title", where: "id = 1").first.inspect
23403 actual = +""
23404 type: nil,
23405 written_on: 2003-07-16 14:28:11(?:\.2233)? UTC,
23406 created_at: [^,]+,
23407 updated_at: [^,>]+>
23408 assert_match(/\A#{expected}\z/, actual)
23409 assert_match(/id: 1/, actual)
23410 assert_difference -> { topic_find_by_cache.size }, +1 do
23411 Topic.find_by(id: 1)
23412 cs = @pool.size.times.map { @pool.checkout }
23413 t = new_thread { @pool.checkout }
23414 :@idle_since,
23415 assert_equal [recent_conn, active_conn].sort_by(&:__id__), @pool.connections.sort_by(&:__id__)
23416 assert_equal [active_conn].sort_by(&:__id__), @pool.connections.sort_by(&:__id__)
23417 4.times do |i|
23418 expected = (1..@pool.size).to_a.freeze
23419 order = []
23420 t = new_thread {
23421 mutex.synchronize { order << i }
23422 mutex.synchronize { errors << e }
23423 conns.each { |conn| @pool.checkin(conn); sleep 0.1 }
23424 conns = (1..10).map { @pool.checkout }
23425 make_thread = proc do |i|
23426 group1 = (1..5).map(&make_thread)
23427 group2 = (6..10).map(&make_thread)
23428 checkin = proc do |n|
23429 c = conns.pop
23430 payloads = []
23431 assert_equal({ size: 1, connections: 1, busy: 1, dead: 0, idle: 0, waiting: 0, checkout_timeout: 5 }, stats)
23432 assert_equal({ size: 1, connections: 1, busy: 0, dead: 0, idle: 1, waiting: 0, checkout_timeout: 5 }, stats)
23433 assert_equal({ size: 1, connections: 1, busy: 0, dead: 1, idle: 0, waiting: 0, checkout_timeout: 5 }, stats)
23434 def new_thread(...)
23435 Thread.new(...)
23436 resume while alive? && (!timeout || Time.now - now < timeout)
23437 @calls = []
23438 @calls << env
23439 [200, {}, ["hi mom"]]
23440 @env = {}
23441 @app = App.new
23442 _, _, body = @management.call(@env)
23443 bits = []
23444 body.each { |bit| bits << bit }
23445 assert_equal ["hi mom"], bits
23446 app = Class.new(App) do
23447 body = Class.new(String) { def to_path; "/path"; end }.new
23448 app = lambda { |_| [200, {}, body] }
23449 original_response = [200, {}, "hi"]
23450 app = lambda { |_| original_response }
23451 a, b, c = executor.wrap { app.call(env) }
23452 [a, b, Rack::BodyProxy.new(c) { }]
23453 decimal: %w{decimal(2) decimal(2,0) numeric(2) numeric(2,0)},
23454 integer: %w{number(2) number(2,0)}
23455 { decimal: %w{decimal(2) decimal(2,0) numeric(2) numeric(2,0) number(2) number(2,0)} }
23456 tempfile = Tempfile.new(["schema_cache-", ".yml"])
23457 tempfile = Tempfile.new(["schema_cache-", ".yml.gz"])
23458 tempfile = Tempfile.new(["schema_cache-", ".dump"])
23459 tempfile = Tempfile.new(["schema_cache-", ".dump.gz"])
23460 coder = {
23461 assert_lookup_type :string, "enum('one', 'two', 'three')"
23462 assert_lookup_type :string, "ENUM('one', 'two', 'three')"
23463 assert_lookup_type :string, "enum ('one', 'two', 'three')"
23464 assert_lookup_type :string, "ENUM ('one', 'two', 'three')"
23465 assert_lookup_type :string, "set('one', 'two', 'three')"
23466 assert_lookup_type :string, "SET('one', 'two', 'three')"
23467 assert_lookup_type :string, "set ('one', 'two', 'three')"
23468 assert_lookup_type :string, "SET ('one', 'two', 'three')"
23469 assert_lookup_type :string, "SET('unicode', '8bit', 'none', 'time')"
23470 assert_lookup_type :string, "ENUM('unicode', '8bit', 'none', 'time')"
23471 config = { "foo" => "bar" }
23472 config = { "foo" => :bar }
23473 expected = { adapter: "postgresql", database: "foo", host: "localhost" }
23474 config = { "not_production" => { "adapter" => "not_postgres", "database" => "not_foo" } }
23475 config = { "foo" => { "adapter" => "postgres", "url" => ENV["DATABASE_URL"] } }
23476 config = { "production" => { "adapter" => "not_postgres", "database" => "not_foo", "host" => "localhost" } }
23477 expected = { adapter: "not_postgres", database: "not_foo", host: "localhost" }
23478 expected = { adapter: "postgresql", database: "foo_test", host: "localhost" }
23479 expect_prod = {
23480 config = { "default_env" => { "adapter" => "not_postgres", "database" => "not_foo", "host" => "localhost" } }
23481 expected = { adapter: "ibm_db", database: "foo", host: "localhost" }
23482 config = { "default_env" => { "url" => "postgres://localhost/foo" } }
23483 expected = { options: "-cmyoption=on", adapter: "postgresql", database: "foo", host: "localhost" }
23484 config = { "production" => { "adapter" => "postgres", "database" => "foo" } }
23485 host: "::1",
23486 database: "baz",
23487 other_env: {
23488 pool: "5"
23489 expected = { pool: 5 }
23490 config = { "production" => { "adapter" => "not_postgres", "database" => "not_foo", "host" => "localhost" }, "default_env" => {} }
23491 default: { writing: :primary },
23492 ActiveRecord::Base.connects_to(database: { writing: :arunit }, shards: { shard_one: { writing: :arunit } })
23493 SecondaryBase.connects_to shards: { one: { writing: { database: ":memory:", adapter: "sqlite3" } } }
23494 SomeOtherBase.connects_to shards: { one: { writing: { database: ":memory:", adapter: "sqlite3" } } }
23495 default: { writing: { database: ":memory:", adapter: "sqlite3" } },
23496 one: { writing: { database: ":memory:", adapter: "sqlite3" } }
23497 [:default, :one].each do |shard_name|
23498 default: { writing: { database: tf_default.path, adapter: "sqlite3" } },
23499 one: { writing: { database: tf_shard_one.path, adapter: "sqlite3" } }
23500 one: { writing: { database: tf_shard_one.path, adapter: "sqlite3" }, secondary: { database: tf_shard_one_reading.path, adapter: "sqlite3" } }
23501 one: { writing: { database: tf_shard_one2.path, adapter: "sqlite3" }, secondary: { database: tf_shard_one_reading2.path, adapter: "sqlite3" } }
23502 SecondaryBase.connects_to database: { writing: { database: ":memory:", adapter: "sqlite3" }, secondary: { database: ":memory:", adapter: "sqlite3" } }
23503 ActiveRecord::Base.connects_to(shards: { default: { also_writing: :arunit }, one: { also_writing: :arunit } })
23504 config = { "primary" => { "adapter" => "sqlite3", "database" => "test/db/primary.sqlite3" } }
23505 config = { "development" => { "adapter" => "sqlite3", "database" => "test/db/primary.sqlite3" } }
23506 klass2 = Class.new(Base) { def self.name; "klass2"; end }
23507 outer_pid = fork {
23508 @connection.create_table("blank_comments", comment: " ", force: true) do |t|
23509 t.index :space_comment, comment: " "
23510 index = @connection.indexes("commenteds").find { |idef| idef.name == "idx_obvious" }
23511 assert_match %r[t\.index\s+.+\s+comment: "\\"Very important\\" index that powers all the performance.\
And it's fun!"], output
23512 assert_match %r[t\.index\s+.+\s+name: "idx_obvious",\s+comment: "We need to see obvious comments"], output
23513 { string: "varchar" }
23514 assert_match(/\Adevelopers\/query-(\h+)-(\d+)-(\d+)\z/, Developer.collection_cache_key)
23515 assert_match(/\Adevelopers\/query-(\h+)-(\d+)-(\d+)\z/, developers.cache_key)
23516 /\Adevelopers\/query-(\h+)-(\d+)-(\d+)\z/ =~ developers.cache_key
23517 assert_match(/\Adevelopers\/query-(\h+)-(\d+)-(\d+)\z/, developers_with_select.cache_key)
23518 /\Adevelopers\/query-(\h+)-(\d+)-(\d+)\z/ =~ developers_with_select.cache_key
23519 assert_match(/\Acomments\/query-(\h+)-(\d+)-(\d+)\z/, comments.cache_key)
23520 other_relation = Developer.where(name: "David").where("1 = 1")
23521 topics = Topic.where("title like ?", "%Topic%")
23522 /\Adevelopers\/query-(\h+)\z/ =~ developers.cache_key
23523 assert_match(/(\d+)-(\d+)\z/, developers.cache_version)
23524 /(\d+)-(\d+)\z/ =~ developers.cache_version
23525 assert_match(/\Adevelopers\/query-(\h+)-(\d+)-(\d+)\z/, key_with_version_1)
23526 coder.dump("a")
23527 assert_equal %{can't dump `tags`: was supposed to be a Array, but was a String. -- "a"}, error.to_s
23528 coder.load "--- foo"
23529 assert_equal %{can't load `tags`: was supposed to be a Array, but was a String. -- "foo"}, error.to_s
23530 assert_nil coder.load "--- "
23531 coder.load([])
23532 bad_yaml = "--- {"
23533 david = CallbackDeveloper.create("name" => "David", "salary" => 1000000)
23534 [ :before_validation, :method ],
23535 [ :before_validation, :object ],
23536 before_save(on: :create) { }
23537 around_save(on: :create) { }
23538 after_save(on: :create) { }
23539 NumericData.create!([{ bank_balance: 37.50 }, { bank_balance: 37.45 }])
23540 [1, 6, 2].each do |firm_id|
23541 c = Account.group("firm_id", :credit_limit).count(:all)
23542 [ [nil, 50], [1, 50], [6, 50], [6, 55], [9, 53], [2, 60] ].each { |firm_and_limit| assert_includes c.keys, firm_and_limit }
23543 assert_equal({ [1, 2] => 2 }, res)
23544 c = Topic.group(:author_name, "COALESCE(type, title)").count(:all)
23545 assert_equal 1, c[["Carl", "The Third Topic of the day"]]
23546 assert_equal 1, c[["Mary", "Reply"]]
23547 assert_equal 1, c[["David", "The First Topic"]]
23548 assert_equal 1, c[["Carl", "Reply"]]
23549 expected = { nil => 50, 1 => 50, 2 => 60, 6 => 105, 9 => 53 }
23550 nil => 50,
23551 1 => 50,
23552 2 => 60,
23553 6 => 105,
23554 9 => 53
23555 6 => 55,
23556 6 => 50,
23557 assert_equal [1, 2, 6, 9], c.keys.compact
23558 c = Account.group(:firm_id).order("firm_id").sum(:credit_limit)
23559 assert_equal [105, 60, 53, 50, 50], c.keys.collect { |k| c[k] }
23560 assert_equal [6, 2, 9, 1], c.keys.compact
23561 c = Account.where("firm_id IS NOT NULL").group(:firm_id).order("firm_id").limit(2).sum(:credit_limit)
23562 c = Account.where("firm_id IS NOT NULL").group(:firm_id).order("firm_id").
23563 expected = { nil => 4, 1 => 1, 2 => 1, 4 => 1, 5 => 1, 7 => 1 }
23564 expected = { nil => 6, 1 => 1, 2 => 1, 4 => 1, 5 => 1, 7 => 1 }
23565 assert_equal({ 6 => 2 }, Account.group(:firm_id).distinct.order("1 DESC").limit(1).count)
23566 c = Account.group(:firm_id).having("sum(credit_limit) > 50").sum(:credit_limit)
23567 c = Account.where("firm_id > 1").group(:firm_id).sum(:credit_limit)
23568 relation = Account.where("firm_id > 1").group(:firm_id).having("sum(credit_limit) > 60")
23569 assert_equal 1, c[1]
23570 assert_equal 2, c[6]
23571 assert_equal 1, c[2]
23572 c = Account.group(:firm).count(:all)
23573 assert_equal 3, c["FIRM"]
23574 assert_equal 6, [1, 2, 3].sum(&:abs)
23575 c = companies(:rails_core).companies.group(:name).having("sum(id) > 7").sum(:id)
23576 expected = { nil => 1, 1 => 1, 2 => 1, 6 => 2, 9 => 1 }
23577 [1, 6, 2, 9].each { |firm_id| assert_includes c.keys, firm_id }
23578 assert_equal({ "active" => 2, "trial" => 2, "suspended" => 1 }, counts)
23579 expected = { 1 => 2, 2 => 1, 4 => 5, 5 => 3, 7 => 1 }
23580 assert_equal 0, Account.where("1 = 2").sum("2 * credit_limit")
23581 assert_equal 0, Post.where(id: []).sum(:tags_count)
23582 edges = Edge.from("edges /*! USE INDEX(unique_edge_index) */")
23583 assert_equal Edge.where("sink_id < 5").count(:all), edges.where("sink_id < 5").count(:all)
23584 assert_equal [1, 2, 3, 4, 5], Topic.order(:id).pluck(:id)
23585 assert_async_equal [1, 2, 3, 4, 5], Topic.order(:id).async_pluck(:id)
23586 assert_equal [], Topic.where(id: []).pluck(:id)
23587 assert_async_equal [], Topic.where(id: []).async_pluck(:id)
23588 assert_equal [[1, "Firm", 1, nil, "37signals", nil, 1, nil, nil, "active"]], Company.order(:id).limit(1).pluck
23589 assert_equal [[1, "Firm", 1, nil, "37signals", nil, 1, nil, "", "active"]], Company.order(:id).limit(1).pluck
23590 [Date.new(2004, 4, 15), "unread"],
23591 [Date.new(2004, 4, 15), "reading"],
23592 [Date.new(2004, 4, 15), "read"],
23593 .where("books.last_read": [:unread, :reading, :read])
23594 .pluck(:"topics.last_read", :"books.last_read")
23595 [nil, "unread"],
23596 ["ebook", "reading"],
23597 ["paperback", "read"],
23598 t = Topic.create!(content: { "foo" => "bar" })
23599 assert_equal [{ "foo" => "bar" }], Topic.where(id: t.id).pluck(:content)
23600 assert_equal [1, 2, 3, 4, 5], Topic.order(:id).pluck("topics.id")
23601 c = Company.create!(name: "test", contracts: [Contract.new])
23602 assert_equal [50 + 53 + 55 + 60], Account.pluck(Arel.sql("SUM(DISTINCT(credit_limit))"))
23603 scoped_ids = [1, 2]
23604 empty_scope_ids = []
23605 assert_equal [], Topic.includes(:replies).limit(1).where("0 = 1").ids
23606 assert_equal [], Topic.includes(:replies).limit(1).where("0 = 1").pluck(:id)
23607 assert_equal [[2, 2], [4, 4]], Reply.includes(:topic).order(:id).pluck(:id, :"topics.id")
23608 expected = { "SpecialPost" => 1, "StiPost" => 2 }
23609 expected = { "StiPost" => 3, "SpecialPost" => 1 }
23610 expected = { "SpecialPost" => 1, "Post" => 8 }
23611 expected = { "SpecialPost" => 1 }
23612 expected = { "SpecialPost" => 1, "StiPost" => 1, "Post" => 9 }
23613 [1, "The First Topic"], [2, "The Second Topic of the day"],
23614 [3, "The Third Topic of the day"], [4, "The Fourth Topic of the day"],
23615 [5, "The Fifth Topic of the day"]
23616 ], Topic.order(:id).pluck(:id, :title)
23617 [1, "The First Topic", "David"], [2, "The Second Topic of the day", "Mary"],
23618 [3, "The Third Topic of the day", "Carl"], [4, "The Fourth Topic of the day", "Carl"],
23619 [5, "The Fifth Topic of the day", "Jason"]
23620 ], Topic.order(:id).pluck(:id, :title, :author_name)
23621 assert_equal [[1, 50], [2, 50], [3, 50], [4, 60], [5, 55], [6, 53]],
23622 assert_equal [1, 2, 3, 4, 5], takes_relation.pluck(:id)
23623 expected = [["The First Topic", "The Second Topic of the day"], ["The Third Topic of the day", "The Fourth Topic of the day"]]
23624 ], Topic.order(:id).pluck(
23625 ["1", "The First Topic"], ["2", "The Second Topic of the day"],
23626 ["3", "The Third Topic of the day"], ["4", "The Fourth Topic of the day"],
23627 ["5", "The Fifth Topic of the day"]
23628 assert_equal [[1, "37signals"], [2, "Summit"], [3, "Microsoft"]], companies.pluck(:id, :name)
23629 assert_equal({ "has trinket" => part.id }, ShipPart.joins(:trinkets).group("ship_parts.name").sum(:id))
23630 returns: ActiveRecord::Result.new(["count"], [["10"]])
23631 returns: ActiveRecord::Result.new(["sum"], [[10.to_d]])
23632 assert_equal({ "proposed" => 2, "published" => 2 }, Book.group(:status).count)
23633 assert_equal({ "proposed" => 0, "published" => 4 }, Book.group(:status).sum(:status))
23634 assert_equal({ "proposed" => 0, "published" => 1 }, Book.group(:status).sum(:difficulty))
23635 assert_equal({ "proposed" => 0, "published" => 0 }, Book.group(:status).minimum(:difficulty))
23636 assert_equal({ "proposed" => 0, "published" => 1 }, Book.group(:status).maximum(:difficulty))
23637 assert_equal({ false => Date.new(2004, 4, 15), true => nil }, Topic.group(:approved).minimum(:last_read))
23638 assert_equal({ false => Date.new(2004, 4, 15), true => nil }, Topic.group(:approved).maximum(:last_read))
23639 assert_equal Time.utc(2003, 7, 16, 14, 28, 11, 223300), actual
23640 assert_equal Time.utc(2013, 7, 13, 11, 11, 0, 9900), actual
23641 false => Time.utc(2003, 7, 16, 14, 28, 11, 223300),
23642 true => Time.utc(2004, 7, 15, 14, 28, 0, 9900),
23643 true => Time.utc(2013, 7, 13, 11, 11, 0, 9900),
23644 assert_equal Time.utc(2004, 7, 15, 14, 28, 0, 9900), actual
23645 1 => Time.utc(2003, 7, 16, 14, 28, 11, 223300),
23646 2 => Time.utc(2004, 7, 15, 14, 28, 0, 9900),
23647 .group(:firm_id)
23648 .take!
23649 .group(:id)
23650 Account.count(:firm_id) { true }
23651 record_from_db.updated_at = { 1 => 2016, 2 => 11, 3 => 12, 4 => 1, 5 => 2, 6 => 3, 7 => 22 }
23652 b_blank = Boolean.create!(value: "")
23653 b_false = Boolean.create!(value: "0")
23654 calls << args
23655 assert_equal [1], topics.map(&:id)
23656 assert_equal 1, Topic.find_by!(id: 1).id
23657 topic_sql = cached_statement(Topic, ["id"])
23658 topics = Topic.where(id: [1, 3]).order(:id)
23659 assert_equal [1, 3], topics.map(&:id)
23660 topics = Topic.where("topics.id = ?", 1)
23661 topics = Topic.where(id: (1 .. bind_params_length).to_a << 2**63)
23662 topics = Topic.where.not(id: (1 .. bind_params_length).to_a << 2**63)
23663 topics = Topic.where(id: (1 .. bind_params_length + 1).to_a)
23664 topics = Topic.where.not(id: (1 .. bind_params_length + 1).to_a)
23665 message = @subscriber.calls.find { |args| args[4][:sql] == sql }
23666 message = @subscriber.calls.find { |args| args[4][:binds].any? { |attr| attr.value == 1 } }
23667 binds = [Relation::QueryAttribute.new("id", "10", Type::Integer.new)]
23668 binds = ["abcd"]
23669 pk = "#{table}.#{Author.quoted_primary_key}"
23670 authors = Author.where(id: [1, 2, 3, nil])
23671 bind_params = ids.map { |i| Arel::Nodes::BindParam.new(i) }
23672 @connection.respond_to?(:sql_key, true) ? @connection.send(:sql_key, sql) : sql
23673 sql: "select * from topics where id = ?",
23674 @debugs << str
23675 assert_match %r(\[\["id", 10\]\]\z), logger.debugs.first
23676 sql: "select * from topics where title = $1",
23677 assert_match %r(\[\[nil, "abcd"\]\]\z), logger.debugs.first
23678 sql: "select * from users where auth_token = ?",
23679 assert_match %r/#{Regexp.escape '[["auth_token", "[FILTERED]"]]'}/, logger.debugs.first
23680 binary_data = "\xEE\x49\xC7".b
23681 @posts = Post.order("id asc")
23682 Post.select(:title).find_each(batch_size: 1) { |post|
23683 Post.select("id, title, type").find_each(batch_size: 2) do |post|
23684 limit = @total - 1
23685 total = 0
23686 total += 1
23687 Post.order("title").find_each { |post| post }
23688 Post.select(:title).find_each(batch_size: 1, order: :invalid) { |post|
23689 not_a_post = +"not a post"
23690 not_a_post.stub(:id, -> { raise StandardError.new("not_a_post had #id called on it") }) do
23691 batch.map! { not_a_post }
23692 posts = []
23693 subscribers = []
23694 enum = nil
23695 ids = Post.order("id ASC").pluck(:id)
23696 not_deleted_count = Post.where("id <= 2").count
23697 Post.where("id > 2").in_batches(of: 2).delete_all
23698 assert_equal 0, Post.where("id > 2").count
23699 post = Post.order("id ASC").where("id >= ?", 2).first
23700 post = Post.order("id DESC").where("id <= ?", 5).first
23701 assert_sql(/WHERE #{quoted_posts_id} > .+ AND #{quoted_posts_id} <= .+/i) do
23702 assert_sql(/#{quoted_posts_id} IN \(.+\)/i) do
23703 Post.where("id < ?", 5).in_batches(of: 2) { |relation| assert_kind_of Post, relation.first }
23704 assert_sql(/#{quoted_posts_id} > .+ AND #{quoted_posts_id} <= .+/i) do
23705 Post.where("id < ?", 5).in_batches(of: 2, use_ranges: true) { |relation| assert_kind_of Post, relation.first }
23706 assert_sql(/DELETE FROM #{c.quote_table_name("posts")} WHERE #{quoted_posts_id} > .+ AND #{quoted_posts_id} <=/i) do
23707 assert_sql(/ORDER BY #{c.quote_table_name('posts')}\.#{c.quote_column_name('id')}/) do
23708 Post.in_batches(of: 1, order: :desc) do |relation|
23709 enum = Post.in_batches(of: 1)
23710 seen_posts = []
23711 Post.in_batches(of: 2) do |batch|
23712 batch.where("author_id >= 1").update_all("author_id = author_id + 1")
23713 [true, false].each do |load|
23714 posts.find_each { }
23715 Post.find_each { }
23716 Post.find_each(start: 1, finish: 1) do |post|
23717 Post.in_batches { }
23718 payload = { "foo" => 42 }
23719 Topic.connection.stub(:lookup_cast_type_from_column, ->(_) { raise "Some Error" }) do
23720 classname = conn.class.name[/[^:]*$/]
23721 pk = Author.columns_hash["id"]
23722 car = Car.new name: "<3<3<3"
23723 20_000.times { car.engines_count += 1 }
23724 Topic.limit("1, 7 procedure help()").to_a
23725 topic_ids = Topic.select(:id).map(&:id).sort
23726 topic.title = "<3<3<3"
23727 expected = ["The First Topic", "<3<3<3"]
23728 topic = Topic.create("written_on" => time)
23729 assert_equal [0, 0, 0, 1, 1, 2000, 6, 1, false, "EST"], time.to_a
23730 assert_equal [0, 0, 5, 1, 1, 2000, 6, 1, false, "UTC"], saved_time.to_a
23731 assert_equal [0, 0, 0, 1, 1, 2000, 6, 1, false, "CST"], time.to_a
23732 assert_equal [0, 0, 6, 1, 1, 2000, 6, 1, false, "UTC"], saved_time.to_a
23733 assert_equal [0, 0, 0, 1, 1, 2000, 6, 1, false, "UTC"], time.to_a
23734 assert_equal [0, 0, 19, 31, 12, 1999, 5, 365, false, "EST"], saved_time.to_a
23735 assert_equal [0, 0, 1, 1, 1, 2000, 6, 1, false, "EST"], saved_time.to_a
23736 pet = Pet.create(name: "Bidu")
23737 Topic.new("title" => "test",
23738 cb = CustomBulb.create { |c| c.name = "Dude" }
23739 cbs = CustomBulb.create([{ name: "Dude" }, { name: "Bob" }])
23740 topics = Topic.all.merge!(order: "id").to_a
23741 topics = Topic.all.merge!(where: "author_name = 'Mary'").to_a
23742 attributes = { "bonus_time" => "5:42:00AM" }
23743 assert_equal Time.utc(2000, 1, 1, 5, 42, 0), topic.bonus_time
23744 attributes = { "bonus_time(1i)" => "2000",
23745 assert_equal Time.utc(2000, 1, 1, 10, 35, 50), topic.bonus_time
23746 assert_equal Topic.find([1, 2]), Topic.find(["1-meowmeow", "2-hello"])
23747 assert_equal Topic.where(id: "1-meowmeow".."2-hello"), Topic.where(id: 1..2)
23748 one = Subscriber.new(id: "")
23749 two = Subscriber.new(id: "")
23750 assert_equal [ Topic.find(1) ], [ Topic.find(2).topic ] & [ Topic.find(1) ]
23751 assert_equal [topic_2, topic_1].sort, [topic_1, topic_2]
23752 [ topics(:first), posts(:welcome) ].sort
23753 [1, topic].sort
23754 post[:title] = "changed via []="
23755 post[:body] = "changed via []="
23756 assert_equal ["EUC-JP"], Weird.columns.map { |c| c.name.encoding.name }.uniq
23757 weird = Weird.create("a$b" => "value")
23758 weird.update_columns("a$b" => "value2")
23759 Weird.create("a$b" => "value", :from => "aaron")
23760 assert_equal Time.local(2000, 1, 1, 5, 42, 0), topic.bonus_time
23761 topic.title = "a"
23762 duped_topic.title = "b"
23763 dup = nil
23764 assert_equal Time.local(2004, 1, 1, 0, 0, 0, 0), default.fixed_time
23765 assert_equal Time.utc(2004, 1, 1, 0, 0, 0, 0), default.fixed_time_with_time_zone
23766 assert_equal Time.utc(2004, 1, 1, 0, 0, 0, 0), default.fixed_time
23767 assert(auto.id > 0)
23768 Topic.find("123456 OR id > 0")
23769 replies = Reply.all.merge!(where: [ "id IN (?)", topics(:first).replies.collect(&:id) ]).to_a
23770 replies = Reply.all.merge!(where: [ "id IN (?)", [] ]).to_a
23771 author_name = "\\ \001 '
\
\""
23772 t1 = Topic.find(1)
23773 t2 = Topic.find(1)
23774 k = Class.new(Joke)
23775 def k.name; "Foo"; end
23776 def k.table_name; super + "ks"; end
23777 k = Class.new(ak)
23778 res5 = Post.where("p.#{QUOTED_TYPE} = 'Post' AND p.id=co.post_id").joins("p, comments co").select("p.id").count
23779 res7 = Post.where("p.#{QUOTED_TYPE} = 'Post' AND p.id=co.post_id").joins("p, comments co").select("p.id").distinct.count
23780 assert_queries(2) { 2.times { query.call } }
23781 expected = ["id", "type", "firm_id", "firm_name", "name", "client_of", "rating", "account_id", "description", "status", "metadata"]
23782 types = { "author_name" => typecast.new }
23783 u = person.create!(first_name: "cool")
23784 u.first_name = "nah"
23785 @count ||= 0
23786 @count += 1 if reflection.name == :parts
23787 @count += 1 if reflection.name == :ship
23788 @count += 1 if reflection.name == :pirate
23789 firm = Firm.find(1)
23790 firm = Firm.new("name" => "GlobalMegaCorp")
23791 firm.account = a = Account.new("credit_limit" => 1000)
23792 firm.name += "-changed"
23793 assert_queries(1) { firm.save! }
23794 assert_queries(Firm.partial_updates? ? 0 : 1) { firm.save! }
23795 assert_queries(2) { firm.save! }
23796 eye = Eye.create(iris_attributes: { color: "honey" })
23797 eye.update(iris_attributes: { color: "blue" })
23798 client = Client.new(name: "Joe (the Plumber)")
23799 apple = Firm.new("name" => "Apple")
23800 final_cut = Client.new("name" => "Final Cut")
23801 mouse = Mouse.create!(name: "Will")
23802 assert_equal [{ error: :not_a_number, value: nil }], guitar.errors.details[:"tuning_pegs[1].pitch"]
23803 new_firm = Firm.new("name" => "A New Firm, Inc")
23804 new_firm.clients_of_firm.concat([c = Client.new, Client.new("name" => "Apple")])
23805 client = new_firm.clients.new("name" => "Apple")
23806 client = Client.new("name" => "Apple")
23807 { content: "Best content" },
23808 { content: "Best content" }
23809 c = Client.new("name" => "Apple")
23810 firm = Firm.new("name" => "Apple")
23811 company.name += "-changed"
23812 assert_queries(0) { company.clients_of_firm.build([{ "name" => "Another Client" }, { "name" => "Another Client II" }]) }
23813 company.clients_of_firm.build([{ "name" => "Another Client" }, { "name" => "Another Client II" }]) do |client|
23814 firm = Firm.new("name" => "New Firm")
23815 firm.clients = [companies(:second_client), Client.new("name" => "New Client")]
23816 firm = Firm.create!("name" => "New Firm").dup
23817 new_firm = Firm.new("name" => "some firm")
23818 new_autosaved_firm = Firm.new("name" => "some firm")
23819 firm = Firm.new("name" => "some firm")
23820 id = @pirate.ship.id
23821 @pirate.ship.name = ""
23822 assert_difference("Ship.count", -1) { @pirate.save! }
23823 def save(**)
23824 raise "Oh noes!"
23825 id = @ship.pirate.id
23826 assert_difference("Pirate.count", -1) { @ship.save! }
23827 2.times { |i| @pirate.birds.create!(name: "birds_#{i}") }
23828 ids = @pirate.birds.map(&:id)
23829 ids.each { |id| assert klass.find_by_id(id) }
23830 ids.each { |id| assert_nil klass.find_by_id(id) }
23831 @pirate.birds.each { |bird| bird.name = "" }
23832 assert_difference("Bird.count", -2) { @pirate.save! }
23833 before = @pirate.birds.map { |c| c.mark_for_destruction ; c }
23834 3.times { |i| @pirate.birds.build(name: "birds_#{i}") }
23835 3.times { |i| @pirate.birds.create(name: "unique_birds_#{i}") }
23836 2.times { |i| @pirate.parrots.create!(name: "parrots_#{i}") }
23837 @pirate.parrots.each { |parrot| parrot.name = "" }
23838 before = @pirate.parrots.map { |c| c.mark_for_destruction ; c }
23839 assert_no_queries { @ship.save! }
23840 assert_queries(1) { @ship.save! }
23841 assert_equal ["", ""], [@pirate.reload.catchphrase, @pirate.ship.name]
23842 2.times { |i| @pirate.ship.parts.create!(name: "part #{i}") }
23843 @pirate.ship.parts.each { |part| part.name = "" }
23844 assert_equal ["", "", "", ""], values
23845 assert_queries(1) { @pirate.catchphrase = "Arr"; @pirate.save! }
23846 post = Post.create! author: author, title: "foo", body: "bar"
23847 @ship.name = nil
23848 @ship.name = ""
23849 assert_equal ["", ""], [@ship.reload.name, @ship.pirate.catchphrase]
23850 assert_queries(1) { @ship.name = "The Vile Serpent"; @ship.save! }
23851 parent = Post.new title: "foo", body: "..."
23852 child = parent.comments.build body: "..."
23853 @pirate.public_send(@association_name).each { |child| child.name = "" }
23854 { @associated_model_name.to_s.to_sym => { blank: "cannot be blank" } }
23855 assert_equal [nil, nil, nil], [
23856 assert_equal ["", "", ""], [
23857 assert_no_difference("#{ @association_name == :birds ? 'Bird' : 'Parrot' }.count") do
23858 assert_difference("#{ @association_name == :birds ? 'Bird' : 'Parrot' }.count", 2) do
23859 @child_1.name = "Changed"
23860 @habtm = true
23861 @author = Author.new(name: "DHH")
23862 @pirate.parrot = Parrot.new(name: "")
23863 @pirate.parrots = [ Parrot.new(name: "popuga") ]
23864 post = Post.new(title: "Test", body: "...")
23865 comment = post.comments.build(body: "...")
23866 attribute :starts_at, :datetime, precision: 3, limit: 2, scale: 1, default: -> { Time.now.utc }
23867 attribute :starts_at, :datetime, precision: 3, default: -> { Time.now.utc }
23868 attribute :ends_at, default: -> { Time.now.utc }
23869 def cast(*)
23870 attribute :counter, :integer, default: -> { @@counter += 1 }
23871 model.foo << "asdf"
23872 model.foo = "lol"
23873 assert_equal "foo", klass.new(no_type: "foo").no_type
23874 t = topics(:first)
23875 t.content = ["some_value"]
23876 t.content = (1..11).to_a
23877 assert_equal "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]", t.attribute_for_inspect(:content)
23878 t.title = "hello there!"
23879 t.author_name = ""
23880 topic.attributes = { title: "Budget", author_name: "Jason" }
23881 test = AutoId.create(value: "")
23882 topic = Topic.new do |t|
23883 t.author_name = "Jason"
23884 content = %w( one two three )
23885 category_attrs = { "name" => "Test category", "id" => nil, "type" => nil, "categorizations_count" => nil }
23886 bool = Boolean.create!("value" => false)
23887 topic = Topic.new(content: ["ok"])
23888 topic = Topic.new(title: "Hello")
23889 topic.content = { "one" => 1, "two" => 2 }
23890 tz = "Pacific Time (US & Canada)"
23891 date_string = "2011-03-24"
23892 topic.content["three"] = 3
23893 topic.content = %w( one two three )
23894 topic.content << "five"
23895 expected = ["created_at", "developer", "extendedWarranty", "id", "system", "timezone", "updated_at"]
23896 new_topic = { "title" => "New Topic", "content" => { "key" => "First value" } }
23897 new_topic_values = { "title" => "AnotherTopic", "content" => { "key" => "Second value" } }
23898 topic["title"] = "Still another topic: part 4"
23899 assert_nothing_raised { topic[:title] = "Hello!" }
23900 topic[:title] = "Yet another topic: part 2"
23901 topic["title"] = "Yet another topic: part 4"
23902 topic = Topic.new(title: "a")
23903 def topic.title() "b" end
23904 [nil, "", " "].each do |value|
23905 [nil, 0, "0"].each do |value|
23906 [nil, "", false, "false", "f", 0].each do |value|
23907 [true, "true", "1", 1].each do |value|
23908 topic = klass.new(user_defined_json: { key: "value" })
23909 topic = klass.new(user_defined_json: {})
23910 object.int_value = "0"
23911 topic = @target.new(title: "Budget")
23912 %w(default_ title_).each do |prefix|
23913 meth = "#{prefix}title"
23914 assert_equal ["title", "a"], topic.public_send(meth, "a")
23915 assert_equal ["title", 1, 2, 3], topic.public_send(meth, 1, 2, 3)
23916 meth = "title#{suffix}"
23917 [["mark_", "_for_update"], ["reset_", "!"], ["default_", "_value?"]].each do |prefix, suffix|
23918 meth = "#{prefix}title#{suffix}"
23919 myobj = { "value1" => "value2" }
23920 topic = Topic.all.merge!(select: "topics.*, 0 as is_test").first
23921 topic = Topic.all.merge!(select: "topics.*, 1=2 as is_test").first
23922 topic = Topic.all.merge!(select: "topics.*, 1 as is_test").first
23923 topic = Topic.all.merge!(select: "topics.*, 2=2 as is_test").first
23924 klass.class_eval "def #{method}() 'defined #{method}' end"
23925 record.last_read = Time.utc(2010, 1, 1, 10)
23926 utc_time = Time.utc(2008, 1, 1)
23927 cst_time = utc_time.in_time_zone("Central Time (US & Canada)")
23928 (-11..13).each do |timezone_offset|
23929 record.written_on = " "
23930 time_string = "Tue Jan 01 00:00:00 2008"
23931 record = Topic.new(id: 1)
23932 time_string = "10:00:00"
23933 record.bonus_time = ""
23934 time_string = "ABC"
23935 record = @target.new(bonus_time: "10:00:00")
23936 expected_time = Time.utc(2000, 01, 01, 10)
23937 record = @target.new(bonus_time: [])
23938 2.times { klass = Class.new(klass) }
23939 dev = klass.new(name: "arthurnn")
23940 def title; "omg"; end
23941 topic.title = "lol"
23942 def system; "omg"; end
23943 super + "!"
23944 model = @target.select("id").last!
23945 model.id = "omg"
23946 @target.class_eval(<<-private_method, __FILE__, __LINE__ + 1)
23947 %w{ one two three }
23948 part = ship.parts.create!(name: "Mast")
23949 reader = Reader.create! person: person, post: Post.new(title: "foo", body: "bar")
23950 firm = Firm.new("name" => "A New Firm, Inc")
23951 client = Client.new("name" => "TheClient.com", "firm_id" => firm.id)
23952 blog_post.comments = []
23953 tag = Sharded::Tag.new(name: "Ruby on Rails", blog_id: blog_post.blog_id)
23954 david.posts << (post = Post.new(title: "New on Edge", body: "More cool stuff!"))
23955 josh = Author.new(name: "Josh")
23956 josh.posts << Post.new(title: "New on Edge", body: "More cool stuff!")
23957 post = authors(:david).posts.create(title: "New on Edge") { |p| p.body = "More cool stuff!" }
23958 post = authors(:david).posts.create!(title: "New on Edge") { |p| p.body = "More cool stuff!" }
23959 book = books(:awdr)
23960 comments = [
23961 post = Post.create!(
23962 title: "test post",
23963 title: "test post 2",
23964 title: "test post 3",
23965 .where(name: "David")
23966 bob_post = posts(:misc_by_bob)
23967 .where(blog_id: tag.blog_id, tag_id: tag.id)
23968 assert_sql(%r{/\* that tells jokes \*/}) do
23969 assert_sql(%r{/\* that are very colorful \*/}) do
23970 assert_sql(%r{/\* that is a rocket \*/}) do
23971 assert_sql(%r{/\* that are also parrots \*/}) do
23972 assert_sql(%r{/\* yarrr \*/}) do
23973 Author.where("tags.id" => tags(:general).id),
23974 [authors(:david)], :tags
23975 [:includes, :preload, :joins, :eager_load].each do |q|
23976 assert_equal [posts(:misc_by_bob), posts(:misc_by_mary), posts(:other_by_bob), posts(:other_by_mary)],
23977 blue = tags(:blue)
23978 .left_outer_joins(agents: { agents: { primary_contact: :agents } }).to_a
23979 assert queries.any? { |sql| /agents_people_4/i.match?(sql) }
23980 all_post_ids = Post.pluck(:id)
23981 assert queries.any? { |sql| /INNER JOIN/i.match?(sql) }
23982 queries = capture_sql { Author.left_outer_joins({}).to_a }
23983 queries = capture_sql { Author.left_outer_joins([]).to_a }
23984 assert_raise(ArgumentError) { Author.left_outer_joins('LEFT OUTER JOIN "posts" ON "posts"."user_id" = "users"."id"').to_a }
23985 assert queries.any? { |sql| /writer_type.*?=.*?(Author|\?|\$1|:a1)/i.match?(sql) }
23986 assert queries.none? { |sql| /WHERE/i.match?(sql) }
23987 authors = Author.select("authors.name, #{%{(authors.author_address_id || ' ' || authors.author_address_extra_id) as addr_id}}").left_outer_joins(:posts)
23988 post = Post.new title: "foo", body: "bar"
23989 Tag.has_many :null_taggings, -> { none }, class_name: :Tagging
23990 options = { where: "comments.#{QUOTED_TYPE}='SpecialComment'", order: "comments.id" }
23991 author = Author.all.merge!(where: ["name = ?", "David"], includes: :comments, order: "comments.id").first
23992 assert_equal [1, 2, 3, 5, 6, 7, 8, 9, 10, 12, 13], author.comments.collect(&:id)
23993 new_tag = Tag.new(name: "new")
23994 push = Tag.create!(name: "pushme")
23995 assert_nil(wrong = post_thinking.tags.detect { |t| t.class != Tag },
23996 tag = Tag.create!(name: "doomed")
23997 doomed = Tag.create!(name: "doomed")
23998 quaked = Tag.create!(name: "quaked")
23999 p = Post.all.merge!(includes: { taggings: :taggable }).find(posts(:welcome).id)
24000 taggings = Tagging.all.merge!(includes: :taggable, where: ["taggable_type != ?", "FakeModel"]).to_a
24001 comments = Comment.all.merge!(includes: :post, where: "post_id = 1").to_a
24002 sub_sti_post = SubStiPost.create!(title: "test", body: "test", author_id: 1)
24003 bulb = Bulb.create!(car: car)
24004 car.bulb.color = "Blue"
24005 bulb.color = "Red"
24006 human.name = "Bongo"
24007 human = Human.all.merge!(where: { name: "Gordon" }, includes: :face).first
24008 human = Human.all.merge!(where: { name: "Gordon" }, includes: :face, order: "faces.id").first
24009 human = Human.all.merge!(where: { name: "Gordon" }, includes: :interests).first
24010 human = Human.all.merge!(where: { name: "Gordon" }, includes: :interests, order: "interests.id").first
24011 comment.body = "OMG"
24012 face = Face.all.merge!(includes: :human, order: "humans.id", where: { description: "trusting" }).first
24013 iz = human.interests.detect { |_iz| _iz.id == interest.id }
24014 face = Face.all.merge!(where: { description: "confused" }, includes: :human, order: "humans.id").first
24015 iz = human.polymorphic_interests.detect { |_iz| _iz.id == interest.id }
24016 sql = Person.joins(agents: { agents: :agents }).joins(agents: { agents: { primary_contact: :agents } }).to_sql
24017 string_join = <<~SQL
24018 constraint = agents[:primary_contact_id].eq(agents_2[:id]).and(agents[:id].gt(agents_2[:id]))
24019 sql = Author.joins({}).to_sql
24020 sql = Author.joins([]).to_sql
24021 assert_match(/writer_type.*?=.*?Author/i, sql)
24022 real_count = Author.all.to_a.sum { |a| a.posts.count }
24023 real_count = Author.all.to_a.select { |a| a.posts.any? { |p| p.title.start_with?("Welcome") } }.length
24024 joins = capture_sql { @member.club }
24025 club = Club.new(name: "Da Club")
24026 Member.all.merge!(includes: :club, where: ["name = ?", "Groucho Marx"]).to_a
24027 Member.all.merge!(includes: :sponsor_club, where: ["name = ?", "Groucho Marx"]).to_a
24028 Member.all.merge!(includes: :club, where: ["members.name = ?", "Groucho Marx"], order: "clubs.name").to_a # force fallback
24029 Member.all.merge!(includes: :sponsor_club, where: ["members.name = ?", "Groucho Marx"], order: "clubs.name").to_a # force fallback
24030 Member.all.merge!(includes: :sponsor_club, where: ["members.name = ?", "Groucho Marx"], order: "clubs.name DESC").to_a # force fallback
24031 @club = @member.club
24032 apple = Firm.create("name" => "Apple")
24033 author.update!(name: "J.R.R. Tolkien")
24034 car = Car.create(name: "honda")
24035 bulb = car.build_bulb car_id: car.id + 1
24036 bulb = car.create_bulb car_id: car.id + 1
24037 bulb = car.build_bulb { |b| b.color = "Red" }
24038 bulb = car.create_bulb { |b| b.color = "Red" }
24039 bulb = car.create_bulb! { |b| b.color = "Red" }
24040 ship.name = "new name"
24041 new_ship = Ship.create(name: "new name")
24042 post = Post.create(id: 1234, title: "Some title", body: "Some content")
24043 author = Author.new(id: 33, name: "Hank Moody")
24044 post = Post.create!(author_id: 42, title: "foo", body: "bar")
24045 post = Post.create! title: "foo", body: "bar"
24046 [:errors, "errors", :save, "save"].each do |name|
24047 where_clause = { books: { subscriptions: { subscriber_id: nil } } }
24048 @post = @author.posts.create(title: "title", body: "body")
24049 @post2 = @author.posts.create(title: "title", body: "body")
24050 posts = Post.where(id: [authors(:david).id, authors(:mary).id]).
24051 has_many :posts, -> { order("posts.id DESC") }, through: :readers
24052 lesson, _, student = make_no_pk_hm_t
24053 sicp = lesson.new(name: "SICP")
24054 post = Post.create!(title: "Rails 6", body: "")
24055 posts(:thinking).body += "-changed"
24056 post = Post.new(title: "Hello", body: "world")
24057 tag.tagged_posts = []
24058 p = Post.new
24059 [:added, :before, "Michael"],
24060 [:added, :after, "Michael"]
24061 ], log.last(2)
24062 [:added, :before, "David"],
24063 [:added, :after, "David"],
24064 [:added, :before, "Bob"],
24065 [:added, :after, "Bob"],
24066 [:added, :before, "Lary"],
24067 [:added, :after, "Lary"]
24068 ], log.last(6)
24069 [:added, :before, "Ted"],
24070 [:added, :after, "Ted"]
24071 [:added, :before, "Sam"],
24072 [:added, :after, "Sam"]
24073 assert_equal((%w(Ted Bob Sam Lary) * 2).sort, log[-12..-5].collect(&:last).sort)
24074 [:added, :before, "Julian"],
24075 [:added, :after, "Julian"],
24076 [:added, :before, "Roger"],
24077 [:added, :after, "Roger"]
24078 ], log.last(4)
24079 post = Post.create!(author: author, title: "TITLE", body: "BODY")
24080 john = Person.create!(first_name: "John", primary_contact_id: sarah.id, gender: "M", number1_fan_id: 1)
24081 ids = [Developer.first.id, -9999]
24082 post = TaggedPost.create!(title: "Tagged", body: "Post")
24083 tag = post.tags.create!(name: "Tag")
24084 post = tags(:general).tagged_posts.create! title: "foo", body: "bar"
24085 assert_equal ["parrot", "bulbul"], owner.toys.map { |r| r.pet.name }
24086 post1 = Post.create(title: "active", body: "sample")
24087 post = Post.create!(title: "Beaches", body: "I like beaches!")
24088 users = 3.times.map { User.create! }
24089 raise "No pet!" if added.pet.nil?
24090 fall = Session.new(name: "Fall")
24091 sections = [
24092 tag_ids = []
24093 tag_ids = blog_post.tags.to_a.map(&:id)
24094 assert_match(/.* ON.* #{quoted_tags_blog_id} = #{quoted_posts_tags_blog_id} .* WHERE/, sql)
24095 assert_match(/.* WHERE #{quoted_posts_tags_blog_id} = .*/, sql)
24096 blog_post_ids = []
24097 blog_post_ids = tag.blog_posts.to_a.map(&:id)
24098 assert_match(/.* ON.* #{quoted_blog_posts_blog_id} = #{quoted_posts_tags_blog_id} .* WHERE/, sql)
24099 :posts, :readers, :taggings, :cars, :tags,
24100 assert_operator len, :>, 0
24101 dev = self
24102 counter += 1
24103 where("id = :inc", inc: counter)
24104 sql = capture_sql { post.comments.to_a }
24105 bulb = car.bulbs.create!(name: "exotic")
24106 car = Car.new(name: "honda")
24107 author.posts.create!(title: "test", body: "body")
24108 posts.create!(title: "test", body: "body")
24109 data = [{ name: "first" }, { name: "second" }]
24110 bulb = car.bulbs.new car_id: car.id + 1
24111 bulb = car.bulbs.build car_id: car.id + 1
24112 bulb = car.bulbs.create car_id: car.id + 1
24113 new_clients = []
24114 assert_equal 3, Firm.order(:id).find { |f| f.id > 0 }.clients.length
24115 has_many :posts, -> { order(:id) }
24116 firm = Firm.new(name: "Firm")
24117 firm = Firm.new(name: "Firm", id: 100)
24118 clients.each { |c| assert_equal firm.id, c.firm_id }
24119 summit = firm.clients.where("name = 'Summit'").to_a
24120 assert_equal summit, firm.clients.where("name = ?", "Summit").to_a
24121 firm = Firm.create!(name: "firm name")
24122 Developer.all.merge!(joins: :audit_logs, where: { "audit_logs.message" => nil, :name => "Smith" }).to_a
24123 all_clients_of_firm1 = Client.all.merge!(where: "firm_id = 1").to_a
24124 grouped_clients_of_firm1 = Client.all.merge!(where: "firm_id = 1", group: "firm_id", select: "firm_id, count(id) as clients_count").to_a
24125 assert_equal [1], posts(:welcome).comments.select { |c| c.id == 1 }.map(&:id)
24126 natural = Client.new("name" => "Natural Company")
24127 result = companies(:first_firm).clients_of_firm.concat([Client.new("name" => "Natural Company"), Client.new("name" => "Apple")])
24128 good = Client.new(name: "Good")
24129 firm.clients_of_firm << Client.new("name" => "Natural Company")
24130 new_clients = assert_queries(0) { company.clients_of_firm.build([{ "name" => "Another Client" }, { "name" => "Another Client II" }]) }
24131 companies(:first_firm).clients_of_firm.create([{ "name" => "Another Client" }, { "name" => "Another Client II" }])
24132 new_firm = Firm.new("name" => "A New Firm, Inc.")
24133 { title: "re: zoom", content: "speedy quick!" },
24134 { title: "re: zoom 2", content: "OMG lol!" },
24135 reply1 = Reply.create!(title: "re: zoom", content: "speedy quick!")
24136 reply2 = Reply.create!(title: "re: zoom 2", content: "OMG lol!")
24137 client = Client.new("name" => "New Client")
24138 post = posts.create!(title: "test", body: "body")
24139 topic = Topic.create "title" => "neat and simple"
24140 reply = topic.replies.create "title" => "neat and simple", "content" => "still digging it"
24141 reply.replies.create "title" => "neat and simple", "content" => "ain't complaining"
24142 assert_equal 3, Client.all.merge!(where: "firm_id=#{firm.id}").to_a.size
24143 firm.clients = []
24144 assert_equal [], firm.public_send("clients=", [])
24145 firm.clients_of_firm = [Client.new("name" => "New Client")]
24146 firm = Firm.create!(name: "Startup")
24147 assert_equal [2, 3, 11], firm.client_ids
24148 firm = Firm.create!(name: "Apple")
24149 lambda { authors(:mary).comments << Comment.create!(body: "Yay", post_id: 424242) },
24150 expected = [13, 12, 10, 9, 8, 7, 6, 5, 3, 2, 1]
24151 firm.clients.one? { true }
24152 bulb = Bulb.new(color: "red")
24153 post = SubStiPost.create! title: "fooo", body: "baa"
24154 firm = Firm.create! name: "omg"
24155 speedometer.minivans.create!(minivan_id: "a-van-red", name: "a van", color: "red")
24156 Post.create!(title: "signed post by bob", body: "stuff", author: authors(:bob))
24157 car = Car.create!(name: "honda") do |c|
24158 c.bulbs << bulb
24159 c.tyres << tyre
24160 car = Car.create!(name: "honda", bulbs: [bulb])
24161 new_bulb.name = "foo"
24162 car.bulbs = [new_bulb]
24163 car = klass.create!(bulbs: [bulb])
24164 car = Car.new
24165 car = Car.create!(name: "honda", bulbs: [first_bulb, second_bulb])
24166 firm = Firm.create!(name: "Firm")
24167 Bulb.before_save { |record| record.car.save && count += 1 }
24168 before_destroy -> { throw :abort }
24169 car = Car.create!(name: "Car")
24170 firm = Firm.create!(name: "A New Firm, Inc")
24171 firm = Firm.find(15)
24172 has_and_belongs_to_many :developers, -> { unscope(where: "name") },
24173 treaty.treaty_id = "t1"
24174 aredridel.projects.concat([Project.find(1), p = Project.new("name" => "Projekt")])
24175 new_project = Project.new("name" => "Grimetime")
24176 developers = (0...amount_of_developers).reverse_each.map { |i| Developer.create(name: "JME #{i}") }
24177 devel = Developer.create("name" => "Fred Wu")
24178 proj = assert_queries(0) { devel.projects.build("name" => "Projekt") }
24179 proj = assert_queries(0) { devel.projects.new("name" => "Projekt") }
24180 proj = devel.projects.create("name" => "Projekt")
24181 new_developer = Developer.new("name" => "Matz")
24182 developer = Developer.new("name" => "Kano")
24183 2,
24184 group = Developer.columns.inject([]) do |g, c|
24185 g << "developers.#{c.name}"
24186 g << "developers_projects_2.#{c.name}"
24187 Project.columns.each { |c| group << "projects.#{c.name}" }
24188 developer = Developer.new("name" => "Joe")
24189 assert_equal ["$10.00", "$20.00"].to_set, pirates(:redbeard).treasure_estimates.map(&:price).to_set
24190 detect { |p| p.id == first_project.id }
24191 assert_nil posts.detect { |p| p.author_id != authors(:david).id },
24192 assertions = ->(firm) {
24193 [:other_by_mary, :other_by_bob, :misc_by_mary, :misc_by_bob, :eager_other,
24194 posts = Post.select("posts.*").from("authors, posts").eager_load(:comments).where("posts.author_id = authors.id").order("posts.id").to_a
24195 posts = Post.all.merge!(includes: [ :comments, :author, :categories ], order: "posts.id").to_a
24196 comments = Comment.all.merge!(where: "post_id = 1", includes: [post: :author]).to_a
24197 popular_post = Post.create!(title: "foo", body: "I like cars!")
24198 readers = Reader.all.merge!(where: ["post_id = ?", popular_post.id],
24199 includes: { post: :comments }).to_a
24200 car_post = Post.create!(title: "foo", body: "I like cars!")
24201 categories = Category.all.merge!(where: { "posts.id" => car_post.id },
24202 includes: { posts: :comments }).to_a
24203 post = Post.create!(title: "foo", body: "I like cars!")
24204 Post.preload(comments: [{ author: :essays }]).find(post_id)
24205 includes: { author: :posts },
24206 where: "authors.id > 0"
24207 where: "posts.id > 0"
24208 titles = comments.map { |c| c.post.title }
24209 assert_equal [1, 2, 3, 5, 6], comments.collect(&:id)
24210 comments = Comment.all.merge!(includes: :post, where: "post_id = 4", limit: 3, order: "comments.id").to_a
24211 assert_equal [5, 6, 7], comments.collect(&:id)
24212 assert_equal [3, 5, 6], comments.collect(&:id)
24213 comments = Comment.all.merge!(includes: :post, where: "post_id = 4", limit: 3, offset: 1, order: "comments.id").to_a
24214 assert_equal [6, 7, 8], comments.collect(&:id)
24215 comments = Comment.all.merge!(includes: :post, where: ["post_id = ?", 4], limit: 3, offset: 1, order: "comments.id").to_a
24216 comments = []
24217 comments = Comment.all.merge!(includes: :post, where: { posts: { id: 4 } }, limit: 3, order: "comments.id").to_a
24218 Comment.includes(:post).references(:posts).where("#{quoted_posts_id} = ?", 4)
24219 posts = Post.all.merge!(includes: [:author, :very_special_comment], limit: 1, order: "posts.id").to_a
24220 posts = Post.all.merge!(includes: [:author, :very_special_comment], limit: 1, offset: 1, order: "posts.id").to_a
24221 s = Subscriber.create! do |c|
24222 c.id = "PL"
24223 b = Book.create!
24224 s.book_ids = s.book_ids
24225 books = books(:awdr, :rfr)
24226 Post.create!(author: author, title: "TITLE", body: "BODY")
24227 author_a = Author.create!(name: "A")
24228 author_b = Author.create!(name: "B")
24229 post_a = StiPost.create!(author: author_a, title: "TITLE", body: "BODY")
24230 post_b = SpecialPost.create!(author: author_b, title: "TITLE", body: "BODY")
24231 assert_equal [["David", 1], ["Mary", 0], ["Bob", 0]], special_comment_authors
24232 posts = Post.all.merge!(order: "posts.id asc", includes: [ :author, :comments ], limit: 2).to_a
24233 assert_equal 3, posts.inject(0) { |sum, post| sum + post.comments.size }
24234 posts = Post.all.merge!(includes: [ :author, :comments ], limit: 2, where: "posts.body = 'hello'", order: "posts.id").to_a
24235 assert_equal [4, 5], posts.collect(&:id)
24236 posts = Post.all.merge!(includes: [ :author, :comments ], limit: 2, where: [ "posts.body = ?", "hello" ], order: "posts.id").to_a
24237 posts = Post.includes(:author, :comments).limit(2).references("author").where("authors.name = ?", "David")
24238 posts = Post.all.merge!(includes: [ :author, :comments ], limit: 2, offset: 10, where: { "authors.name" => "David" }).to_a
24239 merge(includes: [ :author, :comments ], limit: 2, offset: 10,
24240 where: [ "authors.name = ? and comments.body = ?", "David", "go wild" ]).to_a
24241 posts = Post.all.merge!(includes: [ :author, :comments ], limit: 2, offset: 10,
24242 where: { "authors.name" => "David", "comments.body" => "go wild" }).to_a
24243 posts = Post.all.merge!(includes: [ :author, :comments ], limit: 2, offset: 10, where: { "authors.name" => "David" }).count(:all)
24244 posts = Post.all.merge!(includes: [ :author, :comments ], limit: 2, where: "posts.title = 'magic forest'").to_a
24245 posts = Post.all.merge!(includes: :categories, order: "posts.id", limit: 3).to_a
24246 post1 = general.posts.to_a.find { |p| p == welcome }
24247 post2 = technology.posts.to_a.find { |p| p == welcome }
24248 .limit(2)
24249 post = Post.all.merge!(includes: [ :special_comments ]).find(4)
24250 where: ["companies.name = ?", "37signals"]).first
24251 Post.all.merge!(includes: [ :monkeys ]).find(6)
24252 Post.all.merge!(includes: [ "monkeys" ]).find(6)
24253 Post.all.merge!(includes: [ :monkeys, :elephants ]).find(6)
24254 post1 = Post.create!(title: "Beaches", body: "I like beaches!")
24255 post2 = Post.create!(title: "Pools", body: "I like pools!")
24256 includes: [:author, :comments], where: { "authors.name" => "David" },
24257 order: "UPPER(posts.title)", limit: 2, offset: 1
24258 order: "UPPER(posts.title) DESC", limit: 2, offset: 1
24259 order: ["UPPER(posts.title)", "posts.id"], limit: 2, offset: 1
24260 order: ["UPPER(posts.title) DESC", "posts.id"], limit: 2, offset: 1
24261 people(:david, :susan),
24262 order: "people.id", limit: 2, offset: 0
24263 assert_equal(item1.sort { |a, b| a.id <=> b.id }, item2.sort { |a, b| a.id <=> b.id })
24264 assert_equal(item3.sort { |a, b| a.id <=> b.id }, item2.sort { |a, b| a.id <=> b.id }) if item3
24265 d1.each_index do |i|
24266 assert_equal(d1[i], d2[i])
24267 post_types[1..-1].each do |post_type|
24268 assert_equal(d1[i], d3[i])
24269 if (expected = d1[i].public_send(type)).nil?
24270 Comment.all.merge!(where: "123.456 = 123.456", includes: :post).to_a
24271 one = posts.detect { |p| p.id == 1 }
24272 Post.all.merge!(select: "distinct posts.*", includes: :author, joins: [:comments], where: "comments.body like 'Thank you%'", order: "posts.id").to_a
24273 Post.all.merge!(includes: :author, joins: { taggings: :tag }, where: "tags.name = 'General'", order: "posts.id").to_a
24274 Post.all.merge!(includes: :author, joins: { taggings: { tag: :taggings } }, where: "taggings_tags.super_tag_id=2", order: "posts.id").to_a
24275 firm = Firm.all.merge!(includes: :account_using_primary_key, order: "accounts.id").to_a.detect { |f| f.id == 1 }
24276 c = Client.create!(name: "Foo", client_of: Company.maximum(:id) + 1)
24277 client = assert_queries(2) { Client.preload(:firm).find(c.id) }
24278 t = Tagging.create!(taggable_type: "Post", taggable_id: Post.maximum(:id) + 1, tag: tags(:general))
24279 firm = Firm.where(id: "1").eager_load(:account).first!
24280 post = Post.where(id: "1").eager_load(:author).first!
24281 post = Post.includes(:tags).references(:tags).where("tags.name = ?", "General").first
24282 post = Post.eager_load(:tags).where("tags.name = ?", "General").first
24283 sponsors = []
24284 sponsors.map(&:sponsorable).map { |s| s.respond_to?(:posts) ? s.post.author : s.membership }
24285 post = posts.find { |post| post.id == sharded_blog_posts(:great_post_blog_one).id }
24286 .pluck(:tag_id)
24287 blog_post = blog_posts.find { |post| post.id == expected_blog_post.id }
24288 def remembered; @remembered ||= []; end
24289 res = ShapeExpression.all.merge!(includes: [ :shape, { paint: :non_poly } ]).to_a
24290 res.each do |se|
24291 assert_equal 11, authors[0].posts.collect { |post| post.comments.size }.inject(0) { |sum, i| sum + i }
24292 authors = Author.joins(:posts).eager_load(:comments).where(posts: { tags_count: 1 }).order(:id).to_a
24293 authors = Author.all.merge!(includes: { posts: [:comments, :author] }, order: "authors.id").to_a
24294 authors = Author.all.merge!(includes: { posts: :comments }, where: "authors.id=1", order: "authors.id").to_a
24295 firms = Firm.all.merge!(includes: { account: { firm: :account } }, order: "companies.id").to_a
24296 reply = Reply.new(title: "gaga", content: "boo-boo", parent_id: 1)
24297 topics = Topic.all.merge!(includes: :replies, order: ["topics.id", "replies_topics.id"]).to_a
24298 author = Author.all.merge!(includes: { posts: [ :special_comments, :very_special_comment ] }, order: ["authors.name", "comments.body", "very_special_comments_posts.body"], where: "posts.id = 4").first
24299 posts = Post.where(id: 3).preload(author: { comments: :post }).to_a
24300 source = Vertex.all.merge!(includes: { sinks: { sinks: { sinks: :sinks } } }, order: "vertices.id").first
24301 sink = Vertex.all.merge!(includes: { sources: { sources: { sources: :sources } } }, order: "vertices.id DESC").first
24302 assert_equal 3, authors[0].posts.collect { |post| post.categorizations.size }.inject(0) { |sum, i| sum + i }
24303 old_post = author.posts.create!(title: "first post", body: "test")
24304 post = Post.create!(title: "hello", body: "abc")
24305 post = Post.create!(title: "hello", body: "abc", author: author)
24306 jack = Author.new name: "Jack"
24307 firm = Firm.create! name: "Firm"
24308 assert_equal ["before_adding#{david.id}", "after_adding#{david.id}", "before_adding#{david.id}",
24309 new_dev = nil
24310 before_add: lambda { |o, r|
24311 new_dev = r.new_record?
24312 callback_log = ["before_adding<new>", "after_adding<new>"]
24313 :essays, :posts, :tags, :taggings, :comments, :sponsors, :members, :nodes
24314 sql_log = capture_sql { Client.find(3).firm }
24315 def self.name; "Temp"; end
24316 belongs_to :developer, default: -> { david }
24317 create_table(:admin_regions, force: true) { |t| t.string :name }
24318 assert_match(/^Region\([^)]+\) expected, got "wrong value" which is an instance of String\([^)]+\)$/, e.message)
24319 Firm.create("name" => "Apple")
24320 Client.create("name" => "Citibank", :firm_name => "Apple")
24321 debate = Topic.create("title" => "debate")
24322 trash = debate.replies.create("title" => "blah!", "content" => "world around!")
24323 reply = Reply.create!(title: "blah!", content: "world around!", topic: topic)
24324 debate2 = Topic.create("title" => "debate2")
24325 topic1 = Topic.create("title" => "t1")
24326 topic2 = Topic.create("title" => "t2")
24327 reply1 = Reply.new("title" => "r1", "content" => "r1")
24328 topic1 = Web::Topic.create("title" => "t1")
24329 topic2 = Web::Topic.create("title" => "t2")
24330 reply1 = Web::Reply.new("title" => "r1", "content" => "r1")
24331 time = 1.day.ago
24332 topic = Topic.create!(title: "37s")
24333 client = Client.new("firm_id" => 1)
24334 reply = Reply.create(title: "re: zoom", content: "speedy quick!")
24335 firm = client.build_firm { |f| f.name = "Agency Company" }
24336 firm = client.create_firm { |f| f.name = "Agency Company" }
24337 firm = client.create_firm! { |f| f.name = "Agency Company" }
24338 def self.name; "Post"; end
24339 post = Post.new(title: "foo", body: "bar")
24340 post = Post.create!(title: "title", body: "body")
24341 node = nodes(:child_one_of_a)
24342 @table = Table.new(:users)
24343 @attr = @table[:id]
24344 _(sql).must_be_like "?"
24345 values = Nodes::ValuesList.new([[bp]])
24346 _(sql).must_be_like "VALUES (?)"
24347 { Arel::Table => "hello" }
24348 _(sql).must_be_like '"users".*'
24349 _(sql).must_be_like %{ omg(*) = 2 }
24350 _(sql).must_be_like %{ omg(*) IS NULL }
24351 assert_equal "omg(*, *)", compile(function)
24352 _(compile(test)).must_be_like %{
24353 _(sql).must_be_like %{ 'f' = 'f' }
24354 _(sql).must_be_like %{ "users"."name" IS NULL }
24355 _(sql).must_equal "('foo')"
24356 _(sql).must_be_like %{ "users"."active" != 'f' }
24357 _(sql).must_be_like %{ "users"."name" IS NOT NULL }
24358 Class.new(String).new(":'("),
24359 Class.new(Class.new(String)).new(":'("),
24360 ].each do |obj|
24361 _(sql).must_be_like %{ "users"."name" != ':\\'(' }
24362 assert_match(/LIMIT 'omg'/, compile(sc))
24363 sc = table.where(table[:name].eq(0)).take(1).ast
24364 assert_match(/WHERE "users"."name" = 0 LIMIT 1/, compile(sc))
24365 _(sql).must_be_like %{"users"."created_at" = '#{dt.strftime("%Y-%m-%d %H:%M:%S")}'}
24366 test = Table.new(:products)[:price].eq 2.14
24367 _(sql).must_be_like %{"products"."price" = 2.14}
24368 sql = compile Nodes::Not.new(Arel.sql("foo"))
24369 _(sql).must_be_like "NOT (foo)"
24370 node = Nodes::And.new [@attr.eq(10), @attr.eq(11)]
24371 _(sql).must_be_like %{NOT ("users"."id" = 10 AND "users"."id" = 11)}
24372 as = Nodes::As.new(Arel.sql("foo"), Arel.sql("bar"))
24373 _(sql).must_be_like "foo AS bar"
24374 _(sql).must_be_like %{"users"."created_at" = '#{dt.strftime("%Y-%m-%d")}'}
24375 mgr = Table.new(:foo).project(:bar)
24376 _(compile(mgr)).must_be_like '(SELECT bar FROM "foo")'
24377 _(compile(node)).must_be_like %{
24378 node = Nodes::Or.new @attr.eq(10), @attr.eq(11)
24379 column = @table["id"]
24380 test = Table.new(:users)[:bool].eq(true)
24381 _(compile(test)).must_be_like %{ "users"."bool" = 't' }
24382 node = @table[:name].matches("foo%")
24383 node = @table[:name].matches("foo!%", "!")
24384 subquery = @table.project(:id).where(@table[:name].matches("foo%"))
24385 node = @table[:name].does_not_match("foo%")
24386 node = @table[:name].does_not_match("foo!%", "!")
24387 subquery = @table.project(:id).where(@table[:name].does_not_match("foo%"))
24388 node = @attr.in [1, 2, 3]
24389 node = @attr.in []
24390 _(compile(node)).must_equal "1=0"
24391 node = @attr.between 1..3
24392 node = @attr.between 1...3
24393 _(compile(node)).must_be_like %{1=1}
24394 _(compile(node)).must_equal %("products"."price" * "currency_rates"."rate")
24395 node = Arel::Attribute.new(Table.new(:products), :price) / 5
24396 _(compile(node)).must_equal %("products"."price" / 5)
24397 node = Arel::Attribute.new(Table.new(:products), :price) + 6
24398 _(compile(node)).must_equal %(("products"."price" + 6))
24399 node = Arel::Attribute.new(Table.new(:products), :price) - 7
24400 _(compile(node)).must_equal %(("products"."price" - 7))
24401 node = table[:name].concat(table[:name])
24402 _(compile(node)).must_equal %("users"."name" || "users"."name")
24403 _(compile(node)).must_equal %("users"."name" @> "users"."name")
24404 _(compile(node)).must_equal %("users"."name" && "users"."name")
24405 _(compile(node)).must_equal %(("products"."bitmap" & 16))
24406 _(compile(node)).must_equal %(("products"."bitmap" | 16))
24407 _(compile(node)).must_equal %(("products"."bitmap" ^ 16))
24408 node = Arel::Attribute.new(Table.new(:products), :bitmap) << 4
24409 _(compile(node)).must_equal %(("products"."bitmap" << 4))
24410 node = Arel::Attribute.new(Table.new(:products), :bitmap) >> 4
24411 _(compile(node)).must_equal %(("products"."bitmap" >> 4))
24412 _(compile(node)).must_equal %("products"."name" && "products"."name")
24413 _(compile(node)).must_equal %( ~ "products"."bitmap")
24414 _(compile(node)).must_equal %( ! "products"."active")
24415 subnode = Nodes::Union.new Arel.sql("left"), Arel.sql("right")
24416 node = @attr.not_in [1, 2, 3]
24417 node = @attr.not_in []
24418 _(compile(node)).must_equal "1=1"
24419 node = @attr.not_between 1..3
24420 %{("users"."id" < 1 OR "users"."id" > 3)}
24421 node = @attr.not_between 1...3
24422 %{("users"."id" < 1 OR "users"."id" >= 3)}
24423 node = @attr.not_between(-Float::INFINITY...3)
24424 _(compile(node)).must_be_like %{1=0}
24425 node = Nodes::BoundSqlLiteral.new("id = ?", [1], {})
24426 id = ?
24427 node = Nodes::BoundSqlLiteral.new("id = :id", [], { id: 1 })
24428 node = Nodes::BoundSqlLiteral.new("id = :0abc", [], { "0abc": 1 })
24429 id = :0abc
24430 node = Nodes::BoundSqlLiteral.new("id IN (?)", [[1, 2, 3]], {})
24431 id IN (?, ?, ?)
24432 Nodes::BoundSqlLiteral.new("id = ? AND name = :name", [1], { name: "Aaron" })
24433 Nodes::BoundSqlLiteral.new("id IN (?, ?, ?)", [1, 2], {})
24434 Nodes::BoundSqlLiteral.new("id IN (?, ?, ?)", [1, 2, 3, 4], {})
24435 Nodes::BoundSqlLiteral.new("id IN (:foo, :bar)", [], { foo: 1 })
24436 node = Nodes::BoundSqlLiteral.new("id = :id", [], { foo: 2, id: 1, bar: 3 })
24437 inner_literal = Nodes::BoundSqlLiteral.new("? * 2", [4], {})
24438 node = Nodes::BoundSqlLiteral.new("id IN (?)", [[1, [2, 3], inner_literal]], {})
24439 id IN (?, ?, ? * 2)
24440 node = Nodes::BoundSqlLiteral.new("id IN (?)", [[1, [2, 3]]], {})
24441 id IN (?, ?)
24442 node = Arel.sql("?", [1, 2, Arel.sql("?", 3)])
24443 ?, ?, ?
24444 test = Table.new(:users).alias("zomgusers")[:id].eq "3"
24445 node = Arel::Nodes::Regexp.new(@table[:name], Nodes.build_quoted("foo%"))
24446 node = Arel::Nodes::NotRegexp.new(@table[:name], Nodes.build_quoted("foo%"))
24447 node = Arel::Nodes::Case.new(@table[:name])
24448 .when("foo").then(1)
24449 .else(0)
24450 .when(@table[:name].in(%w(foo bar))).then(1)
24451 .when("bar").then(2)
24452 node = Arel::Nodes::Case.new @table[:name]
24453 { foo: 1, bar: 0 }.reduce(node) { |_node, pair| _node.when(*pair) }
24454 node = @table[:name].when("foo").then("bar").else("baz")
24455 _(compile(manager.ast)).must_be_like %{
24456 sql = Arel.sql("SELECT foo, bar") + Arel.sql(" FROM customers")
24457 sql += Arel.sql("FROM customers")
24458 node = Nodes::True.new()
24459 node = Nodes::False.new()
24460 _(compile(Nodes::Lock.new(Arel.sql("FOR UPDATE")))).must_be_like %{
24461 sc.orders << Arel.sql("xyz")
24462 assert_match(/LIMIT 'omg'/, sql)
24463 _(compile(subquery.lateral("bar"))).must_be_like %{
24464 node = @table[:name].matches("foo%", nil, true)
24465 node = @table[:name].does_not_match("foo%", nil, true)
24466 node = @table[:name].matches_regexp("foo.*")
24467 node = @table[:name].matches_regexp("foo.*", false)
24468 subquery = @table.project(:id).where(@table[:name].matches_regexp("foo.*"))
24469 node = @table[:name].does_not_match_regexp("foo.*")
24470 node = @table[:name].does_not_match_regexp("foo.*", false)
24471 subquery = @table.project(:id).where(@table[:name].does_not_match_regexp("foo.*"))
24472 query = @table[:name].eq(Arel::Nodes::BindParam.new(1))
24473 .and(@table[:id].eq(Arel::Nodes::BindParam.new(1)))
24474 _(compile(query)).must_be_like %{
24475 node = Arel::Nodes::Cube.new([@table[:name], @table[:bool]])
24476 CUBE( "users"."name", "users"."bool" )
24477 node = Arel::Nodes::Cube.new([dim1, dim2])
24478 CUBE( ( "users"."name" ), ( "users"."bool", "users"."created_at" ) )
24479 node = Arel::Nodes::GroupingSet.new([@table[:name], @table[:bool]])
24480 group = Arel::Nodes::GroupingElement.new([@table[:name], @table[:bool]])
24481 GROUPING SETS( ( "users"."name" ), ( "users"."bool", "users"."created_at" ) )
24482 node = Arel::Nodes::RollUp.new([@table[:name], @table[:bool]])
24483 ROLLUP( "users"."name", "users"."bool" )
24484 ROLLUP( ( "users"."name" ), ( "users"."bool", "users"."created_at" ) )
24485 inner = Nodes.build_quoted('{"foo":"bar"}')
24486 _(sql).must_be_like %{ "products"."metadata" @> '{"foo":"bar"}' }
24487 _(sql).must_be_like %{ "products"."tags" && '{foo,bar,baz}' }
24488 assert_equal("UPDATE \"users\" LIMIT 'omg'", compile(sc))
24489 query = @table[:name].concat(@table[:name])
24490 CONCAT("users"."name", "users"."name")
24491 _(sql).must_be_like %{ "users"."name" <=> NULL }
24492 NOT "users"."first_name" <=> "users"."last_name"
24493 _(sql).must_be_like %{ NOT "users"."name" <=> NULL }
24494 assert_match(/->.*label="#{edge_name}"/, dot_string)
24495 ].each do |klass|
24496 define_method("test_#{klass.name.gsub('::', '_')}") do
24497 op = klass.new(:a, "z")
24498 Arel::Nodes::On,
24499 op = klass.new(:a)
24500 Arel::Nodes::In,
24501 Arel::Nodes::Or,
24502 Arel::Nodes::As,
24503 binary = klass.new(:a, :b)
24504 node = Arel::Nodes::Case.new(foo)
24505 assert_match '[label="<f0>Arel::Nodes::Case"]', dot
24506 assert_match '[label="<f0>Arel::Nodes::When"]', dot
24507 assert_match '[label="<f0>Arel::Nodes::Else"]', dot
24508 node = Arel::Nodes::Regexp.new(table[:name], Nodes.build_quoted("foo%"))
24509 assert_match '[label="<f0>Arel::Nodes::Regexp"]', dot
24510 assert_match '[label="<f0>Arel::Nodes::NotRegexp"]', dot
24511 node = Arel::Nodes::UnaryOperation.new(:-, 1)
24512 node = Arel::Nodes::With.new(["query1", "query2", "query3"])
24513 assert_match '[label="<f0>Arel::Nodes::With"]', dot
24514 assert_edge("0", dot)
24515 assert_edge("1", dot)
24516 assert_edge("2", dot)
24517 assert_edge("key", dot)
24518 um.set [[table[:name], Arel::Nodes::BindParam.new(1)]]
24519 um.key = "id"
24520 um.set [[table[:name], nil]]
24521 _(um.to_sql).must_be_like %{ UPDATE "users" SET foo = bar }
24522 um.set [[table[:id], 1], [table[:name], "hello"]]
24523 _(um.to_sql).must_be_like %{
24524 _(um.set([[table[:id], 1], [table[:name], "hello"]])).must_equal um
24525 _(um.to_sql).must_be_like %{ UPDATE "users" }
24526 um.where table[:id].eq(1)
24527 _(um.where(table[:id].eq(1))).must_equal um
24528 @um.key = @table[:foo]
24529 _(@um.ast.key).must_equal @table[:foo]
24530 _(@um.key).must_equal @table[:foo]
24531 join = @relation.create_join "foo", "bar"
24532 _(mgr.to_sql).must_be_like %{
24533 it "noops on nil" do
24534 _(mgr.to_sql).must_be_like %{ SELECT FROM "users" }
24535 predicate = @relation[:id].eq(right[:id])
24536 ON "users"."id" = "users_2"."id"
24537 _(manager.to_sql).must_be_like %{
24538 _(node.name).must_equal "users_2"
24539 rel = Table.new :users, as: "foo"
24540 rel = Table.new :users, as: "users"
24541 _(manager.to_sql).must_be_like %{ SELECT * FROM "users" }
24542 _(manager.to_sql).must_be_like %{ SELECT *, * FROM "users" }
24543 column = @relation[:id]
24544 _(column.name).must_equal "id"
24545 @columns = {
24546 Column.new("id", :integer),
24547 Column.new("name", :string),
24548 Column.new("bool", :boolean),
24549 @columns_hash = {
24550 @primary_keys = {
24551 as = manager.as(Arel.sql("foo"))
24552 as = manager.as("foo")
24553 _(manager.to_sql).must_be_like 'SELECT "users"."id" FROM users'
24554 as = manager2.as Arel.sql("omg")
24555 _(manager1.to_sql).must_be_like %{
24556 mgr.having Arel::Nodes::And.new([Arel.sql("foo"), Arel.sql("bar")])
24557 mgr.join(right).on("omg")
24558 mgr.join(right).on("omg", "123")
24559 table = Table.new :users, as: "foo"
24560 m3 = m2.clone
24561 _(m2.to_sql).must_be_like %{ SELECT EXISTS (#{manager.to_sql}) }
24562 _(m2.to_sql).must_be_like %{ SELECT EXISTS (#{manager.to_sql}) AS foo }
24563 @m1.where(table[:age].lt(18))
24564 @m2.where(table[:age].gt(99))
24565 node = @m1.union @m2
24566 _(node.to_sql).must_be_like %{
24567 node = @m1.union :all, @m2
24568 @m1.where(table[:age].gt(18))
24569 @m2.where(table[:age].lt(99))
24570 @m1.where(table[:age].between(18..60))
24571 @m2.where(table[:age].between(40..99))
24572 node = @m1.except @m2
24573 _(select_manager.to_sql).must_be_like %{
24574 _(sql).must_be_like %{
24575 SELECT "comments"."id", "comments"."parent_id" FROM "comments" WHERE "comments"."id" = 42
24576 SELECT "comments"."id", "comments"."parent_id" FROM "comments" INNER JOIN "replies" ON "comments"."parent_id" = "replies"."id"
24577 order = table[:id]
24578 it "takes *args" do
24579 predicate = left[:id].eq(right[:id])
24580 ON "users"."id" = "users_2"."id" AND
24581 left[:name].eq(right[:name])
24582 children = ["foo", "bar", "baz"]
24583 join = relation.create_join "foo", "bar"
24584 manager.join("")
24585 assert_match 'INNER JOIN "users" "users_2" "users"."id" = "users_2"."id"',
24586 assert_match 'LEFT OUTER JOIN "users" "users_2" "users"."id" = "users_2"."id"',
24587 comments[:user_id].as("user_id"),
24588 ).as("counts")
24589 _(joins.to_sql).must_be_like %{
24590 it "can be empty" do
24591 manager.window("a_window").order(table["foo"].asc, table["bar"].desc)
24592 Nodes::And.new([
24593 ])))
24594 _(stmt.to_sql).must_be_like %{ DELETE FROM "users" }
24595 _(stmt.to_sql).must_be_like %{
24596 _(manager.where_sql).must_be_like %{ WHERE "users"."id" = 10 }
24597 _(manager.where_sql).must_be_like %{ WHERE "users"."id" = 10 AND "users"."id" = 11}
24598 _(manager.where_sql).must_be_like %{ WHERE "users"."id" = 10 AND "users"."name" ILIKE 'foo%' }
24599 stmt = manager.compile_update({ table[:id] => 1 }, Arel::Attributes::Attribute.new(table, "id"))
24600 _(stmt.to_sql).must_be_like %{ UPDATE "users" SET foo = bar }
24601 stmt.key = table["id"]
24602 _(manager.to_sql).must_be_like %{ SELECT * }
24603 _(manager.to_sql).must_be_like %{ SELECT foo, bar }
24604 _(manager.projections).must_equal [Arel.sql("foo"), Arel.sql("bar")]
24605 _(manager.to_sql).must_be_like %{ SELECT bar }
24606 manager.where(table["id"].eq(1))
24607 _(manager.to_sql).must_be_like 'SELECT "users"."id" FROM "users"'
24608 SELECT "users"."id" FROM "users" /* selecting */ /* with */ /* comment */
24609 eqeq_owner < Arel::Nodes::Node &&
24610 eqeq_owner == eql_owner &&
24611 window1.orders = [1, 2]
24612 window2.orders = [1, 2]
24613 statement.wheres = %w[a b c]
24614 statement.values = %w[x y z]
24615 array = [UnaryOperation.new(:-, 1), UnaryOperation.new(:-, 1)]
24616 array = [UnaryOperation.new(:-, 1), UnaryOperation.new(:-, 2)]
24617 array = [True.new, True.new]
24618 array = [True.new, Node.new]
24619 array = [node1, node2]
24620 _(table[:id].sum.as("foo").to_sql).must_be_like %{
24621 array = [Arel::Nodes::Sum.new("foo"), Arel::Nodes::Sum.new("foo")]
24622 array = [Arel::Nodes::Sum.new("foo"), Arel::Nodes::Sum.new("foo!")]
24623 _(table[:id].sum.desc.to_sql).must_be_like %{
24624 sql = Arel.sql "foo"
24625 node = SqlLiteral.new("*").count
24626 _(compile(node)).must_be_like %{ COUNT(*) }
24627 node = SqlLiteral.new("foo").eq(1)
24628 _(compile(node)).must_be_like %{ foo = 1 }
24629 array = [SqlLiteral.new("foo"), SqlLiteral.new("foo")]
24630 array = [SqlLiteral.new("foo"), SqlLiteral.new("bar")]
24631 node = SqlLiteral.new("foo").eq_any([1, 2])
24632 _(compile(node)).must_be_like %{ (foo = 1 OR foo = 2) }
24633 node = SqlLiteral.new("foo").eq_all([1, 2])
24634 _(compile(node)).must_be_like %{ (foo = 1 AND foo = 2) }
24635 sql + "Not a node"
24636 statement1.orders = %w[x y z]
24637 statement2.orders = %w[x y z]
24638 core.projections = %w[d e f]
24639 core1.projections = %w[d e f]
24640 core2.projections = %w[d e f]
24641 array = [core1, core2]
24642 _(table[:id].count.over.as("foo").to_sql).must_be_like %{
24643 _(table[:id].count.over("foo").to_sql).must_be_like %{
24644 _(table[:id].count.over(Arel.sql("foo")).to_sql).must_be_like %{
24645 _(table[:id].count.over.to_sql).must_be_like %{
24646 _(table[:id].count.over(window).to_sql).must_be_like %{
24647 array = [
24648 Arel::Nodes::Over.new("foo", "bar"),
24649 Arel::Nodes::Over.new("foo", "bar")
24650 Arel::Nodes::Over.new("foo", "baz")
24651 attr = Table.new(:users)[:id]
24652 right = attr.eq(11)
24653 array = [Or.new("foo", "bar"), Or.new("foo", "bar")]
24654 array = [Or.new("foo", "bar"), Or.new("foo", "baz")]
24655 array = [Not.new("foo"), Not.new("foo")]
24656 array = [Not.new("foo"), Not.new("baz")]
24657 }.grep(Class).each do |klass|
24658 next if /^Arel::Nodes::(?:Test|.*Test$)/.match?(klass.name)
24659 function = NamedFunction.new "omg", "zomg", "wth"
24660 NamedFunction.new("omg", "zomg", "wth"),
24661 NamedFunction.new("omg", "zomg", "wth")
24662 NamedFunction.new("zomg", "zomg", "wth")
24663 statement.columns = %w[a b c]
24664 statement1.columns = %w[a b c]
24665 statement2.columns = %w[a b c]
24666 array = [InfixOperation.new(:+, 1, 2), InfixOperation.new(:+, 1, 2)]
24667 array = [InfixOperation.new(:+, 1, 2), InfixOperation.new(:+, 1, 3)]
24668 expr = Arel::Nodes::HomogeneousIn.new(["Bobby", "Robert"], table[:name], :in)
24669 _(expr.to_sql).must_be_like %{
24670 [table[:nickname], table[:name]],
24671 expr = Arel::Nodes::HomogeneousIn.new(["Bobby", "Robert"], node, :in)
24672 COALESCE("users"."nickname", "users"."name") IN (?, ?)
24673 _(grouping.eq("foo").to_sql).must_be_like "('foo') = 'foo'"
24674 array = [Grouping.new("foo"), Grouping.new("foo")]
24675 array = [Grouping.new("foo"), Grouping.new("bar")]
24676 array = [Fragments.new(["foo", "bar"]), Fragments.new(["foo", "bar"])]
24677 array = [Fragments.new(["foo"]), Fragments.new(["bar"])]
24678 fragments = Fragments.new(["foo", "bar"])
24679 _(table[:id].count.filter(table[:income].gteq(40_000)).to_sql).must_be_like %{
24680 _(table[:id].count.filter(table[:income].gteq(40_000)).as("rich_users_count").to_sql).must_be_like %{
24681 _(table[:id].count.filter(table[:income].gteq(40_000)).over(window).to_sql).must_be_like %{
24682 array = [False.new, False.new]
24683 array = [False.new, Node.new]
24684 _(table[:timestamp].extract("date").to_sql).must_be_like %{
24685 _(table[:timestamp].extract("date").as("foo").to_sql).must_be_like %{
24686 array = [table[:attr].extract("foo"), table[:attr].extract("foo")]
24687 array = [table[:attr].extract("foo"), table[:attr].extract("bar")]
24688 def quote(*args) @quote_count += 1; super; end
24689 test = attr.eq(10)
24690 array = [Equality.new("foo", "bar"), Equality.new("foo", "bar")]
24691 array = [Equality.new("foo", "bar"), Equality.new("foo", "baz")]
24692 array = [Descending.new("zomg"), Descending.new("zomg")]
24693 array = [Descending.new("zomg"), Descending.new("zomg!")]
24694 statement1.wheres = %w[a b c]
24695 statement2.wheres = %w[a b c]
24696 statement2.wheres = %w[1 2 3]
24697 _(table[:id].count.as("foo").to_sql).must_be_like %{
24698 _(table[:id].count.eq(2).to_sql).must_be_like %{
24699 array = [Arel::Nodes::Count.new("foo"), Arel::Nodes::Count.new("foo")]
24700 array = [Arel::Nodes::Count.new("foo"), Arel::Nodes::Count.new("foo!")]
24701 array = [Comment.new(["foo"]), Comment.new(["foo"])]
24702 array = [Comment.new(["foo"]), Comment.new(["bar"])]
24703 one = Casted.new 1, 2
24704 also_one = Casted.new 1, 2
24705 node = Case.new "foo"
24706 node = Case.new nil, "bar"
24707 array = [case1, case2]
24708 as = node.as("bar")
24709 node1 = BoundSqlLiteral.new("foo + ?", [2], {})
24710 node2 = BoundSqlLiteral.new("foo + ?", [2], {})
24711 node2 = BoundSqlLiteral.new("foo + ?", [3], {})
24712 node3 = BoundSqlLiteral.new("foo + :bar", [], { bar: 2 })
24713 array = [node1, node2, node3]
24714 _(BindParam.new("foo")).must_equal(BindParam.new("foo"))
24715 eq = Equality.new("foo", "bar")
24716 eq2 = Equality.new("foo", "bar")
24717 eq3 = Equality.new("bar", "baz")
24718 neq = NotEqual.new("foo", "bar")
24719 node = Arel::Nodes::Bin.new(Arel.sql("zomg"))
24720 array = [Bin.new("zomg"), Bin.new("zomg")]
24721 array = [Bin.new("zomg"), Bin.new("zomg!")]
24722 array = [Ascending.new("zomg"), Ascending.new("zomg")]
24723 array = [Ascending.new("zomg"), Ascending.new("zomg!")]
24724 as = attr.as(Arel.sql("foo"))
24725 as = attr.as("foo")
24726 array = [As.new("foo", "bar"), As.new("foo", "bar")]
24727 array = [As.new("foo", "bar"), As.new("foo", "baz")]
24728 array = [And.new(["foo", "bar"]), And.new(["foo", "bar"])]
24729 array = [And.new(["foo", "bar"]), And.new(["foo", "baz"])]
24730 aliased = And.new(["foo", "bar"]).as("baz")
24731 assert_equal [%w{ a b }, %w{ c d }], values.rows
24732 %w{1 david},
24733 %w{2 kir},
24734 [Arel.sql("*")],
24735 %w{david},
24736 %w{kir},
24737 manager.insert [[table[:id], nil]]
24738 manager.insert [[table[:id], 1], [table[:name], "aaron"]]
24739 manager.insert [[table[:id], 1]]
24740 insert_result = manager.insert [[table[:id], 1]]
24741 manager.values = Nodes::ValuesList.new([[1], [2]])
24742 manager.values = Nodes::ValuesList.new([[1, "aaron"], [2, "david"]])
24743 self.class.new(target.gsub(/\s+/, " ").strip, ctx).must_equal other.gsub(/\s+/, " ").strip
24744 dm.key = table[:id]
24745 _(dm.to_sql).must_be_like %{ DELETE FROM "users" }
24746 dm.where table[:id].eq(10)
24747 _(dm.where(table[:id].eq(10))).must_equal dm
24748 @spec = self
24749 @config = { adapter: "sqlite3" }
24750 @calls << [name, args]
24751 im = fc.compile_insert [[table[:id], "foo"]]
24752 stmt = fc.compile_update [[table[:id], "foo"]], Arel::Attributes::Attribute.new(table, "id")
24753 assert_equal 'SELECT FROM "users" WHERE "users"."age" = hello AND "users"."name" = world', sql
24754 assert_equal 'SELECT FROM "users" WHERE "users"."age" = "hello" AND "users"."name" = "world"', sql
24755 sql, binds = compile(ast_with_binds(["hello", "world"]))
24756 assert_equal ["hello", "world"], binds
24757 sql, binds = compile(ast_with_binds(["hello2", "world3"]))
24758 assert_equal ["hello2", "world3"], binds
24759 binds = compile(ast_with_binds(["hello", "world"]))
24760 binds = compile(ast_with_binds(["hello2", "world3"]))
24761 array = [Attribute.new("foo", "bar"), Attribute.new("foo", "bar")]
24762 array = [Attribute.new("foo", "bar"), Attribute.new("foo", "baz")]
24763 %i[* /].each do |math_operator|
24764 AVG("users"."id") #{math_operator} 2
24765 _(table[:id].count.public_send(math_operator, 2).to_sql).must_be_like %{
24766 COUNT("users"."id") #{math_operator} 2
24767 MAX("users"."id") #{math_operator} 2
24768 MIN("users"."id") #{math_operator} 2
24769 _(table[:id].public_send(math_operator, 2).to_sql).must_be_like %{
24770 %i[+ - & | ^ << >>].each do |math_operator|
24771 (AVG("users"."id") #{math_operator} 2)
24772 (COUNT("users"."id") #{math_operator} 2)
24773 (MAX("users"."id") #{math_operator} 2)
24774 (MIN("users"."id") #{math_operator} 2)
24775 ("users"."id" #{math_operator} 2)
24776 it "should generate != in sql" do
24777 _(relation[:id].not_eq_any([1, 2])).must_be_kind_of Nodes::Grouping
24778 mgr.where relation[:id].not_eq_any([1, 2])
24779 _(relation[:id].not_eq_all([1, 2])).must_be_kind_of Nodes::Grouping
24780 mgr.where relation[:id].not_eq_all([1, 2])
24781 _(mgr.to_sql).must_match %{"users"."name" > 'fake_name'}
24782 _(mgr.to_sql).must_match %{"users"."created_at" > '#{current_time}'}
24783 _(relation[:id].gt_any([1, 2])).must_be_kind_of Nodes::Grouping
24784 mgr.where relation[:id].gt_any([1, 2])
24785 _(relation[:id].gt_all([1, 2])).must_be_kind_of Nodes::Grouping
24786 mgr.where relation[:id].gt_all([1, 2])
24787 it "should generate >= in sql" do
24788 _(mgr.to_sql).must_match %{"users"."name" >= 'fake_name'}
24789 _(mgr.to_sql).must_match %{"users"."created_at" >= '#{current_time}'}
24790 _(relation[:id].gteq_any([1, 2])).must_be_kind_of Nodes::Grouping
24791 mgr.where relation[:id].gteq_any([1, 2])
24792 _(relation[:id].gteq_all([1, 2])).must_be_kind_of Nodes::Grouping
24793 mgr.where relation[:id].gteq_all([1, 2])
24794 _(mgr.to_sql).must_match %{"users"."name" < 'fake_name'}
24795 _(mgr.to_sql).must_match %{"users"."created_at" < '#{current_time}'}
24796 _(relation[:id].lt_any([1, 2])).must_be_kind_of Nodes::Grouping
24797 mgr.where relation[:id].lt_any([1, 2])
24798 _(relation[:id].lt_all([1, 2])).must_be_kind_of Nodes::Grouping
24799 mgr.where relation[:id].lt_all([1, 2])
24800 it "should generate <= in sql" do
24801 _(mgr.to_sql).must_match %{"users"."name" <= 'fake_name'}
24802 _(mgr.to_sql).must_match %{"users"."created_at" <= '#{current_time}'}
24803 _(relation[:id].lteq_any([1, 2])).must_be_kind_of Nodes::Grouping
24804 mgr.where relation[:id].lteq_any([1, 2])
24805 _(relation[:id].lteq_all([1, 2])).must_be_kind_of Nodes::Grouping
24806 mgr.where relation[:id].lteq_all([1, 2])
24807 _(relation[:id].eq_any([1, 2])).must_be_kind_of Nodes::Grouping
24808 mgr.where relation[:id].eq_any([1, 2])
24809 values = [1, 2]
24810 _(values).must_equal [1, 2]
24811 _(relation[:id].eq_all([1, 2])).must_be_kind_of Nodes::Grouping
24812 mgr.where relation[:id].eq_all([1, 2])
24813 _(relation[:name].matches_any(["%chunky%", "%bacon%"])).must_be_kind_of Nodes::Grouping
24814 mgr.where relation[:name].matches_any(["%chunky%", "%bacon%"])
24815 _(relation[:name].matches_all(["%chunky%", "%bacon%"])).must_be_kind_of Nodes::Grouping
24816 mgr.where relation[:name].matches_all(["%chunky%", "%bacon%"])
24817 _(relation[:name].does_not_match_any(["%chunky%", "%bacon%"])).must_be_kind_of Nodes::Grouping
24818 mgr.where relation[:name].does_not_match_any(["%chunky%", "%bacon%"])
24819 _(relation[:name].does_not_match_all(["%chunky%", "%bacon%"])).must_be_kind_of Nodes::Grouping
24820 mgr.where relation[:name].does_not_match_all(["%chunky%", "%bacon%"])
24821 _(node).must_equal Nodes::NotIn.new(attribute, [])
24822 node = attribute.between(0...)
24823 _(node).must_equal Nodes::In.new(attribute, [])
24824 _(node).must_equal Nodes::And.new([
24825 node = attribute.in([1, 2, 3])
24826 _(node).must_equal Nodes::In.new(
24827 mgr.where relation[:id].in([1, 2, 3])
24828 _(relation[:id].in_any([1, 2])).must_be_kind_of Nodes::Grouping
24829 mgr.where relation[:id].in_any([[1, 2], [3, 4]])
24830 _(relation[:id].in_all([1, 2])).must_be_kind_of Nodes::Grouping
24831 mgr.where relation[:id].in_all([[1, 2], [3, 4]])
24832 node = relation[:id].in(union)
24833 node = attribute.not_in([1, 2, 3])
24834 mgr.where relation[:id].not_in([1, 2, 3])
24835 _(relation[:id].not_in_any([1, 2])).must_be_kind_of Nodes::Grouping
24836 mgr.where relation[:id].not_in_any([[1, 2], [3, 4]])
24837 _(relation[:id].not_in_all([1, 2])).must_be_kind_of Nodes::Grouping
24838 mgr.where relation[:id].not_in_all([[1, 2], [3, 4]])
24839 _(relation[:tags].contains(["foo", "bar"])).must_be_kind_of Nodes::Contains
24840 it "should generate @> in sql" do
24841 mgr.where relation[:tags].contains(["foo", "bar"])
24842 _(mgr.to_sql).must_be_like %{ SELECT "products"."id" FROM "products" WHERE "products"."tags" @> '{foo,bar}' }
24843 _(relation[:tags].overlaps(["foo", "bar"])).must_be_kind_of Nodes::Overlaps
24844 it "should generate && in sql" do
24845 mgr.where relation[:tags].overlaps(["foo", "bar"])
24846 _(mgr.to_sql).must_be_like %{ SELECT "products"."id" FROM "products" WHERE "products"."tags" && '{foo,bar}' }
24847 condition = table["id"].eq 1
24848 _(condition.to_sql).must_equal '"users"."id" = 1'
24849 table = Table.new(:foo)
24850 condition = table["id"].eq("1")
24851 _(condition.to_sql).must_equal %("foo"."id" = '1')
24852 if attr_name == "id"
24853 condition = table["id"].eq("1").and(table["other_id"].eq("2"))
24854 _(condition.to_sql).must_equal %("foo"."id" = 1 AND "foo"."other_id" = '2')
24855 condition = table["id"].eq(Arel.sql("(select 1)"))
24856 _(condition.to_sql).must_equal %("foo"."id" = (select 1))
24857 if attr_name == "tags"
24858 assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* foo \*/}i) do
24859 posts = Post.select(:id).annotate("foo")
24860 assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* \* /foo/ \* \*/}i) do
24861 posts = Post.select(:id).annotate("*/foo/*")
24862 assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* \*\* //foo// \*\* \*/}i) do
24863 posts = Post.select(:id).annotate("**//foo//**")
24864 assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* \* \* //foo// \* \* \*/}i) do
24865 posts = Post.select(:id).annotate("* *//foo//* *")
24866 assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* \* /foo/ \* \*/ /\* \* /bar \*/}i) do
24867 posts = Post.select(:id).annotate("*/foo/*").annotate("*/bar")
24868 customers(:barney).fullname = { first: "Barney", last: "Stinson" }
24869 assert_equal({ first: "Barney", last: "Stinson" }.to_s, customers(:barney).name)
24870 conn1.create_table(:zines) { |t| t.column(:title, :string) } if in_memory_db?
24871 options[:database] ||= "file::memory:"
24872 cache["foo"] = "bar"
24873 assert_equal "bar", cache["foo"]
24874 lookup = cache["foo"]
24875 assert_called_with(File, :join, [@root, @database], returns: "#{@root}/#{@database}") do
24876 ["sqlite3", "--noop", "db_create.sqlite3", ".schema"],
24877 with_structure_dump_flags(["--noop"]) do
24878 open(filename, "w") { |f| f.puts("select datetime('now', 'localtime');") }
24879 url = "sqlite3:#{tf.path}"
24880 url = "sqlite3::memory:"
24881 select = Owner.columns.map { |c| "typeof(#{c.name})" }.join ", "
24882 @conn.exec_insert("insert into ex (number) VALUES (?)", "SQL", vals)
24883 assert_equal [[1, "foo"]], result.rows
24884 str = (+"\x80").force_encoding("ASCII-8BIT")
24885 assert_equal "''", @conn.quote_string("'")
24886 name = "foo"
24887 assert_logged [[sql, name, []]] do
24888 id = @conn.insert(sql, nil, nil, idval)
24889 assert_equal [[0, 1], [1, 2]], rows
24890 sql = "select * from ex"
24891 count_sql = "select count(*) from ex"
24892 assert_equal %w{ ex }, @conn.tables
24893 assert_logged [[sql.squish, "SCHEMA", []]] do
24894 columns = @conn.columns("ex").sort_by(&:name)
24895 column = @conn.columns("ex").find { |x|
24896 x.name == "number"
24897 column = @conn.columns("ex").find { |x| x.name == "number" }
24898 column = @conn.columns("ex").find { |x| x.name == "name" }
24899 assert_logged [["PRAGMA index_list(\"ex\")", "SCHEMA", []]] do
24900 @conn.indexes("ex")
24901 assert_equal [], @conn.indexes("items")
24902 @conn.add_index "ex", "id", unique: true, name: "fun"
24903 index = @conn.indexes("ex").find { |idx| idx.name == "fun" }
24904 @conn.add_index "ex", "id"
24905 @conn.add_index "ex", "id", if_not_exists: true
24906 @conn.add_index "ex", "id", name: "fun"
24907 @conn.add_index "ex", %w{ id number }, name: "fun"
24908 @conn.add_index "ex", "max(id, number)", name: "expression"
24909 index = @conn.indexes("ex").find { |idx| idx.name == "expression" }
24910 @conn.execute "CREATE INDEX expression on ex (number % 10) /* comment */"
24911 @conn.add_index "ex", "id % 10, max(id, number)", name: "expression", where: "id > 1000"
24912 assert_equal "id % 10, (CASE WHEN number > 0 THEN max(id, number) END)", index.columns
24913 assert_equal "(id > 1000)", index.where
24914 @conn.add_index "ex", "id, max(id, number)", name: "expression"
24915 assert_equal "id", @conn.primary_key("ex")
24916 region = "US"
24917 t.index :code, unique: true, name: "unique"
24918 t.index :code, where: :bool_attr, name: "partial"
24919 t.index :code, name: "ordered", order: { code: :desc }
24920 partial_index = indexes.find { |idx| idx.name == "partial" }
24921 unique_index = indexes.find { |idx| idx.name == "unique" }
24922 ordered_index = indexes.find { |idx| idx.name == "ordered" }
24923 pk_column = connection.columns("barcodes").find { |col| col.name == "id" }
24924 statement.stub(:step, -> { raise ::SQLite3::BusyException.new("busy") }) do
24925 definition ||= <<~SQL
24926 bd = BigDecimal "10.0"
24927 value = "hello".encode("ascii-8bit")
24928 value = ::Time.utc(2000, 1, 1, 12, 30, 0, 999999)
24929 value = ::Time.utc(2018, 3, 11, 12, 30, 0, 999999)
24930 expected = expected.getutc.to_fs(:db).sub(/\A\d\d\d\d-\d\d-\d\d /, "2000-01-01 ")
24931 expected = expected.getlocal.to_fs(:db).sub(/\A\d\d\d\d-\d\d-\d\d /, "2000-01-01 ")
24932 t.json "payload", default: {}
24933 @connection.add_column "json_data_type", "permissions", column_type, default: { "users": "read", "posts": ["read", "write"] }
24934 assert_equal({ "users" => "read", "posts" => ["read", "write"] }, klass.column_defaults["permissions"])
24935 assert_equal({ "users" => "read", "posts" => ["read", "write"] }, klass.new.permissions)
24936 assert_match %r(EXPLAIN for: SELECT "authors"\.\* FROM "authors" WHERE "authors"\."id" = (?:\? \[\["id", 1\]\]|1)), explain
24937 assert_match %r(EXPLAIN for: SELECT "posts"\.\* FROM "posts" WHERE "posts"\."author_id" = (?:\? \[\["author_id", 1\]\]|1)), explain
24938 assert_find_cmd_and_exec_called_with(["sqlite3", "-html", root.join("db.sqlite3").to_s]) do
24939 assert_find_cmd_and_exec_called_with(["sqlite3", "-header", root.join("db.sqlite3").to_s]) do
24940 Pathname(__dir__).join("../../../..")
24941 def test_copy_table(from = "customers", to = "customers2", options = {})
24942 rename: { "name" => "person_name" }) do |from, to, options|
24943 @connection.add_index("comments_with_index", ["post_id", "type"])
24944 original_id = @connection.columns("goofy_string_id").detect { |col| col.name == "id" }
24945 copied_id = @connection.columns("goofy_string_id2").detect { |col| col.name == "id" }
24946 def copy_table(from, to, options = {})
24947 @connection.select_all("SELECT #{column} FROM #{table} ORDER BY id").map { |row| row[column] }
24948 column = @connection.columns(:collation_table_sqlite3).find { |c| c.name == "title" }
24949 assert_match %r{t\.text\s+"text_rtrim",\s+collation: "RTRIM"$}, output
24950 count = Post.where("title = ?", "Welcome to the weblog").count
24951 count = Post.where("title = ?", 0).count
24952 count = Post.where("title = ?", 0.0).count
24953 count = Post.where("title = ?", false).count
24954 count = Post.where("title = ?", BigDecimal(0)).count
24955 count = Post.where("title = ?", Rational(0)).count
24956 data = XmlDataType.new(payload: "<foo>bar</foo>")
24957 t.virtual :column2, type: :integer, as: "column1 + 1", stored: true
24958 t.virtual :lower_name, type: :string, as: "LOWER(name)", stored: true
24959 message = <<~MSG
24960 assert_match(/t\.virtual\s+"upper_name",\s+type: :string,\s+as: "upper\(\(name\)::text\)", stored: true$/i, output)
24961 assert_match(/t\.virtual\s+"name_length",\s+type: :integer,\s+as: "length\(\(name\)::text\)", stored: true$/i, output)
24962 assert_match(/t\.virtual\s+"name_octet_length",\s+type: :integer,\s+as: "octet_length\(\(name\)::text\)", stored: true$/i, output)
24963 assert_match(/t\.virtual\s+"column2",\s+type: :integer,\s+as: "\(column1 \+ 1\)", stored: true$/i, output)
24964 t.uuid "guid"
24965 assert_match %r{t\.uuid "thingy", default: \[\], array: true$}, schema
24966 @uuid = uuid
24967 ].each do |valid_uuid|
24968 0,
24969 0.0,
24970 assert_match %r{t\.uuid "guid"}, output
24971 connection.create_table("pg_uuids", id: :uuid, default: "uuid_generate_v1()") do |t|
24972 t.uuid "other_uuid", default: "uuid_generate_v4()"
24973 connection.create_table("pg_uuids_2", id: :uuid, default: "my_uuid_generator()") do |t|
24974 t.uuid "other_uuid_2", default: "my_uuid_generator()"
24975 connection.create_table("pg_uuids_3", id: :uuid, **uuid_default) do |t|
24976 assert_match(/\bcreate_table "pg_uuids", id: :uuid, default: -> { "uuid_generate_v1\(\)" }/, schema)
24977 assert_match(/t\.uuid "other_uuid", default: -> { "uuid_generate_v4\(\)" }/, schema)
24978 assert_match(/\bcreate_table "pg_uuids_2", id: :uuid, default: -> { "my_uuid_generator\(\)" }/, schema)
24979 assert_match(/t\.uuid "other_uuid_2", default: -> { "my_uuid_generator\(\)" }/, schema)
24980 assert_match(/\bcreate_table "pg_uuids_3", id: :uuid, default: -> { "gen_random_uuid\(\)" }/, schema)
24981 assert_match(/\bcreate_table "pg_uuids_3", id: :uuid, default: -> { "uuid_generate_v4\(\)" }/, schema)
24982 create_table("pg_uuids_4", id: :uuid)
24983 assert_match(/\bcreate_table "pg_uuids_4", id: :uuid, default: -> { "uuid_generate_v4\(\)" }/, schema)
24984 create_table("pg_uuids_4", id: :uuid, default: nil)
24985 assert_match(/\bcreate_table "pg_uuids_4", id: :uuid, default: nil/, schema)
24986 has_many :uuid_posts, -> { order("title DESC") }
24987 %("schema"."table_name") => %w{schema table_name},
24988 }.each do |given, expect|
24989 obj = Name.new("public", "articles")
24990 obj = Name.new(nil, "articles")
24991 name = Name.new('"quoted_schema"', '"quoted_table"')
24992 assert_equal Name.new("access", "users"), Name.new("access", "users")
24993 assert_equal Name.new(nil, "users"), Name.new(nil, "users")
24994 assert_not_equal Name.new(nil, "users"), Name.new("access", "users")
24995 assert_not_equal Name.new("access", "users"), Name.new("public", "users")
24996 assert_not_equal Name.new("public", "users"), Name.new("public", "articles")
24997 hash = { Name.new("schema", "article_seq") => "success" }
24998 int_array = @connection.send(:type_map).lookup(1007, -1, "integer[]")
24999 bigint_array = @connection.send(:type_map).lookup(1016, -1, "bigint[]")
25000 s = Sample.create!(value: 1)
25001 sleep(0.5)
25002 assert_equal Time.utc(2010, 1, 1, 11, 0, 0), timestamp.time
25003 keys.each { |k| assert_kind_of Time, k }
25004 d = Developer.create!(name: "aaron", updated_at: 1.0 / 0.0)
25005 assert_equal(1.0 / 0.0, d.updated_at)
25006 d = Developer.create!(name: "aaron", updated_at: -1.0 / 0.0)
25007 assert_equal(-1.0 / 0.0, d.updated_at)
25008 date = Time.new(0) - 1.week
25009 date = Time.utc(-4, 2, 29)
25010 date = Time.utc(0, 4, 7)
25011 assert_equal({ "data_type" => "timestamp without time zone" },
25012 assert_equal({ "data_type" => "timestamp with time zone" },
25013 assert_equal({ "data_type" => "USER-DEFINED", "udt_name" => "custom_time_format" },
25014 pg_connection.stub(:get_last_result, -> { raise "random error" }) do
25015 t.integer :serials_id, default: -> { "nextval('postgresql_serials_id_seq')" }
25016 assert_match %r{t\.serial\s+"seq",\s+null: false$}, output
25017 assert_match %r{t\.integer\s+"serials_id",\s+default: -> \{ "nextval\('postgresql_serials_id_seq'::regclass\)" \}$}, output
25018 t.bigint :serials_id, default: -> { "nextval('postgresql_big_serials_id_seq')" }
25019 assert_match %r{t\.bigserial\s+"seq",\s+null: false$}, output
25020 assert_match %r{t\.bigint\s+"serials_id",\s+default: -> \{ "nextval\('postgresql_big_serials_id_seq'::regclass\)" \}$}, output
25021 assert_match %r{t\.serial\s+"bar_id",\s+null: false$}, output
25022 assert_match %r{t\.bigserial\s+"bar_baz_id",\s+null: false$}, output
25023 INDEX_C_COLUMN = "(to_tsvector('english', coalesce(things.name, '')))"
25024 @connection.exec_query "select * from developers where id = ?", "sql", [bind_param(1)]
25025 @connection.exec_query "select * from developers where id = $1", "sql", [bind_param(1)]
25026 ].each do |given|
25027 new_name = "#{old_name}_new"
25028 index_a, index_b, index_c, index_d, index_e = indexes
25029 assert_match(/opclass: \{ position: :text_pattern_ops \}/, output)
25030 assert_match(/order: \{ name: "NULLS FIRST" \}/, output)
25031 t.text "text_col", default: "some value"
25032 assert_equal 't.index ["firm_id", "type"], name: "company_include_index", include: [:name, :account_id]', index_definition
25033 st = SchemaThing.new id: 5, name: "TEST2"
25034 assert_changes(-> { num_indices_named("before_rename_pkey") }, from: 1, to: 0) do
25035 assert_changes(-> { num_indices_named("after_rename_pkey") }, from: 0, to: 1) do
25036 JOIN "pg_class" ON "pg_index"."indexrelid" = "pg_class"."oid"
25037 WHERE "pg_class"."relname" = '#{name}'
25038 date_range: "[''2012-01-02'', ''2012-01-04'']",
25039 num_range: "[0.1, 0.2]",
25040 ts_range: "[''2010-01-01 14:30'', ''2011-01-01 14:30'']",
25041 tstz_range: "[''2010-01-01 14:30:00+05'', ''2011-01-01 14:30:00-03'']",
25042 int4_range: "[1, 10]",
25043 int8_range: "[10, 100]",
25044 float_range: "[0.5, 0.7]")
25045 date_range: "[''2012-01-02'', ''2012-01-04'')",
25046 num_range: "[0.1, 0.2)",
25047 ts_range: "[''2010-01-01 14:30'', ''2011-01-01 14:30'')",
25048 tstz_range: "[''2010-01-01 14:30:00+05'', ''2011-01-01 14:30:00-03'')",
25049 int4_range: "[1, 10)",
25050 int8_range: "[10, 100)",
25051 float_range: "[0.5, 0.7)")
25052 date_range: "[''2012-01-02'',]",
25053 num_range: "[0.1,]",
25054 ts_range: "[''2010-01-01 14:30'',]",
25055 tstz_range: "[''2010-01-01 14:30:00+05'',]",
25056 int4_range: "[1,]",
25057 int8_range: "[10,]",
25058 float_range: "[0.5,]")
25059 date_range: "[,]",
25060 num_range: "[,]",
25061 ts_range: "[,]",
25062 tstz_range: "[,]",
25063 int4_range: "[,]",
25064 int8_range: "[,]",
25065 float_range: "[,]")
25066 date_range: "[''2012-01-02'', ''2012-01-02'')",
25067 num_range: "[0.1, 0.1)",
25068 ts_range: "[''2010-01-01 14:30'', ''2010-01-01 14:30'')",
25069 tstz_range: "[''2010-01-01 14:30:00+05'', ''2010-01-01 06:30:00-03'')",
25070 int4_range: "[1, 1)",
25071 int8_range: "[10, 10)",
25072 float_range: "[0.5, 0.5)")
25073 assert_equal Date.new(2012, 1, 2)...Date.new(2012, 1, 5), @first_range.date_range
25074 assert_equal Date.new(2012, 1, 2)...Date.new(2012, 1, 4), @second_range.date_range
25075 assert_equal Time.public_send(tz, 2010, 1, 1, 14, 30, 0)..Time.public_send(tz, 2011, 1, 1, 14, 30, 0), @first_range.ts_range
25076 assert_equal Time.public_send(tz, 2010, 1, 1, 14, 30, 0)...Time.public_send(tz, 2011, 1, 1, 14, 30, 0), @second_range.ts_range
25077 assert_equal Time.public_send(tz, 2010, 1, 1, 14, 30, 0)...nil, @third_range.ts_range
25078 to_time_string = (from_time + 1.hour).to_s
25079 assert_equal [from_time...to_time, from_time..to_time, from_time..., ..to_time], record.tstz_ranges
25080 tstzrange = Time.parse("2010-01-01 14:30:00 +0100")...Time.parse("2011-02-02 14:30:00 CDT")
25081 Time.parse("2010-01-01 14:30:00 CDT")...Time.parse("2011-02-02 14:30:00 CET"))
25082 Time.parse("2010-01-01 14:30:00 +0100")...Time.parse("2010-01-01 13:30:00 +0000"))
25083 Time.parse("-1000-01-01 14:30:00 CDT")...Time.parse("2020-02-02 14:30:00 CET"))
25084 Time.public_send(tz, 2010, 1, 1, 14, 30, 0)...Time.public_send(tz, 2011, 2, 2, 14, 30, 0))
25085 Time.public_send(tz, 2010, 1, 1, 14, 30, 0)...Time.public_send(tz, 2010, 1, 1, 14, 30, 0))
25086 Time.public_send(tz, -1000, 1, 1, 14, 30, 0)...Time.public_send(tz, 2020, 2, 2, 14, 30, 0))
25087 assert_equal_round_trip @first_range, :ts_range, Time.public_send(tz, 2010, 1, 1, 14, 30, 0)...nil
25088 assert_equal_round_trip @first_range, :ts_range, nil..Time.public_send(tz, 2010, 1, 1, 14, 30, 0)
25089 assert_equal [from_time...to_time, from_time..to_time, from_time..., ..to_time], record.ts_ranges
25090 Time.parse("2010-01-01 14:30:00.245124 CDT")...Time.parse("2011-02-02 14:30:00.451274 CET"))
25091 Time.parse("2010-01-01 14:30:00.245124 +0100")...Time.parse("2010-01-01 13:30:00.245124 +0000"))
25092 Time.public_send(tz, 2010, 1, 1, 14, 30, 0, 125435)...Time.public_send(tz, 2011, 2, 2, 14, 30, 0, 225435))
25093 Time.public_send(tz, 2010, 1, 1, 14, 30, 0, 142432)...Time.public_send(tz, 2011, 2, 2, 14, 30, 0, 224242))
25094 Time.public_send(tz, 2010, 1, 1, 14, 30, 0, 142432)...Time.public_send(tz, 2010, 1, 1, 14, 30, 0, 142432))
25095 BigDecimal("0.5")...BigDecimal("1"))
25096 BigDecimal("0.5")...BigDecimal("0.5"))
25097 Range.new(Date.new(2012, 1, 1), Date.new(2013, 1, 1), true))
25098 Date.new(2012, 2, 3)...Date.new(2012, 2, 10))
25099 Date.new(2012, 2, 3)...Date.new(2012, 2, 3))
25100 assert_raises(ArgumentError) { PostgresqlRange.create!(date_range: "(''2012-01-02'', ''2012-01-04'']") }
25101 assert_raises(ArgumentError) { PostgresqlRange.create!(ts_range: "(''2010-01-01 14:30'', ''2011-01-01 14:30'']") }
25102 assert_raises(ArgumentError) { PostgresqlRange.create!(tstz_range: "(''2010-01-01 14:30:00+05'', ''2011-01-01 14:30:00-03'']") }
25103 range = 1..100
25104 range = "-1,2]'; DROP TABLE postgresql_ranges; --".."a"
25105 VALUES (106, '["ca""t","do\\\\g")')
25106 assert_equal('ca"t'...'do\\g', escaped_range.string_range)
25107 int4_range: 1..,
25108 int8_range: 10..,
25109 float_range: 0.5..
25110 id,
25111 nan = 0.0 / 0
25112 assert_equal "'NaN'", @conn.quote(nan)
25113 infinity = 1.0 / 0
25114 assert_equal "'[1,0]'", @conn.quote(type.serialize(range))
25115 value = "user posts"
25116 mock.expect(:call, nil, [{ adapter: "postgresql", database: "postgres", schema_search_path: "public" }])
25117 mock.expect(:call, nil, [db_config])
25118 merge("encoding" => "latin")
25119 merge("collation" => "ja_JP.UTF8", "ctype" => "ja_JP.UTF8")
25120 ["my-app-db"]
25121 assert_equal [" statement
", "-- lower comment
"], File.readlines(@filename).first(2)
25122 expected_command = [expected_env, "pg_dump", "--schema-only", "--no-privileges", "--no-owner", "--file", @filename, "my-app-db"]
25123 expected_command = [{}, "pg_dump", "--schema-only", "--no-privileges", "--no-owner", "--file", @filename, "--noop", "my-app-db"]
25124 expected_command = [{}, "pg_dump", "--schema-only", "--no-privileges", "--no-owner", "--file", @filename, "my-app-db"]
25125 with_structure_dump_flags({ mysql2: ["--noop"] }) do
25126 with_structure_dump_flags({ postgresql: ["--noop"] }) do
25127 [{}, "pg_dump", "--schema-only", "--no-privileges", "--no-owner", "--file", @filename, "--schema=foo", "--schema=bar", "my-app-db"],
25128 [{}, "pg_dump", "--schema-only", "--no-privileges", "--no-owner", "--file", filename, "my-app-db"],
25129 [{}, "psql", "--set", "ON_ERROR_STOP=1", "--quiet", "--no-psqlrc", "--output", File::NULL, "--file", filename, @configuration["database"]],
25130 with_structure_load_flags(["--noop"]) do
25131 with_structure_load_flags({ mysql2: ["--noop"] }) do
25132 with_structure_load_flags({ postgresql: ["--noop"] }) do
25133 [{}]
25134 result = @connection.exec_query("SELECT id, data FROM ex WHERE id = $1", nil, [bind])
25135 @connection.add_index "ex", %w{ id number }, name: "partial", where: "number > 100"
25136 index = @connection.indexes("ex").find { |idx| idx.name == "partial" }
25137 @connection.add_index "ex", %w{ id }, name: "include", include: :number
25138 index = @connection.indexes("ex").find { |idx| idx.name == "include" }
25139 @connection.add_index "ex", %w{ id }, name: "include", include: [:number, :data]
25140 expr = "mod(id, 10), abs(number)"
25141 index = @connection.indexes("ex").find { |idx| idx.name == "expression" }
25142 index = @connection.indexes("ex").find { |idx| idx.name == "index_ex_on_data" }
25143 assert_not @connection.indexes("ex").find { |idx| idx.name == "index_ex_on_data" }
25144 @connection.create_enum "feeling", ["good", "bad"]
25145 self.table_name = "ex"
25146 assert_sql(%r{\ASELECT /\*\+ SeqScan\(posts\) \*/}) do
25147 posts = posts.select(:id).where(author_id: [0, 1])
25148 posts = posts.select(:id).where(author_id: [0, 1]).limit(5)
25149 posts = Post.optimizer_hints("/*+ SeqScan(posts) */")
25150 posts = Post.optimizer_hints("**// \"posts\".*, //**")
25151 assert_equal({ "id" => 1 }, posts.first.as_json)
25152 assert_sql(%r{\ASELECT "posts"\."id"}) do
25153 t.column "single", "REAL"
25154 t.inet "inet_address", default: "192.168.1.1"
25155 t.cidr "cidr_address", default: "192.168.1.0/24"
25156 t.macaddr "mac_address", default: "ff:ff:ff:ff:ff:ff"
25157 inet_address: "172.16.1.254/32",
25158 mac_address: "01:23:45:67:89:0a")
25159 address.cidr_address = "10.1.2.3/32"
25160 address.inet_address = "10.0.0.0/8"
25161 assert_match %r{t\.inet\s+"inet_address",\s+default: "192\.168\.1\.1"}, output
25162 assert_match %r{t\.cidr\s+"cidr_address",\s+default: "192\.168\.1\.0/24"}, output
25163 assert_match %r{t\.macaddr\s+"mac_address",\s+default: "ff:ff:ff:ff:ff:ff"}, output
25164 t.money "depth", default: "150.55"
25165 assert_equal(-1.15, type.cast(+"-$1.15"))
25166 assert_equal(-2.25, type.cast(+"($2.25)"))
25167 assert_equal(-1.15, type.cast(+"-1.15"))
25168 assert_equal(-2.25, type.cast(+"(2.25)"))
25169 assert_equal(0.0, type.cast("$" + "," * 100000 + ".11!"))
25170 assert_equal(0.0, type.cast("$" + "." * 100000 + ",11!"))
25171 assert_match %r{t\.money\s+"wealth",\s+scale: 2$}, output
25172 assert_match %r{t\.money\s+"depth",\s+scale: 2,\s+default: "150\.55"$}, output
25173 ltree = Ltree.new(path: "1.2.3.4")
25174 assert_match %r[t\.ltree "path"], output
25175 t.public_send column_type, "payload", default: {} # t.json 'payload', default: {}
25176 x = klass.new(objects: ["foo" => "bar"])
25177 assert_equal ["foo" => "bar"], x.objects
25178 def write(*); end
25179 using: :gin,
25180 create_enum :color, ["blue", "green"]
25181 t.enum :best_color, enum_type: "color", default: "blue", null: false
25182 drop_enum :color, ["blue", "green"], if_exists: true
25183 maximum_term: 6.year + 5.month + 4.days + 3.hours + 2.minutes + 1.seconds,
25184 minimum_term: 1.year + 2.month + 3.days + 4.hours + 5.minutes + (6.234567).seconds,
25185 t.hstore "tags", default: ""
25186 @connection.add_column "hstores", "permissions", :hstore, default: '"users"=>"read", "articles"=>"write"'
25187 assert_equal({ "users" => "read", "articles" => "write" }, Hstore.column_defaults["permissions"])
25188 assert_equal({ "users" => "read", "articles" => "write" }, Hstore.new.permissions)
25189 t.hstore "users", default: ""
25190 change_table("hstores") do |t|
25191 x = Hstore.new tags: { "bool" => true, "number" => 5 }
25192 assert_equal({ "bool" => true, "number" => 5 }, x.tags_before_type_cast)
25193 assert_equal({ "bool" => "true", "number" => "5" }, x.tags)
25194 assert_equal({ "bool" => "true", "number" => "5" }, x.reload.tags)
25195 assert_equal({ "1" => "2" }, @type.deserialize("\"1\"=>\"2\""))
25196 assert_equal({}, @type.deserialize(""))
25197 assert_cycle("key" => nil)
25198 assert_cycle("c" => "}", '"a"' => 'b "a b')
25199 x = Hstore.new(language: "fr", timezone: "GMT")
25200 x.language = "de"
25201 x = Hstore.new(language: "de")
25202 hstore = Hstore.create!(settings: { "one" => "two" })
25203 hstore.settings["three"] = "four"
25204 settings = { "alongkey" => "anything", "key" => "value" }
25205 hstore.settings = { "key" => "value", "alongkey" => "anything" }
25206 assert_cycle(" " => " ")
25207 assert_cycle("," => "")
25208 assert_cycle("=" => ">")
25209 assert_cycle({ "a" => nil, "b" => nil, "c" => "NuLl", "null" => "c" })
25210 assert_cycle("=a" => "q=w")
25211 assert_cycle("\"a" => "q>w")
25212 assert_cycle("\"a" => "q\"w")
25213 x.tags = { '"a\'' => "b" }
25214 assert_equal({ "1" => "2" }, x.tags)
25215 assert_array_cycle([{ "AA" => "BB", "CC" => "DD" }, { "AA" => nil }])
25216 assert_array_cycle([{ "this has" => 'some "s that need to be escaped"' }])
25217 assert_array_cycle([{ "this,has" => "many,values" }])
25218 assert_array_cycle(["{" => "}"])
25219 assert_array_cycle([{ "NULL" => "NULL" }])
25220 assert_array_cycle([{ "NULL" => nil }])
25221 @connection.execute "insert into hstores (tags) VALUES ('1=>2,2=>3')"
25222 assert_equal({ "1" => "2", "2" => "3" }, x.tags)
25223 assert_cycle("a" => "b", "1" => "2")
25224 assert_cycle("a" => nil)
25225 assert_cycle("a" => 'b"ar', '1"foo' => "2")
25226 assert_cycle("a b" => "b ar", '1"foo' => "2")
25227 assert_cycle('a\\b' => 'b\\ar', '1"foo' => "2")
25228 assert_cycle('a\\"' => 'b\\ar', '1"foo' => "2")
25229 assert_cycle("a\\" => "bar\\", '1"foo' => "2")
25230 assert_cycle("a, b" => "bar", '1"foo' => "2")
25231 assert_cycle("a=>b" => "bar", '1"foo' => "2")
25232 assert_cycle("a
b" => "c
d")
25233 assert_equal({ "one" => "two" }, record.tags.to_hash)
25234 record.tags = TagCollection.new("three" => "four")
25235 assert_equal({ "one" => "two" }, dupe.tags.to_hash)
25236 assert_match %r[t\.hstore "tags",\s+default: {}], output
25237 assert_equal "\"hi\"=>\"hi\"", @type.serialize(ProtectedParams.new("hi" => "hi"))
25238 x = Hstore.create!(payload: [])
25239 x = Hstore.create!(tags: hash)
25240 x = Hstore.create!(tags: {})
25241 x.tags = hash
25242 t.point :x
25243 t.point :y, default: [12.2, 13.3]
25244 t.point :z, default: "(14.4,15.5)"
25245 t.point :legacy_y, default: [12.2, 13.3]
25246 t.point :legacy_z, default: "(14.4,15.5)"
25247 assert_match %r{t\.point\s+"x"$}, output
25248 assert_match %r{t\.point\s+"y",\s+default: \[12\.2, 13\.3\]$}, output
25249 assert_match %r{t\.point\s+"z",\s+default: \[14\.4, 15\.5\]$}, output
25250 p.x.y = 25
25251 p = PostgresqlPoint.new(x: [1, 2])
25252 p = PostgresqlPoint.new(x: "(1, 2)")
25253 p = PostgresqlPoint.new(x: "")
25254 assert_match %r{t\.point\s+"legacy_x"$}, output
25255 assert_match %r{t\.point\s+"legacy_y",\s+default: \[12\.2, 13\.3\]$}, output
25256 assert_match %r{t\.point\s+"legacy_z",\s+default: \[14\.4, 15\.5\]$}, output
25257 record.legacy_x = [1.1, 2.2]
25258 assert_equal [1.1, 2.2], record.legacy_x
25259 p.legacy_x[1] = 25
25260 assert_equal [10.0, 25.0], p.legacy_x
25261 a_line_segment: "(2.0, 3), (5.5, 7.0)",
25262 a_box: "2.0, 3, 5.5, 7.0",
25263 a_path: "[(2.0, 3), (5.5, 7.0), (8.5, 11.0)]",
25264 a_polygon: "((2.0, 3), (5.5, 7.0), (8.5, 11.0))",
25265 a_circle: "<(5.3, 10.4), 2>"
25266 assert_equal "[(2,3),(5.5,7)]", h.a_line_segment
25267 assert_equal "[(2,3),(5.5,7),(8.5,11)]", h.a_path
25268 assert_equal "((2,3),(5.5,7),(8.5,11))", h.a_polygon
25269 assert_equal "<(5.3,10.4),2>", h.a_circle
25270 a_line_segment: "((2.0, 3), (5.5, 7.0))",
25271 a_box: "(2.0, 3), (5.5, 7.0)",
25272 a_path: "((2.0, 3), (5.5, 7.0), (8.5, 11.0))",
25273 a_polygon: "2.0, 3, 5.5, 7.0, 8.5, 11.0",
25274 a_circle: "((5.3, 10.4), 2)"
25275 assert_equal "((2,3),(5.5,7),(8.5,11))", h.a_path
25276 assert_match %r{t\.lseg\s+"a_line_segment"$}, output
25277 assert_match %r{t\.box\s+"a_box"$}, output
25278 assert_match %r{t\.path\s+"a_path"$}, output
25279 assert_match %r{t\.polygon\s+"a_polygon"$}, output
25280 assert_match %r{t\.circle\s+"a_circle"$}, output
25281 a_line: "{2.0, 3, 5.5}"
25282 assert_equal "{2,3,5.5}", h.a_line
25283 a_line: "(2.0, 3), (4.0, 6.0)"
25284 assert_equal "{1.5,-1,0}", h.a_line
25285 assert_match %r{t\.line\s+"a_line"$}, output
25286 column = connection.columns(table_name).find { |c| c.name == column_name.to_s }
25287 tsvector.text_vector = "'new' 'text' 'vector'"
25288 assert_match %r(EXPLAIN SELECT "authors"\.\* FROM "authors" WHERE "authors"\."id" = (?:\$1 \[\["id", 1\]\]|1)), explain
25289 assert_match %r(EXPLAIN SELECT "posts"\.\* FROM "posts" WHERE "posts"\."author_id" = (?:\$1 \[\["author_id", 1\]\]|1)), explain
25290 sad: "sad",
25291 happy: "happy",
25292 }, _prefix: true
25293 @connection.create_enum("mood", ["sad", "ok", "happy"])
25294 assert_includes output, 'create_enum "mood", ["sad", "ok", "happy"]'
25295 @connection.create_enum("mood_in_other_schema", ["sad", "ok", "happy"])
25296 @connection.create_enum("test_schema.mood_in_other_schema", ["sad", "ok", "happy"])
25297 @connection.create_enum("mood_in_test_schema", ["sad", "ok", "happy"])
25298 assert_includes output, 'create_enum "public.mood", ["sad", "ok", "happy"]'
25299 assert_includes output, 'create_enum "mood_in_test_schema", ["sad", "ok", "happy"]'
25300 create_enum "mood_in_test_schema", ["sad", "ok", "happy"]
25301 create_enum "public.mood", ["sad", "ok", "happy"]
25302 record.price = "34.15"
25303 def run(*)
25304 assert_find_cmd_and_exec_called_with(["psql", "db"]) do
25305 database: "db",
25306 host: "host",
25307 ENV_VARS.zip(old_values).each { |var, value| ENV[var] = value }
25308 topic = Topic.create!(last_read: 1.0 / 0.0)
25309 assert_equal(1.0 / 0.0, topic.last_read)
25310 topic = Topic.create!(last_read: -1.0 / 0.0)
25311 assert_equal(-1.0 / 0.0, topic.last_read)
25312 date = Date.new(0) - 1.week
25313 date = Time.utc(-4, 2, 29).to_date
25314 date = Time.utc(0, 4, 7).to_date
25315 column = @connection.columns("ex").find { |col| col.name == "data" }
25316 params[:options] = "-c geqo=off"
25317 @connection.exec_query("SELECT $1::integer", "SQL", [bind], prepare: true)
25318 assert_equal set_true.rows, [["on"]]
25319 assert_equal set_false.rows, [["off"]]
25320 (classid::bigint << 32) | objid::bigint AS lock_id
25321 advisory_lock = @connection.query(list_advisory_locks).find { |l| l[1] == lock_id }
25322 advisory_locks = @connection.query(list_advisory_locks).select { |l| l[1] == lock_id }
25323 if value =~ /\("?([^",]*)"?,"?([^",]*)"?\)/
25324 FullAddress.new($1, $2)
25325 column = @connection.columns(:postgresql_collations).find { |c| c.name == "string_c" }
25326 column = @connection.columns(:postgresql_collations).find { |c| c.name == "title" }
25327 assert_match %r{t\.string\s+"string_c",\s+collation: "C"$}, output
25328 assert_match %r{t\.text\s+"text_posix",\s+collation: "POSIX"$}, output
25329 x = Citext.new(cival: "Some CI Text")
25330 type = OID::Cidr.new
25331 ip = IPAddr.new("255.0.0.0/8")
25332 ip2 = IPAddr.new("127.0.0.1")
25333 column = connection.columns(:strings).find { |c| c.name == "somedate" }
25334 data = "\u001F\x8B"
25335 data = (+"\u001F\x8B").force_encoding("BINARY")
25336 data = "\u001F"
25337 data = "'\u001F\\"
25338 assert_equal([[data]], result)
25339 data = File.read(File.join(__dir__, "..", "..", "..", "assets", "example.log"))
25340 def load(str); str; end
25341 def dump(str); str; end
25342 t.bit :a_bit, default: "00000011", limit: 8
25343 assert_match %r{t\.bit\s+"a_bit",\s+limit: 8,\s+default: "00000011"$}, output
25344 assert_match %r{t\.bit_varying\s+"a_bit_varying",\s+limit: 4,\s+default: "0011"$}, output
25345 Post.where("title = ?", 0).count
25346 Post.where("title = ?", 0.0).count
25347 Post.where("title = ?", false).count
25348 Post.where("title = ?", BigDecimal(0)).count
25349 Post.where("title = ?", Rational(0)).count
25350 t.string "tags", array: true, limit: 255
25351 t.decimal :decimals, array: true, default: [], precision: 10, scale: 2
25352 def to_a; @tags end
25353 new_klass.create!(tags: MyTags.new(["one", "two"]))
25354 assert_equal ["one", "two"], record.tags.to_a
25355 record.tags = MyTags.new(["three", "four"])
25356 @connection.add_column "pg_arrays", "score", :integer, array: true, default: [4, 4, 2]
25357 assert_equal([4, 4, 2], PgArray.new.score)
25358 @connection.add_column "pg_arrays", "names", :string, array: true, default: ["foo", "bar"]
25359 assert_equal(["foo", "bar"], PgArray.column_defaults["names"])
25360 assert_equal(["foo", "bar"], PgArray.new.names)
25361 @connection.change_column :pg_arrays, :snippets, :text, array: true, default: [], using: "string_to_array(\"snippets\", ',')"
25362 assert_equal(["1", "2", "3"], @type.deserialize("{1,2,3}"))
25363 assert_equal([], @type.deserialize("{}"))
25364 assert_equal([nil], @type.deserialize("{NULL}"))
25365 x = PgArray.new(ratings: ["1", "2"])
25366 assert_equal([1, 2], x.ratings)
25367 assert_match %r[t\.string\s+"tags",\s+limit: 255,\s+array: true], output
25368 assert_match %r[t\.decimal\s+"decimals",\s+precision: 10,\s+scale: 2,\s+default: \[\],\s+array: true], output
25369 @connection.execute "insert into pg_arrays (tags) VALUES ('{1,2,3}')"
25370 assert_equal(["1", "2", "3"], x.tags)
25371 x.tags = ["1", "2", "3", "4"]
25372 assert_equal ["1", "2", "3", "4"], x.reload.tags
25373 assert_equal([1, 2, 3], x.ratings)
25374 x.ratings = [2, "3", 4]
25375 assert_equal [2, 3, 4], x.reload.ratings
25376 assert_cycle(:tags, [[["1"], ["2"]], [["2"], ["3"]]])
25377 assert_cycle(:tags, [ "1", "2", "", "4", "", "5" ])
25378 assert_cycle(:tags, [[["1", "2"], ["", "4"], ["", "5"]]])
25379 assert_cycle(:ratings, [[[1], [7]], [[8], [10]]])
25380 assert_cycle(:tags, ["this has", 'some "s that need to be escaped"'])
25381 assert_cycle(:tags, ["this,has", "many,values"])
25382 assert_cycle(:tags, ["{", "}"])
25383 assert_cycle(:tags, ["1", nil, nil])
25384 tag_values = ["val1", "val2", "val3_with_'_multiple_quote_'_chars"]
25385 @connection.insert_fixture({ "tags" => tag_values }, "pg_arrays")
25386 record = PgArray.new { |a| a.ratings = (1..10).to_a }
25387 assert_equal("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]", record.attribute_for_inspect(:ratings))
25388 record = PgArray.new { |a| a.ratings = (1..11).to_a }
25389 assert_equal("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]", record.attribute_for_inspect(:ratings))
25390 unknown = 'foo\\",bar,baz,\\'
25391 tags = ["hello_#{unknown}"]
25392 strings = ["hello,", "world;"]
25393 x = PgArray.create!(tags: %w(one two))
25394 x.tags << "three"
25395 x = PgArray.create!(hstores: [{ a: "a" }, { b: "b" }])
25396 x.hstores.first["a"] = "c"
25397 assert_equal [{ "a" => "c" }, { "b" => "b" }], x.hstores
25398 record = PgArray.new(tags: "")
25399 record = PgArray.new(tags: "{1,2,3}")
25400 assert_equal ["1", "2", "3"], record.tags
25401 tags = ["black", "blue"]
25402 e1 = klass.create("tags" => ["black", "blue"])
25403 e2 = klass.create("tags" => ["black", "blue"])
25404 x = PgArray.create!(field => array)
25405 x = PgArray.create!(field => [])
25406 x.public_send("#{field}=", array)
25407 assert_equal expected, add_index(:people, [:last_name, :first_name], order: { last_name: :desc, first_name: :asc })
25408 assert_equal expected, add_index(:people, ["last_name", :first_name], order: { last_name: :desc, "first_name" => :asc })
25409 expected = %(CREATE INDEX "index_people_on_last_name" ON "people" USING #{type} ("last_name"))
25410 assert_equal expected, add_index(:people, [:last_name, :first_name], order: { last_name: "DESC NULLS LAST", first_name: :asc })
25411 t.virtual :lower_name, type: :string, as: "LOWER(name)"
25412 assert_match(/t\.virtual\s+"upper_name",\s+type: :string,\s+as: "(?:UPPER|UCASE)\(`name`\)"$/i, output)
25413 assert_match(/t\.virtual\s+"name_length",\s+type: :integer,\s+as: "(?:octet_length|length)\(`name`\)",\s+stored: true$/i, output)
25414 assert_match(/t\.virtual\s+"name_octet_length",\s+type: :integer,\s+as: "(?:octet_length|length)\(`name`\)",\s+stored: true$/i, output)
25415 assert_match(/t\.virtual\s+"profile_email",\s+type: :string,\s+as: "json_extract\(`profile`,\w*?'\$\.email'\)", stored: true$/i, output)
25416 assert_match(/t\.virtual\s+"time_mirror",\s+type: :datetime,\s+as: "`time`"$/i, output[/^.*time_mirror.*$/])
25417 @connection.columns("unsigned_types").select { |c| /^unsigned_/.match?(c.name) }.each do |column|
25418 expected = /create_table "mysql_table_options", charset: "utf8mb4"(?:, collation: "\w+")?, options: "ENGINE=MyISAM", force: :cascade/
25419 expected = /create_table "mysql_table_options", charset: "latin1"(?:, collation: "\w+")?, force: :cascade/
25420 @connection.execute("SET @@SESSION.sql_mode='#{new_sql_mode}'")
25421 @connection.execute("SET @@SESSION.sql_mode='#{old_sql_mode}'")
25422 expected = /create_table "mysql_table_options", charset: "utf8mb4"(?:, collation: "\w+")?(:?, options: "ENGINE=InnoDB ROW_FORMAT=DYNAMIC")?, force: :cascade/
25423 expected = /create_table "mysql_table_options", charset: "utf8mb4"(?:, collation: "\w+")?, force: :cascade/
25424 rows = @connection.select_rows("CALL ten();")
25425 assert_equal 10, rows[0][0].to_i, "ten() did not return 10 as expected: #{rows.inspect}"
25426 t.column :set_column, "set('text','blob','tiny','medium','long','unsigned','bigint')"
25427 assert_match %r{t\.column "set_column", "set\('text','blob','tiny','medium','long','unsigned','bigint'\)"$}, schema
25428 self.table_name = "#{db}.#{table}"
25429 column_no_limit = @connection.columns(:mysql_doubles).find { |c| c.name == "float_no_limit" }
25430 column_short = @connection.columns(:mysql_doubles).find { |c| c.name == "float_short" }
25431 column_long = @connection.columns(:mysql_doubles).find { |c| c.name == "float_long" }
25432 column_23 = @connection.columns(:mysql_doubles).find { |c| c.name == "float_23" }
25433 column_24 = @connection.columns(:mysql_doubles).find { |c| c.name == "float_24" }
25434 column_25 = @connection.columns(:mysql_doubles).find { |c| c.name == "float_25" }
25435 table = "key_tests"
25436 index_a = indexes.select { |i| i.name == index_a_name }[0]
25437 index_b = indexes.select { |i| i.name == index_b_name }[0]
25438 index_c = indexes.select { |i| i.name == index_c_name }[0]
25439 fks.map { |fk| [fk.from_table, fk.to_table, fk.on_delete] })
25440 assert_equal "'4.2'", expected
25441 assert_sql(%r{\ASELECT /\*\+ \*\* // `posts`\.\*, // \*\* \*/}) do
25442 posts = Post.optimizer_hints("**// `posts`.*, //**")
25443 assert_sql(%r{\ASELECT `posts`\.`id`}) do
25444 mock.expect(:call, nil, [adapter: "mysql2", database: nil])
25445 assert_called_with(@connection, :create_database, ["my-app-db", {}]) do
25446 ["my-app-db", collation: "latin1_swedish_ci"]
25447 ["test-db", charset: "latin", collation: "latin1_swedish_ci"]
25448 ["mysqldump", "--result-file", filename, "--no-data", "--routines", "--skip-comments", "test-db"],
25449 expected_command = ["mysqldump", "--noop", "--result-file", filename, "--no-data", "--routines", "--skip-comments", "test-db"]
25450 expected_command = ["mysqldump", "--result-file", filename, "--no-data", "--routines", "--skip-comments", "test-db"]
25451 ["mysqldump", "--port=10000", "--result-file", filename, "--no-data", "--routines", "--skip-comments", "test-db"],
25452 ["mysqldump", "--ssl-ca=ca.crt", "--result-file", filename, "--no-data", "--routines", "--skip-comments", "test-db"],
25453 @configuration.merge("sslca" => "ca.crt"),
25454 def query(*)
25455 @conn.columns_for_distinct("posts.id", [])
25456 %r/Column `old_car_id` on table `engines` does not match column `id` on `old_cars`, which has type `int(\(11\))?`\./,
25457 %r/To resolve this issue, change the type of the `old_car_id` column on `engines` to be :integer\. \(For example `t.integer :old_car_id`\)\./,
25458 @conn.execute(<<~SQL)
25459 %r/Column `old_car_id` on table `foos` does not match column `id` on `old_cars`, which has type `int(\(11\))?`\./,
25460 %r/To resolve this issue, change the type of the `old_car_id` column on `foos` to be :integer\. \(For example `t.integer :old_car_id`\)\./,
25461 %r/Column `car_id` on table `foos` does not match column `id` on `cars`, which has type `bigint(\(20\))?`\./,
25462 %r/To resolve this issue, change the type of the `car_id` column on `foos` to be :bigint\. \(For example `t.bigint :car_id`\)\./,
25463 result = @conn.execute('SELECT 1 + "foo"')
25464 @conn.execute('SELECT 1 + "foo"')
25465 @conn.execute("SET @@SESSION.sql_mode='#{old_sql_mode}'")
25466 super(@conn, "ex", definition, &block)
25467 @conn.update("UPDATE `engines` SET `engines`.`car_id` = '9989' WHERE `engines`.`car_id` = '138853948594'")
25468 @conn.execute("REPLACE INTO `engines` SET `engines`.`car_id` = '249823948'")
25469 assert_equal 1, @conn.execute("/*action:index*/(
( SELECT `engines`.* FROM `engines` WHERE `engines`.`car_id` = '138853948594' ) )").entries.count
25470 assert_nil @conn.execute("USE #{db_name}")
25471 assert_match %r(posts |.* ALL), explain
25472 conn.database_version >= "6.0"
25473 conn.mariadb? && conn.database_version >= "10.1.0"
25474 enum state: {
25475 start: 0,
25476 middle: 1,
25477 t.column :enum_column, "enum('text','blob','tiny','medium','long','unsigned','bigint')"
25478 assert_match %r{t\.column "enum_column", "enum\('text','blob','tiny','medium','long','unsigned','bigint'\)"$}, schema
25479 args = [
25480 config = make_db_config(adapter: "mysql2", database: "db", username: "user", password: "qwerty")
25481 assert_find_cmd_and_exec_called_with([%w[mysql mysql5], "--user=user", "--password=qwerty", "db"]) do
25482 stub_version "5.6.4" do
25483 stub_version "5.6.3" do
25484 Bulb.create!(name: "Jimmy", color: "blue")
25485 @connection.send(:rename_column_for_alter, "bar_baz", "foo", "foo2")
25486 lock_name = "test lock'n'name"
25487 lock_name = "fake lock'n'name"
25488 column = @connection.columns(:charset_collations).find { |c| c.name == "title" }
25489 BooleanType.columns.find { |c| c.name == "archived" }
25490 BooleanType.columns.find { |c| c.name == "published" }
25491 str = "foo?bar"
25492 str = "foo\0bar"
25493 assert_match(/t\.integer\s+"id",\s+null: false,\s+auto_increment: true$/, output)
25494 sql: sql,
25495 expected = "CREATE INDEX `index_people_on_last_name` ON `people` (`last_name`(10))"
25496 expected = "CREATE INDEX `index_people_on_last_name_and_first_name` ON `people` (`last_name`(15), `first_name`(15))"
25497 assert_equal expected, add_index(:people, [:last_name, :first_name], length: { last_name: 15 })
25498 assert_equal expected, add_index(:people, ["last_name", "first_name"], length: { last_name: 15 })
25499 expected = "CREATE INDEX `index_people_on_last_name_and_first_name` ON `people` (`last_name`(15), `first_name`(10))"
25500 assert_equal expected, add_index(:people, [:last_name, :first_name], length: { last_name: 15, first_name: 10 })
25501 assert_equal expected, add_index(:people, ["last_name", :first_name], length: { last_name: 15, "first_name" => 10 })
25502 expected = "CREATE #{type} INDEX `index_people_on_last_name` ON `people` (`last_name`)"
25503 %w(btree hash).each do |using|
25504 expected = /\ACREATE TABLE `people` \(#{type} INDEX `index_people_on_last_name` \(`last_name`\)\)/
25505 expected = "ALTER TABLE `people` ADD #{type} INDEX `index_people_on_last_name` (`last_name`)"
25506 b = Book.create(name: "my \x00 book")
25507 b.update(name: "my other \x00 book")
25508 id = @connection.insert("INSERT INTO events(id) VALUES (#{bind_param.to_sql})", nil, nil, nil, nil, binds)
25509 assert_equal({ "id" => 1, "title" => "foo" }, result.first)
25510 Post.create!(author: author, title: "foo", body: "bar")
25511 assert_equal({ "title" => "foo" }, @connection.select_one(query))
25512 Post.create!(title: "foo", body: "bar")
25513 @connection.execute "INSERT INTO fk_test_has_fk (id,fk_id) VALUES (#{id_value},#{fk_id})"
25514 sub.id = "bob drake"
25515 if attempts == 0
25516 attempts += 1
25517 sleep(0.2)
25518 t.index ["foo"], name: "multiple_indexes_foo_1"
25519 t.index ["foo"], name: "multiple_indexes_foo_2"
25520 require_relative "../../../tools/test_common"
25521 tag = Tag.create!(name: "Der be treasure")
25522 tag2 = Tag.create!(name: "Der be rum")
25523 book.tags << [tag, tag2]
25524 assert_difference -> { Tag.count }, -2 do
25525 parent.tags << [tag, tag2]
25526 assert_difference -> { Tag.count }, -1 do
25527 job_1_args = ->(job_args) { job_args.first[:association_ids] == [tag.id] }
25528 job_2_args = ->(job_args) { job_args.first[:association_ids] == [tag2.id] }
25529 assert_difference -> { Content.count }, -1 do
25530 book.essays << [essay, essay2]
25531 assert_no_difference -> { Tag.count } do
25532 @columns = Hash.new { |h, k| h[k] = [] }
25533 @data_sources = []
25534 @primary_keys = {}
25535 @primary_keys[table] || "id"
25536 def merge_column(table_name, name, sql_type = nil, options = {})
25537 name.to_s,
25538 attributes.each { |a| a.attr_options.delete(:index) if a.reference? && !a.has_index? } if options[:indexes] == false
25539 template "model.rb", File.join("app/models", class_path, "#{file_name}.rb")
25540 template "module.rb", File.join("app/models", "#{class_path.join('/')}.rb") if behavior == :invoke
25541 attributes.select { |a| !a.reference? && a.has_index? }
25542 when /^(add)_.*_to_(.*)/, /^(remove)_.*?_from_(.*)/
25543 when /^create_(.+)/
25544 attr.index_name = [attr, attributes[i - 1]].map { |a| index_name_for(a) }
25545 unless /^[_a-z0-9]+$/.match?(file_name)
25546 def over(expr = nil)
25547 @dispatch_cache ||= Hash.new do |hash, klass|
25548 hash[klass] = :"visit_#{(klass.name || "").gsub("::", "_")}"
25549 collector << " FROM "
25550 collect_nodes_for o.wheres, collector, " WHERE ", " AND "
25551 collector << " ("
25552 collector << ", " unless i == 0
25553 collector << ")"
25554 collector = visit(o.expressions, collector) << ")"
25555 collector << " AS "
25556 collector << "("
25557 collector << ", " unless k == 0
25558 collector << " "
25559 collector = o.cores.inject(collector) { |c, x|
25560 if o.source && !o.source.empty?
25561 collect_nodes_for o.havings, collector, " HAVING ", " AND "
25562 hints = o.expr.map { |v| sanitize_as_sql_comment(v) }.join(" ")
25563 collector << "/*+ #{hints} */"
25564 collector << o.values.map { |v| "/* #{sanitize_as_sql_comment(v)} */" }.join(" ")
25565 collector << "WITH "
25566 collector << "( "
25567 infix_value(o, collector, " INTERSECT ") << " )"
25568 infix_value(o, collector, " EXCEPT ") << " )"
25569 collector << " " if o.partitions.any?
25570 collector << " " if o.partitions.any? || o.orders.any?
25571 collector << "ROWS "
25572 visit(o.left, collector) << " OVER ()"
25573 visit(o.left, collector) << " OVER #{quote_column_name o.right.to_s}"
25574 visit(o.expr, collector) << ")"
25575 if o.type == :in
25576 collector << " IN ("
25577 visit(o.ast, collector) << ")"
25578 visit(o.expr, collector) << " ASC"
25579 visit(o.expr, collector) << " DESC"
25580 collector = inject_join(o.expressions, collector, ", ") << ")"
25581 return collector << "1=0"
25582 return collector << "1=1"
25583 collector << " >= "
25584 collector << " > "
25585 collector << " <= "
25586 collector << " < "
25587 collector << " LIKE "
25588 collector << " " if o.left
25589 collector << "ON "
25590 collector << "NOT ("
25591 collector << quote_table_name(o.name) << " " << quote_table_name(o.table_alias)
25592 attr, values = o.left, o.right
25593 if Array === values
25594 visit(attr, collector) << " IN ("
25595 visit(values, collector) << ")"
25596 visit(attr, collector) << " NOT IN ("
25597 stack = [o.right, o.left]
25598 if o.is_a?(Arel::Nodes::Or)
25599 collector << " OR " unless stack.empty?
25600 collector << " = "
25601 collector << " = 0"
25602 collector << " = 1"
25603 collector << " != "
25604 collector << "CASE "
25605 collector << "END"
25606 collector << "WHEN "
25607 collector << " THEN "
25608 collector << "ELSE "
25609 collector << quote_table_name(join_name) << "." << quote_column_name(o.name)
25610 collector << o.to_s
25611 if value.none? { |v| Arel.arel_node?(v) }
25612 o.sql_with_placeholders.scan(/\?|([^?]+)/) do
25613 if $1
25614 collector << $1
25615 bind_index += 1
25616 o.sql_with_placeholders.scan(/:(?<!::)([a-zA-Z]\w*)|([^:]+|.)/) do
25617 if $2
25618 collector << $2
25619 value = o.named_binds[$1.to_sym]
25620 collector << " #{o.operator} "
25621 inject_join o, collector, ", "
25622 list.each_with_index do |x, i|
25623 collector << join_str unless i == 0
25624 o.limit || o.offset || !o.orders.empty?
25625 !o.groups.empty? && !o.havings.empty?
25626 if o.key && (has_limit_or_offset_or_orders?(o) || has_join_sources?(o))
25627 stmt.orders = []
25628 stmt.wheres = [Nodes::In.new(o.key, [build_subselect(o.key, o)])]
25629 collector << "#{name}("
25630 collector << " OR ("
25631 o.limit = Arel::Nodes::Limit.new(-1) if o.offset && !o.limit
25632 collector << "1"
25633 collector << "0"
25634 collector << " IS "
25635 op = o.case_sensitive ? " ~ " : " ~* "
25636 op = o.case_sensitive ? " !~ " : " !~* "
25637 visit(o.expr, collector) << " )"
25638 collector << " )"
25639 collector << "CAST("
25640 if o.offset && !o.limit
25641 o.froms ||= Arel.sql("DUAL")
25642 collector << ", "
25643 collector << ") "
25644 collector << " <=> "
25645 collector << "NOT "
25646 if o.offset || has_group_by_and_having?(o) ||
25647 class Node # :nodoc:
25648 def initialize(name, id, fields = [])
25649 class Edge < Struct.new :name, :from, :to # :nodoc:
25650 @node_stack = []
25651 @edge_stack = []
25652 visit_edge o, "expr"
25653 visit_edge o, "left"
25654 visit_edge o, "name"
25655 visit_edge o, "rows"
25656 visit_edge o, "lock"
25657 visit_edge o, "with"
25658 visit_edge o, "key"
25659 visit_edge o, "type"
25660 edge(i) { visit child }
25661 visit_edge(o, "value")
25662 o.each_with_index do |pair, i|
25663 edge("pair_#{i}") { visit pair }
25664 edge(i) { visit member }
25665 visit_edge(o, "values")
25666 visit_edge(o, "case")
25667 if node = @seen[o.object_id]
25668 @seen[node.id] = node
25669 @nodes << node
25670 @edges << edge
25671 string.to_s.gsub('"', '\"')
25672 @nodes.map { |node|
25673 label = "<f0>#{node.name}"
25674 label += "|<f#{i + 1}>#{quote field}"
25675 }.join("
") + "
" + @edges.map { |edge|
25676 }.join("
") + "
}"
25677 if String === values
25678 @ast.values = [values]
25679 @ast.values = values.map { |column, value|
25680 @ast.havings << expr
25681 def key=(key)
25682 @ast.wheres << expr
25683 @ast = @ast.clone
25684 @engine = nil
25685 @name = name.to_s
25686 if as.to_s == @name
25687 as = nil
25688 def alias(name = "#{self.name}_2")
25689 def [](name, table = self)
25690 name = name.to_s if name.is_a?(Symbol)
25691 self.class == other.class &&
25692 self.name == other.name &&
25693 alias :== :eql?
25694 @ctx = @ast.cores.last
25695 @ast.limit && @ast.limit.expr
25696 @ast.cores.filter_map { |x| x.from }
25697 @ctx.havings << expr
25698 @ast.orders.concat expr.map { |x|
25699 @ctx.wheres << expr
25700 base = table_name.nil? ? ast : as(table_name)
25701 @ast.limit = nil
25702 exprs.map! { |expr|
25703 if String === expr
25704 if exprs.length == 1
25705 if unboundable?(other.begin) == 1 || unboundable?(other.end) == -1
25706 self.in([])
25707 if infinity?(other.begin) == 1 || infinity?(other.end) == -1
25708 not_in([])
25709 others.map { |v| quoted_node(v) }
25710 nodes = others.map { |expr| send(method_id, expr, *extras) }
25711 value.nil? || infinity?(value) || unboundable?(value)
25712 @orders = []
25713 @partitions = []
25714 @orders.concat expr.map { |x|
25715 String === x || Symbol === x ? Nodes::SqlLiteral.new(x.to_s) : x
25716 def rows(expr = nil)
25717 @orders = @orders.map { |x| x.clone }
25718 self.orders == other.orders &&
25719 super && self.name == other.name
25720 [@relation, @wheres, @values, @orders, @limit, @offset, @key].hash
25721 self.wheres == other.wheres &&
25722 self.values == other.values &&
25723 self.groups == other.groups &&
25724 self.limit == other.limit &&
25725 self.offset == other.offset &&
25726 super(:~, operand)
25727 @expr = expr
25728 }.each do |name|
25729 [@cores, @orders, @limit, @lock, @offset, @with].hash
25730 self.cores == other.cores &&
25731 self.lock == other.lock &&
25732 alias :froms= :from=
25733 ].hash
25734 self.source == other.source &&
25735 !left && right.empty?
25736 self.select == other.select &&
25737 super(:*, left, right)
25738 super(:/, left, right)
25739 super(:+, left, right)
25740 super(:-, left, right)
25741 super(:"||", left, right)
25742 super(:"@>", left, right)
25743 super(:"&&", left, right)
25744 super(:&, left, right)
25745 super(:|, left, right)
25746 super(:^, left, right)
25747 super(:<<, left, right)
25748 super(:>>, left, right)
25749 super || (self.class == other.class && self.ivars == other.ivars)
25750 type == :in
25751 Arel::Nodes::HomogeneousIn.new(values, attribute, type == :in ? :notin : :in)
25752 [@attribute, @values, @type]
25753 self.alias == other.alias &&
25754 self.class.new([*@values, other])
25755 super &&
25756 def initialize(relation = nil, wheres = [])
25757 @groups = []
25758 @havings = []
25759 @limit = nil
25760 @offset = nil
25761 @key = nil
25762 [self.class, @relation, @wheres, @orders, @limit, @offset, @key].hash
25763 def nil?; value.nil?; end
25764 self.value == other.value &&
25765 class Quoted < Arel::Nodes::Unary # :nodoc:
25766 @conditions = []
25767 @case = @case.clone if @case
25768 @conditions = @conditions.map { |x| x.clone }
25769 self.case == other.case &&
25770 class When < Binary # :nodoc:
25771 class Else < Unary # :nodoc:
25772 tokens_in_string = sql_with_placeholders.scan(/:(?<!::)([a-zA-Z]\w*)/).flatten.map(&:to_sym).uniq
25773 if !(missing = (tokens_in_string - tokens_in_hash)).empty?
25774 if missing.size == 1
25775 other.is_a?(BindParam) &&
25776 [self.class, @left, @right].hash
25777 self.left == other.left &&
25778 def &(other)
25779 def |(other)
25780 def ^(other)
25781 def <<(other)
25782 def >>(other)
25783 def ~@
25784 def values=(val); @ast.values = val; end
25785 if String === fields
25786 super("#{message} in: #{sql.inspect}")
25787 key = nil,
25788 um.key = key
25789 dm.key = key
25790 self << binds.map { |bind| quoter.quote(bind) }.join(", ")
25791 @bind_index = 1
25792 self << yield(@bind_index)
25793 @bind_index += 1
25794 self << (@bind_index...@bind_index += binds.size).map(&block).join(", ")
25795 @str = +""
25796 @str << str
25797 @left = left
25798 left << str
25799 right << str
25800 @binds = []
25801 @binds << bind
25802 def self.star # :nodoc:
25803 sql "*"
25804 def self.arel_node?(value) # :nodoc:
25805 value.is_a?(Arel::Nodes::Node) || value.is_a?(Arel::Attribute) || value.is_a?(Arel::Nodes::SqlLiteral)
25806 unless Array(options[:scope]).all? { |scope| scope.respond_to?(:to_sym) }
25807 @covered ||= self.attributes.map(&:to_s).select do |attr|
25808 index.where.nil? &&
25809 if !options.key?(:case_sensitive) || bind.nil?
25810 if Array(value).reject { |r| valid_object?(r) }.any?
25811 def save!(**options)
25812 new_record? ? :create : :update
25813 options[:validate] == false || valid?(options[:context])
25814 class Map # :nodoc:
25815 super * 2
25816 @mapping = {}
25817 @mapping[key] = proc { value }
25818 metadata = sql_type[/\(.*\)/, 0]
25819 lookup("#{target_key}#{metadata}")
25820 key === lookup_key
25821 value.__getobj__
25822 raw_old_value.nil? != raw_new_value.nil? ||
25823 @cache = Concurrent::Map.new do |h, key|
25824 register_type(type) { |_, *args| lookup(alias_type, *args) }
25825 @registrations = []
25826 block = proc { |_, *args| klass.new(*args) }
25827 def call(_registry, *args, adapter: nil, **kwargs)
25828 def matches?(type_name, *args, **kwargs)
25829 type_name == name && matches_adapter?(**kwargs)
25830 result = 0
25831 result |= 1
25832 result |= 2
25833 (self.adapter.nil? || adapter == self.adapter)
25834 (override.nil? && other.adapter) ||
25835 def matches?(*args, **kwargs)
25836 super | 4
25837 kwargs[key] == value
25838 ACTIONS = [:create, :destroy, :update]
25839 scope: [:kind, :name]
25840 def before_commit(*args, &block) # :nodoc:
25841 set_options_for_callbacks!(args, on: [ :create, :update ])
25842 fire_on = Array(options[:on])
25843 options[:if] = [
25844 -> { transaction_include_any_action?(fire_on) },
25845 def save(**) # :nodoc:
25846 def save!(**) # :nodoc:
25847 def touch(*, **) # :nodoc:
25848 @_start_transaction_state ||= {
25849 id: id,
25850 def touch_later(*names) # :nodoc:
25851 @_defer_touch_attrs |= names.map! do |name|
25852 if r.macro == :belongs_to
25853 elsif r.macro == :has_one
25854 def touch(*names, time: nil) # :nodoc:
25855 @_defer_touch_attrs, @_touch_time = nil, nil
25856 @full_purpose ||= [defining_class.name, purpose, expires_in].join("
")
25857 block ? [model.id, model.instance_eval(&block).as_json] : [model.id]
25858 attribute_names |= names.map(&:to_s)
25859 ["created_at", "created_on"].map! { |name| attribute_aliases[name] || name }
25860 ["updated_at", "updated_on"].map! { |name| attribute_aliases[name] || name }
25861 @_touch_record = nil
25862 .filter_map { |attr| self[attr]&.to_time }
25863 fixture_set_names = Dir[::File.join(fixture_path, "{**,*}/*.{yml}")].uniq
25864 fixture_set_names.map! { |f| f[fixture_path.to_s.size..-5].delete_prefix("/") }
25865 key = fs_name.to_s.include?("/") ? -fs_name.to_s.tr("/", "_") : fs_name
25866 key = -key.to_s if key.is_a?(Symbol)
25867 fs_name = -fs_name.to_s if fs_name.is_a?(Symbol)
25868 @fixture_cache = {}
25869 @@already_loaded_fixtures ||= {}
25870 @saved_pool_configs = Hash.new { |hash, key| hash[key] = {} }
25871 @saved_pool_configs[name][shard_name] ||= {}
25872 @fixture_cache[fs_name] ||= {}
25873 f_name = f_name.to_s if f_name.is_a?(Symbol)
25874 db_config._database = "#{db_config.database}-#{i}"
25875 file = File.absolute_path?(db_path) ? db_path : File.join(root, db_path)
25876 condition = ignore_tables.map { |table| connection.quote(table) }.join(", ")
25877 args << ".schema"
25878 msg = +"failed to execute:
"
25879 msg << "#{cmd} #{args.join(' ')}

"
25880 search_path = \
25881 args = ["--schema-only", "--no-privileges", "--no-owner"]
25882 args.concat(["--file", filename])
25883 args += search_path.split(",").map do |part|
25884 args += ignore_tables.flat_map { |table| ["-T", table] }
25885 run_cmd("pg_dump", args, "dumping")
25886 File.open(filename, "a") { |f| f << "SET search_path TO #{connection.schema_search_path};

" }
25887 args = ["--set", ON_ERROR_STOP_1, "--quiet", "--no-psqlrc", "--output", File::NULL, "--file", filename]
25888 run_cmd("psql", args, "loading")
25889 {}.tap do |env|
25890 args.concat(["--result-file", "#{filename}"])
25891 args.concat(["--no-data"])
25892 args.concat(["--routines"])
25893 args.concat(["--skip-comments"])
25894 args += ignore_tables.map { |table| "--ignore-table=#{db_config.database}.#{table}" }
25895 run_cmd("mysql", args, "loading")
25896 sslcapath: "--ssl-capath",
25897 sslcipher: "--ssl-cipher",
25898 }.filter_map { |opt, arg| "#{arg}=#{configuration_hash[opt]}" if configuration_hash[opt] }
25899 msg = +"failed to execute: `#{cmd}`
"
25900 @tasks ||= {}
25901 File.join(root, "test", "fixtures")
25902 @root ||= Rails.root
25903 @env ||= Rails.env
25904 @name ||= "primary"
25905 dbs_list = []
25906 dbs_list << "#{command}:#{db.name}"
25907 db_configs_with_versions = Hash.new { |h, k| h[k] = [] }
25908 puts "-" * 50
25909 File.open(filename, "w:utf-8") do |file|
25910 File.open(filename, "a") do |f|
25911 f.print "
"
25912 next if name && name != db_config.name
25913 if stored && stored != current
25914 define_method("#{accessor_key}=") do |value|
25915 prev_store&.dig(key) != new_store&.dig(key)
25916 [prev_store&.dig(key), new_store&.dig(key)]
25917 parent.merge!(local_stored_attributes) { |k, a, b| a | b }
25918 @coder =
25919 obj.respond_to?(:to_hash) ? obj.to_hash : {}
25920 @sql = sql
25921 }.map(&:last)
25922 @indexes.each do |i|
25923 @parts = []
25924 @parts << str
25925 @binds << obj
25926 @parts << ", " unless i == 0
25927 [@parts, @binds]
25928 @indexes = []
25929 @indexes << i
25930 @indexes.each_with_index { |offset, i| bas[offset] = bas[offset].with_cast_value(values[i]) }
25931 @bind_map = bind_map
25932 options = options ? options.dup : {}
25933 options[:except] = Array(options[:except]).map(&:to_s)
25934 !has_attribute?(name) && has_attribute?("#{name}_digest")
25935 end.map(&:to_h)
25936 return if passwords.any? { |name, value| value.nil? || value.empty? }
25937 raise ArgumentError, "You tried to define a scope named \"#{name}\" " \
25938 scope = all._exec_scope(*args, &body)
25939 scope = body.call(*args) || all
25940 def default_scope(scope = nil, all_queries: nil, &block) # :doc:
25941 if scope.is_a?(Relation) || !scope.respond_to?(:call)
25942 @ignore_default_scope = {}
25943 @global_current_scope = {}
25944 versions.map(&:to_i)
25945 cattr_accessor :fk_ignore_pattern, default: /^fk_rails_[0-9a-f]{10}$/
25946 @ignore_tables = [
25947 stringified.insert(4, "_").insert(7, "_").insert(10, "_")
25948 @version ? "version: #{formatted_version}" : ""
25949 tbl.print ", primary_key: #{pk.inspect}" unless pk == "id"
25950 pkcol = columns.detect { |c| c.name == pk }
25951 pkcolspec = { id: { type: pkcolspec.delete(:id), **pkcolspec }.compact }
25952 tbl.print ", primary_key: #{pk.inspect}"
25953 tbl.print ", id: false"
25954 tbl.puts ", force: :cascade do |t|"
25955 index_parts = [
25956 parts = [
25957 parts << "name: #{foreign_key.name.inspect}"
25958 options.map { |key, value| "#{key}: #{value.inspect}" }.join(", ")
25959 table.sub(/\A#{prefix}(.+)#{suffix}\z/, "\\1")
25960 def define(info = {}, &block)
25961 def define(info, &block) # :nodoc:
25962 def self.[](version)
25963 @class_for_version ||= {}
25964 if condition.is_a?(Array) && condition.first.to_s.include?("?")
25965 if string.include?(escape_character) && escape_character != "%" && escape_character != "_"
25966 string.gsub(/(?=[%_])/, escape_character)
25967 if values.first.is_a?(Hash) && /:\w+/.match?(statement)
25968 next if arg.is_a?(Symbol) || Arel.arel_node?(arg) || permit.match?(arg.to_s.strip)
25969 (unexpected ||= []) << arg
25970 statement.gsub(/\?/) do
25971 statement.gsub(/(:?):([a-zA-Z]\w*)/) do |match|
25972 if $1 == ":" # skip postgresql casts
25973 if value.respond_to?(:map) && !value.acts_like?(:string)
25974 values = value.map { |v| v.respond_to?(:id_for_database) ? v.id_for_database : v }
25975 values.map! { |v| c.quote(c.cast_bound_value(v)) }.join(",")
25976 hash_rows.to_enum { @rows.size }
25977 alias :to_a :to_ary
25978 def last(n = nil)
25979 n ? hash_rows.last(n) : hash_rows.last
25980 def result # :nodoc:
25981 def cancel # :nodoc:
25982 def cast_values(type_overrides = {}) # :nodoc:
25983 rows.map do |(value)|
25984 Array.new(values.size) { |i| types[i].deserialize(values[i]) }
25985 def freeze # :nodoc:
25986 @hash_rows ||=
25987 columns = @columns.map(&:-@)
25988 @rows.map { |row|
25989 index = -1
25990 row[index += 1]
25991 index = 0
25992 index += 1
25993 EMPTY = new([].freeze, [].freeze, {}.freeze).freeze
25994 delegate :any?, :empty?, to: :predicates
25995 left = self - other
25996 common = self - left
25997 if left.empty? || right.empty?
25998 alias :eql? :==
25999 @empty ||= new([]).freeze
26000 Array === x.right && x.right.empty?
26001 attrs = []
26002 each_attributes { |attr, _| attrs << attr }
26003 each_attributes { |attr, node| hash[attr] = node }
26004 equalities = []
26005 !node.is_a?(String) && node.equality?
26006 attrs = columns.extract! { |node| node.is_a?(Arel::Attribute) }
26007 non_attrs = columns.extract! { |node| node.is_a?(Arel::Predications) }
26008 if ::String === node
26009 elsif Array === node
26010 node.map { |v| extract_node_value(v) }
26011 def spawn # :nodoc:
26012 def merge!(other, *rest) # :nodoc:
26013 if other.is_a?(Hash)
26014 def not(opts, *rest)
26015 ["#{name}_clause", name == :from ? "Relation::FromClause.empty" : "Relation::WhereClause.empty"]
26016 def includes!(*args) # :nodoc:
26017 def eager_load!(*args) # :nodoc:
26018 def preload!(*args) # :nodoc:
26019 def _select!(*fields) # :nodoc:
26020 def with!(*args) # :nodoc:
26021 def reselect!(*args) # :nodoc:
26022 def group!(*args) # :nodoc:
26023 def regroup!(*args) # :nodoc:
26024 def order!(*args) # :nodoc:
26025 def reorder!(*args) # :nodoc:
26026 def unscope!(*args) # :nodoc:
26027 if key != :where
26028 def joins!(*args) # :nodoc:
26029 def left_outer_joins!(*args) # :nodoc:
26030 elsif args.length == 1 && args.first.blank?
26031 def where!(opts, *rest) # :nodoc:
26032 def and!(other) # :nodoc:
26033 def or!(other) # :nodoc:
26034 opts.blank? ? self : spawn.having!(opts, *rest)
26035 def having!(opts, *rest) # :nodoc:
26036 def limit!(value) # :nodoc:
26037 def offset!(value) # :nodoc:
26038 def lock!(locks = true) # :nodoc:
26039 def none! # :nodoc:
26040 def readonly!(value = true) # :nodoc:
26041 def strict_loading!(value = true) # :nodoc:
26042 def create_with!(value) # :nodoc:
26043 def from!(value, subquery_name = nil) # :nodoc:
26044 def distinct!(value = true) # :nodoc:
26045 def extending!(*modules, &block) # :nodoc:
26046 def skip_query_cache!(value = true) # :nodoc:
26047 def annotate!(*args) # :nodoc:
26048 values.uniq! if values.is_a?(Array) && !values.empty?
26049 def arel(aliases = nil) # :nodoc:
26050 @arel ||= build_arel(aliases)
26051 def build_where_clause(opts, rest = []) # :nodoc:
26052 parts = [klass.sanitize_sql(rest.empty? ? opts : [opts, *rest])]
26053 parts = [opts]
26054 @async = true
26055 name ||= "subquery"
26056 buckets = Hash.new { |h, k| h[k] = [] }
26057 stashed_left_joins = []
26058 if join.is_a?(Arel::Nodes::Join)
26059 if klass.columns_hash.key?(field) && (!from || table_name_matches?(from))
26060 elsif field.match?(/\A\w+\.\w+\z/)
26061 table, column = field.split(".")
26062 /(?:\A|(?<!FROM)\s)(?:\b#{table_name}\b|#{quoted_table_name})(?!\.)/i.match?(from.to_s)
26063 o.split(",").map! do |s|
26064 s.gsub!(/\sasc\Z/i, " DESC") || s.gsub!(/\sdesc\Z/i, " ASC") || (s << " DESC")
26065 (order.include?(",") && order.split(",").find { |section| section.count("(") != section.count(")") }) ||
26066 /\bnulls\s+(?:first|last)\b/i.match?(order)
26067 arg.each do |_key, value|
26068 order_args.flat_map { |a| a.is_a?(Hash) ? a.keys : a },
26069 arg.map { |field, dir|
26070 key if key.is_a?(String) || key.is_a?(Symbol)
26071 references.map! { |arg| arg =~ /^\W?(\w+)\W?\./ && $1 }.compact!
26072 if attr_name == "count" && !group_values.empty?
26073 attr = attr.to_s
26074 if attr.include?(".")
26075 table, column = attr.split(".", 2)
26076 if field.is_a?(Hash)
26077 arel_column("#{key}.#{column}") do
26078 arel_column("#{key}.#{column}", &:itself)
26079 ).freeze # :nodoc:
26080 v1, v2 = @values[method], values[method]
26081 if v1.is_a?(Array)
26082 v1 = v1.uniq
26083 v2 = v2.uniq
26084 serializable? { |value| @_unboundable = value <=> 0 } && @_unboundable = nil
26085 query = {}
26086 default_hash = Hash.new { |hsh, key| hsh[key] = [] }
26087 value.map { |v| convert_to_id(v) }
26088 values = value.map { |x| x.is_a?(Base) ? x.id : x }
26089 nils = values.extract!(&:nil?)
26090 ranges = values.extract! { |v| v.is_a?(Range) }
26091 @handlers = []
26092 result << Arel.sql(key)
26093 elsif key.include?(".")
26094 result << Arel.sql(key.split(".").first)
26095 def [](attr_name, value, operator = nil)
26096 if value.is_a?(Hash) && !table.has_column?(key)
26097 values = value.nil? ? [nil] : Array.wrap(value)
26098 if mapping.length == 1 || values.empty?
26099 queries.map! { |query| query.reduce(&:and) }
26100 k.include?(".") && !v.is_a?(Hash)
26101 table_name, column_name = key.split(".")
26102 attributes[table_name] ||= {}
26103 @handlers.detect { |klass, _| klass === object }.last
26104 k = :_select if k == :select
26105 if Array === v
26106 other.public_send("#{k}!", *v)
26107 other.public_send("#{k}!", v)
26108 unless value.nil? || (value.blank? && false != value)
26109 relation.public_send(:"#{name}!", *value)
26110 end || return
26111 self.class == other.class && value == other.value && name == other.name
26112 @empty ||= new(nil, nil).freeze
26113 def find_by(arg, *args)
26114 def find_by!(arg, *args)
26115 where(arg, *args).take!
26116 if loaded? || offset_value || limit_value || having_clause.any?
26117 record.is_a?(klass) && exists?(record.id)
26118 error = +"Couldn't find #{name}"
26119 error = "Couldn't find #{name} with '#{key}'=#{ids}#{conditions}"
26120 error = +"Couldn't find all #{name.pluralize} with '#{key}': "
26121 error << "(#{ids.join(", ")})#{conditions} (found #{result_size} results, but was looking for #{expected_size})."
26122 error << " Couldn't find #{name.pluralize(not_found_ids.size)} with #{key.to_s.pluralize(not_found_ids.size)} #{not_found_ids.join(', ')}." if not_found_ids
26123 relation = except(:select, :distinct, :order)._select!(ONE_AS_ONE).limit!(1)
26124 if eager_loading && has_limit_or_offset? && !(
26125 ), nil
26126 expects_array ? [ result ] : result
26127 ids = ids.slice(offset_value || 0, limit_value || ids.size) || []
26128 result.in_order_of(:id, ids.map { |id| @klass.type_for_attribute(primary_key).cast(id) })
26129 @take ||= limit(1).records.first
26130 @offsets ||= {}
26131 records[index, limit] || []
26132 limit = [limit_value - index, limit].min
26133 if limit > 0
26134 oc = []
26135 mangled_name = klass.name.gsub("::", "_")
26136 def #{method}(...)
26137 scoping { klass.#{method}(...) }
26138 delegate :to_xml, :encode_with, :length, :each, :join,
26139 :[], :&, :|, :+, :-, :sample, :reverse, :rotate, :compact, :in_groups, :in_groups_of,
26140 :to_sentence, :to_fs, :to_formatted_s, :as_json,
26141 :shuffle, :split, :slice, :index, :rindex, to: :records
26142 scoping { @klass.public_send(method, *args, &block) }
26143 @aliases = Hash.new(0)
26144 if @aliases[aliased_name] == 0
26145 count = @aliases[aliased_name] += 1
26146 column_alias.gsub!(/\*/, "all")
26147 column_alias.gsub!(/\W+/, " ")
26148 column_alias.gsub!(/ +/, "_")
26149 eager_loading? || (includes_values.present? && column_name && column_name != :all)
26150 if operation == "count"
26151 if column_name == :all
26152 column_name.is_a?(::String) && /\bDISTINCT[\s(]/i.match?(column_name)
26153 Arel.sql(column_name == :all ? "*" : name)
26154 if operation == "count" && (column_name == :all && distinct || has_limit_or_offset?)
26155 if operation != "count"
26156 type = column.try(:type_caster) ||
26157 key_types = group_columns.each_with_object({}) do |(aliaz, col_name), types|
26158 types[aliaz] = col_name.try(:type_caster) ||
26159 hash[col_name] = row[i]
26160 key = group_aliases.map { |aliaz| row[aliaz] }
26161 key = key.first if key.size == 1
26162 field_name = field.respond_to?(:name) ? field.name.to_s : field.to_s.split(".").last
26163 when "sum"
26164 else # "minimum", "maximum"
26165 select_values.join(", ")
26166 def initialize(of: 1000, start: nil, finish: nil, relation:, order: :asc, use_ranges: nil) # :nodoc:
26167 @of
26168 @relation.to_enum(:in_batches, of: @of, start: @start, finish: @finish, load: true, order: @order).each do |relation|
26169 enum = @relation.to_enum(:in_batches, of: @of, start: @start, finish: @finish, load: false, order: @order, use_ranges: @use_ranges)
26170 (total - 1).div(batch_size) + 1
26171 unless [:asc, :desc].include?(order)
26172 ids = records.map(&:id)
26173 elsif (empty_scope && use_ranges != false) || use_ranges
26174 :with]
26175 scoping { _new(attributes, &block) }
26176 scoping { _create!(attributes, &block) }
26177 def first_or_create!(attributes = nil, &block) # :nodoc:
26178 def none?(*args)
26179 def any?(*args)
26180 def one?(*args)
26181 @cache_keys ||= {}
26182 @cache_versions ||= {}
26183 if size > 0
26184 select_values = "COUNT(*) AS #{connection.quote_column_name("size")}, MAX(%s) AS timestamp"
26185 size = 0
26186 def _exec_scope(...) # :nodoc:
26187 _scoping(nil, registry) { instance_exec(...) || self }
26188 def update(id = :all, attributes) # :nodoc:
26189 if id == :all
26190 def update!(id = :all, attributes) # :nodoc:
26191 updates = {}
26192 names = touch if touch != true
26193 method == :distinct ? value : value&.any?
26194 if !loaded? || scheduled?
26195 @to_sql = @arel = @loaded = @should_eager_load = nil
26196 @offsets = @take = nil
26197 @to_sql ||= if eager_loading?
26198 create_with_value.each { |k, v| hash[k.to_s] = v } unless create_with_value.empty?
26199 @should_eager_load ||=
26200 other.to_sql == to_sql
26201 entries[10] = "..." if entries.size == 11
26202 def empty_scope? # :nodoc:
26203 def alias_tracker(joins = [], aliases = nil) # :nodoc:
26204 -> record do
26205 [attr, value]
26206 expr = value < 0 ? expr - bind : expr + bind
26207 [].freeze
26208 joined_tables = build_joins([]).flat_map do |join|
26209 string.scan(/[a-zA-Z_][.\w]+(?=.?\.)/).map!(&:downcase) - ["raw_sql_"]
26210 name = -name.to_s
26211 @__reflections ||= begin
26212 ref = {}
26213 @__reflections = nil
26214 @class_name ||= -(options[:class_name] || derive_class_name).to_s
26215 scope ? [scope] : []
26216 -(options[:counter_cache]&.to_s || "#{name}_count")
26217 if has_inverse? && inverse_of == self
26218 message = +"`#{owner}` is marked for strict_loading."
26219 message << " The #{polymorphic? ? "polymorphic association" : "#{klass} association"}"
26220 message << " named `:#{name}` cannot be lazily loaded."
26221 super ||
26222 mapping = options[:mapping] || [name, name]
26223 if error.name.match?(/(?:\A|::)#{name}\z/)
26224 @type = -(options[:foreign_type]&.to_s || "#{options[:as]}_type") if options[:as]
26225 @foreign_type = -(options[:foreign_type]&.to_s || "#{name}_type") if options[:polymorphic]
26226 key = self
26227 @join_table ||= -(options[:join_table]&.to_s || derive_join_table)
26228 -(options[:foreign_key]&.to_s || derive_foreign_key)
26229 -(options[:primary_key]&.to_s || primary_key(active_record))
26230 def join_id_for(owner) # :nodoc:
26231 Array(join_foreign_key).map { |key| owner[key] }
26232 [self]
26233 !options[:validate].nil? ? options[:validate] : (options[:autosave] == true || collection?)
26234 seed + [self]
26235 reflection != self &&
26236 def has_one?; true; end
26237 scope || options[:source_type] ||
26238 names = names.find_all { |n|
26239 :name, :scope_for, to: :@reflection
26240 lambda { |object| where(type => source_type) }
26241 if operation == :perform && block
26242 messages << ("ActiveRecord: %.1fms" % db_runtime.to_f) if db_runtime
26243 def initialize(...) # :nodoc:
26244 self.db_runtime = (db_runtime || 0) + db_rt_before_render
26245 configs.each do |k, v|
26246 setter = "#{k}="
26247 path = app.paths["db"].first
26248 if Class === value && ActiveRecord::Base > value
26249 :find, :find_by, :find_by!, :take, :take!, :sole, :find_sole_by, :first, :first!, :last, :last!,
26250 :second, :second!, :third, :third!, :fourth, :fourth!, :fifth, :fifth!,
26251 :forty_two, :forty_two!, :third_to_last, :third_to_last!, :second_to_last, :second_to_last!,
26252 :exists?, :any?, :many?, :none?, :one?,
26253 :destroy_all, :delete_all, :update_all, :touch_all, :destroy_by, :delete_by,
26254 :select, :reselect, :order, :regroup, :in_order_of, :reorder, :group, :limit, :offset, :joins, :left_joins, :left_outer_joins,
26255 :having, :create_with, :distinct, :references, :none, :unscope, :merge, :except, :only,
26256 :count, :average, :minimum, :maximum, :sum, :calculate,
26257 :pluck, :pick, :ids, :async_ids, :strict_loading, :excluding, :without, :with,
26258 ].freeze # :nodoc:
26259 def find_by_sql(sql, binds = [], preparable: nil, &block)
26260 def async_find_by_sql(sql, binds = [], preparable: nil, &block)
26261 def _query_by_sql(sql, binds = [], preparable: nil, async: false) # :nodoc:
26262 def _load_from_sql(result_set, &block) # :nodoc:
26263 column_types = column_types.reject { |k, _| attribute_types.key?(k) }
26264 @key_value_separator = ":"
26265 pairs.map! do |key, value|
26266 end.join(",")
26267 @key_value_separator = "="
26268 pairs.sort_by!(&:first)
26269 comment.gsub!(%r{\A\s*/\*\+?\s?|\s?\*/\s*\Z}, "")
26270 comment.gsub!("*/", "* /")
26271 comment.gsub!("/*", "/ *")
26272 pairs = tags.flat_map { |i| [*i] }.filter_map do |tag|
26273 [key, val] unless val.nil?
26274 undef_method :==, :!, :!=
26275 @value = if @block
26276 Promise.new(@future_result, @block ? @block >> block : block)
26277 [:class, :respond_to?, :is_a?].each do |method|
26278 def pretty_print(q) # :nodoc:
26279 if id.is_a?(Array)
26280 id.map { |one_id| find(one_id) }.each_with_index { |object, idx|
26281 elsif id == :all
26282 !new_record? && destroyed?
26283 !(@new_record || @destroyed)
26284 def save!(**options, &block)
26285 public_send("#{name}=", value)
26286 name = key.to_s
26287 attributes = attributes.each_with_object({}) do |(k, v), h|
26288 h[k] = @attributes.write_cast_value(k, v)
26289 self[attribute] ||= 0
26290 change = public_send(attribute) - (public_send(:"#{attribute}_in_database") || 0)
26291 self[attribute] = !public_send("#{attribute}?")
26292 _find_record((options || {}).merge(all_queries: true))
26293 end.map(&:first)
26294 { @primary_key => id }
26295 !(options && options[:unscoped]) &&
26296 { @primary_key => id_in_database }
26297 def create_or_update(**, &block)
26298 result = new_record? ? _create_record(&block) : _update_record(&block)
26299 self.id ||= new_id if @primary_key
26300 group_values.any? ? Hash.new : 0
26301 self[name] = self[name]
26302 def apply_to(klass) # :nodoc:
26303 def applied_to?(klass) # :nodoc:
26304 klasses.any? { |k| k >= klass }
26305 def touch_later(*) # :nodoc:
26306 REJECT_ALL_BLANK_PROC = proc { |attributes| attributes.all? { |key, value| key == "_destroy" || value.blank? } }
26307 generated_association_methods.module_eval <<-eoruby, __FILE__, __LINE__ + 1
26308 if (options[:update_only] || !attributes["id"].blank?) && existing_record &&
26309 (options[:update_only] || existing_record.id.to_s == attributes["id"].to_s)
26310 attribute_ids = attributes_collection.filter_map { |a| a["id"] || a[:id] }
26311 limit = \
26312 model, "id", record_id)
26313 [first_table.to_s, second_table.to_s].sort.join("\0").gsub(/^(.*[_.])(.+)\0\1(.+)/, '\1\2_\3').tr("\0", "_")
26314 value = value && value.to_s
26315 (@sequence_name ||= nil) || base_class.sequence_name
26316 c.name == primary_key ||
26317 c.name.end_with?("_id", "_count")
26318 contained += "_"
26319 def find_join_table_name(table_1, table_2, options = {})
26320 name = "V#{version.tr('.', '_')}"
26321 versions = constants.grep(/\AV[0-9_]+\z/).map { |s| s.to_s.delete("V").tr("_", ".").inspect }
26322 class V7_0 < V7_1
26323 class << t
26324 class V6_1 < V7_0
26325 type.to_sym == :datetime ? :timestamp : type
26326 if type == :datetime
26327 class V6_0 < V6_1
26328 class V5_1 < V5_2
26329 class V5_0 < V5_1
26330 type = :integer if type == :primary_key
26331 super(*args, type: :integer, **options)
26332 if options[:id] == :uuid && !options.key?(:default)
26333 options[:default] = "uuid_generate_v4()"
26334 unless connection.adapter_name == "Mysql2" && options[:id] == :bigint
26335 if [:integer, :bigint].include?(options[:id]) && !options.key?(:default)
26336 options[:id] = :integer
26337 if type == :primary_key
26338 class V4_2 < V5_0
26339 options[:index] ||= false
26340 options[:name] =
26341 @commands = []
26342 @commands << (command << block)
26343 method = :"invert_#{command}"
26344 @commands << [:change_table, [table_name], -> t { bulk_change_table(table_name, commands) }]
26345 }.each do |cmd, inv|
26346 [[inv, cmd], [cmd, inv]].uniq.each do |method, inverse|
26347 if args.size == 1 && block == nil
26348 unless args[-1].is_a?(Hash) && args[-1].has_key?(:type)
26349 [:add_columns, args]
26350 [:rename_index, [table_name, new_name, old_name]]
26351 [:rename_column, [table_name, new_name, old_name]]
26352 args = [table, columns]
26353 [:add_index, args]
26354 unless options.is_a?(Hash) && options.has_key?(:from) && options.has_key?(:to)
26355 [:change_column_default, [table, column, from: options[:to], to: options[:from]]]
26356 args[2] = !args[2]
26357 [:change_column_comment, [table, column, from: options[:to], to: options[:from]]]
26358 [:change_table_comment, [table, from: options[:to], to: options[:from]]]
26359 message = "

#{message}

" if message
26360 message += " RAILS_ENV=#{::Rails.env}" if defined?(Rails.env) && !Rails.env.local?
26361 message += "

"
26362 message += "You have #{pending_migrations.size} pending #{pending_migrations.size > 1 ? 'migrations:' : 'migration:'}

"
26363 msg << "You are running in `#{ current }` environment. "
26364 super("#{msg}

")
26365 MigrationFilenameRegexp = /\A([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?\.rb\z/ # :nodoc:
26366 /\A\d(_?\d)*\z/ # integer with optional underscores
26367 ].any? { |pattern| pattern.match?(version_string) }
26368 @file_watcher.new([], paths.index_with(["rb"]), &block)
26369 def method_missing(name, *args, &block) # :nodoc:
26370 dir = opts[:direction] || :up
26371 dir = (dir == :down ? :up : :down) if opts[:revert]
26372 time = nil
26373 text = "#{version} #{name}: #{message}"
26374 length = [0, 75 - text.length].max
26375 write "== %s %s" % [text, "=" * length]
26376 say "%.4fs" % time.real, :subitem
26377 say("#{result} rows", :subitem) if result.is_a?(Integer)
26378 arg_list = arguments.map(&:inspect) * ", "
26379 say_with_time "#{method}(#{arg_list})" do
26380 if method == :rename_table ||
26381 (method == :remove_foreign_key && !arguments.second.is_a?(Hash))
26382 copied = []
26383 magic_comments = +""
26384 source.sub!(/\A(?:#.*\b(?:en)?coding:\s*\S+|#\s*frozen_string_literal:\s*(?:true|false)).*
/) do |magic_comment|
26385 end || break
26386 if !magic_comments.empty? && source.start_with?("
")
26387 magic_comments << "
"
26388 source = source[1..-1]
26389 if options[:on_skip] && duplicate.scope != scope.to_s
26390 [Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % number].max
26391 when current_version == 0 && target_version == 0
26392 def rollback(steps = 1) # :nodoc:
26393 def forward(steps = 1) # :nodoc:
26394 move(:up, steps)
26395 def up(target_version = nil, &block) # :nodoc:
26396 def down(target_version = nil, &block) # :nodoc:
26397 def open # :nodoc:
26398 status = db_list.delete(version) ? "up" : "down"
26399 ["up", version, "********** NO FILE **********"]
26400 (db_list + file_list).sort_by { |_, version, _| version.to_i }
26401 Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
26402 if up?
26403 runnable.reject { |m| ran?(m) }
26404 runnable.find_all { |m| ran?(m) }
26405 @target_version && @target_version != 0 && !target
26406 msg = +"An error has occurred, "
26407 msg << "all later migrations canceled:

#{e}"
26408 up? ? 0 : (migrations.index(current) || 0)
26409 name, = migrations.group_by(&:name).find { |_, v| v.length > 1 }
26410 version, = migrations.group_by(&:version).find { |_, v| v.length > 1 }
26411 @direction == :up
26412 @direction == :down
26413 time.to_i * 1000 + time.usec / 1000
26414 timestamp ? Time.at(timestamp / 1000, (timestamp % 1000) * 1000) : Time.at(0)
26415 def self.call(context, options = {})
26416 binds = []
26417 elsif attr.respond_to?(:[]) && attr[i].respond_to?(:name)
26418 attr = nil
26419 [attr&.name, value]
26420 when /select .*for update/mi, /\A\s*lock/mi
26421 when /\A\s*select/i
26422 when /\A\s*insert/i
26423 when /\A\s*update/i
26424 when /\A\s*delete/i
26425 def lock!(lock = true)
26426 raise(<<-MSG.squish)
26427 Changed attributes: #{changed.map(&:inspect).join(', ')}.
26428 lock = args.present? ? args.first : true
26429 def increment!(*, **) # :nodoc:
26430 def define_attribute(name, cast_type, **) # :nodoc:
26431 self === subtype ? subtype : super
26432 __setobj__(coder["subtype"])
26433 coder["subtype"] = __getobj__
26434 um.set [
26435 sm.limit = 1
26436 if (default = super()) &&
26437 (result = send(method_name).to_s).present? &&
26438 timestamp.is_a?(String) &&
26439 key = timestamp.delete("- :.")
26440 key.ljust(20, "0")
26441 @keys = []
26442 @keys = @keys.to_set
26443 @returning = false if @returning == []
26444 message = +"#{model} "
26445 message << "Bulk " if inserts.many?
26446 message << (on_duplicate == :update ? "Upsert" : "Insert")
26447 match = Array(name_or_columns).map(&:to_s)
26448 if index = unique_indexes.find { |i| match.include?(i.name) || i.columns == match }
26449 return if !value.is_a?(String) || Arel.arel_node?(value)
26450 sql = +"(#{format_columns(index.columns)})"
26451 sql << " WHERE #{index.where}" if index.where
26452 columns.respond_to?(:map) ? quote_columns(columns).join(",") : columns
26453 if abstract_class? || self == Base
26454 if self == Base
26455 :true == (@finder_needs_type_condition ||= descends_from_active_record? ? :false : :true)
26456 def dup # :nodoc:
26457 if type_name.start_with?("::")
26458 name.scan(/::|$/) { candidates.unshift "#{$`}::#{type_name}" }
26459 @base_class = if self == Base
26460 if attrs.is_a?(Hash)
26461 delegate :empty?, :to_a, to: :result
26462 def instrument(name, payload = {}, &block)
26463 events, @events = @events, []
26464 @pool = pool
26465 @error = nil
26466 @result = nil
26467 @pending && (!@session || @session.active?)
26468 @session && !@session.active?
26469 @lock_wait = 0.0
26470 @result = exec_query(connection, *@args, **@kwargs, async: async)
26471 def exec_query(*, **)
26472 @@all_cached_fixtures = Hash.new { |h, k| h[k] = {} }
26473 def [](fs_name)
26474 if column_type == :uuid
26475 fixtures_map = {}
26476 table_rows_for_connection = Hash.new { |h, k| h[k] = [] }
26477 set.each { |fs| conn.reset_pk_sequence!(fs.table_name) }
26478 def [](x)
26479 def []=(k, v)
26480 fixtures[k] = v
26481 ).to_hash
26482 if class_name.is_a?(Class) # TODO: Should be an AR::Base type class, or any?
26483 [base]
26484 yaml_files = Dir["#{path}/{**,*}/*.yml"].select { |f|
26485 ::File.file?(f)
26486 } + [yaml_file_path(path)]
26487 @tables = Hash.new { |h, table| h[table] = [] }
26488 @tables.transform_values { |rows| rows.map(&:to_hash) }
26489 now: now,
26490 @now = now
26491 @row[c_name] = @now unless @row.key?(c_name)
26492 @row.each do |key, value|
26493 @row[key] = value.gsub("$LABEL", @label.to_s) if value.is_a?(String)
26494 next if !model_metadata.has_column?(pk) || @row.include?(pk)
26495 @row[name] = values.fetch(@row[name], @row[name])
26496 if value.sub!(/\s*\(([^)]*)\)\s*$/, "")
26497 targets = targets.is_a?(Array) ? targets : targets.split(/\s*,\s*/)
26498 join = { lhs_key => @row[model_metadata.primary_key_name],
26499 join[col] = @now
26500 %(!!binary "#{Base64.strict_encode64(File.binread(path))}")
26501 @column_type ||= {}
26502 @column_names ||= @model_class ? @model_class.columns.map(&:name).to_set : Set.new
26503 class File # :nodoc:
26504 x = new file
26505 block_given? ? yield(x) : x
26506 @rows ||= raw_rows.reject { |fixture_name, _| fixture_name == "_fixture" }
26507 @config_row ||= begin
26508 row = raw_rows.find { |fixture_name, _| fixture_name == "_fixture" }
26509 { 'model_class': nil, 'ignore': nil }
26510 @raw_rows ||= begin
26511 data ? validate(data).to_a : []
26512 unless Hash === data
26513 unless Hash === data || YAML::Omap === data
26514 invalid = data.reject { |_, row| Hash === row }
26515 EXPLAINED_SQLS = /\A\s*(\/\*.*\*\/)?\s*(with|select|update|delete|insert)\b/i
26516 payload[:cached] ||
26517 @queries = []
26518 def exec_explain(queries, options = []) # :nodoc:
26519 str = queries.map do |sql, binds|
26520 msg = +"#{build_explain_clause(options)} #{sql}"
26521 msg << " "
26522 msg << binds.map { |attr| render_bind(attr) }.inspect
26523 msg << "
"
26524 def initialize(message = nil, model = nil, primary_key = nil, id = nil)
26525 super "Wanted only one #{record&.name || "record"}"
26526 super(message || $!&.message)
26527 sql: nil,
26528 msg = <<~EOM.squish
26529 Column `#{foreign_key}` on table `#{table}` does not match column `#{primary_key}` on `#{target_table}`,
26530 To resolve this issue, change the type of the `#{foreign_key}` column on `#{table}` to be :#{type}.
26531 (For example `t.#{type} :#{foreign_key}`).
26532 msg << "
Original message: #{message}"
26533 if @query_parser && !@sql
26534 ).tap do |exception|
26535 def initialize(message = nil, code = nil, level = nil, sql = nil)
26536 @code = code
26537 def load_schema! # :nodoc:
26538 raise "Unknown enum attribute '#{name}' for #{self.name}" if Enum::EnumType === cast_type
26539 raise ArgumentError, "'#{value}' is not a valid #{name}"
26540 def enum(name = nil, values = nil, **options)
26541 options.transform_keys! { |key| :"#{key[1..-1]}" }
26542 definitions.each { |name, values| _enum(name, values, **options) }
26543 detect_enum_conflict!(name, "#{name}=")
26544 value_method_names = []
26545 prefix == true ? "#{name}_" : "#{prefix}_"
26546 suffix == true ? "_#{name}" : "_#{suffix}"
26547 value_method_name = "#{prefix}#{label}#{suffix}"
26548 method_friendly_label = label.gsub(/[\W&&[:ascii:]]+/, "_")
26549 define_method("#{value_method_name}?") { public_send(:"#{name}_for_database") == value }
26550 define_method("#{value_method_name}!") { update!(name => value) }
26551 klass.scope value_method_name, -> { where(name => value) }
26552 klass.scope "not_#{value_method_name}", -> { where.not(name => value) }
26553 if values.keys.any?(&:blank?)
26554 if values.any?(&:blank?)
26555 method_names.select { |m| m.start_with?("not_") }.each do |potential_not|
26556 inverted_form = potential_not.sub("not_", "")
26557 logger.warn "Enum element '#{potential_not}' in #{self.name} uses the prefix 'not_'." \
26558 @fixed ||= @deterministic && (!@deterministic.is_a?(Hash) || @deterministic[:fixed])
26559 delegate :==, :[], :each, :key?, to: :data
26560 compressed: "c",
26561 iv: "iv",
26562 auth_tag: "at",
26563 encoding: "e"
26564 define_method "#{name}=" do |value|
26565 if level > 2
26566 unless data.is_a?(Hash) && data.has_key?("p")
26567 @keys = Array(keys)
26568 @encryption_key ||= @keys.last.tap do |key|
26569 @keys_grouped_by_id ||= @keys.group_by(&:id)
26570 if args.is_a?(Array) && (options = args.first).is_a?(Hash)
26571 if values.is_a?(Array) && values[1..].all?(AdditionalValue)
26572 @clean_values = {}
26573 if default && default == value
26574 default: -> { columns_hash[name.to_s]&.default })
26575 self.custom_contexts ||= []
26576 raise if index == keys.length - 1
26577 match && match.valid? || super
26578 @matchers = []
26579 klass = matchers.find { |k| k.pattern.match?(name) }
26580 @pattern ||= /\A#{prefix}_([_a-zA-Z]\w*)#{suffix}\Z/
26581 def self.#{name}(#{signature})
26582 attribute_names.map { |name| "_#{name}" }.join(", ")
26583 @ids = ids.uniq
26584 records = ids.flat_map { |id| records_by_id[id] }
26585 primary_key = options[:primary_key] || "id"
26586 role_type = options[:foreign_type] || "#{role}_type"
26587 define_method "build_#{role}" do |*params|
26588 public_send("#{role}=", public_send("#{role}_class").new(*params))
26589 scope_name = type.tableize.tr("/", "_")
26590 scope scope_name, -> { where(role_type => type) }
26591 if url.nil? || url.start_with?("jdbc:", "http:", "https:")
26592 { url: url }
26593 def socket # :nodoc:
26594 (configuration_hash[:pool] || 5).to_i
26595 def primary? # :nodoc:
26596 @env_name = env_name
26597 @adapter = @uri.scheme && @uri.scheme.tr("-", "_")
26598 @adapter = "postgresql" if @adapter == "postgres"
26599 @uri.opaque, @query = @uri.opaque.split("?", 2)
26600 @query = @uri.query
26601 @uri_parser ||= URI::Parser.new
26602 Hash[(@query || "").split("&").map { |pair| pair.split("=", 2) }].symbolize_keys
26603 if @adapter == "sqlite3"
26604 self.db_config_handlers = [] # :nodoc:
26605 .sort_by.with_index { |db_config, i| db_config.for_current_env? ? [0, i] : [1, i] }
26606 .find do |db_config|
26607 db_config.env_name == env.to_s ||
26608 (db_config.for_current_env? && db_config.name == env.to_s)
26609 def primary?(name) # :nodoc:
26610 names = config.map(&:name)
26611 raise InvalidConfigurationError, "'{ #{env_name} => #{config} }' is not a valid configuration. Expected '#{config}' to be a URL string or a Hash."
26612 url = config[:url]
26613 url = ENV[name_env_key]
26614 id = super
26615 return hash[:role] if hash[:role] && hash[:klasses].include?(Base)
26616 @find_by_statement_cache = { true => Concurrent::Map.new, false => Concurrent::Map.new }
26617 def find(*ids) # :nodoc:
26618 cached_find_by([primary_key], [id]) ||
26619 raise(RecordNotFound.new("Couldn't find #{name} with '#{primary_key}'=#{id}", name, primary_key, id))
26620 def find_by(*args) # :nodoc:
26621 hash = hash.each_with_object({}) do |(key, value), h|
26622 h[key] = value
26623 def find_by!(*args) # :nodoc:
26624 attr_list = attribute_types.map { |name, type| "#{name}: #{type.type}" } * ", "
26625 def ===(object) # :nodoc:
26626 @arel_table ||= Arel::Table.new(table_name, klass: self)
26627 coder["new_record"] = new_record?
26628 !id.nil? &&
26629 id = self.id
26630 def <=>(other_object)
26631 to_key <=> other_object.to_key
26632 def present? # :nodoc:
26633 def blank? # :nodoc:
26634 unless [:all, :n_plus_one_only].include?(mode)
26635 pp.seplist(attr_names, proc { pp.text "," }) do |attr_name|
26636 pp.breakable " "
26637 pp.text ":"
26638 pp.text __getobj__
26639 def connects_to(database: {}, shards: {})
26640 connections = []
26641 if self != Base && !abstract_class
26642 if self != Base || classes.include?(Base)
26643 current_role == role.to_sym && current_shard == shard.to_sym
26644 def clear_cache! # :nodoc:
26645 @cache = Hash.new { |h, pid| h[pid] = {} }
26646 def []=(sql, stmt)
26647 gem "sqlite3", "~> 1.4"
26648 args << "-#{options[:mode]}" if options[:mode]
26649 args << "-header" if options[:header]
26650 when ":memory:"
26651 when /\Afile:/
26652 @config[:database] == ":memory:" || File.exist?(@config[:database].to_s)
26653 database_version >= "3.9.0"
26654 database_version >= "3.8.3"
26655 database_version >= "3.24.0"
26656 pks = table_structure(table_name).select { |f| f["pk"] > 0 }
26657 pks.sort_by { |f| f["pk"] }.map { |f| f["name"] }
26658 fk_info = exec_query("PRAGMA foreign_key_list(#{quote(table_name)})", "SCHEMA")
26659 fk_info.map do |row|
26660 column: row["from"],
26661 primary_key: row["to"],
26662 sql = +"INSERT #{insert.into} #{insert.values_list}"
26663 sql << insert.updatable_columns.map { |column| "#{column}=excluded.#{column}" }.join(",")
26664 if database_version < "3.8.0"
26665 limit || 8
26666 TYPE_MAP = Type::TypeMap.new.tap { |m| initialize_type_map(m) }
26667 when /^null$/i
26668 when /^'(.*)'$/m
26669 $1.gsub("''", "'")
26670 when /^"(.*)"$/m
26671 $1.gsub('""', '"')
26672 when /\A-?\d+(\.\d*)?\z/
26673 $&
26674 when /x'(.*)'/
26675 [ $1 ].pack("H*")
26676 type.to_sym == :primary_key || options[:primary_key] ||
26677 options[:null] == false && options[:default].nil?
26678 rename = options[:rename] || {}
26679 def move_table(from, to, options = {}, &block)
26680 options[:id] = false
26681 (options[:rename][column.name] ||
26682 copy_table_indexes(from, to, options[:rename] || {})
26683 options[:rename] || {})
26684 def copy_table_indexes(from, to, rename = {})
26685 if to == "a#{from}"
26686 name = "t#{name}"
26687 elsif from == "a#{to}"
26688 name = name[1..-1]
26689 columns = columns.map { |c| rename[c] || c }.select do |column|
26690 options = { name: name.gsub(/(^|_)(#{from})_/, "\\1#{to}_"), internal: true }
26691 column_mappings = Hash[columns.map { |name| [name, name] }]
26692 rename.each { |a| column_mappings[a.last] = a.first }
26693 quoted_columns = columns.map { |col| quote_column_name(col) } * ","
26694 quoted_from_columns = from_columns_to_copy.map { |col| quote_column_name(col) } * ","
26695 if exception.message.match?(/(column(s)? .* (is|are) not unique|UNIQUE constraint failed: .*)/i)
26696 collation_hash = {}
26697 auto_increments = {}
26698 WHERE type = 'table' AND name = #{quote(table_name)}
26699 columns_string = result.split("(", 2).last
26700 next if row["name"].start_with?("sqlite_")
26701 WHERE name = #{quote(row['name'])} AND type = 'index'
26702 columns = exec_query("PRAGMA index_info(#{quote(row['name'])})", "SCHEMA").map do |col|
26703 col["name"]
26704 orders = {}
26705 index_sql.scan(/"(\w+)" DESC/).flatten.each { |order_column|
26706 row["name"],
26707 row["unique"] != 0,
26708 to_table ||= options[:to_table]
26709 table = to_table || begin
26710 table = options[:column].to_s.delete_suffix("_id")
26711 fk_to_table == table && options.all? { |k, v| fk.options[k].to_s == v.to_s }
26712 end || raise(ArgumentError, "Table '#{from_table}' has no foreign key for #{to_table || options}")
26713 WHERE name = #{quote(table_name)} AND type = 'table'
26714 table_sql.to_s.scan(/CONSTRAINT\s+(?<name>\w+)\s+CHECK\s+\((?<expression>(:?[^()]|\(\g<expression>\))+)\)/i).map do |name, expression|
26715 super + [:rename]
26716 field["name"],
26717 field["notnull"].to_i == 0,
26718 scope[:type] ||= "'table','view'"
26719 sql << " AND name = #{scope[:name]}" if scope[:name]
26720 sql << " AND type IN (#{scope[:type]})"
26721 type = \
26722 scope = {}
26723 sql << " COLLATE \"#{options[:collation]}\""
26724 self.class.quoted_table_names[name] ||= super.gsub(".", "\".\"").freeze
26725 self.class.quoted_column_names[name] ||= %Q("#{super.gsub('"', '""')}")
26726 value = value.change(year: 2000, month: 1, day: 1)
26727 quoted_date(value).sub(/\A\d\d\d\d-\d\d-\d\d /, "2000-01-01 ")
26728 if value.is_a?(Proc)
26729 if value.match?(/\A\w+\(.*\)\z/)
26730 def type_cast(value) # :nodoc:
26731 (?:
26732 ((?:\w+\.|"\w+"\.)?(?:\w+|"\w+") | \w+\((?:|\g<2>)\))
26733 (?:(?:\s+AS)?\s+(?:\w+|"\w+"))?
26734 (?:\s*,\s*\g<1>)*
26735 \z
26736 /ix
26737 row.join("|")
26738 end.join("
") + "
"
26739 ) # :nodoc:
26740 def write_query?(sql) # :nodoc:
26741 def explain(arel, binds = [], _options = [])
26742 result = exec_query(sql, "EXPLAIN", [])
26743 def execute(sql, name = nil, allow_retry: false) # :nodoc:
26744 def exec_query(sql, name = nil, binds = [], prepare: false, async: false) # :nodoc:
26745 stmt = @statements[sql] ||= conn.prepare(sql)
26746 def exec_delete(sql, name = "SQL", binds = []) # :nodoc:
26747 def initialize(*, auto_increment: nil, **)
26748 other.is_a?(Column) &&
26749 @sql_type = sql_type
26750 sql_type == other.sql_type &&
26751 type == other.type &&
26752 limit == other.limit &&
26753 precision.hash >> 1 ^
26754 scale.hash >> 2
26755 @sql_type = -sql_type
26756 if File.extname(filename) == ".gz"
26757 @columns_hash = {}
26758 @data_sources = {}
26759 tables_to_cache.each { |table| add(table) }
26760 open(filename) { |f|
26761 @indexes ||= {}
26762 value.map { |i| deep_deduplicate(i) }
26763 gem "pg", "~> 1.1"
26764 rescue ::PG::Error => error
26765 if conn_params && conn_params[:dbname] == "postgres"
26766 end.join(" ")
26767 bit_varying: { name: "bit varying" },
26768 database_version >= 11_00_00 # >= 11.0
26769 database_version >= 12_00_00 # >= 12.0
26770 database_version >= 9_05_00 # >= 9.5
26771 @counter = 0
26772 @type_map = nil
26773 def discard! # :nodoc:
26774 database_version >= 9_04_00 # >= 9.4
26775 unless lock_id.is_a?(Integer) && lock_id.bit_length <= 63
26776 schema, name = name.to_s.split(".").values_at(-2, -1)
26777 sql << " SCHEMA #{schema}" if schema
26778 name, schema = row[0], row[2]
26779 full_name = [schema, name].compact.join(".")
26780 sql_values = values.map { |s| quote(s) }.join(", ")
26781 WHERE t.typname = #{scope[:name]}
26782 AND n.nspname = #{scope[:schema]}
26783 $$;
26784 index.using == :btree || super
26785 if database_version < 9_03_00 # < 9.3
26786 m.alias_type "char", "varchar"
26787 m.alias_type "name", "varchar"
26788 m.register_type "numeric" do |_, fmod, sql_type|
26789 if fmod && (fmod - 4 & 0xffff).zero?
26790 when /\A[(B]?'(.*)'.*::"?([\w. ]+)"?(?:\[\])?\z/m
26791 if $1 == "now" && $2 == "date"
26792 when "true", "false"
26793 when /\A\(?(-?\d+(\.\d*)?)\)?(::bigint)?\z/
26794 $1
26795 when /\A-?\d+\z/
26796 def get_oid_type(oid, fmod, column_name, sql_type = "")
26797 if !type_map.key?(oid)
26798 yield query + "WHERE t.oid IN (%s)" % oids.join(", ")
26799 sql_key = sql_key(sql)
26800 variables.map do |k, v|
26801 if v == ":default" || v == :default
26802 elsif !v.nil?
26803 sql[/into\s("[A-Za-z0-9_."\[\]\s]+"|[A-Za-z0-9_."\[\]]+)\s*/im]
26804 $1.strip if $1
26805 @case_insensitive_cache ||= { "citext" => false }
26806 ) OR exists(
26807 coders_by_name = {
26808 known_coder_types = coders_by_name.keys.map { |n| quote(n) }
26809 query = <<~SQL % known_coder_types.join(", ")
26810 @timestamp_decoder = coders.find { |coder| coder.name == "timestamp" }
26811 coder_class.new(oid: row["oid"].to_i, name: row["typname"])
26812 def decode(value, tuple = nil, field = nil)
26813 class Name # :nodoc:
26814 def ==(o)
26815 o.class == self.class && o.parts == parts
26816 alias_method :eql?, :==
26817 @parts ||= [@schema, @identifier].compact
26818 schema, table = string.scan(/[^".]+|"[^"]*"/)
26819 @oid = oid
26820 @fmod = fmod
26821 __getobj__ == other.__getobj__ &&
26822 oid == other.oid &&
26823 __getobj__.hash ^
26824 oid.hash ^
26825 __setobj__(__getobj__.deduplicate)
26826 def recreate_database(name, options = {}) # :nodoc:
26827 option_string = options.each_with_object(+"") do |(key, value), memo|
26828 memo << case key
26829 execute "DROP TABLE#{' IF EXISTS' if options[:if_exists]} #{quote_table_name(table_name)}#{' CASCADE' if options[:force] == :cascade}"
26830 AND i.relname = #{index[:name]}
26831 AND t.relname = #{table[:name]}
26832 AND n.nspname = #{table[:schema]}
26833 AND t.relname = #{scope[:name]}
26834 index_name = row[0]
26835 unique = row[1]
26836 indkey = row[2].split(" ").map(&:to_i)
26837 inddef = row[3]
26838 oid = row[4]
26839 comment = row[5]
26840 valid = row[6]
26841 opclasses = {}
26842 include_columns = include ? include.split(",").map(&:strip) : []
26843 columns = Hash[query(<<~SQL, "SCHEMA")].values_at(*indkey).compact
26844 WHERE a.attrelid = #{oid}
26845 AND a.attnum IN (#{indkey.join(",")})
26846 orders[column] = [desc, nulls].compact.join(" ")
26847 { comment: comment }
26848 WHERE c.relname = #{scope[:name]}
26849 AND c.relkind IN (#{scope[:type]})
26850 WHERE nspname !~ '^pg_.*'
26851 def default_sequence_name(table_name, pk = "id") # :nodoc:
26852 PostgreSQL::Name.new(nil, "#{table_name}_#{pk}_seq").to_s
26853 query_value("SELECT pg_get_serial_sequence(#{quote(table)}, #{quote(column)})", "SCHEMA")
26854 query_value("SELECT setval(#{quote(quoted_sequence)}, #{value})", "SCHEMA")
26855 def reset_pk_sequence!(table, pk = nil, sequence = nil) # :nodoc:
26856 pk ||= default_pk
26857 if @logger && pk && !sequence
26858 max_pk = query_value("SELECT MAX(#{quote_column_name pk}) FROM #{quote_table_name(table)}", "SCHEMA")
26859 query_value("SELECT setval(#{quote(quoted_sequence)}, #{max_pk || minvalue}, #{max_pk ? true : false})", "SCHEMA")
26860 WHEN split_part(pg_get_expr(def.adbin, def.adrelid), '''', 2) ~ '.' THEN
26861 substr(split_part(pg_get_expr(def.adbin, def.adrelid), '''', 2),
26862 strpos(split_part(pg_get_expr(def.adbin, def.adrelid), '''', 2), '.')+1)
26863 ELSE split_part(pg_get_expr(def.adbin, def.adrelid), '''', 2)
26864 AND cons.contype = 'p'
26865 [pk, nil]
26866 ) i
26867 AND a.attnum = i.indkey[i.idx]
26868 idx = "#{table_name}_pkey"
26869 new_idx = "#{new_name}_pkey"
26870 if seq && seq.identifier == "#{table_name}_#{pk}_seq"
26871 new_seq = "#{new_name}_#{pk}_seq"
26872 sqls, procs = Array(change_column_for_alter(table_name, column_name, type, **options)).partition { |v| v.is_a?(String) }
26873 execute "ALTER TABLE #{quote_table_name(table_name)} #{sqls.join(", ")}"
26874 AND t1.relname = #{scope[:name]}
26875 AND t3.nspname = #{scope[:schema]}
26876 name: row["name"],
26877 options[:validate] = row["valid"]
26878 name: row["conname"],
26879 expression = row["constraintdef"][/CHECK \((.+)\)/m, 1]
26880 exclusion_info = exec_query(<<-SQL, "SCHEMA")
26881 method_and_elements_parts = method_and_elements.match(/EXCLUDE(?: USING (?<using>\S+))? \((?<expression>.+)\)/)
26882 WHERE a.attrelid = #{row['conindid']}
26883 def type_to_sql(type, limit: nil, precision: nil, scale: nil, array: nil, enum_type: nil, **) # :nodoc:
26884 sql = \
26885 when 1, 2; "smallint"
26886 when nil, 3, 4; "integer"
26887 when 5..8; "bigint"
26888 sql = "#{sql}[]" if array && type != :primary_key
26889 }.compact_blank.map.with_index { |column, i| "#{column} AS alias_#{i}" }
26890 (order_columns << super).join(", ")
26891 if match = default_function&.match(/\Anextval\('"?(?<sequence_name>.+_(?<suffix>seq\d*))"?'::regclass\)\z/)
26892 when "c"; :cascade
26893 when "n"; :nullify
26894 when "r"; :restrict
26895 deferrable && (deferred ? :deferred : true)
26896 column << " #{opclasses[name]}" if opclasses[name].present?
26897 identifier = "#{table_name}_#{column_name}_unique"
26898 scope[:type] ||= "'r','v','m','p','f'" # (r)elation/table, (v)iew, (m)aterialized view, (p)artitioned table, (f)oreign table
26899 sql << " WHERE n.nspname = #{scope[:schema]}"
26900 sql << " AND c.relname = #{scope[:name]}" if scope[:name]
26901 sql << " AND c.relkind IN (#{scope[:type]})"
26902 scope[:schema] = schema ? quote(schema) : "ANY (current_schemas(false))"
26903 parts << "name: #{unique_key.name.inspect}"
26904 spec[:array] = "true" if column.array?
26905 spec[:stored] = true
26906 spec[:enum_type] = "\"#{column.sql_type}\"" if column.enum?
26907 column.type == :uuid || (column.type == :integer && !column.serial?)
26908 if type == :uuid
26909 :hstore, :inet, :interval, :int4range, :int8range, :jsonb, :ltree, :macaddr,
26910 :money, :numrange, :oid, :point, :line, :lseg, :box, :path, :polygon, :circle,
26911 def initialize(*, **)
26912 @unique_keys = []
26913 super + [:array, :using, :cast_as, :as, :type, :enum_type, :stored]
26914 if type == :bigint || options[:limit] == 8
26915 @unique_key_adds = []
26916 @unique_key_drops = []
26917 sql << o.unique_key_adds.map { |con| visit_AddUniqueKey con }.join(" ")
26918 sql << o.unique_key_drops.map { |con| visit_DropUniqueKey con }.join(" ")
26919 super.dup.tap { |sql| sql << " NOT VALID" unless o.validate? }
26920 sql << o.name
26921 sql << "USING #{o.using}" if o.using
26922 sql << "(#{o.expression})"
26923 sql << "WHERE (#{o.where})" if o.where
26924 sql.join(" ")
26925 column_name = Array(o.columns).map { |column| quote_column_name(column) }.join(", ")
26926 sql << "(#{column_name})"
26927 change_column_sql << " COLLATE \"#{options[:collation]}\""
26928 change_column_sql << " USING #{options[:using]}"
26929 cast_as_type = type_to_sql(options[:cast_as], **options)
26930 change_column_sql << " USING CAST(#{quoted_column_name} AS #{cast_as_type})"
26931 sql = +"ALTER COLUMN #{quote_column_name(o.column.name)} "
26932 if as = options[:as]
26933 String === o ? o : quoted_include_columns_for_index(o)
26934 do $$
26935 def quote(value) # :nodoc:
26936 def quote_string(s) # :nodoc:
26937 if value.year <= 0
26938 bce_year = format("%04d", -value.year + 1)
26939 super.sub(/^-?\d+/, bce_year) + " BC"
26940 elsif column.type == :uuid && value.is_a?(String) && value.include?("()")
26941 { value: value.to_s, format: 1 }
26942 super(query_value("SELECT #{quote(sql_type)}::regtype::oid", "SCHEMA").to_i)
26943 infinity?(value) ? "" : type_cast(value)
26944 module OID # :nodoc:
26945 class Xml < Type::String # :nodoc:
26946 class Vector < Type::Value # :nodoc:
26947 class Uuid < Type::Value # :nodoc:
26948 new_value && old_value.casecmp(new_value) != 0
26949 new_value && raw_old_value.casecmp(new_value) != 0
26950 nodes = records.reject { |row| @store.key? row["oid"].to_i }
26951 mapped = nodes.extract! { |row| @store.key? row["typname"] }
26952 ranges = nodes.extract! { |row| row["typtype"] == "r" }
26953 enums = nodes.extract! { |row| row["typtype"] == "e" }
26954 domains = nodes.extract! { |row| row["typtype"] == "d" }
26955 arrays = nodes.extract! { |row| row["typinput"] == "array_in" }
26956 composites = nodes.extract! { |row| row["typelem"].to_i != 0 }
26957 known_type_names = @store.keys.map { |n| "'#{n}'" }
26958 <<~SQL % known_type_names.join(", ")
26959 t.typname IN (%s)
26960 known_type_types = %w('r' 'e' 'd')
26961 <<~SQL % known_type_types.join(", ")
26962 t.typtype IN (%s)
26963 known_type_oids = @store.keys.reject { |k| k.is_a?(String) }
26964 <<~SQL % [known_type_oids.join(", ")]
26965 t.typelem IN (%s)
26966 alias_type row["oid"], row["typname"]
26967 warn "unknown base type (OID: #{row["typbasetype"]}) for domain #{row["typname"]}."
26968 register(oid) do |_, *args|
26969 if is_utc?
26970 class Range < Type::Value # :nodoc:
26971 return if value == "empty"
26972 other.is_a?(Range) &&
26973 def map(value) # :nodoc:
26974 value.is_a?(::Range)
26975 from, to = value[1..-2].split(",", 2)
26976 exclude_start: value.start_with?("("),
26977 if value.start_with?('"') && value.end_with?('"')
26978 unquoted_value = value[1..-2]
26979 unquoted_value.gsub!('""', '"')
26980 unquoted_value.gsub!("\\\\", "\\")
26981 Point = Struct.new(:x, :y)
26982 class Point < Type::Value # :nodoc:
26983 if value.start_with?("(") && value.end_with?(")")
26984 value = value[1...-1]
26985 x, y = value.split(",")
26986 [value.x, value.y]
26987 value = value.sub(/^\((.+)\)$/, '-\1') # (4)
26988 value.gsub!(/[^-\d.]/, "")
26989 value.gsub!(/[^-\d,]/, "").sub!(/,/, ".")
26990 cast(value.split(","))
26991 value.map { |v| Float(v) }
26992 if value.is_a?(::Array)
26993 class Jsonb < Type::Json # :nodoc:
26994 class Inet < Cidr # :nodoc:
26995 class Hstore < Type::Value # :nodoc:
26996 unless key = scanner.scan(/^(\\[\\"]|[^\\"])*?(?=")/)
26997 unless scanner.skip(/"=>?/)
26998 unless value = scanner.scan(/^(\\[\\"]|[^\\"])*?(?=")/)
26999 key.gsub!('\"', '"')
27000 key.gsub!("\\\\", "\\")
27001 value.gsub!('\"', '"')
27002 value.gsub!("\\\\", "\\")
27003 unless scanner.skip(/, /) || scanner.eos?
27004 if value.is_a?(::Hash)
27005 value.map { |k, v| "#{escape_hstore(k)}=>#{escape_hstore(v)}" }.join(", ")
27006 if value == ""
27007 class Enum < Type::Value # :nodoc:
27008 def infinity(options = {})
27009 BigDecimal("Infinity") * (options[:negative] ? -1 : 1)
27010 when / BC$/
27011 value = value.sub(/^\d+/) { |year| format("%04d", -year.to_i + 1) }
27012 class Date < Type::Date # :nodoc:
27013 class Cidr < Type::Value # :nodoc:
27014 if IPAddr === value
27015 class Bytea < Type::Binary # :nodoc:
27016 class Bit < Type::Value # :nodoc:
27017 if ::String === value
27018 when /^0x/i
27019 /\A[01]*\Z/.match?(value)
27020 /\A[0-9A-F]*\Z/i.match?(value)
27021 class Array < Type::Value # :nodoc:
27022 Data = Struct.new(:encoder, :values) # :nodoc:
27023 @pg_encoder = PG::TextEncoder::Array.new name: "#{type}[]", delimiter: delimiter
27024 @pg_decoder = PG::TextDecoder::Array.new name: "#{type}[]", delimiter: delimiter
27025 if value.is_a?(::String)
27026 other.is_a?(Array) &&
27027 value.map { |v| subtype.map(v, &block) }
27028 value.is_a?(::Array)
27029 value.map { |item| type_cast_array(item, method) }
27030 width = [header, *lines].map(&:length).max + 2
27031 pp = []
27032 pp << "-" * width
27033 pp += lines.map { |line| " #{line}" }
27034 rows_label = nrows == 1 ? "row" : "rows"
27035 pp << "(#{nrows} #{rows_label})"
27036 pp.join("
") + "
"
27037 def explain(arel, binds = [], options = [])
27038 def query(sql, name = nil) # :nodoc:
27039 :close, :declare, :fetch, :move, :set, :show
27040 def exec_query(sql, name = "SQL", binds = [], prepare: false, async: false, allow_retry: false, uses_transaction: true) # :nodoc:
27041 types = {}
27042 def exec_delete(sql, name = nil, binds = []) # :nodoc:
27043 def sql_for_insert(sql, pk, binds) # :nodoc:
27044 if pk.nil?
27045 sql = "#{sql} RETURNING #{quote_column_name(pk)}"
27046 def exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil) # :nodoc:
27047 if use_insert_returning? || pk == false
27048 ["TRUNCATE TABLE #{table_names.map(&method(:quote_table_name)).join(", ")}"]
27049 exec_query("SELECT currval(#{quote(sequence_name)})", "SQL")
27050 def initialize(*, serial: nil, generated: nil, **)
27051 super && !virtual?
27052 sql_type_metadata.sql_type.end_with?("[]")
27053 type == :enum
27054 super.delete_suffix("[]")
27055 @serial = coder["serial"]
27056 coder["serial"] = @serial
27057 @role_to_shard_mapping = Hash.new { |h, k| h[k] = {} }
27058 @role = role
27059 @pool = nil
27060 gem "mysql2", "~> 0.5"
27061 @config[:flags] ||= 0
27062 !mariadb? && database_version >= "5.7.8"
27063 def each_hash(result, &block) # :nodoc:
27064 indexes = []
27065 next if row[:Key_name] == "PRIMARY" # skip the primary key
27066 indexes << [
27067 row[:Table],
27068 row[:Key_name],
27069 row[:Non_unique].to_i == 0,
27070 lengths: {},
27071 orders: {},
27072 expression = +"(#{expression})" unless expression.start_with?("(")
27073 indexes.last[-1][:expressions] ||= {}
27074 indexes.last[-1][:orders][expression] = :desc if row[:Collation] == "D"
27075 indexes.last[-2] << row[:Column_name]
27076 indexes.last[-1][:lengths][row[:Column_name]] = row[:Sub_part].to_i if row[:Sub_part]
27077 indexes.last[-1][:orders][row[:Column_name]] = :desc if row[:Collation] == "D"
27078 columns = index[-1].to_h { |name|
27079 [ name.to_sym, expressions[name] || +quote_column_name(name) ]
27080 ).values.join(", ")
27081 options[:collation] = collation.sub(/\A[^_]+/, "utf8")
27082 def type_to_sql(type, limit: nil, precision: nil, scale: nil, size: limit_to_size(limit, type), unsigned: nil, **)
27083 sql =
27084 if (0..0xfff) === limit
27085 sql = "#{sql} unsigned" if unsigned && type != :primary_key
27086 database_version >= "10.2.2"
27087 database_version >= "5.7.9"
27088 if query_value("SELECT @@innodb_file_per_table = 1 AND @@innodb_file_format = 'Barracuda'") == 1
27089 super + [:unsigned]
27090 match = create_table_info(table_name)&.match(/`#{field_name}` (.+) DEFAULT ('|\d+|[A-z]+)/)
27091 if default_pre == "'"
27092 elsif default_pre&.match?(/^\d+$/)
27093 elsif default_pre&.match?(/^[A-z]+$/)
27094 if type_metadata.type == :datetime && /\ACURRENT_TIMESTAMP(?:\([0-6]?\))?\z/i.match?(default)
27095 default = +"(#{default})" unless default.start_with?("(")
27096 elsif type_metadata.type == :text && default&.start_with?("'")
27097 default = default[1...-1].gsub("\\'", "'")
27098 elsif default&.match?(/\A\d/)
27099 field[:Null] == "YES",
27100 column << "(#{lengths[name]})" if lengths[name].present?
27101 sql << " WHERE table_schema = #{scope[:schema]}"
27102 sql << " AND table_name = #{scope[:name]}"
27103 sql << " AND table_type = #{scope[:type]}" if scope[:type]
27104 scope[:schema] = schema ? quote(schema) : "database()"
27105 schema, name = string.to_s.scan(/[^`.\s]+|`[^`]*`/)
27106 when nil, "tiny", "medium", "long"
27107 when "text", "blob", "binary"
27108 when nil, 4; "int"
27109 if /\A(?<size>tiny|medium|long)(?:text|blob)/ =~ column.sql_type
27110 spec = { size: size.to_sym.inspect }.merge!(spec)
27111 when /\A(?:enum|set)\b/
27112 super unless /\A(?:tiny|medium|long)?(?:text|blob)\b/.match?(column.sql_type)
27113 if /\Atime(?:stamp)?\b/.match?(column.sql_type) && column.precision == 0
27114 column.precision == 0 ? "nil" : super
27115 @table_collation_cache ||= {}
27116 if %r/#{column_name} #{Regexp.quote(column.sql_type)}(?: COLLATE \w+)? AS \((?<expression>.+?)\) #{column.extra}/ =~ create_table_info
27117 @connection.query_value(sql, "SCHEMA").gsub("\\'", "'").inspect
27118 options[:limit] ||= 8
27119 when /\Aunsigned_(?<type>.+)\z/
27120 type = $~[:type].to_sym
27121 super + [:auto_increment, :charset, :as, :size, :unsigned, :first, :after, :type, :stored]
27122 change_column_sql = +"CHANGE #{quote_column_name(o.name)} #{accept(o.column)}"
27123 if o.default.nil? && !o.column.null
27124 sql << " #{o.algorithm}" if o.algorithm
27125 index_type = o.type&.to_s&.upcase || o.unique && "UNIQUE"
27126 sql = create ? ["CREATE"] : []
27127 sql << "ON #{quote_table_name(o.table)}" if create
27128 sql << "(#{quoted_columns(o)})"
27129 add_sql_comment!(sql.join(" "), o.comment)
27130 sql << " NULL" unless options[:null] == false || options_include_default?(options)
27131 sql << " AS (#{as})"
27132 sql << " AFTER #{quote_column_name(options[:after])}"
27133 self.class.quoted_column_names[name] ||= "`#{super.gsub('`', '``')}`"
27134 self.class.quoted_table_names[name] ||= super.gsub(".", "`.`").freeze
27135 super.sub(/\.\d{6}\z/, "")
27136 ((?:\w+\.|`\w+`\.)?(?:\w+|`\w+`) | \w+\((?:|\g<2>)\))
27137 (?:(?:\s+AS)?\s+(?:\w+|`\w+`))?
27138 pp << build_cells(row, widths)
27139 [].tap do |widths|
27140 cells_in_column = [column] + result.rows.map { |r| r[i].nil? ? "NULL" : r[i].to_s }
27141 cells = []
27142 item = "NULL" if item.nil?
27143 justifier = item.is_a?(Numeric) ? "rjust" : "ljust"
27144 def select_all(*, **) # :nodoc:
27145 :desc, :describe, :set, :show, :use
27146 def exec_query(sql, name = "SQL", binds = [], prepare: false, async: false) # :nodoc:
27147 build_result(columns: [], rows: [])
27148 explain_clause = "EXPLAIN #{options.join(" ").upcase}"
27149 flags = @config[:flags]
27150 previous_packet << ";
"
27151 mariadb? && database_version >= "10.1.0"
27152 /\bunsigned(?: zerofill)?\z/.match?(sql_type)
27153 collation && !collation.end_with?("_ci")
27154 @registry ||= {}
27155 def new(*, **)
27156 @null = null
27157 /\Abigint\b/.match?(sql_type)
27158 @name = coder["name"]
27159 @null = coder["null"]
27160 coder["name"] = @name
27161 coder["null"] = @null
27162 name == other.name &&
27163 null == other.null &&
27164 @name = -name
27165 host: "--host",
27166 port: "--port",
27167 socket: "--socket",
27168 username: "--user",
27169 sslca: "--ssl-ca",
27170 sslcert: "--ssl-cert",
27171 sslkey: "--ssl-key",
27172 ssl_mode: "--ssl-mode"
27173 }.filter_map { |opt, arg| "#{arg}=#{mysql_config[opt]}" if mysql_config[opt] }
27174 args << "--password=#{mysql_config[:password]}"
27175 args << "-p"
27176 find_cmd_and_exec(["mysql", "mysql5"], *args)
27177 def mariadb? # :nodoc:
27178 !mariadb? && database_version >= "8.0.1"
27179 !mariadb? && database_version >= "8.0.13"
27180 database_version >= "10.3.10" || (database_version < "10.3" && database_version >= "10.2.22")
27181 database_version >= "8.0.16"
27182 mariadb? || database_version >= "5.6.4"
27183 mariadb? || database_version >= "5.7.5"
27184 !mariadb? && database_version >= "5.7.7"
27185 database_version >= "10.2.1"
27186 database_version >= "8.0.1"
27187 query_value("SELECT GET_LOCK(#{quote(lock_name.to_s)}, #{timeout})") == 1
27188 def execute_and_free(sql, name = nil, async: false) # :nodoc:
27189 AND table_name = #{scope[:name]}
27190 comment = "" if comment.nil?
27191 execute "DROP#{' TEMPORARY' if options[:temporary]} TABLE#{' IF EXISTS' if options[:if_exists]} #{quote_table_name(table_name)}#{' CASCADE' if options[:force] == :cascade}"
27192 sql << " COMMENT #{quote(comment)}" if comment.present?
27193 AND fk.table_schema = #{scope[:schema]}
27194 AND fk.table_name = #{scope[:name]}
27195 AND rc.table_name = #{scope[:name]}
27196 AND tc.table_name = #{scope[:name]}
27197 sql += " AND cc.table_name = #{scope[:name]}" if mariadb?
27198 chk_info = exec_query(sql, "SCHEMA")
27199 name: row["name"]
27200 raw_table_options = create_table_info.sub(/\A.*
\) ?/m, "").sub(/
\/\*!.*\*\/
\z/m, "").strip
27201 table_options = {}
27202 raw_table_options = $` + $' # before part + after part
27203 if raw_table_options.sub!(/ COMMENT='.+'/, "")
27204 AND table_schema = #{scope[:schema]}
27205 sql << insert.touch_model_timestamps_unless { |column| "#{column}<=>VALUES(#{column})" }
27206 sql << insert.updatable_columns.map { |column| "#{column}=VALUES(#{column})" }.join(",")
27207 if database_version < "5.5.8"
27208 m.register_type %r(^tinyint\(1\))i, Type::Boolean.new
27209 m.register_type(%r(char)i) do |sql_type|
27210 m.register_type %r(mediumtext)i, Type::Text.new(limit: 2**24 - 1)
27211 m.alias_type %r(year)i, "integer"
27212 if /\A(?:date)?time(?:stamp)?\b/.match?(sql_type)
27213 super || 0
27214 warning.level == "Note" || super
27215 database_version >= "10.5.2"
27216 database_version >= "5.7.6"
27217 database_version >= "8.0.3"
27218 defaults = [":default", :default].to_set
27219 sql_mode_assignment = "@@SESSION.sql_mode = #{sql_mode}, " if sql_mode
27220 encoding = +"NAMES #{@config[:encoding]}"
27221 encoding << " COLLATE #{@config[:collation]}" if @config[:collation]
27222 encoding << ", "
27223 /Referencing column '(\w+)' and referenced/i =~ message ? $1 : '\w+'
27224 match = %r/
27225 FOREIGN\s+KEY\s*\(`?(?<foreign_key>#{foreign_key_pat})`?\)\s*
27226 REFERENCES\s*(`?(?<target_table>\w+)`?)\s*\(`?(?<primary_key>\w+)`?\)
27227 full_version_string.match(/^(?:5\.5\.5-)?(\d+\.\d+\.\d+)/)[1]
27228 Type::ImmutableString.new(true: "1", false: "0", **args)
27229 Type::String.new(true: "1", false: "0", **args)
27230 if config == "false"
27231 when "utc", "local"
27232 DEFAULT_READ_QUERY = [:begin, :commit, :explain, :release, :rollback, :savepoint, :select, :with] # :nodoc:
27233 parts = parts.map { |part| /#{part}/i }
27234 @quoted_column_names ||= {}
27235 @quoted_table_names ||= {}
27236 commands = commands.map { |cmd| "#{cmd}#{ext}" }
27237 abort("Couldn't find database client: #{commands.join(', ')}. Check your $PATH and try again.")
27238 @config = (deprecated_config || {}).symbolize_keys
27239 @lock =
27240 @config[:replica] || false
27241 (@config[:connection_retries] || 1).to_i
27242 @version = version_string.split(".").map(&:to_i)
27243 def <=>(version_string)
27244 @version <=> version_string.split(".").map(&:to_i)
27245 @version.join(".")
27246 def valid_type?(type) # :nodoc:
27247 if in_use?
27248 msg << "it is already in use by a different thread: #{@owner}. " \
27249 def steal! # :nodoc:
27250 def create_enum(*) # :nodoc:
27251 def drop_enum(*) # :nodoc:
27252 def clean! # :nodoc:
27253 m.alias_type %r(\A[^\(]*timestamp)i, "datetime"
27254 if scale == 0
27255 when /\((\d+)\)/ then 0
27256 when /\((\d+)(,(\d+))\)/ then $3.to_i
27257 $1.to_i if sql_type =~ /\((\d+)(,\d+)?\)/
27258 $1.to_i if sql_type =~ /\((.*)\)/
27259 (@verified && @raw_connection) ||
27260 message = "#{e.class.name}: #{e.message}"
27261 def log(sql, name = "SQL", binds = [], type_casted_binds = [], statement_name = nil, async: false, &block) # :doc:
27262 columns(table_name).detect { |c| c.name == column_name } ||
27263 @children ||= []
27264 @state == :committed || @state == :fully_committed
27265 @state == :rolledback || @state == :fully_rolledback
27266 @children&.each { |c| c.rollback! }
27267 @children&.each { |c| c.invalidate! }
27268 @state = nil
27269 def add_record(record, _ = true); end
27270 @dirty = true
27271 @records ||= []
27272 joinable? && !dirty?
27273 ite&.each do |i|
27274 ite&.each { |i| i.committed!(should_run_callbacks: false) }
27275 def open?; !closed?; end
27276 records.uniq(&:__id__)
27277 @stack = []
27278 @stack.each(&:restore!)
27279 @stack.none?(&:dirty?)
27280 table_name[0...table_alias_length].tr(".", "_")
27281 indexes(table_name).any? { |i| i.defined_for?(column_name, **options) }
27282 checks = []
27283 checks << lambda { |c| c.name == column_name }
27284 checks << lambda { |c| c.type == type.to_sym rescue nil } if type
27285 checks << lambda { |c| c.send(attr) == options[attr] } if options.key?(attr)
27286 columns(table_name).any? { |c| checks.all? { |check| check[c] } }
27287 pk = pk.first unless pk.size > 1
27288 t1_ref, t2_ref = [table_1, table_2].map { |t| reference_name_for_table(t) }
27289 def add_columns(table_name, *column_names, type:, **options) # :nodoc:
27290 if type == :datetime && !options.key?(:precision)
27291 old_index_def = indexes(table_name).detect { |i| i.name == old_name }
27292 if Hash === options
27293 indexes(table_name).detect { |i| i.name == index_name }
27294 foreign_key_options[:column] ||= "#{ref_name}_id"
27295 if !options.key?(:name) && !options.key?(:expression)
27296 { primary_key: true }
27297 inserting = (versions - migrated).select { |v| v < version }
27298 if (duplicate = inserting.detect { |v| inserting.count(v) > 1 })
27299 def type_to_sql(type, limit: nil, precision: nil, scale: nil, **) # :nodoc:
27300 column_type_sql = (native.is_a?(Hash) ? native[:name] : native).dup
27301 scale ||= native[:scale]
27302 column_type_sql << "(#{precision},#{scale})"
27303 column_type_sql << "(#{precision})"
27304 if (0..6) === precision
27305 elsif (type != :primary_key) && (limit ||= native.is_a?(Hash) && native[:limit])
27306 column_type_sql << "(#{limit})"
27307 execute "ALTER TABLE #{quote_table_name(table_name)} #{fragments.join(', ')}"
27308 index_name = name&.to_s
27309 lengths: options[:length] || {},
27310 orders: options[:order] || {},
27311 opclasses: options[:opclass] || {},
27312 options.include?(:default) && !(options[:null] == false && options[:default].nil?)
27313 sql_fragments = []
27314 method = :"#{command}_for_alter"
27315 sqls, procs = Array(send(method, table, *arguments)).partition { |v| v.is_a?(String) }
27316 [:temporary, :if_not_exists, :options, :as, :comment, :charset, :collation]
27317 [:limit, :default, :precision]
27318 unless value == true || value == false
27319 [:limit, :precision, :scale, :default, :null, :collation, :comment]
27320 column << " #{orders[name].upcase}" if orders[name].present?
27321 Hash.new { |hash, column| hash[column] = options }
27322 column_names = []
27323 checks << lambda { |i| i.name == options[:name].to_s } if options.key?(:name)
27324 checks << lambda { |i| index_name(table_name, i.columns) == index_name(table_name, column_names) }
27325 matching_indexes = indexes(table_name).select { |i| checks.all? { |check| check[i] } }
27326 column_names = column_names.scan(/\w+/).join("_")
27327 column_name.is_a?(String) && /\W/.match?(column_name)
27328 table_name.to_s =~ /#{prefix}(.+)#{suffix}/ ? $1 : table_name.to_s
27329 identifier = "#{table_name}_#{options.fetch(:column)}_fk"
27330 identifier = "#{table_name}_#{expression}_chk"
27331 column_name.nil? && options.key?(:name) && options.except(:name, :algorithm).empty?
27332 sql << versions.reverse.map { |v| "(#{quote(v)})" }.join(",
")
27333 sql << ";"
27334 spec = {}
27335 attr_reader :table, :name, :unique, :columns, :lengths, :orders, :opclasses, :where, :type, :using, :include, :comment, :valid
27336 columns = [],
27337 opclasses: {},
27338 def defined_for?(columns = nil, name: nil, unique: nil, valid: nil, include: nil, **options)
27339 (columns.nil? || Array(self.columns) == Array(columns).map(&:to_s)) &&
27340 (name.nil? || self.name == name.to_s) &&
27341 (unique.nil? || self.unique == unique) &&
27342 (valid.nil? || self.valid == valid) &&
27343 (include.nil? || Array(self.include) == Array(include))
27344 :null,
27345 (self::OPTION_NAMES - [:primary_key]).each do |option_name|
27346 def #{option_name}=(value)
27347 options[:#{option_name}] = value
27348 (to_table.nil? || to_table.to_s == self.to_table) &&
27349 (validate.nil? || validate == self.options.fetch(:validate, validate)) &&
27350 options.all? { |k, v| self.options[k].to_s == v.to_s }
27351 self.name == name.to_s &&
27352 value.is_a?(Hash) ? value : {}
27353 result = [[column_name, type, options]]
27354 :float, :integer, :json, :string, :text, :time, :timestamp, :virtual
27355 def #{column_type}(*names, **options)
27356 names.each { |name| column(name, :#{column_type}, **options) }
27357 as: nil,
27358 @conn = conn
27359 @foreign_keys = []
27360 @check_constraints = []
27361 @as = as
27362 if id && !as
27363 if id.is_a?(Hash)
27364 id = id.fetch(:type, :primary_key)
27365 if pk.is_a?(Array)
27366 primary_key(pk, id, **options)
27367 def primary_keys(name = nil) # :nodoc:
27368 index_options = index.is_a?(Hash) ? index : {}
27369 options[:primary_key] ||= type == :primary_key
27370 to_table = "#{prefix}#{to_table}#{suffix}"
27371 options[:primary_key] && [:integer, :bigint].include?(type) && !options.key?(:default)
27372 @adds = []
27373 @foreign_key_adds = []
27374 @foreign_key_drops = []
27375 def name; @td.name; end
27376 @base = base
27377 key == :if_exists || key == :if_not_exists
27378 conditional = unrecognized_option == :if_exists ? "if" : "unless"
27379 message = <<~TXT
27380 m = @cache[o.class] ||= "visit_#{o.class.name.split('::').last}"
27381 send m, o
27382 to: :@conn, private: true
27383 sql << o.adds.map { |col| accept col }.join(" ")
27384 sql << o.foreign_key_adds.map { |fk| visit_AddForeignKey fk }.join(" ")
27385 sql << o.foreign_key_drops.map { |fk| visit_DropForeignKey fk }.join(" ")
27386 o.sql_type = type_to_sql(o.type, **o.options)
27387 column_sql = +"#{quote_column_name(o.name)} #{o.sql_type}"
27388 +"ADD #{accept(o.column)}"
27389 create_sql << "#{quote_table_name(o.name)} "
27390 statements = o.columns.map { |c| accept c }
27391 create_sql << "(#{statements.join(', ')})" if statements.present?
27392 create_sql << " AS #{to_sql(o.as)}" if o.as
27393 sql << " #{action_sql('DELETE', o.on_delete)}" if o.on_delete
27394 sql << " #{action_sql('UPDATE', o.on_update)}" if o.on_update
27395 sql << "#{quote_column_name(index.name)} ON #{quote_table_name(index.table)}"
27396 sql << "USING #{index.using}" if supports_index_using? && index.using
27397 sql << "(#{quoted_columns(index)})"
27398 create_sql << " #{o.options}" if o.options
27399 if options[:null] == false
27400 sql = sql.to_sql if sql.respond_to?(:to_sql)
27401 when Type::Time::Value then "'#{quoted_time(value)}'"
27402 when Date, Time then "'#{quoted_date(value)}'"
27403 Consider Arel.sql(".. ? ..", value) or #sanitize_sql instead.
27404 s.gsub("\\", '\&\&').gsub("'", "''") # ' (for ruby-mode)
27405 quote_table_name("#{table}.#{attr}")
27406 result = value.to_fs(:db)
27407 if value.respond_to?(:usec) && value.usec > 0
27408 result << "." << sprintf("%06d", value.usec)
27409 quoted_date(value).sub(/\A\d\d\d\d-\d\d-\d\d /, "")
27410 ((?:\w+\.)?\w+ | \w+\((?:|\g<2>)\))
27411 (?:(?:\s+AS)?\s+\w+)?
27412 Record.where("duration = ?", 1.hour.to_i)
27413 base.class_eval <<-end_code, __FILE__, __LINE__ + 1
27414 def #{method_name}(*)
27415 def select_all(arel, name = nil, binds = [], preparable: nil, async: false)
27416 if @query_cache_enabled && !(arel.respond_to?(:locked) && arel.locked)
27417 type_casted_binds: -> { type_casted_binds(binds) },
27418 def to_sql(arel_or_sql_string, binds = [])
27419 sql, _ = to_sql_and_binds(arel_or_sql_string, binds)
27420 def to_sql_and_binds(arel_or_sql_string, binds = [], preparable = nil) # :nodoc:
27421 if Arel.arel_node?(arel_or_sql_string) && !(String === arel_or_sql_string)
27422 def select_one(arel, name = nil, binds = [], async: false)
27423 def select_value(arel, name = nil, binds = [], async: false)
27424 def select_values(arel, name = nil, binds = [])
27425 def select_rows(arel, name = nil, binds = [], async: false)
27426 def query_value(sql, name = nil) # :nodoc:
27427 def query_values(sql, name = nil) # :nodoc:
27428 query(sql, name).map(&:first)
27429 def exec_query(sql, name = "SQL", binds = [], prepare: false)
27430 def exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil)
27431 sql, binds = sql_for_insert(sql, pk, binds)
27432 def exec_delete(sql, name = nil, binds = [])
27433 def exec_update(sql, name = nil, binds = [])
27434 def exec_insert_all(sql, name) # :nodoc:
27435 def explain(arel, binds = [], options = []) # :nodoc:
27436 def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [])
27437 def update(arel, name = nil, binds = [])
27438 def delete(arel, name = nil, binds = [])
27439 if limit.is_a?(Integer) || limit.is_a?(Arel::Nodes::SqlLiteral)
27440 if value.is_a?(Hash) || value.is_a?(Array)
27441 raise Fixture::FixtureError, %(table "#{table_name}" has no columns named #{unknown_columns.map(&:inspect).join(', ')}.)
27442 new_values = []
27443 new_values << values[i]
27444 total_sql.join(";
")
27445 def select(sql, name = nil, binds = [], prepare: false, async: false)
27446 [sql, binds]
27447 row && row.first
27448 @pools = {}
27449 @threads = {}
27450 @pools[frequency] ||= []
27451 @lock = lock
27452 @cond = @lock.new_cond
27453 @num_waiting = 0
27454 @queue = []
27455 @num_waiting > 0
27456 no_wait_poll || (timeout && wait_poll(timeout))
27457 @num_waiting += 1
27458 @num_waiting -= 1
27459 @num_waiting_on_real_cond -= 1
27460 @num_waiting_on_real_cond += 1
27461 def checkin(_); end
27462 def remove(_); end
27463 @connections = []
27464 conn.in_use? && !conn.owner.alive?
27465 !conn.in_use? && conn.seconds_idle >= minimum_idle
27466 flush(-1)
27467 busy: @connections.count { |c| c.in_use? && c.owner.alive? },
27468 dead: @connections.count { |c| c.in_use? && !c.owner.alive? },
27469 idle: @connections.count { |c| !c.in_use? },
27470 newly_checked_out = []
27471 thread_report = []
27472 thread_report << "#{conn} is owned by #{conn.owner}"
27473 msg << " (#{thread_report.join(', ')})" if thread_report.any?
27474 @now_connecting += 1
27475 @now_connecting -= 1
27476 elsif role == :all
27477 role = nil if role == :all
27478 message = "No connection pool for '#{connection_name}' found for the '#{role}' role."
27479 roles = []
27480 if owner_name.is_a?(String) || owner_name.is_a?(Symbol)
27481 if Gem::Version.new(Psych::VERSION) >= Gem::Version.new("5.1")
27482 unsafe_load = coder["unsafe_load"] || false
27483 @coder ||= begin
27484 @attr_name = coder["attr_name"]
27485 @coder = coder["coder"]
27486 if @object_class != ::Object
27487 def increment!(attribute, by = 1, touch: nil) # :nodoc:
27488 touch ? _run_touch_callbacks { super } : super
27489 [ :autosave ]
27490 result = true; @_already_called ||= {}
27491 if autosave != false && (new_record_before_save || record.new_record?)
27492 :id
27493 prev_cast_type = -> subtype { subtype }
27494 -> subtype { yield Proc === prev_cast_type ? prev_cast_type[subtype] : prev_cast_type }
27495 name = @primary_key if name == "id" && @primary_key
27496 map(value) do |v|
27497 def serialize(attr_name, class_name_or_coder = nil, coder: nil, type: Object, yaml: {}, **options)
27498 if class_name_or_coder == ::JSON || [:load, :dump].all? { |x| class_name_or_coder.respond_to?(x) }
27499 Coders::YAMLColumn.new(attr_name, type, **(yaml || {}))
27500 elsif coder.respond_to?(:new) && !coder.respond_to?(:load)
27501 elsif type && type != Object
27502 cast_type.is_a?(ActiveRecord::Type::Json) && coder == ::JSON ||
27503 cast_type.respond_to?(:type_cast_array, true) && type == ::Array
27504 name = @primary_key if name == "id" && @primary_key && !@primary_key.is_a?(Array)
27505 if Numeric === value || !value.match?(/[^0-9]/)
27506 key = id
27507 [key] if key
27508 @primary_key.map { |pk| _read_attribute(pk) }
27509 attr_name == "id" || super
27510 value.map { |v| -v.to_s }.freeze
27511 def reload(*)
27512 changes = {}
27513 ).map { |m| -m.to_s }.to_set.freeze
27514 super || (table_exists? && column_names.include?(attribute.to_s.delete_suffix("=")))
27515 def _has_attribute?(attr_name) # :nodoc:
27516 !value.nil? && !(value.respond_to?(:empty?) && value.empty?)
27517 def [](attr_name)
27518 def []=(attr_name, value)
27519 (pk_attribute?(name) && id.nil?) ||
27520 elsif value.is_a?(Date) || value.is_a?(Time)
27521 %("#{value.to_fs(:inspect)}")
27522 name == @primary_key
27523 key = k.to_s
27524 if key.include?("(")
27525 (multi_parameter_attributes ||= {})[key] = v
27526 elsif v.is_a?(Hash)
27527 (nested_parameter_attributes ||= {})[key] = v
27528 pairs.each { |k, v| _assign_attribute(k, v) }
27529 send("#{name}=", values)
27530 attributes[attribute_name] ||= {}
27531 multiparameter_name =~ /\([0-9]*([if])\)/ ? value.send("to_" + $1) : value
27532 multiparameter_name.scan(/\(([0-9]*).*\)/).first.first.to_i
27533 if inverse && target && !target.is_a?(Array)
27534 if !loaded? || stale_target?
27535 map(&:klass)
27536 owners.all? { |owner| loaded?(owner) } ||
27537 through_preloaders.all?(&:run?) && source_preloaders.all?(&:run?)
27538 root? || (@loaders && @loaders.all?(&:run?))
27539 (h[reflection] ||= []) << record
27540 @loaders ||=
27541 @keys_to_load = Set.new
27542 keys_to_load << key
27543 loaders.each { |l| l.set_inverse(record) }
27544 @run = false
27545 [@klass]
27546 @run = true
27547 @owners_by_key ||= owners.each_with_object({}) do |owner, result|
27548 (result[key] ||= []) << owner if key
27549 @scope ||= build_scope
27550 entries = (@records_by_owner[owner] ||= [])
27551 if i == 0 # Set inverse on first owner
27552 if key.is_a?(Array)
27553 key.map { |k| convert_key(owner[k]) }
27554 @tree = Branch.new(
27555 joins = []
27556 chain = []
27557 @table ||= table
27558 if nodes.is_a?(Arel::Nodes::And)
27559 @alias_cache = tables.each_with_object({}) { |table, h|
27560 h[table.node] = table.columns.each_with_object({}) { |column, i|
27561 @columns_cache = tables.each_with_object({}) { |table, h|
27562 Table = Struct.new(:node, :columns) do # :nodoc:
27563 hash[associations.to_sym] ||= {}
27564 cache = hash[k] ||= {}
27565 @joined_tables = {}
27566 @references = {}
27567 seen = Hash.new { |i, parent|
27568 i[parent] = Hash.new { |j, child_class|
27569 j[child_class] = {}
27570 model_cache = Hash.new { |h, klass| h[klass] = {} }
27571 column_names << name unless /\At\d+_r\d+\z/.match?(name)
27572 column_types = {}
27573 column_types = column_types.slice(*column_names).delete_if { |k, _| attribute_types.key?(k) }
27574 relation._select!(-> { aliases.columns })
27575 column_names = if join_part == join_root && !join_root_alias
27576 primary_key ? [primary_key] : []
27577 Aliases::Column.new column_name, "t#{i}_r#{j}"
27578 if table && (!root || !terminated)
27579 root ? name : "#{name}_join"
27580 }.partition(&:first)
27581 joins = intersection.flat_map { |l, r| r.table = l.table; walk(l, r, join_type) }
27582 id = row[key]
27583 if row[key].nil?
27584 seen[ar_parent][node][id] = model if id
27585 if save && !record.save
27586 except_keys = [
27587 a - b
27588 a & b
27589 def build(attributes = {}, &block)
27590 def create(attributes = {}, &block)
27591 def create!(attributes = {}, &block)
27592 def <<(*records)
27593 alias_method :push, :<<
27594 alias_method :append, :<<
27595 alias_method :concat, :<<
27596 def prepend(*args) # :nodoc:
27597 @scope = nil
27598 ].flat_map { |klass|
27599 } - self.public_instance_methods(false) - [:select] + [
27600 :scoping, :values, :insert, :insert_all, :insert!, :insert_all!, :upsert, :upsert_all, :load_async
27601 ids.map! { |i| pk_type.cast(i) }
27602 @target = []
27603 if !find_target? || loaded?
27604 loaded? ||
27605 owner.new_record? ||
27606 target.any? { |record| record.new_record? || record.changed? }
27607 @_was_loaded = loaded?
27608 @_was_loaded = true
27609 elsif @_was_loaded || !loaded?
27610 @_was_loaded = nil
27611 } || target.include?(record)
27612 if ids.size == 1
27613 record = load_target.detect { |r| id == r.id.to_s }
27614 expects_array ? [ record ] : record
27615 load_target.select { |r| ids.include?(r.id.to_s) }
27616 super + [:required, :touch]
27617 def build_#{name}(*args, &block)
27618 association(:#{name}).build(*args, &block)
27619 def create_#{name}(*args, &block)
27620 association(:#{name}).create(*args, &block)
27621 def create_#{name}!(*args, &block)
27622 association(:#{name}).create!(*args, &block)
27623 valid += [:as, :foreign_type] if options[:as]
27624 valid += [:through, :source, :source_type] if options[:through]
27625 touch != true ?
27626 callback = -> (record) { HasOne.touch_record(record, name, touch) }
27627 valid = super + [:counter_cache, :join_table, :index_errors]
27628 join_model.table_name_resolver = -> { table_name }
27629 association_name.to_s].sort.join("_").gsub("::", "_").to_sym
27630 middle_options = {}
27631 middle_options[:class_name] = "#{lhs_model.name}::#{join_model.name}"
27632 [lhs_model.table_name, klass.table_name].sort.join("\0").gsub(/^(.*[._])(.+)\0\1(.+)/, '\1\2_\3').tr("\0", "_")
27633 rhs_options = {}
27634 super + [:before_add, :after_add, :before_remove, :after_remove, :extend]
27635 full_callback_name = "#{callback_name}_for_#{name}"
27636 ->(method, owner, record) { owner.send(callback, record) }
27637 ->(method, owner, record) { callback.call(owner, record) }
27638 ->(method, owner, record) { callback.send(method, owner, record) }
27639 if touch != true
27640 }}
27641 model.generated_association_methods.class_eval <<-CODE, __FILE__, __LINE__ + 1
27642 self.extensions = []
27643 if scope && scope.arity == 0
27644 proc { instance_exec(&scope) }
27645 @_after_commit_jobs ||= []
27646 !loaded? && foreign_key_present? && klass
27647 target_key_values = record ? Array(primary_key(record.class)).map { |key| record._read_attribute(key) } : []
27648 if force || reflection_fk.map { |fk| owner._read_attribute(fk) } != target_key_values
27649 block ||= lambda { |val| val }
27650 scope.where!(key => value)
27651 scope.where!(table.name => { key => value })
27652 @target = nil
27653 loaded? && @stale_state != stale_state
27654 @target = find_target if (@stale_state && stale_target?) || find_target?
27655 !loaded? && (!owner.new_record? || foreign_key_present?) && klass
27656 record &&
27657 ((!record.persisted? || !owner.persisted?) || matches_foreign_key?(record))
27658 aliases ||= Hash.new(0)
27659 default_proc = aliases.default_proc || proc { 0 }
27660 aliases.default_proc = proc { |h, k|
27661 h[k] = initial_count_for(connection, k, joins) + default_proc.call(h, k)
27662 aliases = Hash.new { |h, k|
27663 /JOIN(?:\s+\w+)?\s+(?:\S+\s+)?(?:#{quoted_name}|#{name})\sON/i
27664 ).size
27665 join.left.name == name ? 1 : 0
27666 aliased_name = "#{truncate(aliased_name)}_#{count}" if count > 1
27667 @association_cache = {}
27668 def has_one(name, scope = nil, **options)
27669 hm_options = {}
27670 scoping { klass.#{method}(attributes, **kwargs) }
27671 @aggregation_cache = {}
27672 def composed_of(part_id, options = {})
27673 if @aggregation_cache[name].nil? && (!allow_nil || mapping.any? { |key, _| !read_attribute(key).nil? })
27674 attrs = mapping.collect { |key, _| read_attribute(key) }
27675 define_method("#{name}=") do |part|
27676 unless part.is_a?(klass) || converter.nil? || part.nil?
27677 part = klass.new(*part.sort.map(&:last))
27678 if part.nil? && allow_nil
27679 mapping.each { |key, _| write_attribute(key, nil) }
27680 ->(warning) do
27681 warning_message += " (#{warning.code})" if warning.code
27682 ->(warning) { raise warning }
27683 self.queues = {}
27684 bob = Person.create!(name: "bob")
27685 conn = { adapter: "sqlite3", database: ":memory:" }
27686 def progress_bar(int); print "." if (int % 100).zero? ; end
27687 LOREM.grep(/^\w*$/).sort_by { rand }.first(2).join " "
27688 LOREM.grep(/^\w*$/).sort_by { rand }.first(2).join("@") + ".com"
27689 puts "Done!
"
27690 attrs_second = { name: "tom" }
27691 x.report("Model#id") do
27692 Exhibit.find_by_sql("SELECT * FROM exhibits WHERE id = #{(rand * 1000 + 1).to_i}").first
27693 Exhibit.connection.send(:log, "hello", "world") { }
27694 ActiveRecord::Base.connection.execute("SELECT * FROM exhibits WHERE id = #{(rand * 1000 + 1).to_i}")
27695 unless /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i.match?(value)
27696 super | [ :message ]
27697 public_send "#{key}=", value
27698 instance_variable_get(:"@#{attr}")
27699 errors.add(:title, "is Empty") unless title && title.size > 0
27700 if title && content && content == "Mismatch"
27701 errors.add(:title, "is Wrong Create") if title && title == "Wrong Create"
27702 errors.add(:title, "is Wrong Update") if title && title == "Wrong Update"
27703 @with = options[:with]
27704 @data[key] = value
27705 { git: :github }
27706 options.each { |name, value| public_send("#{name}=", value) }
27707 instance_variable_set("@#{k}", v)
27708 r = Reply.new
27709 r.title = "There's no content!"
27710 r.content = ""
27711 errors = r.errors.to_a.inject([]) { |result, error| result + [error] }
27712 hits = 0
27713 hits += 1
27714 t = Topic.new("title" => "valid", "content" => "whatever")
27715 t = CustomReader.new("title" => "valid", "content" => "whatever")
27716 t = Topic.new("title" => "Title", "content" => "whatever")
27717 Topic.validate(if: opts, on: :create) { }
27718 @call_sequence = []
27719 @call_sequence << :a
27720 @call_sequence << :b
27721 @call_sequence << :c
27722 klass.validate :validator_a, if: -> { true }
27723 klass.validate :validator_c, unless: -> { true }
27724 assert_equal [:b, :a], t.call_sequence
27725 t = Topic.new("title" => "")
27726 t = Topic.new title: ""
27727 Topic.validates_presence_of :title, if: Proc.new { |x| x.author_name = "bad"; true }, on: :update
27728 t = Topic.new(title: "")
27729 assert t.author_name == "bad"
27730 ], validators.map(&:class).sort_by(&:to_s)
27731 t = Topic.new(title: "Valid title")
27732 options = { presence: true }
27733 if options[:field] == :first_name
27734 raise "boom!"
27735 validator.expect(:new, validator, [{ foo: :bar, if: :condition_is_true, class: Topic }])
27736 topic = Topic.new content: ""
27737 topic = Topic.new title: "foo"
27738 Person.validates :title, presence: { message: "" }
27739 person.gender = "m"
27740 p.karma = "Cold"
27741 p[:karma] = "Cold"
27742 t = Topic.new(title: "something")
27743 t.title = ""
27744 t.title = nil
27745 BLANK = ["", " ", " \t \r
"]
27746 FLOAT_STRINGS = %w(0.0 +0.0 -0.0 10.0 10.5 -10.5 -0.0001 -090.1 90.1e1 -90.1e5 -90.1e-5 90e-5)
27747 assert_invalid_values([-97.18, BigDecimal("97.18"), BigDecimal("-97.18")], "must be greater than 97.18")
27748 assert_valid_values([97.19, 98, BigDecimal("98"), BigDecimal("97.19")])
27749 assert_invalid_values(["-10", "9", "9.9", "10"], "must be greater than 10")
27750 assert_valid_values(["10.1", "11"])
27751 assert_invalid_values([-97.18, 97.17, 97, BigDecimal("97.17"), BigDecimal("-97.18")], "must be greater than or equal to 97.18")
27752 assert_valid_values([97.18, 98, BigDecimal("97.19")])
27753 assert_invalid_values(["-10", "9", "9.9"], "must be greater than or equal to 10")
27754 assert_valid_values(["10", "10.1", "11"])
27755 assert_invalid_values([-10, 11] + INFINITY, "must be equal to 10")
27756 assert_invalid_values(["-10", "9", "9.9", "10.1", "11"], "must be equal to 10")
27757 assert_valid_values([-9, 9])
27758 assert_valid_values([-97.0, 97.0, -97, 97, BigDecimal("-97"), BigDecimal("97")])
27759 assert_invalid_values(["10", "10.1", "11"], "must be less than 10")
27760 assert_valid_values(["-10", "9", "9.9"])
27761 assert_valid_values([-10, 10])
27762 assert_valid_values([-97.18, BigDecimal("-97.18"), BigDecimal("97.18")])
27763 assert_invalid_values(["10.1", "11"], "must be less than or equal to 10")
27764 assert_valid_values(["-10", "9", "9.9", "10"])
27765 assert_invalid_values([-2, 2], "must be odd")
27766 assert_valid_values([-1, 1])
27767 assert_invalid_values([-1, 1], "must be even")
27768 assert_valid_values([-2, 2])
27769 assert_invalid_values([1, 3, 4])
27770 assert_valid_values([-1, 42])
27771 assert_valid_values([1, 2, 3])
27772 assert_invalid_values(["0", "0.0"])
27773 assert_valid_values(["-1", "1.1", "42"])
27774 topic = Topic.new("title" => "numeric test", "approved" => 10)
27775 topic = Topic.new("title" => "numeric test", "approved" => 1)
27776 p.karma = "Pix"
27777 assert_equal ["is not a number"], p.errors[:karma]
27778 p.karma = "1234"
27779 topic.approved = (base + 1).to_s
27780 assert_invalid_values([Float("65.5"), BigDecimal("65.7")], "must be equal to 65.6")
27781 assert_valid_values([Float("65.6"), BigDecimal("65.6")])
27782 assert_predicate Topic.new("title" => "ab"), :invalid?
27783 assert_predicate Topic.new("title" => ""), :invalid?
27784 assert_predicate Topic.new("title" => "abcde"), :valid?
27785 assert_predicate Topic.new("title" => ""), :valid?
27786 t.title = "not"
27787 t.title = "notvalid"
27788 t = Topic.new("title" => "a!", "content" => "I'm ooooooooh so very long")
27789 t.title = "abe"
27790 t.content = "mad"
27791 t = Topic.new("title" => "9 chars!!")
27792 t.title = "Now I'm 10"
27793 t.title = "Four"
27794 [10.., 9],
27795 [..10, 11],
27796 [...11, 11],
27797 t = Topic.new("title" => "a" * 10)
27798 t.title = "a" * invalid_length
27799 t = Topic.new("title" => "abc", "content" => "abcd")
27800 bigmin = 2**30
27801 bigmax = 2**32
27802 t = Topic.new("title" => "uhoh", "content" => "whatever")
27803 assert_equal ["boo 5"], t.errors[:title]
27804 assert_equal ["hoo 5"], t.errors[:title]
27805 t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
27806 Topic.validates_length_of(:title, in: 10..20, message: "hoo %{count}")
27807 assert_equal ["hoo 10"], t.errors["title"]
27808 assert_equal ["hoo 20"], t.errors["title"]
27809 assert_equal ["hoo 5"], t.errors["title"]
27810 t = Topic.new(title: "a")
27811 assert_equal ["too short"], t.errors["title"]
27812 t = Topic.new(title: "aaaaaa")
27813 assert_equal ["too long"], t.errors["title"]
27814 Topic.validates_length_of(:title, is: 5, message: "boo %{count}")
27815 assert_equal ["boo 5"], t.errors["title"]
27816 Topic.validates_length_of(:title, is: 5, wrong_length: "hoo %{count}")
27817 t = Topic.new("title" => "uhohuhoh", "content" => "whatever", approved: 1)
27818 t = Topic.new("title" => "uhohuhoh", "content" => "whatever", approved: 1234)
27819 p.karma = "The Smiths"
27820 t = Topic.new("title" => "1234")
27821 t.title = "12345"
27822 Topic.validates_length_of(:title, is: 5, if: Proc.new { false })
27823 assert_predicate Topic.new("title" => "david"), :valid?
27824 Topic.validates_length_of :title, maximum: ->(model) { 5 }
27825 Topic.validates_length_of :title, maximum: -> { 5 }
27826 assert_predicate Topic.new("title" => "bbc", "content" => "abc"), :invalid?
27827 assert_predicate Topic.new("title" => "aa", "content" => "abc"), :invalid?
27828 assert_predicate Topic.new("title" => "aaab", "content" => "abc"), :invalid?
27829 assert_predicate Topic.new("title" => "aaa", "content" => "abc"), :valid?
27830 assert_predicate Topic.new("title" => "abc", "content" => "abc"), :valid?
27831 assert_predicate Topic.new("title" => "bbb", "content" => "abc"), :valid?
27832 Topic.validates_inclusion_of(:title, in: %w( a b c d e f g ))
27833 assert_predicate Topic.new("title" => "a!", "content" => "abc"), :invalid?
27834 assert_predicate Topic.new("title" => "a b", "content" => "abc"), :invalid?
27835 assert_predicate Topic.new("title" => nil, "content" => "def"), :invalid?
27836 t = Topic.new("title" => "a", "content" => "I know you are but what am I?")
27837 t.title = "uhoh"
27838 Topic.validates_inclusion_of(:title, in: %w( a b c d e f g ), allow_nil: true)
27839 Topic.validates_inclusion_of(:title, in: %w( a b c d e f g ), message: "option %{value} is not in the list")
27840 assert_predicate Topic.new("title" => "a", "content" => "abc"), :valid?
27841 t = Topic.new("title" => "uhoh", "content" => "abc")
27842 Topic.validates_inclusion_of(:title, within: %w( a b c d e f g ))
27843 p.karma = "Lifo"
27844 p.karma = "monkey"
27845 Topic.validates_inclusion_of :title, in: lambda { |topic| topic.author_name == "sikachu" ? %w( monkey elephant ) : %w( abe wasabi ) }
27846 t.title = "wasabi"
27847 t.title = "elephant"
27848 %w()
27849 %w(Lifo)
27850 p.karma = %w(Lifo monkey)
27851 p.karma = %w(abe monkey)
27852 @person.errors.add("name", "empty")
27853 errors: { models: { person: { attributes: { name: { format: "%{message}" } } } } } })
27854 errors: { models: { person: { attributes: { gender: "Gender" } } } },
27855 attributes: { "person/contacts": { gender: "Gender" } }
27856 errors: { models: { person: { format: "%{message}" } } } })
27857 errors: { models: { 'person/contacts/addresses': { attributes: { street: { format: "%{message}" } } } } } })
27858 errors: { models: { 'person/contacts/addresses': { format: "%{message}" } } } })
27859 attributes: { 'person/contacts[0]/addresses[0]': { country: "Country" } }
27860 @person.title = "72x"
27861 @person.title = "z"
27862 @person.title = "a"
27863 call = [:title, :not_a_number, @person, generate_message_options.merge(value: "a")]
27864 @person.title = "0.0"
27865 I18n.backend.store_translations "en", activemodel: { errors: { models: { person: { attributes: { attribute => { error_type => "custom message" } } } } } }
27866 yield(@person, {})
27867 I18n.backend.store_translations "en", activemodel: { errors: { models: { person: { attributes: { attribute => { error_type => "custom message with %{extra}" } } } } } }
27868 yield(@person, { extra: "extra information" })
27869 person.title = "a"
27870 person.title = "1.0"
27871 I18n.backend.store_translations "en", activemodel: { errors: { models: { person: { attributes: { title: { custom_error: "I am a custom error" } } } } } }
27872 I18n.backend.store_translations "en", activemodel: { errors: { models: { person: { custom_error: "I am a custom error" } } } }
27873 t = Topic.new("title" => "i'm incorrect", "content" => "Validation macros rule!")
27874 assert_equal ["is bad data"], t.errors[:title]
27875 Topic.validates_format_of(:title, :content, with: /\A[1-9][0-9]*\z/, message: "is bad data")
27876 t = Topic.new("title" => "72x", "content" => "6789")
27877 t.title = "-11"
27878 t.title = "03"
27879 t.title = "z44"
27880 t.title = "5v7"
27881 t.title = "1"
27882 Topic.validates_format_of(:title, with: /\AValid Title\z/, message: "can't be %{value}")
27883 t.title = "foobar"
27884 assert_equal [], t.errors[:title]
27885 Topic.validates_format_of :content, with: lambda { |topic| topic.title == "digit" ? /\A\d+\z/ : /\A\S+\z/ }
27886 t.title = "digit"
27887 t.content = "Pixies"
27888 t.content = "1234"
27889 Topic.validates_format_of :title, with: lambda { /\A[A-Z]/ }
27890 Topic.validates_format_of :content, without: lambda { |topic| topic.title == "characters" ? /\A\d+\z/ : /\A\S+\z/ }
27891 Person.validates_format_of :karma, with: /\A\d+\z/
27892 p.karma = "Pixies"
27893 assert_predicate Topic.new("title" => "something", "content" => "abc"), :valid?
27894 assert_predicate Topic.new("title" => "monkey", "content" => "abc"), :invalid?
27895 assert Topic.new("title" => "something", "content" => "abc")
27896 t = Topic.new("title" => "monkey")
27897 p.karma = "abe"
27898 Topic.validates_exclusion_of :title, in: lambda { |topic| topic.author_name == "sikachu" ? %w( monkey elephant ) : %w( abe wasabi ) }
27899 t.title = "monkey"
27900 Topic.validates_exclusion_of :content, in: ("a".."g")
27901 %w(abe)
27902 t = Topic.new("title" => "We should be confirmed", "title_confirmation" => "")
27903 p.karma = "None"
27904 activemodel: { attributes: { topic: { title: "Test Title" } } })
27905 if: Proc.new { |r| r.content.size > 4 })
27906 unless: Proc.new { |r| r.content.size > 4 })
27907 if: Proc.new { |r| r.title != "uhohuhoh" })
27908 unless: Proc.new { |r| r.title != "uhohuhoh" })
27909 Date.parse("2019-08-03"),
27910 Date.parse("2020-07-03"),
27911 Date.parse("2020-08-01"),
27912 Date.parse("2020-08-02"),
27913 DateTime.new(2020, 8, 1, 12, 34)], "must be greater than 2020-08-02")
27914 assert_valid_values([Date.parse("2020-08-03"), DateTime.new(2020, 8, 2, 12, 34)])
27915 assert_invalid_values(["ant", "cat"], "must be greater than cat")
27916 assert_valid_values(["dog", "whale"])
27917 DateTime.new(2020, 8, 1, 12, 34)], "must be greater than or equal to 2020-08-02")
27918 assert_valid_values([Date.parse("2020-08-03"), DateTime.new(2020, 8, 2, 12, 34), Date.parse("2020-08-02")])
27919 assert_valid_values(["cat", "dog", "whale"])
27920 assert_invalid_values([-12, 5, 11], "must be equal to 10")
27921 DateTime.new(2020, 8, 1, 12, 34),
27922 Date.parse("2020-08-03"),
27923 DateTime.new(2020, 8, 2, 12, 34)], "must be equal to 2020-08-02")
27924 assert_valid_values([Date.parse("2020-08-02"), DateTime.new(2020, 8, 2, 0, 0)])
27925 Time.at(1596285230)], "must be equal to #{time_value}")
27926 assert_invalid_values(["dog", "whale"], "must be equal to cat")
27927 assert_valid_values([-12, -5, 5])
27928 DateTime.new(2020, 8, 2, 12, 34)], "must be less than 2020-08-02")
27929 DateTime.new(2020, 8, 1, 12, 34)])
27930 Time.at(1596393000)], "must be less than #{time_value}")
27931 assert_valid_values(["ant", "cat"])
27932 assert_valid_values([-11, 5, 10])
27933 DateTime.new(2020, 8, 2, 12, 34)], "must be less than or equal to 2020-08-02")
27934 assert_valid_values(["ant", "cat", "dog"])
27935 assert_valid_values([-12, 5, 11])
27936 assert_invalid_values([Date.parse("2020-08-02"), DateTime.new(2020, 8, 2, 0, 0)], "must be other than 2020-08-02")
27937 DateTime.new(2020, 8, 2, 12, 34)])
27938 Topic.define_method(:requested) { Date.new(2020, 8, 1) }
27939 assert_invalid_values([Date.new(2020, 7, 1), Date.new(2019, 7, 1), DateTime.new(2020, 7, 1, 22, 34)], "must be greater than or equal to 2020-08-01")
27940 assert_valid_values([Date.new(2020, 8, 2), DateTime.new(2021, 8, 1)])
27941 custom = Struct.new(:amount) {
27942 amount % 100 <=> other.amount % 100
27943 assert_valid_values([nil, ""])
27944 d.valid?(:save)
27945 d.valid?(:context_a)
27946 d.valid?(:context_b)
27947 d.valid?([:context_a, :context_b])
27948 ], d.history)
27949 before_validation(if: opts, on: :create) { }
27950 after_validation(if: opts, on: :create) { }
27951 t = klass.new("title" => "We should not be confirmed")
27952 t = klass.new("title" => "We should be confirmed", "terms_of_service" => "")
27953 t.terms_of_service = "1"
27954 t = klass.new("title" => "We should be confirmed", "eula" => "")
27955 t.eula = "1"
27956 t.terms_of_service = "I agree."
27957 t.terms_of_service = "I concur."
27958 p = klass.new
27959 p.karma = ""
27960 p.karma = "1"
27961 t.title = "foo"
27962 t.content = "bar"
27963 t.content = ""
27964 p.karma = "good"
27965 p.karma = nil
27966 p[:karma] = "excellent"
27967 p[:karma] = ""
27968 assert_equal type.new({}), ActiveModel::Type.lookup(:foo, {})
27969 assert_nil type.cast(" " * 129)
27970 time_string = ::Time.now.utc.strftime("%T")
27971 ::Time.use_zone("Pacific Time (US & Canada)") do
27972 assert_nil type.user_input_in_time_zone(" " * 129)
27973 object, array, hash = Object.new, [true], { a: :b }
27974 s = +"foo"
27975 f = -"foo"
27976 s = "foo"
27977 mod = Module.new { def serialize(value); super; end }
27978 assert_equal [:a, :a], registry.lookup(:bar, 2, :a) # Array.new(2, :a)
27979 assert_equal [{}, {}], registry.lookup(:bar, 2, {}) # Array.new(2, {})
27980 [type, args, "block for foo"]
27981 [type, args, "block for bar"]
27982 [type, kwargs, "block for baz"]
27983 assert_equal [:foo, [1], "block for foo"], registry.lookup(:foo, 1)
27984 assert_equal [:foo, [2], "block for foo"], registry.lookup(:foo, 2)
27985 assert_equal [:bar, [1, 2, 3], "block for bar"], registry.lookup(:bar, 1, 2, 3)
27986 assert_equal [:baz, { kw: 1 }, "block for baz"], registry.lookup(:baz, kw: 1)
27987 assert_equal 1, type.cast("1")
27988 assert_nil type.cast([1, 2])
27989 assert_nil type.cast(1 => 2)
27990 assert_nil type.cast(1.0 / 0.0)
27991 assert_equal(-5, type.serialize(" -5"))
27992 assert type.changed?(0, 0, "wibble")
27993 assert type.changed?(5, 0, "wibble")
27994 assert_not type.changed?(5, 5, "5")
27995 assert_not type.changed?(5, 5, "5.0")
27996 assert_not type.changed?(5, 5, "+5")
27997 assert_not type.changed?(5, 5, "+5.0")
27998 assert_not type.changed?(-5, -5, "-5")
27999 assert_not type.changed?(-5, -5, "-5.0")
28000 assert_equal 1.0, type.cast("1")
28001 assert type.changed?(0.0, 0, "wibble")
28002 assert type.changed?(5.0, 0, "wibble")
28003 assert_not type.changed?(5.0, 5.0, "5wibble")
28004 assert_not type.changed?(5.0, 5.0, "5")
28005 assert_not type.changed?(5.0, 5.0, "5.0")
28006 assert_not type.changed?(500.0, 500.0, "0.5E+4")
28007 assert_not type.changed?(0.0 / 0.0, 0.0 / 0.0, 0.0 / 0.0)
28008 assert type.changed?(0.0 / 0.0, BigDecimal("0.0") / 0, BigDecimal("0.0") / 0)
28009 assert_equal BigDecimal("1"), type.cast(:"1")
28010 type = Decimal.new(precision: ::Float::DIG + 2)
28011 assert_not type.changed?(5.0, 5.0, "5.0wibble")
28012 assert_not type.changed?(-5.0, -5.0, "-5.0")
28013 assert_not type.changed?(5.0, 5.0, "0.5e+1")
28014 assert_not type.changed?(BigDecimal("0.0") / 0, BigDecimal("0.0") / 0, BigDecimal("0.0") / 0)
28015 assert type.changed?(BigDecimal("0.0") / 0, 0.0 / 0.0, 0.0 / 0.0)
28016 datetime_string = ::Time.now.utc.strftime("%FT%T")
28017 ["UTC", "US/Eastern"].each do |zone|
28018 assert_equal ::Time.utc(2013, 9, 4, 0, 0, 0), type.cast("Wed, 04 Sep 2013 03:00:00 EAT")
28019 assert_equal ::Time.utc(2018, 10, 15, 0, 0, 0), type.cast(1 => 2018, 2 => 10, 3 => 15)
28020 assert_nil type.cast(" ")
28021 now = ::Time.now.utc
28022 values_hash = { 1 => now.year, 2 => now.mon, 3 => now.mday }
28023 date_string = now.strftime("%F")
28024 time = ::Time.utc(1, 1, 1)
28025 date = ::Date.new(time.year, time.mon, time.mday)
28026 values_hash_for_multiparameter_assignment = { 1 => 1, 2 => 1, 3 => 1 }
28027 assert type.cast(" ")
28028 assert type.cast("\u3000\r
")
28029 assert type.cast(:"1")
28030 assert_equal "1", type.cast("1")
28031 person: { gender: "person gender" },
28032 options = { default: "person model" }
28033 options = { default: "Cool gender" }
28034 @contact.created_at = Time.utc(2006, 8, 1)
28035 @contact.preferences = { "shows" => "anime" }
28036 assert_no_match %r{^\{"contact":\{}, json
28037 assert_match %r{^\{"json_contact":\{}, json
28038 options = { except: :name }
28039 json = @contact.to_json(root: :true)
28040 assert_no_match %r{"awesome":}, json
28041 def @contact.as_json(options = {}); super(options.merge(only: [:name])); end
28042 @name, @email, @gender = name, email, gender
28043 @friends = []
28044 if method_name == :bar
28045 @user = User.new("David", "david@example.com", "male")
28046 @user.address.state = "CA"
28047 @user.friends = [User.new("Joe", "joe@example.com", "male"),
28048 User.new("Sue", "sue@example.com", "female")]
28049 expected = { "name" => "David", "gender" => "male", "email" => "david@example.com" }
28050 expected = { "name" => "David" }
28051 expected = { "gender" => "male", "email" => "david@example.com" }
28052 expected = { "foo" => "i_am_foo", "bar" => "i_am_bar" }
28053 expected = { "gender" => "male", "foo" => "i_am_foo", "bar" => "i_am_bar" }
28054 expected = { "name" => "Jon" }
28055 expected = { "name" => "David", "gender" => "male", "email" => "david@example.com",
28056 expected = { "email" => "david@example.com", "gender" => "male", "name" => "David",
28057 { "name" => "Sue", "email" => "sue@example.com", "gender" => "female" }] }
28058 @user.friends = []
28059 expected = { "email" => "david@example.com", "gender" => "male", "name" => "David", "friends" => [] }
28060 { "name" => "Sue", "email" => "sue@example.com", "gender" => "female", "friends" => [] }] }
28061 expected = { "name" => "David", "friends" => [{ "name" => "Joe" }, { "name" => "Sue" }] }
28062 expected = { "name" => "David", "email" => "david@example.com",
28063 { "name" => "Sue", "email" => "sue@example.com" }] }
28064 assert_equal expected, @user.serializable_hash(include: [{ address: { only: "street" } }, :friends])
28065 assert_equal expected, @user.serializable_hash(include: [address: { only: "street" }, friends: { only: "name" }])
28066 @user.password = "a" * 72
28067 @user.password = " " * 72
28068 @user.password = ""
28069 @user.password = "a" * 73
28070 @existing_user.password = "a" * 72
28071 @existing_user.password = "a" * 73
28072 @user.password_digest = " "
28073 @app ||= Class.new(::Rails::Application) do
28074 @model_name = ActiveModel::Name.new(Blog::Post, nil, "Uzivatel", :cs)
28075 @record = @klass.new
28076 @plural = "contacts"
28077 @route_key = "contacts"
28078 @param_key = "contact"
28079 @attr ||= "default value"
28080 params = ProtectedParams.new("a" => "b")
28081 params = ProtectedParams.new("a" => "b").permit!
28082 assert_equal({ "a" => "b" }, Account.new.sanitize_for_mass_assignment(params))
28083 assert_equal({ a: "b" }, Account.new.sanitize_for_mass_assignment(a: "b"))
28084 errors.add(:name, :blank, message: "cannot be nil") if name == nil
28085 errors.add(:foo, "omg")
28086 assert errors.any? { |_| true }, "any? should return true"
28087 errors.add(:name, "omg")
28088 assert_equal ["omg"], errors["name"]
28089 errors.add(:baz, "zomg")
28090 errors.add(:foo, "zomg")
28091 msg = "custom msg"
28092 type = Proc.new { msg }
28093 type = Proc.new { :blank }
28094 person.errors.add(:name, :too_long, if: -> { true })
28095 person.errors.add(:name, :too_long, message: proc { "foo" })
28096 message = Proc.new { "cannot be blank" }
28097 I18n.backend.store_translations("en", errors: { attributes: { name: { wrong: "is wrong", used: "is wrong" } } })
28098 assert_equal({ name: ["cannot be blank"] }, person.errors.to_hash)
28099 @errors.add(:name, "bar")
28100 assert_equal({ name: ["cannot be nil"] }, person.errors.as_json)
28101 assert_equal({ name: [{ error: :invalid }] }, person.errors.details)
28102 assert_equal({ name: [{ error: :greater_than, count: 5 }] }, person.errors.details)
28103 errors.add("foo", "bar")
28104 errors.add(:age, :invalid, count: 3, message: "%{count} is too low")
28105 name: [{ error: "cannot be nil" }],
28106 foo: [{ error: "bar" }],
28107 baz: [{ error: nil }],
28108 age: [{ error: :invalid, count: 3 }]
28109 assert_equal({ name: [error] }, hash)
28110 assert_raises(FrozenError) { errors.details[:foo] << "foo" }
28111 base: *1
28112 errors: []
28113 options: {}
28114 assert_equal({ name: ["is invalid"] }, errors.messages)
28115 assert_equal({ name: [{ error: :invalid }] }, errors.details)
28116 error = ActiveModel::Error.new(base, :name, :too_long, foo: :bar)
28117 assert_equal({ foo: :bar }, error.options)
28118 options = { message: "bar" }
28119 foo: "foo",
28120 bar: "bar",
28121 baz: Proc.new { "baz" },
28122 I18n.with_locale(:pl) {
28123 attributes: { reports: { name: { presence: "must be present" } } } } } } })
28124 e1 = ActiveModel::Error.new(person, :name, foo: :bar)
28125 e2 = ActiveModel::Error.new(person, :name, foo: :bar)
28126 foo: :bar,
28127 if: :foo,
28128 unless: :bar,
28129 on: :baz,
28130 { error: :too_short, foo: :bar }
28131 assert_equal(error.details, { error: :invalid, foo: :bar })
28132 @color = nil
28133 @size = nil
28134 @name = val
28135 @color = val
28136 @size = val
28137 @status = val
28138 @model.name = "Ringo"
28139 @model.name = "Paul"
28140 @model.name = "John"
28141 assert_equal [nil, "John"], @model.changes["name"]
28142 assert_not @model.name_changed?(from: "Pete", to: "Ringo")
28143 @model.name = "David"
28144 @model.name = "Rafael"
28145 @model.instance_variable_set("@name", +"Yam")
28146 @model.name = "Bob"
28147 @model.color = "red"
28148 @model.name = "Alf"
28149 assert_equal({ "name" => nil, "status" => "initialized" }, @model.changed_attributes)
28150 assert_equal({ "name" => "Paul", "status" => "waiting" }, @model.changed_attributes)
28151 @model.name = "Otto"
28152 @model.size = 1
28153 @model.name = "Dmitry"
28154 @model.color = "Red"
28155 @model.color = "White"
28156 assert_equal "{\"name\":\"Dmitry\",\"color\":null,\"size\":null,\"status\":\"initialized\"}", @model.to_json
28157 assert_equal "{\"color\":null,\"size\":null,\"status\":\"initialized\"}", @model.to_json(except: "name")
28158 assert_equal "{\"color\":null,\"size\":null,\"status\":\"initialized\"}", @model.to_json(except: ["name"])
28159 assert_equal [1], Contact.new(id: 1).to_key
28160 assert_equal "abc-xyz", Contact.new(id: ["abc", "xyz"]).to_param
28161 after_create(if: opts) { }
28162 run_callbacks(:create) { }
28163 attribute :date_field, :date, default: -> { Date.new(2016, 1, 1) }
28164 def attribute=(_, _)
28165 integer_field: "2.3",
28166 decimal_field: "12.3",
28167 string_field: "1.1",
28168 date_field: Date.new(2016, 1, 1),
28169 names = [
28170 @model.name = "Yam"
28171 assert_equal({ "name" => nil }, @model.changed_attributes)
28172 assert_equal({ "name" => "Paul" }, @model.changed_attributes)
28173 @model.size = "2.3"
28174 @model.size = "2.1"
28175 @model.size = "5.1"
28176 assert_equal({ "size" => [2, 5] }, @model.changes)
28177 value + " from user"
28178 block = proc { |name| name.to_s + "!" }
28179 attribute.value << "!"
28180 if value == 1
28181 attribute.value << "1"
28182 attributes = builder.build_from_database(foo: "1.1", bar: "2.2")
28183 attributes = builder.build_from_database({ foo: "3.3", bar: "4.4" }, { bar: Type::Integer.new })
28184 duped[:bar].value << "bar"
28185 assert_equal({ foo: 1, bar: 2.2 }, attributes.to_hash)
28186 assert_equal({ foo: 1, bar: 2.2 }, attributes.to_h)
28187 attributes = builder.build_from_database(foo: "2.2", bar: "3.3")
28188 assert_equal [[:foo, 2], [:bar, 3.3]], hash.to_a
28189 assert_equal({ foo: "1.1", bar: "2.2" }, attributes.values_before_type_cast)
28190 value = attributes.fetch_value(:bar) { |n| n.to_s + "!" }
28191 defaults = { foo: Attribute.from_user(:foo, nil, nil) }
28192 assert_equal({ foo: "1" }, attributes.to_hash)
28193 attributes = builder.build_from_database(foo: "1", bar: "2")
28194 klass = class_with { attribute :foo, TYPE_1 }
28195 child = class_with(parent) { attribute :foo, TYPE_1 }
28196 parent = class_with { attribute :foo, TYPE_1 }
28197 child = class_with(parent) { attribute :foo, TYPE_2 }
28198 { foo: "value of foo", baz: "value of baz" }
28199 def attribute_test(name, attrs = {})
28200 { 'foo bar': "value of foo bar" }
28201 define_method(:'c?d') do
28202 { 'a?b': "value of a?b" }
28203 { begin: "value of begin", end: "value of end" }
28204 assert_equal({ "bar" => "foo" }, klass.attribute_aliases)
28205 m.attributes = { "foo" => "bar" }
28206 attrs = {}
28207 assert_equal "bar", m.foo_kw(kw: 2)
28208 assert_equal "bar", attrs["foo"]
28209 m.attributes = { "private_method" => "<3", "protected_method" => "O_o" }
28210 model.attributes = { name: "hello", description: "world" }
28211 model = Model.new(name: "Guille", description: "m")
28212 @vector[0]
28213 @vector[1]
28214 @vector[2]
28215 @point = Point.new(123, 456, 789)
28216 expected = { z: @point.z, x: @point.x }.with_indifferent_access
28217 actual = @point.slice(:z, :x)
28218 assert_equal expected, @point.slice([:z, :x])
28219 assert_equal [@point.x, @point.z], @point.values_at(:x, :z)
28220 assert_equal [@point.z, @point.x], @point.values_at(:z, :x)
28221 assert_equal [@point.x, @point.z], @point.values_at([:x, :z])
28222 assert_equal [@point.z, @point.x], @point.values_at([:z, :x])
28223 next if (value.nil? && options[:allow_nil]) || (value.blank? && options[:allow_blank])
28224 [:if, :unless, :on, :allow_blank, :allow_nil, :strict]
28225 { in: options }
28226 { with: options }
28227 if value.arity == 0
28228 unless value.is_a?(Numeric) || value.is_a?(Proc) || value.is_a?(Symbol)
28229 came_from_user = :"#{attr_name}_came_from_user?"
28230 RESERVED_OPTIONS = [:minimum, :maximum, :within, :is, :too_short, :too_long]
28231 if range = (options.delete(:in) || options.delete(:within))
28232 options[:maximum] = (range.exclude_end? ? range.end - 1 : range.end) if range.end
28233 if options[:allow_blank] == false && options[:minimum].nil? && options[:is].nil?
28234 unless (value.is_a?(Integer) && value >= 0) ||
28235 value.is_a?(Symbol) || value.is_a?(Proc)
28236 if !value.nil? || skip_nil_check?(key)
28237 key == :maximum && options[:allow_nil].nil? && options[:allow_blank].nil?
28238 source.start_with?("^") || (source.end_with?("$") && !source.end_with?("\\$"))
28239 if value.nil? || value.blank?
28240 COMPARE_CHECKS = { greater_than: :>, greater_than_or_equal_to: :>=,
28241 equal_to: :==, less_than: :<, less_than_or_equal_to: :<=,
28242 other_than: :!= }.freeze
28243 @delimiter ||= options[:in] || options[:within]
28244 if options.key?(:on)
28245 options[:on] = Array(options[:on])
28246 ->(o) {
28247 super({ allow_nil: true, accept: ["1", true] }.merge!(options))
28248 mod = self
28249 attr_name = method_name.to_s.chomp("=")
28250 attributes.any? { |name| name == attr_name }
28251 attr_writers = attributes.reject { |name| klass.attribute_method?("#{name}=") }
28252 @lock = nil
28253 class_attribute :_validators, instance_writer: false, default: Hash.new { |h, k| h[k] = [] }
28254 base._validators = dup.each { |k, v| dup[k] = v.dup }
28255 @errors = nil
28256 @errors ||= Errors.new(self)
28257 Dir[File.expand_path("validations/*.rb", __dir__)].each { |file| require file }
28258 def binary? # :nodoc:
28259 scale == other.scale &&
28260 def cast_value(value) # :doc:
28261 defaults: { 1 => 2000, 2 => 1, 3 => 1, 4 => 0, 5 => 0 }
28262 value = "2000-01-01 #{value}"
28263 ::Date._parse(value)
28264 return if time_hash.nil? || time_hash[:hour].nil?
28265 value = value.change(year: 2000, day: 1, month: 1)
28266 dummy_time_value = value.sub(/\A\d{4}-\d\d-\d\d(?:T|\s)|/, "2000-01-01 ")
28267 new_time(*time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction, :offset))
28268 if new_value.is_a?(::String)
28269 true: @true,
28270 @registrations = {}
28271 @range = min_value...max_value
28272 in_range?(cast_value) || begin
28273 !value || range.member?(value)
28274 1 << (_limit * 8 - 1) # 8 bits per byte with one bit for sign
28275 @false = -(args.delete(:false)&.to_s || "f")
28276 ::Time.zone_default.nil? || ::Time.zone_default.match?("UTC")
28277 is_utc? ? :utc : :local
28278 def new_time(year, mon, mday, hour, min, sec, microsec, offset = nil)
28279 return if year.nil? || (year == 0 && mon == 0 && mday == 0)
28280 time = ::Time.utc(year, mon, mday, hour, min, sec, microsec) rescue nil
28281 time -= offset unless offset == 0
28282 is_utc? ? time : time.getlocal
28283 /x
28284 ::Time.at(::Time.new(string, in: "UTC"))
28285 usec = $7.to_i
28286 usec_len = $7&.length
28287 if usec_len&.< 6
28288 usec *= 10**(6 - usec_len)
28289 if $8
28290 offset = $8 == "Z" ? 0 : $8.to_i * 3600 + $9.to_i * 60
28291 new_time($1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i, usec, offset)
28292 value = if value <=> 0
28293 (old_value.is_a?(::Float) || old_value.is_a?(BigDecimal)) &&
28294 old_value.nan? &&
28295 defaults.each do |k, v|
28296 values_hash[k] ||= v
28297 return "::Float::NAN" if value.try(:nan?)
28298 casted_value = \
28299 if precision.to_i > ::Float::DIG + 1
28300 defaults: { 4 => 0, 5 => 0 }
28301 time[:sec_fraction] ? (time[:sec_fraction] * 1_000_000).to_i : 0
28302 missing_parameters = [1, 2, 3].delete_if { |key| values_hash.key?(key) }
28303 new_date $1.to_i, $2.to_i, $3.to_i
28304 new_date(*parts.values_at(:year, :mon, :mday)) if parts
28305 unless year.nil? || (year == 0 && mon == 0 && mday == 0)
28306 false, 0,
28307 def type # :nodoc:
28308 if value.is_a?(Data)
28309 @value = value.to_s
28310 @value.unpack1("H*")
28311 other == to_s || super
28312 def lookup(...) # :nodoc:
28313 registry.lookup(...)
28314 ancestors.select { |x| x.respond_to?(:model_name) }
28315 if attribute.include?(".")
28316 namespace.tr!(".", "/")
28317 defaults << :"#{i18n_scope}.attributes.#{namespace}.#{attribute}"
28318 root = if options && options.key?(:root)
28319 { root => hash }
28320 attribute_names &= Array(only).map(&:to_s)
28321 Array(options[:methods]).each { |m| hash[m.to_s] = send(m) }
28322 includes = Hash[Array(includes).flat_map { |n| n.is_a?(Hash) ? n.to_a : [[n, {}]] }]
28323 delegate :==, :===, :<=>, :=~, :"!~", :eql?, :match?, :to_s,
28324 :to_str, :as_json, to: :name
28325 @name = name || klass.name
28326 @route_key << "_index" if @uncountable
28327 def human(options = {})
28328 @i18n_scope ||= @klass.respond_to?(:i18n_scope) ? [@klass.i18n_scope, :models] : []
28329 @_model_name ||= begin
28330 @_model_name = nil
28331 def model.to_key() [1] end
28332 assert result == true || result == false, "#{name} should be a boolean"
28333 def_delegators :@errors, :each, :clear, :empty?, :size, :uniq!
28334 def copy!(other) # :nodoc:
28335 @errors.each { |error|
28336 [:attribute, :type].each do |key|
28337 @errors.any? { |error|
28338 def added?(attribute, type = :invalid, options = {})
28339 super("unknown attribute '#{attribute}' for #{@record.class}.")
28340 attribute = attribute.remove(/\[\d+\]/)
28341 parts = attribute.split(".")
28342 defaults = []
28343 defaults << "%{attribute} %{message}"
28344 attr_name = attribute.tr(".", "_").humanize
28345 attribute = attribute.to_s.remove(/\[\d+\]/)
28346 [ :"#{i18n_scope}.errors.models.#{klass.model_name.i18n_key}.attributes.#{attribute}.#{type}",
28347 :"#{i18n_scope}.errors.models.#{klass.model_name.i18n_key}.#{type}" ]
28348 defaults << :"#{i18n_scope}.errors.messages.#{type}"
28349 defaults << :"errors.attributes.#{attribute}.#{type}"
28350 defaults << :"errors.messages.#{type}"
28351 @raw_type = type
28352 @type = type || :invalid
28353 @raw_type = @raw_type.dup
28354 @type = @type.dup
28355 if @attribute != attribute || (type && @type != type)
28356 if @options[key] != value
28357 def ==(other) # :nodoc:
28358 def hash # :nodoc:
28359 def as_json(options = {}) # :nodoc:
28360 __send__("#{attr_name}=", attribute_was(attr_name))
28361 key = respond_to?(:id) && id
28362 key ? [key] : nil
28363 (persisted? && key = to_key) ? key.join("-") : nil
28364 def _to_partial_path # :nodoc:
28365 @_to_partial_path ||= begin
28366 scope: [:kind, :name],
28367 only: [:before, :around, :after]
28368 set_callback(:"#{callback}", :before, *args, options, &block)
28369 set_callback(:"#{callback}", :around, *args, options, &block)
28370 v != false
28371 options[:if] = Array(options[:if]) + [conditional]
28372 set_callback(:"#{callback}", :after, *args, options, &block)
28373 def attribute(name, ...)
28374 def build_from_database(values = {}, additional_types = {})
28375 @casted_values = {}
28376 (values.key?(name) || types.key?(name) || @attributes.key?(name)) && self[name].initialized?
28377 values.each_key { |key| self[key] }
28378 types.each_key { |key| self[key] }
28379 delegate_hash.key?(key) || values.key?(key) || types.key?(key)
28380 def []=(name, value)
28381 keys.index_with { |name| self[name].value }
28382 alias :to_h :to_hash
28383 if key?(key)
28384 def attribute(name, type = nil, default: (no_default = true), **options)
28385 @pending_attributes ||= {}
28386 attr_names.any? { |attr| changed?(attr) }
28387 (OPTION_NOT_GIVEN == from || original_value(attr_name) == type_cast(attr_name, from)) &&
28388 (OPTION_NOT_GIVEN == to || fetch_value(attr_name) == type_cast(attr_name, to))
28389 @forced_changes ||= {}
28390 def changed?(attr_name, **)
28391 mangled_name = "__temp__#{target_name.unpack1("h*")}"
28392 call_args = [":'#{target_name}'"]
28393 body <<
28394 ActiveSupport::CodeGenerator.batch(_owner, __FILE__, __LINE__) do |owner|
28395 mangled_name = "__temp__#{name.unpack1("h*")}"
28396 call_args.unshift(":'#{proxy_target}'")
28397 def initialize(prefix: "", suffix: "", parameters: nil)
28398 @regex = /\A(?:#{Regexp.escape(@prefix)})(.*)(?:#{Regexp.escape(@suffix)})\z/
28399 @proxy_target = "#{@prefix}attribute#{@suffix}"
28400 @method_name = "#{prefix}%s#{suffix}"
28401 __send__(match.proxy_target, match.attr_name, *args, &block)
28402 __send__(attr)
28403 method_name = "#{attr_name}#{'=' if writer}"
28404 yield method_name, "'#{attr_name}'"
28405 safe_name = attr_name.unpack1("h*")
28406 const_name = "ATTR_#{safe_name}"
28407 temp_method_name = "__temp__#{safe_name}#{'=' if writer}"
28408 setter = :"#{k}="
28409 def type_cast(*)
28410 @type = coder["type"]
28411 @value = coder["value"] if coder.map.key?("value")
28412 coder["name"] = name
28413 coder["type"] = type if type
28414 coder["value"] = value if defined?(@value)
28415 I18n.load_path << File.expand_path("active_model/locale/en.yml", __dir__)
28416 worker = new(nil, nil, {})
28417 receiver_str, _, message = method.rpartition(".")
28418 @values ||= []
28419 @id = "AJ-#{SecureRandom.uuid}"
28420 def job_executed(id = @id)
28421 def job_executed_at(id = @id)
28422 job_data(id)["locale"]
28423 @@managers = {}
28424 args = Rails::Generators::ARGVScrubber.new(["new", dummy_app_path, "--skip-gemfile", "--skip-bundle",
28425 initializer "i18n.rb", <<-CODE
28426 I18n.available_locales = [:en, :de]
28427 file "app/jobs/test_job.rb", <<-CODE
28428 File.open(Rails.root.join("tmp/\#{x}.new"), "wb+") do |f|
28429 File.rename(Rails.root.join("tmp/\#{x}.new"), Rails.root.join("tmp/\#{x}"))
28430 vhost: "/",
28431 status = ENV["CI"] ? false : true
28432 if Gem::Version.new(Sidekiq::VERSION) >= Gem::Version.new("7")
28433 elsif Sidekiq.respond_to?(:[]=)
28434 config[:timeout] = 1
28435 Resque.redis = Redis::Namespace.new "active_jobs_int_test", redis: Redis.new(url: ENV["REDIS_URL"] || "redis://127.0.0.1:6379/12")
28436 w.work(0.5)
28437 psql = [].tap do |args|
28438 args << "psql -X -U #{user} -t template1"
28439 args << "-h #{host}" if host
28440 args << "-p #{port}" if port
28441 %x{#{psql} -c 'drop database if exists "#{db}"'}
28442 %x{#{psql} -c 'create database "#{db}"'}
28443 @thread = Thread.new { @worker.start }
28444 def initialize(hash = {})
28445 self.id = (self.class.id += 1)
28446 hash.each { |k, v| send(:"#{k}=", v) }
28447 @jobs = []
28448 def self.create(attrs = {})
28449 new(attrs).tap(&:save)
28450 def self.create!(*args); create(*args); end
28451 all.select { |j| j.locked_by == worker_name }.each { |j| j.locked_by = nil; j.locked_at = nil }
28452 jobs = all.select do |j|
28453 j.run_at <= db_time_now &&
28454 (j.locked_at.nil? || j.locked_at < db_time_now - max_run_time || j.locked_by == worker_name) &&
28455 !j.failed?
28456 jobs.sort_by { |j| [j.priority, j.run_at] }[0..limit - 1]
28457 attrs.each { |k, v| send(:"#{k}=", v) }
28458 def save!; save; end
28459 def self.enqueue(job_class, args = [], opts = {})
28460 def ==(other_person)
28461 other_person.is_a?(Person) && id.to_s == other_person.id.to_s
28462 translations = { en: "Hello", de: "Guten Tag" }
28463 JobBuffer.add("#{greeter} says #{hello}")
28464 new_year = localtime(2018, 1, 1)
28465 if now >= new_year
28466 JobBuffer.add("Just #{(new_year - now).div(3600)} hours to go")
28467 Time.zone ? Time.zone.local(*args) : Time.utc(*args)
28468 logger.info "Dummy, here is it: #{dummy}"
28469 if (arguments.first || :abort) == :abort
28470 assert_match(/HelloJob \[[0-9a-f-]+\] from DelayedJob\(default\) with arguments: \[\]/, job.name)
28471 Time.zone = "Hawaii"
28472 assert_job_executed "#{@id}.1"
28473 assert_job_executed "#{@id}.2"
28474 assert_job_executed_before("#{@id}.2", "#{@id}.1")
28475 TestJob.set(priority: 20).perform_later "#{@id}.1"
28476 TestJob.set(priority: 10).perform_later "#{@id}.2"
28477 GlobalID.app = "aj"
28478 puts "Using #{@adapter}"
28479 @job.locale = :de
28480 job.timezone = "Eastern Time (US & Canada)"
28481 assert_match(/2 .* but 1/, error.message)
28482 assert_match(/1 .* but 2/, error.message)
28483 assert_match(/0 .* but 1/, error.message)
28484 assert_enqueued_jobs(1, only: ->(job) { job.fetch(:job).name == "HelloJob" }) do
28485 assert_enqueued_jobs(1, except: ->(job) { job.fetch(:job).name == "LoggingJob" }) do
28486 assert_match(/`:only` and `:except`/, error.message)
28487 assert_match(/1 .* but 0/, error.message)
28488 assert_match(/5 .* but 1/, error.message)
28489 assert_equal [1, 2, 3, { keyword: true }], job.arguments
28490 facets = {
28491 args: ["Rails"],
28492 matcher = ->(job_value) { job_value == value }
28493 refuser = ->(job_value) { false }
28494 assert_enqueued_with(**{ facet => matcher })
28495 assert_enqueued_with(**{ facet => refuser })
28496 args = [{ argument1: [now] }]
28497 now = Time.now.in_time_zone("Tokyo")
28498 Time.utc(1999, 12, 31, 23, 59, "59.123456789".to_r),
28499 date_time = DateTime.new(2001, 2, 3, 4, 5, 6.123456, "+03:00")
28500 args = [{ argument1: [time_with_zone, time, date_time] }]
28501 assert_enqueued_with(job: MultipleKwargsJob, args: [{ argument1: 1, argument2: { a: 1, b: 2 } }]) do
28502 assert_match(/No enqueued job found with {:job=>HelloJob, :args=>\[#{wilma.inspect}\]}/, error.message)
28503 assert_match(/Potential matches: {.*?:job=>HelloJob, :args=>\[#<Person.* @id="9">\], :queue=>"default".*?}/, error.message)
28504 assert_match(/No enqueued job found with {:job=>HelloJob, :args=>\[\]}/, error.message)
28505 assert_performed_jobs(1, only: ->(job) { job.is_a?(HelloJob) }) do
28506 assert_performed_jobs(1, only: ->(job) { job.fetch(:job).name == "HelloJob" })
28507 assert_performed_jobs(1, except: ->(job) { job.is_a?(HelloJob) }) do
28508 assert_performed_jobs(1, except: ->(job) { job.fetch(:job).name == "HelloJob" })
28509 assert_performed_with(job: MultipleKwargsJob, args: [{ argument1: 1, argument2: { a: 1, b: 2 } }]) do
28510 assert_performed_with(**{ facet => matcher })
28511 assert_performed_with(**{ facet => refuser })
28512 args = [{ argument1: { now: now }, argument2: now }]
28513 assert_match(/No performed job found with {:job=>HelloJob, :args=>\[\]}/, error.message)
28514 assert_match(/No performed job found with {:job=>MultipleKwargsJob, :args=>\[#<Person.* @id=11>\]}/, error.message)
28515 super({ "value" => object.value })
28516 { "_aj_serialized" => "SerializersTest::DummySerializer", "value" => 123 },
28517 hash = { "_dummy_serializer" => 123, "_aj_symbol_keys" => [] }
28518 hash = { "_aj_serialized" => "DoNotExist", "value" => 123 }
28519 hash = { "_aj_serialized" => "SerializersTest::DummySerializer", "value" => 123 }
28520 HelloJob.queue_with_priority { arguments.first == "1" ? 99 : 11 }
28521 HelloJob.queue_as { arguments.first == "1" ? :one : :two }
28522 def enqueue(*); end
28523 def enqueue_at(*); end
28524 ActiveSupport::Notifications.subscribed(-> (*args) { events << args }, /enqueue.*\.active_job/, &block)
28525 assert_match(/to .*?\(php_jobs\).*/, @logger.messages)
28526 assert_match(%r{Dummy, here is it: #<Person:.*>}, @logger.messages)
28527 assert_match(%r{Dummy, here is it: .*#<Person:.*>}, @logger.messages)
28528 assert_match(/Enqueued HelloJob \(Job ID: .*?\) to .*?:.*Cristian/, @logger.messages)
28529 key, * = events.first
28530 assert_match(/Performing LoggingJob \(Job ID: .*?\) from .*? with arguments:.*Dummy/, @logger.messages)
28531 assert_match(/Performed LoggingJob \(Job ID: .*?\) from .*? in .*ms/, @logger.messages)
28532 throw(:abort) if arguments[0].pop == :abort
28533 end.new([:dont_abort, :abort])
28534 assert_match(/Performed DisableLogJob \(Job ID: .*?\) from .*? in .*ms/, @logger.messages)
28535 assert_match(/\[LoggingJob\] \[.*?\]/, @logger.messages)
28536 assert_match(/\[ActiveJob\] Enqueued NestedJob \(Job ID: .*\) to/, @logger.messages)
28537 assert_match(/\[ActiveJob\] \[NestedJob\] \[NESTED-JOB-ID\] Performing NestedJob \(Job ID: .*?\) from/, @logger.messages)
28538 assert_match(/\[ActiveJob\] \[NestedJob\] \[NESTED-JOB-ID\] Enqueued LoggingJob \(Job ID: .*?\) to .* with arguments: "NestedJob"/, @logger.messages)
28539 assert_match(/\[ActiveJob\].*\[LoggingJob\] \[LOGGING-JOB-ID\] Performing LoggingJob \(Job ID: .*?\) from .* with arguments: "NestedJob"/, @logger.messages)
28540 assert_match(/\[ActiveJob\].*\[LoggingJob\] \[LOGGING-JOB-ID\] Performed LoggingJob \(Job ID: .*?\) from .* in/, @logger.messages)
28541 assert_match(/\[ActiveJob\] \[NestedJob\] \[NESTED-JOB-ID\] Performed NestedJob \(Job ID: .*?\) from .* in/, @logger.messages)
28542 assert_match(/Enqueued HelloJob \(Job ID: .*\) to .*? at.*Cristian/, @logger.messages)
28543 assert_match(/Performing RescueJob \(Job ID: .*?\) from .*? with arguments:.*other/, @logger.messages)
28544 assert_match(/Error performing RescueJob \(Job ID: .*?\) from .*? in .*ms: RescueJob::OtherError \(Bad hair\):
.*\brescue_job\.rb:\d+:in `perform'/, @logger.messages)
28545 assert_match(/Performing RescueJob \(Job ID: .*?\) from .*? with arguments:.*david/, @logger.messages)
28546 assert_no_match(/Error performing RescueJob \(Job ID: .*?\) from .*? in .*ms: ArgumentError \(Hair too good\):
.*\brescue_job\.rb:\d+:in `perform'/, @logger.messages)
28547 assert_match(/Retrying RescueJob \(Job ID: .*?\) after \d+ attempts in 0 seconds\./, @logger.messages)
28548 job.deserialize "locale" => "es"
28549 delay_for_jitter = -> (delay) { random_amount * delay * ActiveJob::Base.retry_jitter }
28550 arguments = { "some" => { "job" => "arguments" } }
28551 @person = Person.find("5")
28552 :a,
28553 1.day,
28554 Date.new(2001, 2, 3),
28555 Time.new(2002, 10, 31, 2, 2, 2.123456789r, "+02:00"),
28556 DateTime.new(2001, 2, 3, 4, 5, 6.123456r, "+03:00"),
28557 [ 1, "a" ],
28558 { "a" => 1 },
28559 1..,
28560 1...,
28561 1..5,
28562 1...5,
28563 Date.new(2001, 2, 3)..,
28564 Time.new(2002, 10, 31, 2, 2, 2.123456789r, "+02:00")..,
28565 DateTime.new(2001, 2, 3, 4, 5, 6.123456r, "+03:00")..,
28566 ].each do |arg|
28567 [ Object.new, Person.find("5").to_gid, Class.new ].each do |arg|
28568 assert_arguments_roundtrip [{ "a" => @person }]
28569 assert_arguments_roundtrip([a: 1, "b" => 2])
28570 { "a" => 1, "_aj_hash_with_indifferent_access" => true },
28571 symbol_key = { a: 1 }
28572 string_key = { "a" => 1 }
28573 { "a" => 1, "_aj_symbol_keys" => ["a"] },
28574 { "a" => 1, "_aj_symbol_keys" => [] },
28575 symbol_key = { "a" => 1, "_aj_symbol_keys" => ["a"] }
28576 string_key = { "a" => 1, "_aj_symbol_keys" => [] }
28577 another_string_key = { "a" => 1 }
28578 indifferent_access = { "a" => 1, "_aj_hash_with_indifferent_access" => true }
28579 { a: 1 },
28580 time_with_zone = Time.new(2002, 10, 31, 2, 2, 2).in_time_zone
28581 ActiveJob::Arguments.serialize [ { 1 => 2 } ]
28582 ActiveJob::Arguments.serialize [ { a: [{ 2 => 3 }] } ]
28583 ["_aj_globalid", :_aj_globalid,
28584 $LOAD_PATH << File.expand_path("../support/delayed_job", __dir__)
28585 template "job.rb", File.join("app/jobs", class_path, "#{file_name}_job.rb")
28586 expected = { job: job, args: args, at: at, queue: queue, priority: priority }.compact
28587 enqueued_job["job_class"] == job.to_s
28588 message << potential_matches.map { |job| job["job_class"] }.join(", ")
28589 message << "

Potential matches: #{matching_class.join("
")}"
28590 def jobs_with(jobs, only: nil, except: nil, queue: nil, at: nil)
28591 if at && job[:at]
28592 next false if job[:at] > at.to_f
28593 ->(job) { Array(filter).include?(job.fetch(:job)) }
28594 at_range = arguments[:at] - 1..arguments[:at] + 1
28595 arguments[:at] = ->(at) { at_range.cover?(at) }
28596 new_job[:at] = Time.at(new_job[:at]) if new_job[:at]
28597 super("value" => argument.to_s)
28598 def klass # :doc:
28599 value = hash["value"]
28600 super("value" => date.iso8601)
28601 super("value" => big_decimal.to_s)
28602 options.each do |k, v|
28603 send(k, v)
28604 if @queue_name.is_a?(Proc)
28605 @enqueued_jobs ||= []
28606 @performed_jobs ||= []
28607 def enqueue(job) # :nodoc:
28608 def job_to_hash(job, extras = {})
28609 job_data[:job] = job.class
28610 ->(job) { Array(filter).include?(job.class) }
28611 gem "sidekiq", ">= 4.1.0"
28612 job.provider_job_id = qc_job["id"] if qc_job.is_a?(Hash)
28613 def enqueue_at(*) # :nodoc:
28614 @job_data = job_data
28615 base_name = "#{job_data["job_class"]} [#{job_data["job_id"]}] from DelayedJob(#{job_data["queue_name"]})"
28616 if delay > 0
28617 around_enqueue(prepend: true) { |_, block| tag_logger(&block) }
28618 job.arguments.map { |arg| format(arg).inspect }.join(", ")
28619 arg.map { |value| format(value) }
28620 payload[:job] = self
28621 def perform_now(...)
28622 self.executions = (executions || 0) + 1
28623 def retry_job(options = {})
28624 jitter = jitter == JITTER_DEFAULT ? self.class.retry_jitter : (jitter || 0.0)
28625 def perform_later(...)
28626 job = job_or_instantiate(...)
28627 args.first.is_a?(self) ? args.first : new(*args)
28628 def enqueue(options = {})
28629 def set(options = {})
28630 def set(options = {}) # :nodoc:
28631 @job_class.new(...).set(@options).perform_now
28632 @job_class.new(...).enqueue @options
28633 when -> (arg) { arg.respond_to?(:permitted?) }
28634 argument.each_with_object({}) do |(key, value), hash|
28635 match "/echo" => "tests#echo", via: :all
28636 get "/error" => proc { |env| [403, { "content-type" => "text/plain" }, []] }
28637 names = names.map { |name| "/test/#{name}.js" }
28638 payload = JSON.generate(data).gsub("<", "&lt;").gsub(">", "&gt;")
28639 if (window.top && window.top !== window)
28640 </script>
28641 <p>You shouldn't be seeing this. <a href="#{request.env['HTTP_REFERER']}">Go back</a></p>
28642 get "/" => "foo#bar"
28643 get "/other" => "foo#other"
28644 get "/article/:id" => "foo#article", :as => :article
28645 get "/category/:category" => "foo#category"
28646 def hash_for(options = {})
28647 { controller: "foo", action: "bar" }.merge!(options)
28648 assert_equal "/?a=b&c=d", url_for(hash_for(a: :b, c: :d))
28649 assert_equal "/", url_for(hash_for(a: {}))
28650 @controller = Struct.new(:request).new(Struct.new(:env).new({ "HTTP_REFERER" => referer }))
28651 @controller = Struct.new(:request).new(Struct.new(:env).new({}))
28652 assert_equal "/other", url_for([:other, { controller: "foo" }])
28653 assert_equal "http://example.com/other", url_for([:other, { controller: "foo", only_path: false }])
28654 [{ name: "name", value: "David" }, { name: "nationality", value: "Danish" }],
28655 to_form_params("name" => "David", :nationality => "Danish")
28656 [{ name: "country[name]", value: "Denmark" }],
28657 to_form_params(country: { name: "Denmark" })
28658 [{ name: "countries[]", value: "Denmark" }, { name: "countries[]", value: "Sweden" }],
28659 to_form_params({ name: "Denmark" }, "country")
28660 %{<form method="post" action="http://www.example.com" class="button_to"><button type="submit">Hello</button></form>},
28661 button_to("Hello", "http://www.example.com")
28662 assert_dom_equal %{<form method="post" action="http://www.example.com" class="button_to"><button type="submit">Hello</button></form>}, button_to("Hello", "http://www.example.com")
28663 %{<form method="post" action="/article/Hello" class="button_to"><button type="submit">Hello</button></form>},
28664 %{<form method="post" class="button_to"><button type="submit">Hello</button></form>},
28665 button_to(false) { "Hello" }
28666 %{<form method="post" action="/workshops" class="button_to"><button type="submit">Create</button></form>},
28667 button_to(workshop) { "Create" }
28668 button_to([workshop, session]) { "Create" }
28669 %{<form method="post" action="/workshops/1" class="button_to"><input type="hidden" name="_method" value="patch" autocomplete="off" /><button type="submit">Update</button></form>},
28670 button_to(workshop) { "Update" }
28671 session = Session.new("1")
28672 button_to([workshop, session]) { "Update" }
28673 %{<form method="post" action="http://www.example.com" class="button_to"><button data-confirm="Are you sure?" type="submit">Hello</button></form>},
28674 button_to("Hello", "http://www.example.com", data: { confirm: "Are you sure?" })
28675 %{<form method="post" action="http://www.example.com" class="button_to"><button data-disable-with="Greeting..." type="submit">Hello</button></form>},
28676 button_to("Hello", "http://www.example.com", data: { disable_with: "Greeting..." })
28677 button_to("Hello", "http://www.example.com", remote: true, form: { class: "custom-class", "data-type" => "json" })
28678 button_to("Hello", "http://www.example.com", remote: true, data: { confirm: "Are you sure?" })
28679 button_to("Hello", "http://www.example.com", remote: true, data: { disable_with: "Greeting..." })
28680 button_to("Hello", "http://www.example.com", remote: false)
28681 button_to("Hello", "http://www.example.com", disabled: true)
28682 %{<form method="post" action="http://www.example.com" class="button_to"><input type="hidden" name="_method" value="delete" autocomplete="off" /><button type="submit">Hello</button></form>},
28683 button_to("Hello", "http://www.example.com", method: :delete)
28684 %{<form method="get" action="http://www.example.com" class="button_to"><button type="submit">Hello</button></form>},
28685 button_to("Hello", "http://www.example.com", method: :get)
28686 %{<form method="post" action="http://www.example.com" class="button_to"><button type="submit"><span>Hello</span></button></form>},
28687 button_to("http://www.example.com") { content_tag(:span, "Hello") }
28688 button_to("Hello", "http://www.example.com", params: { foo: :bar, baz: "quux" })
28689 %{<form action="/other" class="button_to" method="post"><button class="button" type="submit">Hello</button></form>},
28690 button_to({ controller: "foo", action: "other" }, class: "button") { "Hello" }
28691 %{<form method="post" action="http://www.example.com" class="button_to"><input type="submit" value="Save"/></form>},
28692 button_to("Save", "http://www.example.com")
28693 { foo: :bar, baz: "quux" }
28694 %{<form action="http://www.example.com" class="button_to" method="post"><button type="submit">Hello</button><input type="hidden" name="foo[bar]" value="baz" autocomplete="off" /></form>},
28695 button_to("Hello", "http://www.example.com", params: { foo: { bar: "baz" } })
28696 %{<form action="http://www.example.com" class="button_to" method="post"><button type="submit">Hello</button><input type="hidden" name="foo[]" value="bar" autocomplete="off" /></form>},
28697 button_to("Hello", "http://www.example.com", params: { foo: ["bar"] })
28698 assert_dom_equal %{<a href="http://www.example.com">Hello</a>}, link_to("Hello", "http://www.example.com")
28699 assert_dom_equal(%{<a href="/">Test Link</a>}, link_to("Test Link", url_hash))
28700 hash = hash_for(host: "www.example.com")
28701 expected = %{<a href="http://www.example.com/">Test Link</a>}
28702 expected = %{<a href="http://www.example.com?q1=v1&amp;q2=v2">Hello</a>}
28703 expected = %{<a href="http://www.example.com?q1=v1&amp;q2=v2">http://www.example.com?q1=v1&amp;q2=v2</a>}
28704 env = { "HTTP_REFERER" => "http://www.example.com/referer" }
28705 expected = %{<a href="#{env["HTTP_REFERER"]}">go back</a>}
28706 link = link_to("go back", :back)
28707 assert_dom_equal %{<a href="javascript:history.back()">go back</a>}, link
28708 link = link_to(raw("<img src='/favicon.jpg' />"), "/")
28709 expected = %{<a href="/"><img src='/favicon.jpg' /></a>}
28710 link = link_to("Hello", url_hash, nil)
28711 assert_dom_equal %{<a href="/">Hello</a>}, link
28712 link = link_to("Hello", "http://www.example.com", onclick: "alert('yay!')")
28713 expected = %{<a href="http://www.example.com" onclick="alert(&#39;yay!&#39;)">Hello</a>}
28714 %{<a href="http://www.example.com" data-confirm="Are you sure?">Hello</a>},
28715 link_to("Hello", "http://www.example.com", data: { confirm: "Are you sure?" })
28716 %{<a href="http://www.example.com" data-confirm="You can't possibly be sure, can you?">Hello</a>},
28717 link_to("Hello", "http://www.example.com", data: { confirm: "You can't possibly be sure, can you?" })
28718 %{<a href="http://www.example.com" data-confirm="You can't possibly be sure,
can you?">Hello</a>},
28719 link_to("Hello", "http://www.example.com", data: { confirm: "You can't possibly be sure,
can you?" })
28720 %{<a href="http://www.example.com" data-remote="true">Hello</a>},
28721 link_to("Hello", "http://www.example.com", remote: true)
28722 %{<a href="http://www.example.com">Hello</a>},
28723 link_to("Hello", "http://www.example.com", remote: false)
28724 %{<a href="/" data-remote="true">Hello</a>},
28725 link_to("Hello", hash_for(remote: true), {})
28726 link_to("Hello", hash_for("remote" => true), {})
28727 %{<a href="http://www.example.com" data-method="post" rel="nofollow">Hello</a>},
28728 link_to("Hello", "http://www.example.com", method: :post)
28729 %{<a href="http://www.example.com" rel="nofollow" data-method="delete">Destroy</a>},
28730 link_to("Destroy", "http://www.example.com", method: :delete)
28731 %{<a href="\#" rel="nofollow" data-method="delete">Destroy</a>},
28732 link_to("Destroy", "http://www.example.com", method: :delete, href: "#")
28733 %{<a href="http://www.example.com" data-method="post" rel="example nofollow">Hello</a>},
28734 link_to("Hello", "http://www.example.com", method: :post, rel: "example")
28735 %{<a href="http://www.example.com" data-method="post" rel="nofollow" data-confirm="Are you serious?">Hello</a>},
28736 link_to("Hello", "http://www.example.com", method: :post, data: { confirm: "Are you serious?" })
28737 %{<a href="\#" rel="nofollow" data-confirm="Are you serious?" data-method="delete">Destroy</a>},
28738 link_to("Destroy", "http://www.example.com", method: :delete, href: "#", data: { confirm: "Are you serious?" })
28739 assert_dom_equal %{<a href="/"><span>Example site</span></a>},
28740 link_to("/") { content_tag(:span, "Example site") }
28741 assert_dom_equal %{<a class="special" href="/"><span>Example site</span></a>},
28742 link_to("/", class: "special") { content_tag(:span, "Example site") }
28743 %{<a href="/"><span>Example site</span></a>},
28744 link_to(url_hash) { content_tag(:span, "Example site") }
28745 out = render_erb %{<%= link_to('/') do %>Example site<% end %>}
28746 assert_equal '<a href="/">Example site</a>', out
28747 assert_dom_equal %{<a href="/">Malicious &lt;script&gt;content&lt;/script&gt;</a>},
28748 link_to("Malicious <script>content</script>", "/")
28749 assert_dom_equal %{<a href="/">Malicious <script>content</script></a>},
28750 link_to(raw("Malicious <script>content</script>"), "/")
28751 assert_dom_equal %{<a href="/workshops/1">Workshop 1</a>}, link
28752 assert_dom_equal %{<a href="/">Listing</a>},
28753 link_to_unless(true, "Showing", url_hash) { |name|
28754 raw "<strong>#{name}</strong>"
28755 link_to_unless(true, "Showing", url_hash) {
28756 assert_equal %{&lt;b&gt;Showing&lt;/b&gt;}, link_to_unless(true, "<b>Showing</b>", url_hash)
28757 assert_equal %{<a href="/">&lt;b&gt;Showing&lt;/b&gt;</a>}, link_to_unless(false, "<b>Showing</b>", url_hash)
28758 assert_equal %{<b>Showing</b>}, link_to_unless(true, raw("<b>Showing</b>"), url_hash)
28759 assert_equal %{<a href="/"><b>Showing</b></a>}, link_to_unless(false, raw("<b>Showing</b>"), url_hash)
28760 assert_dom_equal %{<a href="/">Listing</a>}, link_to_if(true, "Listing", url_hash)
28761 assert_equal "Fallback", link_to_if(false, "Showing", url_hash) { "Fallback" }
28762 assert_dom_equal %{<a href="/">Listing</a>}, link_to_if(true, "Listing", url_hash) { "Fallback" }
28763 def request_for_url(url, opts = {})
28764 env = Rack::MockRequest.env_for("http://www.example.com#{url}", opts)
28765 @request = request_for_url("/", method: :head)
28766 @request = request_for_url("/")
28767 @request = request_for_url("/?order=desc&page=1")
28768 assert current_page?(hash_for(order: "desc", page: "1"))
28769 @request = request_for_url("/engine/")
28770 @request = request_for_url("/posts")
28771 @request = request_for_url("/events", method: :post)
28772 @request = request_for_url("/?order=desc")
28773 link_to_unless_current("Showing", hash_for(order: "desc", page: "1"))
28774 assert_equal %{<a href="/?order=asc">Showing</a>},
28775 assert_equal %{<a href="http://www.example.com/?order=asc">Showing</a>},
28776 assert_equal %{<a href="/?order=desc&amp;page=2\">Showing</a>},
28777 assert_equal %{<a href="http://www.example.com/?order=desc&amp;page=2">Showing</a>},
28778 @request = request_for_url("/show")
28779 assert_equal %{<a href="/">Listing</a>},
28780 assert_equal %{<a href="http://www.example.com/">Listing</a>},
28781 assert_dom_equal %{<a href="/">Showing</a>}, link_to_unless(false, "Showing", url_hash) { "Fallback" }
28782 %{<a href="mailto:%23%21%24%25%26%27%2A%2B-%2F%3D%3F%5E_%60%7B%7D%7C@example.org">#!$%&amp;&#39;*+-/=?^_`{}|@example.org</a>},
28783 mail_to("#!$%&'*+-/=?^_`{}|@example.org")
28784 mail_to("me@example.com", "My email", cc: "", bcc: "", subject: "This is an example email", body: "This is the body of the message.")
28785 assert_dom_equal %{<a href="mailto:feedback@example.com"><img src="/feedback.png" /></a>},
28786 mail_to("feedback@example.com", raw('<img src="/feedback.png" />'))
28787 %{<a href="mailto:"></a>},
28788 assert_dom_equal %{<a href="mailto:me@example.com"><span>Email me</span></a>},
28789 mail_to("me@example.com") { content_tag(:span, "Email me") }
28790 mail_to("me@example.com", cc: "ccaddress@example.com", class: "special") { content_tag(:span, "Email me") }
28791 options = { class: "special" }
28792 mail_to "me@example.com", "ME!", options
28793 assert_equal({ class: "special" }, options)
28794 assert_dom_equal %{<a href="sms:15155555785;">Jim Jones</a>}, sms_to("15155555785", "Jim Jones")
28795 %{<a class="admin" href="sms:15155555785;">Jim Jones</a>},
28796 sms_to("15155555785", "Jim Jones", "class" => "admin")
28797 assert_equal sms_to("15155555785", "Jim Jones", "class" => "admin"),
28798 sms_to("15155555785", "Jim Jones", class: "admin")
28799 sms_to("5155555785", "Text me", class: "simple-class", country_code: "01", body: "Hello from Jim")
28800 sms_to("5155555785", class: "simple-class", country_code: "01", body: "Hello from Jim")
28801 sms_to("5155555785", "Text me", body: "This is the body of the message.")
28802 assert_dom_equal %{<a href="sms:15155555785;"><img src="/feedback.png" /></a>},
28803 sms_to("15155555785", raw('<img src="/feedback.png" />'))
28804 %{<a href="sms:1%2B5155555785;">1+5155555785</a>},
28805 %{<a href="sms:;"></a>},
28806 assert_dom_equal %{<a href="sms:15155555785;"><span>Text me</span></a>},
28807 sms_to("15155555785") { content_tag(:span, "Text me") }
28808 sms_to("15155555785", body: "Hello from Jim", class: "special") { content_tag(:span, "Text me") }
28809 sms_to "15155555785", "ME!", options
28810 assert_dom_equal %{<a href="tel:1234567890">Bob</a>},
28811 phone_to("1234567890", "Bob")
28812 %{<a class="phoner" href="tel:1234567890">Bob</a>},
28813 phone_to("1234567890", "Bob", "class" => "phoner")
28814 assert_equal phone_to("1234567890", "Bob", "class" => "admin"),
28815 phone_to("1234567890", "Bob", class: "admin")
28816 %{<a class="example-class" href="tel:+011234567890">Phone</a>},
28817 phone_to("1234567890", "Phone", class: "example-class", country_code: "01")
28818 %{<a href="tel:+011234567890">Phone</a>},
28819 phone_to("1234567890", "Phone", country_code: "01")
28820 assert_dom_equal %{<a href="tel:1234567890"><img src="/feedback.png" /></a>},
28821 phone_to("1234567890", raw('<img src="/feedback.png" />'))
28822 %{<a href="tel:1%2B234567890">1+234567890</a>},
28823 %{<a href="tel:"></a>},
28824 assert_dom_equal %{<a href="tel:1234567890"><span>Phone</span></a>},
28825 phone_to("1234567890") { content_tag(:span, "Phone") }
28826 assert_dom_equal %{<a class="special" href="tel:+011234567890"><span>Phone</span></a>},
28827 phone_to("1234567890", country_code: "01", class: "special") { content_tag(:span, "Phone") }
28828 as: :show
28829 get "/:controller(/:action(/:id))"
28830 render inline: "<%= show_named_route_#{params[:kind]} %>"
28831 render inline: "<%= url_for(nil) %>"
28832 render inline: "<%= url_for(action: :show_url_for) %>"
28833 render inline: "<%= override_url_helper_path %>"
28834 get :show_named_route, params: { kind: "url" }
28835 get :show_named_route, params: { kind: "path" }
28836 { host: "testtwo.host" }
28837 get :show, params: { id: "123" }
28838 get :show, params: { name: "123" }
28839 render inline: "<%= link_to_unless_current('tasks', tasks_path) %>
" \
28840 get :show, params: { id: 1 }
28841 assert_equal %{<a href="/tasks">tasks</a>
} +
28842 %{<a href="#{@request.protocol}#{@request.host_with_port}/tasks">tasks</a>},
28843 render inline: "<%= url_for(@workshop) %>
<%= link_to('Workshop', @workshop) %>"
28844 render inline: "<%= current_page?(@workshop) %>"
28845 render inline: "<%= url_for([@workshop, @session]) %>
<%= link_to('Session', [@workshop, @session]) %>"
28846 @url = [@workshop, @session, format: params[:format]]
28847 render inline: "<%= url_for(@url) %>
<%= link_to('Session', @url) %>"
28848 get :edit, params: { id: 1 }
28849 get :index, params: { workshop_id: 1 }
28850 get :show, params: { workshop_id: 1, id: 1 }
28851 found: { foo: "Foo" },
28852 found_yield_single_argument: { foo: "Foo" },
28853 found_yield_block: { foo: "Foo" },
28854 array: { foo: { bar: "Foo Bar" } },
28855 default: { foo: "Foo" },
28856 partial: { foo: "Partial foo" }
28857 foo: "Foo",
28858 hello: "<a>Hello World</a>",
28859 html: "<a>Hello World</a>",
28860 hello_html: "<a>Hello World</a>",
28861 interpolated_html: "<a>Hello %{word}</a>",
28862 array_html: %w(foo bar),
28863 array: %w(foo bar),
28864 count_html: {
28865 one: "<a>One %{count}</a>",
28866 other: "<a>Other %{count}</a>"
28867 matcher = ->(key, options) do
28868 @time = Time.utc(2008, 7, 8, 12, 18, 38)
28869 assert_called_with(I18n, :localize, [@time], locale: "en") do
28870 assert_equal "Tue, 08 Jul 2008 12:18:38 +0000", localize(@time, locale: "en")
28871 assert_equal expected, translate(:"translations.missing", name: "Kir", year: "2015", vulnerable: %{" onclick="alert()"})
28872 expected = %w(foo bar)
28873 assert_equal "<a>One 1</a>", translate(:'translations.count_html', count: 1)
28874 assert_equal "<a>Other &lt;One&gt;</a>", translate(:'translations.count_html', count: "<One>")
28875 hash = { one: "%{count} thing", other: "%{count} things" }
28876 assert_equal ["<a>Hello World</a>", "<a>Hello World</a>"], translations
28877 @_cycles = nil if defined?(@_cycles)
28878 assert_equal "<p>A paragraph</p>

<p>and another one!</p>", simple_format("A paragraph

and another one!")
28879 assert_equal "<p>A
<br />B
<br />C
<br />D</p>", simple_format(text)
28880 assert_equal '<p class="test">This is a classy test</p>', simple_format("This is a classy test", class: "test")
28881 assert_equal %Q(<p class="test">para 1</p>

<p class="test">para 2</p>), simple_format("para 1

para 2", class: "test")
28882 assert_equal "<p><b> test with unsafe string </b>code!</p>", simple_format("<b> test with unsafe string </b><script>code!</script>")
28883 assert_equal "<p><b> test with unsafe string </b>code!</p>",
28884 simple_format("<b> test with unsafe string </b><script>code!</script>", {}, { sanitize: true })
28885 assert_equal "<p><b> test with unsafe string </b><script>code!</script></p>", simple_format("<b> test with unsafe string </b><script>code!</script>", {}, { sanitize: false })
28886 assert_equal "<div></div>", simple_format(nil, {}, { wrapper_tag: "div" })
28887 text = "<b>Ok</b><script>code!</script>"
28888 options = { class: "foobar" }
28889 options = { wrapper_tag: :div, sanitize: false }
28890 assert_equal "Hello Wor...", truncate("Hello World!!", length: 12)
28891 assert_equal str[0...27] + "...", truncate(str)
28892 assert_equal "Hello W...", truncate("Hello World!", length: 10)
28893 assert_equal "Hello[...]", truncate("Hello World!", omission: "[...]", length: 10)
28894 assert_equal "Hello[...]", truncate("Hello Big World!", omission: "[...]", length: 13, separator: " ")
28895 assert_equal "Hello Big[...]", truncate("Hello Big World!", omission: "[...]", length: 14, separator: " ")
28896 assert_equal "Hello Big[...]", truncate("Hello Big World!", omission: "[...]", length: 15, separator: " ")
28897 options = { length: 10 }
28898 assert_equal "Here is a long test and ...<a href=\"#\">Continue</a>",
28899 truncate("Here is a long test and I need a continue to read link", length: 27) { link_to "Continue", "#" }
28900 assert_equal "Hello &lt;sc...", truncate("Hello <script>code!</script>World!!", length: 12)
28901 assert_equal "Hello <sc...", truncate("Hello <script>code!</script>World!!", length: 12, escape: false)
28902 truncated = truncate("Here's a long test and I need a continue to read link", length: 27) { link_to "Continue", "#" }
28903 assert_equal "&lt;script&gt;code!&lt;/script&gt;He...<a href=\"#\">Continue</a>",
28904 truncate("<script>code!</script>Here's a long test and I need a continue to read link", length: 27) { link_to "Continue", "#" }
28905 assert_equal "<script>code!</script>He...<a href=\"#\">Continue</a>",
28906 truncate("<script>code!</script>Here's a long test and I need a continue to read link", length: 27, escape: false) { link_to "Continue", "#" }
28907 truncated = truncate("<script>code!</script>Here's a long test and I need a continue to read link", length: 27, escape: false) { link_to "Continue", "#" }
28908 assert_equal "Here is a long test and ...&lt;script&gt;alert(&#39;foo&#39;);&lt;/script&gt;",
28909 truncate("Here is a long test and I need a continue to read link", length: 27) { "<script>alert('foo');</script>" }
28910 assert_equal %(<em>wow</em> <em>em</em>), highlight("wow em", %w(wow em), highlighter: '<em>\1</em>')
28911 highlight("<p>This is a <em class=\"error\">beautiful</em> morning, but also a beautiful <span class=\"last\">day</span></p>", "beautiful")
28912 highlight("<div>abc div</div>", "div", highlighter: '<b>\1</b>')
28913 options = { highlighter: '<b>\1</b>', sanitize: false }
28914 highlight("<div>abc div</div>", "div", passed_options)
28915 highlight("one two three", ["one", "two", "three"]) { |word| "<b>#{word}</b>" }
28916 assert_equal("...is a beautiful morn...", excerpt("This is a beautiful morning", "beautiful", radius: 5))
28917 assert_equal("This is a...", excerpt("This is a beautiful morning", "this", radius: 5))
28918 assert_equal("...is a beautiful! mor...", excerpt("This is a beautiful! morning", "beautiful", radius: 5))
28919 assert_equal("...is a beautiful? mor...", excerpt("This is a beautiful? morning", "beautiful", radius: 5))
28920 assert_equal("...is a beautiful? mor...", excerpt("This is a beautiful? morning", /\bbeau\w*\b/i, radius: 5))
28921 assert_equal("...is a beautiful? mor...", excerpt("This is a beautiful? morning", /\b(beau\w*)\b/i, radius: 5))
28922 assert_equal("...judge Allen and...", excerpt("This day was challenging for judge Allen and his colleagues.", /\ballen\b/i, radius: 1, separator: " "))
28923 assert_equal("...was challenging for...", excerpt("This day was challenging for judge Allen and his colleagues.", /\b(\w*allen\w*)\b/i, radius: 5))
28924 assert_equal("", excerpt("", "", radius: 0))
28925 assert_equal("a", excerpt("a", "a", radius: 0))
28926 assert_equal("...b...", excerpt("abc", "b", radius: 0))
28927 assert_equal("abc", excerpt("abc", "b", radius: 1))
28928 assert_equal("abc...", excerpt("abcd", "b", radius: 1))
28929 assert_equal("...abc", excerpt("zabc", "b", radius: 1))
28930 assert_equal("...abc...", excerpt("zabcd", "b", radius: 1))
28931 assert_equal("zabcd", excerpt("zabcd", "b", radius: 2))
28932 assert_equal("[...]is a beautiful morn[...]", excerpt("This is a beautiful morning", "beautiful", omission: "[...]", radius: 5))
28933 omission: "[...]")
28934 options = { omission: "[...]", radius: 5 }
28935 options = { separator: " ", radius: 1 }
28936 assert_equal("...a very beautiful...", excerpt("This is a very beautiful morning", "very", options))
28937 options = { separator: "
", radius: 0 }
28938 assert_equal("...very long...", excerpt("my very
very
very long
string", "long", options))
28939 options = { separator: "
", radius: 1 }
28940 assert_equal "123-+1234-+12-+12-+123-+1 1-+1-+123", word_wrap(input, line_width: 3, break_sequence: "-+")
28941 input = "1
1 1 1
1"
28942 assert_equal "1
1 1
1
1", word_wrap(input, line_width: 3)
28943 assert_equal "1-+1 1-+1-+1", word_wrap(input, line_width: 3, break_sequence: "-+")
28944 input = "1


1 1 1


1"
28945 assert_equal "1


1 1
1


1", word_wrap(input, line_width: 3)
28946 assert_equal "1-+-+-+1 1-+1-+-+-+1", word_wrap(input, line_width: 3, break_sequence: "-+")
28947 input = "1
1 1 1
1


"
28948 assert_equal("1 count", pluralize(1, "count"))
28949 assert_equal("1 count", pluralize("1", "count"))
28950 assert_equal("2 counts", pluralize("2", "count"))
28951 assert_equal("1,066 counts", pluralize("1,066", "count"))
28952 assert_equal("1.25 counts", pluralize("1.25", "count"))
28953 assert_equal("1.0 count", pluralize("1.0", "count"))
28954 assert_equal("1.00 count", pluralize("1.00", "count"))
28955 assert_equal("1 berry", pluralize(1, "berry"))
28956 value = Cycle.new("one", 2, "3")
28957 assert_equal("2", value.to_s)
28958 assert_equal("3", value.to_s)
28959 assert_equal("one", cycle("one", 2, "3"))
28960 assert_equal("2", cycle("one", 2, "3"))
28961 assert_equal("3", cycle("one", 2, "3"))
28962 array = [1, 2, 3]
28963 assert_equal("even", cycle("even", "odd"))
28964 assert_equal("odd", cycle("even", "odd"))
28965 assert_equal("1", cycle(1, 2, 3))
28966 assert_equal("2", cycle(1, 2, 3))
28967 assert_equal("3", cycle(1, 2, 3))
28968 assert_equal("1", cycle(1, 2, 3, name: "numbers"))
28969 assert_equal("red", cycle("red", "blue", name: "colors"))
28970 assert_equal("2", cycle(1, 2, 3, name: "numbers"))
28971 assert_equal("blue", cycle("red", "blue", name: "colors"))
28972 assert_equal("3", cycle(1, 2, 3, name: "numbers"))
28973 cycle("even", "odd")
28974 cycle("red", "blue", name: "colors")
28975 cycle(1, 2, 3)
28976 assert_equal("2", cycle(1, 2, 3, name: "default"))
28977 assert_equal("red", cycle("red", "blue"))
28978 assert_equal("blue", cycle("red", "blue"))
28979 templates = resolver.find_all("path.erb", "arbitrary", false, locale: [], formats: [:html], handlers: [])
28980 templates = resolver.find_all("path", "arbitrary", false, locale: [], formats: [:html], variants: [], handlers: [])
28981 templates = resolver.find_all("path", "arbitrary", false, locale: [], formats: [:html], variants: [], handlers: [:erb])
28982 templates = resolver.find_all("path", "arbitrary", false, locale: [], formats: [:html], variants: [:variant], handlers: [:erb])
28983 en = resolver.find_all("path", "arbitrary", false, locale: [:en], formats: [:html], variants: [], handlers: [:erb])
28984 fr = resolver.find_all("path", "arbitrary", false, locale: [:fr], formats: [:html], variants: [], handlers: [:erb])
28985 templates = resolver.find_all("path", "arbitrary", false, locale: [], formats: [:html], variants: :any, handlers: [:erb])
28986 assert_equal "<h1>Ruby on Rails</h1>", title("Ruby on Rails")
28987 person = Struct.new(:name) {
28988 }.new "David"
28989 assert_equal '<a href="/people/1">David</a>', link_to_person(person)
28990 get "people", to: "people#index", as: :people
28991 render(layout: "test/layout_for_partial", locals: { name: "ChrisCruft" }) { "!" }
28992 assert_called_with(view.request.flash, :[], [:alert]) do
28993 @controller.singleton_class.class_eval <<-EOF, __FILE__, __LINE__ + 1
28994 @a = "b"
28995 @c = "d"
28996 assert_equal({ a: "b", c: "d" }, view_assigns)
28997 from_test_case(suffix: "!")
28998 def from_test_case(suffix: "?"); "Word#{suffix}"; end
28999 controller.request.assign_parameters(@routes, "foo", "index", {}, "/foo", [])
29000 set.draw {
29001 get :foo, to: "foo#index"
29002 get :bar, to: "bar#index"
29003 routes.draw { get "bar", to: lambda { } }
29004 def self.call(*)
29005 set.draw { mount app => "/foo", :as => "foo_app" }
29006 content_for :foo, "bar"
29007 form_tag("/foo") do
29008 safe_concat render(plain: "<ul><li>foo</li></ul>")
29009 assert_select "li", text: "foo"
29010 concat form_tag("/foo")
29011 concat content_tag(:b, "Strong", class: "foo")
29012 locals: []
29013 def new_template(body = "<%= hello %>", details = {})
29014 details = { format: :html, locals: [] }.merge details
29015 I18n.load_path << File.expand_path("locale/en.yml", __dir__)
29016 I18n.load_path << File.expand_path("locale/en.rb", __dir__)
29017 delegate :[], :fetch, to: :config
29018 YAML.load(config).presence || {}
29019 send(name, *args, &block)
29020 undef_method :==
29021 ::Object.send(:raise, *args)
29022 inflect.plural(/$/, "s")
29023 inflect.plural(/s$/i, "s")
29024 inflect.plural(/^(ax|test)is$/i, '\1es')
29025 inflect.plural(/(octop|vir)us$/i, '\1i')
29026 inflect.plural(/(octop|vir)i$/i, '\1i')
29027 inflect.plural(/(alias|status)$/i, '\1es')
29028 inflect.plural(/(bu)s$/i, '\1ses')
29029 inflect.plural(/(buffal|tomat)o$/i, '\1oes')
29030 inflect.plural(/([ti])um$/i, '\1a')
29031 inflect.plural(/([ti])a$/i, '\1a')
29032 inflect.plural(/sis$/i, "ses")
29033 inflect.plural(/(?:([^f])fe|([lr])f)$/i, '\1\2ves')
29034 inflect.plural(/(hive)$/i, '\1s')
29035 inflect.plural(/([^aeiouy]|qu)y$/i, '\1ies')
29036 inflect.plural(/(x|ch|ss|sh)$/i, '\1es')
29037 inflect.plural(/(matr|vert|ind)(?:ix|ex)$/i, '\1ices')
29038 inflect.plural(/^(m|l)ouse$/i, '\1ice')
29039 inflect.plural(/^(m|l)ice$/i, '\1ice')
29040 inflect.plural(/^(ox)$/i, '\1en')
29041 inflect.plural(/^(oxen)$/i, '\1')
29042 inflect.plural(/(quiz)$/i, '\1zes')
29043 inflect.singular(/s$/i, "")
29044 inflect.singular(/(ss)$/i, '\1')
29045 inflect.singular(/(n)ews$/i, '\1ews')
29046 inflect.singular(/([ti])a$/i, '\1um')
29047 inflect.singular(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)(sis|ses)$/i, '\1sis')
29048 inflect.singular(/(^analy)(sis|ses)$/i, '\1sis')
29049 inflect.singular(/([^f])ves$/i, '\1fe')
29050 inflect.singular(/(hive)s$/i, '\1')
29051 inflect.singular(/(tive)s$/i, '\1')
29052 inflect.singular(/([lr])ves$/i, '\1f')
29053 inflect.singular(/([^aeiouy]|qu)ies$/i, '\1y')
29054 inflect.singular(/(s)eries$/i, '\1eries')
29055 inflect.singular(/(m)ovies$/i, '\1ovie')
29056 inflect.singular(/(x|ch|ss|sh)es$/i, '\1')
29057 inflect.singular(/^(m|l)ice$/i, '\1ouse')
29058 inflect.singular(/(bus)(es)?$/i, '\1')
29059 inflect.singular(/(o)es$/i, '\1')
29060 inflect.singular(/(shoe)s$/i, '\1')
29061 inflect.singular(/(cris|test)(is|es)$/i, '\1is')
29062 inflect.singular(/^(a)x[ie]s$/i, '\1xis')
29063 inflect.singular(/(octop|vir)(us|i)$/i, '\1us')
29064 inflect.singular(/(alias|status)(es)?$/i, '\1')
29065 inflect.singular(/^(ox)en/i, '\1')
29066 inflect.singular(/(vert|ind)ices$/i, '\1ex')
29067 inflect.singular(/(matr)ices$/i, '\1ix')
29068 inflect.singular(/(quiz)zes$/i, '\1')
29069 inflect.singular(/(database)s$/i, '\1')
29070 @digest = digest || "SHA1"
29071 data, digest = signed_message.split("--")
29072 data = signed_message.split("--")[0]
29073 coder.represent_seq "!omap", map { |k, v| { k => v } }
29074 dup.tap { |hash| hash.select!(*args, &block) }
29075 dup.tap { |hash| hash.reject!(*args, &block) }
29076 env.value = !env.halted && (!block_given? || yield)
29077 (skipped ||= []) << current
29078 if !halted && user_conditions.all? { |c| c.call(target, value) }
29079 if user_conditions.all? { |c| c.call(target, value) }
29080 options = {
29081 if: @if.dup,
29082 }
29083 @kind == _kind && filter == _filter
29084 Array(chain_config[:scope]).map { |s| public_send(s) }
29085 if conditionals.any? { |c| c.is_a?(String) }
29086 @if.map { |c| CallTemplate.build(c, self).make_lambda } +
29087 new(nil, filter, [], nil)
29088 new(filter, :call, [:target, :value], nil)
29089 new(nil, :instance_exec, [:target, :block], filter)
29090 new(nil, :instance_exec, [:target], filter)
29091 new(nil, :instance_exec, [], filter)
29092 new(filter, method_to_call, [:target], nil)
29093 @before = []
29094 @after = []
29095 arg.halted || !@user_conditions.all? { |c| c.call(arg.target, arg.value) }
29096 @before.each { |b| b.call(arg) }
29097 @after.each { |a| a.call(arg) }
29098 @name = name
29099 @config = {
29100 scope: [:kind],
29101 }.merge!(config)
29102 @chain = []
29103 def each(&block); @chain.each(&block); end
29104 callbacks.each { |c| append_one(c) }
29105 callbacks.each { |c| prepend_one(c) }
29106 @chain.delete_if { |c| callback.duplicates?(c) }
29107 callback = chain.find { |c| c.matches?(type, filter) }
29108 if callback && (options.key?(:if) || options.key?(:unless))
29109 callbacks.each { |c| chain.delete(c) }
29110 l = a.unpack "C#{a.bytesize}"
29111 res = 0
29112 b.each_byte { |byte| res |= byte ^ l.shift }
29113 res == 0
29114 method_name.end_with?("?") || super
29115 if method_name.end_with?("?")
29116 self == method_name[0..-2]
29117 YAML.unsafe_load(source, **options) || {}
29118 YAML.load(source, **options) || {}
29119 erb = ERB.new(@content).tap { |e| e.filename = @content_path }
29120 def as_json(options = {})
29121 { _rails: { message: @message, exp: @expires_at, pur: @purpose } }
29122 class << self
29123 if data.is_a?(Hash) && data.key?("_rails")
29124 new(decode(data["_rails"]["message"]), data["_rails"]["exp"], data["_rails"]["pur"])
29125 @purpose.to_s == purpose.to_s
29126 @expires_at.nil? || Time.now.utc < @expires_at
29127 @signed, @encrypted = [], []
29128 @signed << args
29129 @rotations = []
29130 def fork(*)
29131 @callbacks = []
29132 if @pid != Process.pid
29133 alias_method :_get, :[] # preserve the original #[] method
29134 def []=(key, value)
29135 def [](key)
29136 if name_string.chomp!("=")
29137 bangs = name_string.chomp!("!")
29138 super() { |h, k| parent._get(k) }
29139 super() { |h, k| parent[k] }
29140 @hash_digest_class ||= ::Digest::MD5
29141 def initialize(files, dirs = {}, &block)
29142 @core = Core.new(files, dirs)
29143 @files = files.map { |file| Pathname(file).expand_path }.to_set
29144 @dirs = dirs.each_with_object({}) do |(dir, exts), hash|
29145 hash[Pathname(dir).expand_path] = Array(exts).map { |ext| ext.to_s.sub(/\A\.?/, ".") }.to_set
29146 @missing = []
29147 @dtw, @missing = [*@dtw, *@missing].partition(&:exist?)
29148 @listener = @dtw.any? ? Listen.to(*@dtw, &method(:changed)) : nil
29149 @missing.any?(&:exist?)
29150 @updated.make_true if (modified + added + removed).any? { |f| watching?(f) }
29151 elsif dir == @common_path || dir.root?
29152 dtw = @dirs.keys | @files.map(&:dirname)
29153 accounted_for = dtw.to_set + Gem.path.map { |path| Pathname(path) }
29154 dtw.reject { |dir| dir.ascend.drop(1).any? { |parent| accounted_for.include?(parent) } }
29155 paths.map { |path| path.ascend.to_a }.reduce(&:&)&.first
29156 Dir.glob(File.expand_path("core_ext/*.rb", __dir__)).sort.each do |path|
29157 DATE_TO_PART = { "Y" => :years, "M" => :months, "W" => :weeks, "D" => :days }
29158 TIME_TO_PART = { "H" => :hours, "M" => :minutes, "S" => :seconds }
29159 @parts = {}
29160 @mode = :start
29161 @sign = 1
29162 self.sign = (scanner.matched == "-") ? -1 : 1
29163 fractions = parts.values.reject(&:zero?).select { |a| (a % 1) != 0 }
29164 unless fractions.empty? || (fractions.size == 1 && fractions.last == @parts.values.reject(&:zero?).last)
29165 output = +"P"
29166 time = +""
29167 time << "#{sprintf(@precision ? "%0.0#{@precision}f" : '%g', parts[:seconds])}S"
29168 output << "T#{time}" unless time.empty?
29169 parts = @duration.parts.each_with_object(Hash.new(0)) do |(k, v), p|
29170 {
29171 en: {
29172 number: {
29173 nth: {
29174 when 1; "st"
29175 when 2; "nd"
29176 when 3; "rd"
29177 when 4, 5, 6, 7, 8, 9, 10, 11, 12, 13; "th"
29178 num_modulo %= 10 if num_modulo > 13
29179 config.i18n.load_path = []
29180 I18n.public_send("#{setting}=", value)
29181 I18n.load_path.keep_if { |p| File.exist?(p) }
29182 args = \
29183 [*(fallbacks[:defaults] || []) << fallbacks[:map]].compact
29184 @load_hooks = Hash.new { |h, k| h[k] = [] }
29185 def on_load(name, options = {}, &block)
29186 @load_hooks[name] << [block, options]
29187 @loaded[name] << base
29188 @run_once[name] << block if once
29189 expanded_cache_key = namespace ? +"#{namespace}/" : +""
29190 expanded_cache_key << "#{prefix}/"
29191 raise "Could not find cache store adapter for #{store} (#{e})"
29192 {}.tap do |pool_options|
29193 @options = options ? options.dup : {}
29194 entries = hash.each_with_object({}) do |(name, value), memo|
29195 reads.fetch(name) { writes[name] = yield(name) }
29196 names.map! { |key| normalize_key(key, options) }
29197 if source.start_with?("^")
29198 source = ".*#{source[0, source.length]}"
29199 entries.count { |key| delete_entry(key, **options) }
29200 if key && key.encoding != Encoding::UTF_8
29201 if key.size > 1
29202 key.collect { |k, v| "#{k}=#{v}" }.sort!
29203 (options && options[:version].try(:to_param)) || expanded_version(key)
29204 if logger && logger.debug? && !silence?
29205 logger.debug "Cache #{operation}: #{normalize_key(key, options)}#{options.blank? ? "" : " (#{options.inspect})"}"
29206 payload = { key: key, store: self.class.name }
29207 if (race_ttl > 0) && (Time.now.to_f - entry.expires_at <= race_ttl)
29208 @expires_in = expires_in && expires_in.to_f
29209 @version && version && @version != version
29210 @expires_in && @created_at + @expires_in <= Time.now.to_f
29211 @expires_in ? @created_at + @expires_in : nil
29212 @expires_in = value.to_f - @created_at
29213 @s ||= Marshal.dump(@value).bytesize
29214 if @value && !compressed? && !(@value.is_a?(Numeric) || @value == true || @value == false)
29215 if @value.is_a?(String)
29216 @value = @value.dup
29217 def raw_state # :nodoc:
29218 data = {}
29219 data[thread] = {
29220 @cv = new_cond
29221 @sharing = Hash.new(0)
29222 @waiting = {}
29223 @sleeping = {}
29224 @sharing.size > (@sharing[Thread.current] > 0 ? 1 : 0)
29225 @waiting.any? { |t, (_, c)| t != Thread.current && !c.include?(purpose) }
29226 @waiting.any? { |t, (p, _)| compatible.include?(p) && @waiting.all? { |t2, (_, c2)| t == t2 || c2.include?(p) } }
29227 @cv.wait_while { yield }
29228 mon_try_enter ||
29229 @watching = []
29230 @stack = Hash.new { |h, k| h[k] = [] }
29231 constants = []
29232 constants << ([namespace, suffix] - ["Object"]).join("::")
29233 modules.each { |mod| @stack[mod].pop }
29234 (@blamed_files ||= []).unshift file
29235 @blamed_files ||= []
29236 def depend_on(file_name, message = "No such file to load -- %s.rb")
29237 if file_name = load_error.message[/ -- (.*?)(\.rb)?$/, 1]
29238 file_name = file_name.chomp(".rb")
29239 load_args = ["#{file_name}.rb"]
29240 path = path.chomp(".rb")
29241 paths = []
29242 next if expanded_path[root_size] != ?/
29243 nesting = expanded_path[(root_size + 1)..-1]
29244 path_suffix += ".rb" unless path_suffix.end_with?(".rb")
29245 nil # Gee, I sure wish we had first_match ;-)
29246 autoload_once_paths.any? { |base| path.start_with?(base.to_s) }
29247 parent_paths = const_paths.collect { |const_path| const_path[/.*(?=::)/] || ::Object }
29248 mod_name == "Object" ? name.to_s : "#{mod_name}::#{name}"
29249 elsif (parent = from_mod.module_parent) && parent != from_mod &&
29250 ! from_mod.module_parents.any? { |p| p.const_defined?(const_name, false) }
29251 name_error.set_backtrace(caller.reject { |l| l.start_with? __FILE__ })
29252 def key?(key)
29253 @store.key?(key)
29254 key = key.name if key.respond_to?(:name)
29255 alias :[] :get
29256 real_mod_name(desc) ||
29257 normalized = const.to_s.delete_prefix("::")
29258 normalized.sub!(/\A(Object::)+/, "")
29259 parent_name = constants.join("::")
29260 Null = Object.new # :nodoc:
29261 def self.to_run(*args, &block)
29262 set_callback(:run, *args, &block)
29263 RunHook = Struct.new(:hook) do # :nodoc:
29264 class << self # :nodoc:
29265 def self.active? # :nodoc:
29266 def run! # :nodoc:
29267 @_hook_state ||= {}
29268 undef_method(method) unless method.start_with?("__", "instance_eval", "class", "object_id")
29269 arguments << lambda { |*args| @options.deep_merge(proc.call(*args)) }
29270 @context.__send__(method, *arguments, **options, &block)
29271 @context.__send__(method, *arguments, &block)
29272 sources.any? { |source| source == logger_source }
29273 define_method(:add) do |*args, &block|
29274 super(*args, &block)
29275 define_method(:<<) do |x|
29276 logger << x
29277 if String === number
29278 )
29279 if value.is_a?(::Method) || value.is_a?(::Proc)
29280 if value.arity == 1
29281 type_name ||= value.class.name if value && !value.respond_to?(:to_str)
29282 attributes = options[:skip_types] || type_name.nil? ? {} : { type: type_name }
29283 def rename_key(key, options = {})
29284 left, middle, right = /\A(_*)(.*?)(_*)\Z/.match(key.strip)[1, 3]
29285 key = if klass.is_a?(Module) && klass.respond_to?(:===)
29286 self.rescue_handlers += [[key, with]]
29287 if method.arity == 0
29288 -> e { method.call }
29289 -> e { object.instance_exec(&rescuer) }
29290 -> e { object.instance_exec(e, &rescuer) }
29291 keys.reject { |m| method_defined?(m) }.each do |key|
29292 def #{key}; _get(#{key.inspect}); end
29293 @_config ||= if respond_to?(:superclass) && superclass.respond_to?(:config)
29294 reader, reader_line = "def #{name}; config.#{name}; end", __LINE__
29295 writer, writer_line = "def #{name}=(value); config.#{name} = value; end", __LINE__
29296 send("#{name}=", yield) if block_given?
29297 instance_variable_set :"@#{default}", env == default
29298 class_eval "def #{env}?; @#{env}; end"
29299 @@direct_descendants = {}
29300 arr = []
29301 @refs = []
29302 @refs = @refs.dup
29303 def <<(klass)
29304 @refs.reject! do |ref|
29305 yield ref.__getobj__
29306 @refs.delete_if { |ref| !ref.weakref_alive? }
29307 @@subscribers ||= []
29308 @queue_key = [self.class.name, object_id].join "-"
29309 method = name.split(".").first
29310 @registry = {}
29311 @registry[queue_key] ||= []
29312 all = @files.select { |f| File.exist?(f) }
29313 @updated_at || max_mtime(paths) || Time.at(0)
29314 globs = hash.map do |key, value|
29315 key.gsub(",", '\,')
29316 parameterized_string.gsub!(/[^a-z0-9\-_]+/i, separator)
29317 if separator == "-"
29318 re_leading_trailing_separator = /^-|-$/i
29319 re_leading_trailing_separator = /^#{re_sep}|#{re_sep}$/i
29320 @__instance__ = Concurrent::Map.new
29321 @regex_array = []
29322 def <<(*word)
29323 @regex_array += words.map { |word| to_regex(word) }
29324 @regex_array.any? { |regex| regex.match? str }
29325 /\b#{::Regexp.escape(string)}\Z/i
29326 @__instance__[locale] ||= new
29327 @plurals, @singulars, @uncountables, @humans, @acronyms = [], [], Uncountables.new, [], {}
29328 s0 = singular[0]
29329 srest = singular[1..-1]
29330 p0 = plural[0]
29331 prest = plural[1..-1]
29332 plural(/(#{s0})#{srest}$/i, '\1' + prest)
29333 plural(/(#{p0})#{prest}$/i, '\1' + prest)
29334 singular(/(#{s0})#{srest}$/i, '\1' + srest)
29335 singular(/(#{p0})#{prest}$/i, '\1' + srest)
29336 plural(/#{s0.downcase}(?i)#{srest}$/, p0.downcase + prest)
29337 plural(/#{p0.downcase}(?i)#{prest}$/, p0.downcase + prest)
29338 singular(/#{s0.downcase}(?i)#{srest}$/, s0.downcase + srest)
29339 singular(/#{p0.downcase}(?i)#{prest}$/, s0.downcase + srest)
29340 def clear(scope = :all)
29341 @plurals, @singulars, @uncountables, @humans = [], [], Uncountables.new, []
29342 instance_variable_set "@#{scope}", []
29343 @acronyms_underscore_regex = /(?:(?<=([A-Za-z\d]))|\b)(#{@acronym_regex})(?=\b|[^a-z])/
29344 string = string.sub(/^[a-z\d]*/) { |match| inflections.acronyms[match] || match.capitalize }
29345 string.gsub!(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{inflections.acronyms[$2] || $2.capitalize}" }
29346 string.gsub!("/", "::")
29347 word = camel_cased_word.to_s.gsub("::", "/")
29348 word.gsub!(inflections.acronyms_underscore_regex) { "#{$1 && '_' }#{$2.downcase}" }
29349 word.gsub!(/([A-Z])(?=[A-Z][a-z])|([a-z\d])(?=[A-Z])/) { ($1 || $2) << "_" }
29350 word.tr!("-", "_")
29351 result.sub!(/\A_+/, "")
29352 result.tr!("_", " ")
29353 result.gsub!(/([a-z\d]*)/i) do |match|
29354 result.sub!(/\A\w/) { |match| match.upcase }
29355 string.length > 0 ? string[0].upcase.concat(string[1..-1]) : ""
29356 camelize(singularize(table_name.to_s.sub(/.*\./, "")))
29357 underscored_word.tr("_", "-")
29358 path = path.to_s
29359 if i = path.rindex("::")
29360 path[(i + 2)..-1]
29361 if camel_cased_word.blank? || !camel_cased_word.include?("::")
29362 names = camel_cased_word.split("::")
29363 raise if e.name && !(camel_cased_word.to_s.split("::").include?(e.name.to_s) ||
29364 e.name.to_s == camel_cased_word.to_s)
29365 parts = camel_cased_word.split("::")
29366 part.empty? ? acc : "#{part}(::#{acc})?"
29367 @options = options || {}
29368 def to_json(*)
29369 s = super
29370 result = {}
29371 value.each do |k, v|
29372 value.map { |v| jsonify(v) }
29373 data.map! { |d| convert_dates_from(d) }
29374 def setup # :nodoc:
29375 @flush_count = 0
29376 @logged = Hash.new { |h, k| h[k] = [] }
29377 @logged[level] << yield
29378 @logged[level].compact.map { |l| l.to_s.strip }
29379 @flush_count += 1
29380 Fiber.current.__id__
29381 def add(severity, message = nil, progname = nil, &block) #:nodoc:
29382 if !key.nil? && content_path.exist?
29383 tmp_file = "#{Process.pid}.#{content_path.basename.to_s.chomp('.enc')}"
29384 @iterations = options[:iterations] || 2**16
29385 @cache_keys[args.join("|")] ||= @key_generator.generate_key(*args)
29386 delegate :to_i, :to_f, :to_s, to: :value
29387 def -@
29388 def <=>(other)
29389 if Scalar === other || Duration === other
29390 value <=> other
29391 def +(other)
29392 calculate(:+, other)
29393 def -(other)
29394 calculate(:-, other)
29395 def *(other)
29396 calculate(:*, other)
29397 def /(other)
29398 calculate(:/, other)
29399 def %(other)
29400 calculate(:%, other)
29401 if Scalar === other
29402 PARTS = [:years, :months, :weeks, :days, :hours, :minutes, :seconds].freeze
29403 def ===(other) #:nodoc:
29404 parts = {}
29405 remainder_sign = value <=> 0
29406 parts.inject(0) do |total, (part, value)|
29407 @value, @parts = value, parts
29408 @parts.reject! { |k, v| v.zero? } unless value == 0
29409 [other, self]
29410 seconds = @parts.fetch(:seconds, 0) + other
29411 self + (-other)
29412 if Duration === other || Scalar === other
29413 def -@ #:nodoc:
29414 def +@ #:nodoc:
29415 def is_a?(klass) #:nodoc:
29416 Duration == klass || value.is_a?(klass)
29417 alias :kind_of? :is_a?
29418 def instance_of?(klass) # :nodoc:
29419 def ==(other)
29420 Duration === other && other.value.eql?(value)
29421 sum(1, time)
29422 def ago(time = ::Time.current)
29423 sum(-1, time)
29424 def as_json(options = nil) #:nodoc:
29425 coder.map = { "value" => @value, "parts" => @parts }
29426 def sum(sign, time = ::Time.current)
29427 unless time.acts_like?(:time) || time.acts_like?(:date)
29428 parts.inject(time) do |t, (type, number)|
29429 if type == :seconds
29430 t.since(sign * number * 60)
29431 elsif type == :hours
29432 t.since(sign * number * 3600)
29433 t.advance(type => sign * number)
29434 silencer ? log_at(severity) { yield self } : yield(self)
29435 sign = (seconds < 0 ? "-" : "+")
29436 minutes = (seconds.abs % 3600) / 60
29437 def [](arg)
29438 @lazy_zones_map[arg] ||= create(arg)
29439 arg *= 3600 if arg.abs <= 13
29440 all.find { |z| z.utc_offset == arg.to_i }
29441 @zones = nil
29442 @zones_map = nil
29443 MAPPING.inject([]) do |memo, (key, value)|
29444 memo << self[key] if value == tz_id
29445 @zones_map ||= MAPPING.each_with_object({}) do |(name, _), zones|
29446 def <=>(zone)
29447 result = (utc_offset <=> zone.utc_offset)
29448 result = (name <=> zone.name) if result == 0
29449 def =~(re)
29450 re === name || re === MAPPING[name]
29451 (re == name) || (re == MAPPING[name]) ||
29452 ((Regexp === re) && (re.match?(name) || re.match?(MAPPING[name])))
29453 time = Time.utc(*args)
29454 def at(*args)
29455 time = Time.new(
29456 parts.fetch(:hour, 0),
29457 parts.fetch(:min, 0),
29458 parts.fetch(:sec, 0) + parts.fetch(:sec_fraction, 0),
29459 def parse(str, now = now())
29460 parts.fetch(:sec) + parts.fetch(:sec_fraction, 0),
29461 def strptime(str, format, now = now())
29462 today + 1
29463 today - 1
29464 t : Time.utc(t.year, t.month, t.day, t.hour, t.min, t.sec, t.sec_fraction)
29465 coder.tag = "!ruby/object:#{self.class}"
29466 coder.map = { "name" => tzinfo.name }
29467 parts.fetch(:mday, parts[:year] || parts[:mon] ? 1 : now.day),
29468 if parts[:offset] || parts[:seconds]
29469 @data.with { |c| c.incr(normalize_key(name, options), amount, options[:expires_in]) }
29470 @data.with { |c| c.decr(normalize_key(name, options), amount, options[:expires_in]) }
29471 rescue_error_with(nil) { @data.with { |c| c.flush_all } }
29472 @data.with { |c| c.stats }
29473 rescue_error_with(nil) { deserialize_entry(@data.with { |c| c.get(key, options) }) }
29474 method = options[:unless_exist] ? :add : :set
29475 if options[:race_condition_ttl] && expires_in > 0 && !options[:raw]
29476 @data.with { |c| c.send(method, key, value, expires_in, **options, compress: false) }
29477 raw_values = @data.with { |c| c.get_multi(keys_to_names.keys) }
29478 values = {}
29479 rescue_error_with(false) { @data.with { |c| c.delete(key) } }
29480 key = key.gsub(ESCAPE_KEY_CHARS) { |match| "%#{match.getbyte(0).to_s(16).upcase}" }
29481 key = "#{key[0, 213]}:md5:#{ActiveSupport::Digest.hexdigest(key)}" if key.size > 250
29482 logger.error("DalliError (#{e}): #{e.message}") if logger
29483 gem "redis", ">= 4.0.1"
29484 warn "The Redis cache store requires the redis gem, version 4.0.1 or later. Please add it to your Gemfile: `gem \"redis\", \"~> 4.0\"`"
29485 def build_redis(redis: nil, url: nil, **redis_options) #:nodoc:
29486 if redis.is_a?(Proc)
29487 urls.each { |u| dist.add_node url: u }
29488 @redis ||= begin
29489 cursor = "0"
29490 nodes = c.respond_to?(:nodes) ? c.nodes : [c]
29491 end until cursor == "0"
29492 redis.with { |c| c.flushdb }
29493 raw = options&.fetch(:raw, false)
29494 deserialize_entry(redis.with { |c| c.get(key) }, raw: raw)
29495 return {} if names == []
29496 keys = names.map { |name| normalize_key(name, options) }
29497 redis.with { |c| c.mget(*keys) }
29498 names.zip(values).each_with_object({}) do |(name, value), results|
29499 if race_condition_ttl && expires_in && expires_in > 0 && !raw
29500 modifiers = {}
29501 modifiers[:px] = (1000 * expires_in.to_f).ceil if expires_in
29502 redis.with { |c| c.set key, serialized_entry, **modifiers }
29503 redis.with { |c| c.set key, serialized_entry }
29504 redis.with { |c| c.del key }
29505 redis.with { |c| c.del(entries) }
29506 suffix = ":sha2:#{::Digest::SHA2.hexdigest(key)}"
29507 rescue ::Redis::BaseError => e
29508 options ||= {}
29509 @data = {}
29510 @max_size = options[:size] || 32.megabytes
29511 @max_prune_time = options[:max_prune_time] || 2
29512 @cache_size = 0
29513 keys = synchronize { @data.keys }
29514 entry = @data[key]
29515 @data[key] = payload
29516 prune(@max_size * 0.75, @max_prune_time) if @cache_size > @max_size
29517 num = num.to_i + amount
29518 @data[key]
29519 @data[key] = entry
29520 !!@data.delete(key)
29521 def fetch_entry(key, options = nil) # :nodoc:
29522 entry = @data.fetch(key) { @data[key] = yield }
29523 def clear(**options) # :nodoc:
29524 def cleanup(**options) # :nodoc:
29525 def increment(name, amount = 1, **options) # :nodoc:
29526 def decrement(name, amount = 1, **options) # :nodoc:
29527 hit = true
29528 @local_cache_key ||= "#{self.class.name.underscore}_local_cache_#{object_id}".gsub(/[\/-]/, "_").to_sym
29529 @app = nil
29530 @app = app
29531 [400, {}, []]
29532 FileUtils.rm_r(root_dirs.collect { |f| File.join(cache_path, f) })
29533 entry = File.open(key) { |f| deserialize_entry(f.read) }
29534 rescue => e
29535 logger.error("FileStoreError (#{e}): #{e.message}") if logger
29536 File.open(file_name, "r+") do |f|
29537 fname_paths = []
29538 Dir.each_child(dir) do |d|
29539 name = File.join(dir, d)
29540 @period ||= time_zone.period_for_utc(@utc)
29541 def in_time_zone(new_zone = ::Time.zone)
29542 zone == "UTC" || zone == "UCT"
29543 alias_method :gmt?, :utc?
29544 %(#{time.strftime("%Y/%m/%d %H:%M:%S")} #{formatted_offset(false)})
29545 initialize(coder["utc"], coder["zone"], coder["time"])
29546 coder.map = { "utc" => utc, "zone" => time_zone, "time" => time }
29547 to_s(:rfc822)
29548 if format == :db
29549 format = format.gsub(/((?:\A|[^%])(?:%%)*)%Z/, "\\1#{zone}")
29550 utc <=> other
29551 alias_method :before?, :<
29552 alias_method :after?, :>
29553 alias_method :since, :+
29554 alias_method :in, :+
29555 result = utc.acts_like?(:date) ? utc.ago(other) : utc - other rescue utc.ago(other)
29556 new_zone = ::Time.find_zone(options[:zone])
29557 new_zone ||= time_zone
29558 [time.sec, time.min, time.hour, time.day, time.mon, time.year, time.wday, time.yday, dst?, zone]
29559 def is_a?(klass)
29560 klass == ::Time || super
29561 alias_method :kind_of?, :is_a?
29562 wrap_with_time_zone time.__send__(sym, *args, &block)
29563 @time += 1.hour
29564 return time if time.instance_of?(::Time) && time.utc?
29565 ActiveSupport::Duration === obj && obj.parts.any? { |p| [:years, :months, :weeks, :days].include?(p[0]) }
29566 s = rounded_number.to_s("F")
29567 a, b = s.split(".", 2)
29568 b << "0" * precision
29569 a << "."
29570 a << b[0, precision]
29571 number.sub(/(#{escaped_separator})(\d*[1-9])?0+\z/, '\1\2').sub(/#{escaped_separator}\z/, "")
29572 left, right = number.to_s.split(".")
29573 default_pattern = /(\d{1,3})(\d{3})(\d{4}$)/
29574 default_pattern = /(\d{0,3})(\d{3})(\d{4})$/
29575 opts[:delimiter] || "-"
29576 code.blank? ? "" : "+#{code}#{delimiter}"
29577 ext.blank? ? "" : " x #{ext}"
29578 conversion_format.gsub("%n", number_to_format).gsub("%u", unit)
29579 exp = (Math.log(number) / Math.log(base)).to_i
29580 -1 => :deci, -2 => :centi, -3 => :mili, -6 => :micro, -9 => :nano, -12 => :pico, -15 => :femto }
29581 units = opts[:units]
29582 @number = number / (10**exponent)
29583 format.gsub("%n", rounded_number).gsub("%u", unit).strip
29584 units[exp] || ""
29585 I18n.translate("#{units}.#{exp}", locale: options[:locale], count: number.to_i)
29586 exponent = number != 0 ? Math.log10(number.abs).floor : 0
29587 unit_exponents(units).find { |e| exponent >= e } || 0
29588 if number.sub!(/^-/, "") &&
29589 (options[:precision] != 0 || number.to_f > 0.5)
29590 format.gsub("%n", rounded_number).gsub("%u", options[:unit])
29591 @options ||= begin
29592 defaults[:negative_format] = "-#{opts[:format]}" if opts[:format]
29593 i18n[:negative_format] ||= "-#{i18n[:format]}" if i18n[:format]
29594 format: {
29595 separator: ".",
29596 delimiter: ",",
29597 },
29598 format: "%u%n",
29599 negative_format: "-%u%n",
29600 unit: "$",
29601 delimiter: "",
29602 format: "%n%"
29603 delimiter: ""
29604 human: {
29605 format: "%n %u",
29606 units: {
29607 byte: "Bytes",
29608 unit: "",
29609 key.split(".").reduce(DEFAULTS) { |defaults, k| defaults[k.to_sym] }
29610 define_method("#{name}=") do |attribute|
29611 def reset_all # :nodoc:
29612 def clear_all # :nodoc:
29613 @attributes = {}
29614 self.attributes = {}
29615 new_attributes.each { |key, value| public_send("#{key}=", value) }
29616 keys.index_with { |key| public_send(key) }
29617 @mask = mask
29618 strings, regexps, blocks, deep_regexps, deep_strings = [], [], [], nil, nil
29619 if item.to_s.include?("\\.")
29620 (deep_regexps ||= []) << item
29621 if s.include?("\\.")
29622 (deep_strings ||= []) << s
29623 strings << s
29624 (deep_regexps ||= []) << Regexp.new(deep_strings.join("|"), true) if deep_strings&.any?
29625 def value_for_key(key, value, parents = [], original_params = nil)
29626 if regexps.any? { |r| r.match?(key.to_s) }
29627 value = @mask
29628 elsif deep_regexps && (joined = parents.join(".")) && deep_regexps.any? { |r| r.match?(joined) }
29629 value = value.map { |v| value_for_key(key, v, parents, original_params) }
29630 blocks.each { |b| b.arity == 2 ? b.call(key, value) : b.call(key, value, original_params) }
29631 to_run(:after) { self.class.prepare! }
29632 def self.run!(reset: false) # :nodoc:
29633 def self.check! # :nodoc:
29634 def class_unload!(&block) # :nodoc:
29635 def complete! # :nodoc:
29636 def self.[](*args)
29637 new.merge!(Hash[*args])
29638 alias_method :store, :[]=
29639 alias_method :has_key?, :key?
29640 args[0] = convert_key(args[0]) if args.size > 0
29641 super(*args.map { |arg| convert_key(arg) })
29642 super(*keys.map { |key| convert_key(key) })
29643 super(*indices.map { |key| convert_key(key) }, &block)
29644 slice(*self.keys - keys.map { |key| convert_key(key) })
29645 dup.tap { |hash| hash.transform_values!(*args, &block) }
29646 dup.tap { |hash| hash.transform_keys!(*args, &block) }
29647 self[yield(key)] = delete(key)
29648 keys.map! { |key| convert_key(key) }
29649 dup.tap(&:compact!)
29650 _new_hash = Hash.new
29651 each do |key, value|
29652 key.kind_of?(Symbol) ? key.name : key
29653 key.kind_of?(Symbol) ? key.to_s : key
29654 if block && key?(key)
29655 msg = "the directory '%s' does not contain a file named '%s'"
29656 pid = fork do
29657 failures.map! { |e|
29658 write.puts [result].pack("m")
29659 env = {
29660 test_opts = "-n#{self.class.name}##{name}"
29661 load_path_args = []
29662 $-I.each do |p|
29663 load_path_args << "-I"
29664 child = IO.popen([env, Gem.ruby, *load_path_args, $0, *ORIG_ARGV, test_opts])
29665 stream_io = eval("$#{stream}")
29666 def <<(o)
29667 o[2] = DRbObject.new(o[2]) if o
29668 @queue << o
29669 if test = @queue.pop
29670 @in_flight[[test[0].to_s, test[1]]] = test
29671 error.set_backtrace([""])
29672 @url = url
29673 set_process_title("#{klass}##{method}")
29674 assert warnings.any? { |w| match.match?(w) }, "No deprecation warning matched #{match}: #{warnings.join(', ')}"
29675 @@after_fork_hooks = []
29676 @@after_fork_hooks << blk
29677 @@run_cleanup_hooks = []
29678 @@run_cleanup_hooks << blk
29679 @worker_pool = []
29680 def <<(work)
29681 message ||= "Expected #{mu_pp(object)} to be nil or false"
29682 difference = args[0] || 1
29683 exps = expressions.keys.map { |e|
29684 e.respond_to?(:call) ? e : lambda { eval(e, block.binding) }
29685 before = exps.map(&:call)
29686 exp = expression.respond_to?(:call) ? expression : -> { eval(expression.to_s, block.binding) }
29687 error = "#{message}.
#{error}" if message
29688 error = "#{error}. It was already #{to}" if before == to
29689 error = "Expected change to #{to}
"
29690 assert to === after, error
29691 @stubs = Concurrent::Map.new { |h, k| h[k] = {} }
29692 new_name = "__simple_stub__#{method_name}"
29693 if date_or_time.is_a?(Date) && !date_or_time.is_a?(DateTime)
29694 simple_stubs.stub_object(Time, :now) { at(now.to_i) }
29695 names = test_name.split "::"
29696 names.last.sub!(/Test$/, "")
29697 object.stub(method_name, proc { times_called += 1; returns }) { yield }
29698 error = "Expected #{method_name} to be called #{times} times, " \
29699 if args.all? { |arg| arg.is_a?(Array) }
29700 args.each { |arg| mock.expect(:call, returns, arg) }
29701 klass.define_method("stubbed_#{method_name}") do |*|
29702 test_name = "test_#{name.gsub(/\s+/, '_')}".to_sym
29703 heading = "#{self.class}: #{name}"
29704 divider = "-" * heading.size
29705 @tagged_logger ||= (defined?(Rails.logger) && Rails.logger)
29706 @logger ||= if defined?(Rails) && Rails.respond_to?(:logger)
29707 logger.error "Could not log #{name.inspect} event. #{e.class}: #{e.message} #{e.backtrace}"
29708 def #{level}(progname = nil, &block)
29709 def color(text, color, bold = false) # :doc:
29710 if number.to_i <= 0
29711 padding = (number - size % number) % number
29712 groups = []
29713 start = 0
29714 length = division + (modulo > 0 && modulo > index ? 1 : 0)
29715 last_group << fill_with if fill_with != false &&
29716 modulo > 0 && length == division
29717 groups.each { |g| yield(g) }
29718 arr = dup
29719 result = []
29720 while (idx = arr.index { |i| yield i })
29721 while (idx = arr.index(value))
29722 result << arr
29723 self[position, length] || []
29724 if position >= 0
29725 self[-3]
29726 self[-2]
29727 []
29728 object.to_ary || [object]
29729 def to_sentence(options = {})
29730 words_connector: ", ",
29731 two_words_connector: " and ",
29732 last_word_connector: ", and "
29733 +""
29734 +"#{self[0]}"
29735 +"#{self[0]}#{options[:two_words_connector]}#{self[1]}"
29736 +"#{self[0...-1].join(options[:words_connector])}#{options[:last_word_connector]}#{self[-1]}"
29737 collect(&:id).join(",")
29738 def to_xml(options = {})
29739 if first.class != Hash && all? { |e| e.is_a?(first.class) }
29740 attributes = options[:skip_types] ? {} : { type: "array" }
29741 {}
29742 def unescape(str, escaped = /%[a-fA-F\d]{2}/)
29743 Hash[instance_variables.map { |name| [name[1..-1], instance_variable_get(name)] }]
29744 respond_to?(:empty?) ? !!empty? : !self
29745 empty? ||
29746 collect(&:to_param).join "/"
29747 prefix = "#{key}[]"
29748 collect { |value| value.to_query(prefix) }.join "&"
29749 unless (value.is_a?(Hash) || value.is_a?(Array)) && value.empty?
29750 value.to_query(namespace ? "#{namespace}[#{key}]" : key)
29751 query.join("&")
29752 if options.is_a?(::JSON::State)
29753 finite? ? self : nil
29754 finite? ? to_s : nil
29755 map { |v| options ? v.as_json(options.dup) : v.as_json }
29756 subset.each do |k, v|
29757 result[k.to_s] = options ? v.as_json(options.dup) : v.as_json
29758 %(#{strftime("%Y/%m/%d %H:%M:%S")} #{formatted_offset(false)})
29759 strftime("%Y-%m-%d")
29760 strftime("%Y/%m/%d")
29761 strftime("%Y/%m/%d %H:%M:%S %z")
29762 respond_to? :"acts_like_#{duck}?"
29763 def try(method_name = nil, *args, &b)
29764 if b.arity == 0
29765 def try!(method_name = nil, *args, &b)
29766 def try(_method_name = nil, *)
29767 def try!(_method_name = nil, *)
29768 in?(another_object) ? self : nil
29769 map(&:deep_dup)
29770 hash = dup
29771 if (::String === key && key.frozen?) || ::Symbol === key
29772 def self.civil_from_format(utc_or_local, year, month = 1, day = 1, hour = 0, min = 0, sec = 0)
29773 if utc_or_local.to_sym == :local
29774 offset = ::Time.local(year, month, day).utc_offset.to_r / 86400
29775 offset = 0
29776 (sec_fraction * 1_000_000).to_i
29777 (sec_fraction * 1_000_000_000).to_i
29778 (offset * 86400).to_i
29779 ::Time.zone ? ::Time.zone.now.to_datetime : ::Time.now.to_datetime
29780 sec + (min * 60) + (hour * 3600)
29781 end_of_day.to_i - to_i
29782 new_usec = options.fetch(:usec, (options[:hour] || options[:min] || options[:sec]) ? 0 : Rational(nsec, 1000))
29783 options.fetch(:min, options[:hour] ? 0 : min),
29784 options.fetch(:sec, (options[:hour] || options[:min]) ? 0 : sec) + new_fraction,
29785 options[:days] = options.fetch(:days, 0) + 7 * partial_weeks
29786 options[:hours] = options.fetch(:hours, 0) + 24 * partial_days
29787 options.fetch(:minutes, 0) * 60 +
29788 utc = new_offset(0)
29789 offset == 0
29790 def in_time_zone(zone = ::Time.zone)
29791 time = acts_like?(:time) ? self : nil
29792 time || to_time
29793 sunday: 0,
29794 monday: 1,
29795 friday: 5,
29796 to_date == ::Date.current
29797 first_quarter_month = month - (2 + month) % 3
29798 last_quarter_month = month + (12 - month) % 3
29799 (wday - start_day_number) % 7
29800 from_now += 7 unless from_now > 0
29801 ago += 7 unless ago > 0
29802 other.change(hour: hour, min: min, sec: sec, nsec: try(:nsec))
29803 if exc.message.match(%r|undefined class/module (.+?)(?:::)?\z|)
29804 ary[2] = (ary[2] & 0x0FFF) | (version << 12)
29805 ary[3] = (ary[3] & 0x3FFF) | 0x8000
29806 old_zone, ::Time.zone = ::Time.zone, new_zone
29807 ::Time.zone = old_zone
29808 db: "%Y-%m-%d %H:%M:%S",
29809 inspect: "%Y-%m-%d %H:%M:%S.%9N %z",
29810 number: "%Y%m%d%H%M%S",
29811 time: "%H:%M",
29812 short: "%d %b %H:%M",
29813 long: "%B %d, %Y %H:%M",
29814 time.strftime("%B #{day_format}, %Y %H:%M")
29815 rfc822: lambda { |time|
29816 time.strftime("%a, %d %b %Y %H:%M:%S #{offset_format}")
29817 def ===(other)
29818 super || (self == Time && other.is_a?(ActiveSupport::TimeWithZone))
29819 if month == 2 && ::Date.gregorian_leap?(year)
29820 days_in_month(2, year) + 337
29821 ::Time.zone ? ::Time.zone.now : ::Time.now
29822 to_i - change(hour: 0).to_i + (usec / 1.0e+6)
29823 ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec, new_offset)
29824 ::Time.utc(new_year, new_month, new_day, new_hour, new_min, new_sec)
29825 ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec, zone)
29826 ::Time.local(new_year, new_month, new_day, new_hour, new_min, new_sec)
29827 ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec, utc_offset)
29828 hour: 23,
29829 min: 59,
29830 sec: 59,
29831 def prev_day(days = 1)
29832 def next_day(days = 1)
29833 def to_s(format = nil, options = nil)
29834 if match = message.match(/((::)?([A-Z]\w*)(::[A-Z]\w*)*)$/)
29835 s = s.to_s
29836 name = name.to_s
29837 def [](*args)
29838 to_str[*args]
29839 def initialize(str = "")
29840 self[0, 0]
29841 def []=(*args)
29842 if args.length == 3
29843 def *(*)
29844 def %(args)
29845 defined?(@html_safe) && @html_safe
29846 (!html_safe? || arg.html_safe?) ? arg : CGI.escapeHTML(arg.to_s)
29847 block.binding.eval("proc { |m| $~ = m }").call(match_data)
29848 def pluralize(count = nil, locale = :en)
29849 if count == 1
29850 self[0, position + 1] || +""
29851 def first(limit = 1)
29852 def last(limit = 1)
29853 def to_time(form = :local)
29854 parts.fetch(:offset, form == :utc ? 0 : nil)
29855 form == :utc ? time.utc : time.to_time
29856 gsub!(/[[:space:]]+/, " ")
29857 gsub! pattern, ""
29858 omission = options[:omission] || "..."
29859 stop = \
29860 +"#{self[0, stop]}#{omission}"
29861 omission ||= ""
29862 scan(/\X/) do |grapheme|
29863 sep = options[:separator] || /\s+/
29864 if self =~ /\A((?>.+?#{sep}){#{words_count - 1}}.+?)#{sep}.*/m
29865 $1 + (options[:omission] || "...")
29866 indent_string = indent_string || self[/^[ \t]/] || " "
29867 re = indent_empty_lines ? /^/ : /^(?!$)/
29868 dup.tap { |_| _.indent!(amount, indent_string, indent_empty_lines) }
29869 gsub(/^#{scan(/^[ \t]*(?=\S)/).min}/, "").tap do |stripped|
29870 def step(n = 1, &block)
29871 def ===(value)
29872 if value.is_a?(::Range)
29873 is_backwards_op = value.exclude_end? ? :>= : :>
29874 operator = exclude_end? && !value.exclude_end? ? :< : :<=
29875 value_max = !exclude_end? && value.exclude_end? ? value.max : value.last
29876 db: -> (start, stop) do
29877 inject(:+) || 0
29878 each { |elem| result[yield(elem)] = elem }
29879 to_enum(:index_by) { size if respond_to?(:size) }
29880 each { |elem| result[elem] = yield(elem) }
29881 each { |elem| result[elem] = default }
29882 to_enum(:index_with) { size if respond_to?(:size) }
29883 cnt = 0
29884 cnt > 1
29885 any? { (cnt += 1) > 1 }
29886 map { |element| keys.map { |key| element[key] } }
29887 map { |element| element[key] }
29888 keys.map { |key| first[key] }
29889 reject(&:blank?)
29890 reject { |_k, v| v.blank? }
29891 delete_if { |_k, v| v.blank? }
29892 if block_given? || !(first.is_a?(Integer) && last.is_a?(Integer))
29893 actual_last = exclude_end? ? (last - 1) : last
29894 sum = identity || 0
29895 sum + (actual_last - first + 1) * (actual_last + first) / 2
29896 identity || 0
29897 def sum(init = nil, &block)
29898 if init.is_a?(Numeric) || first.is_a?(Numeric)
29899 init ||= 0
29900 delete_if(&:blank?)
29901 __send__(method, concern(topic, &block))
29902 parent_name = name =~ /::[^:]+\z/ ? -$` : nil
29903 parents = []
29904 parts = module_parent_name.split("::")
29905 definition = []
29906 raise NameError.new("invalid attribute name: #{sym}") unless /\A[_A-Za-z]\w*\z/.match?(sym)
29907 definition << "def self.#{sym}; @@#{sym}; end"
29908 definition << "def #{sym}; @@#{sym}; end"
29909 sym_default_value = (block_given? && default.nil?) ? yield : default
29910 class_variable_set("@@#{sym}", sym_default_value) unless sym_default_value.nil? && class_variable_defined?("@@#{sym}")
29911 definition << "def self.#{sym}=(val); @@#{sym} = val; end"
29912 definition << "def #{sym}=(val); @@#{sym} = val; end"
29913 if prefix == true && /^[^a-z_]/.match?(to)
29914 to = to.to_s
29915 method_def = []
29916 method_names = []
29917 method_name = prefix ? "#{method_prefix}#{method}" : method
29918 definition = if /[^\]]=$/.match?(method)
29919 method_def <<
29920 module_eval(method_def.join(";"), file, line)
29921 return false if name == :marshal_dump || name == :_dump
29922 if #{target}.nil?
29923 if #{allow_nil == true}
29924 attr_name, internal_name = "#{attr_name}=", "#{internal_name}=" if type == :writer
29925 raise NameError.new("invalid attribute name: #{sym}") unless /^[_A-Za-z]\w*$/.match?(sym)
29926 def self.#{sym}
29927 Thread.current["attr_" + name + "_#{sym}"]
29928 def #{sym}
29929 Thread.current["attr_" + name + "_#{sym}"] = default unless default.nil?
29930 def self.#{sym}=(obj)
29931 Thread.current["attr_" + name + "_#{sym}"] = obj
29932 def #{sym}=(obj)
29933 self.class.#{sym} = obj
29934 BASE58_ALPHABET = ("0".."9").to_a + ("A".."Z").to_a + ("a".."z").to_a - ["0", "O", "I", "l"]
29935 def self.base58(n = 16)
29936 idx = byte % 64
29937 def self.base36(n = 16)
29938 number == 0 ? self == 0 : self % number == 0
29939 short: "%d %b",
29940 long: "%B %d, %Y",
29941 db: "%Y-%m-%d",
29942 inspect: "%Y-%m-%d",
29943 number: "%Y%m%d",
29944 date.strftime("%B #{day_format}, %Y") # => "April 25th, 2007"
29945 rfc822: "%d %b %Y",
29946 strftime("%a, %d %b %Y")
29947 ::Time.zone ? ::Time.zone.today : ::Date.today
29948 d = self
29949 d = d >> options[:years] * 12 if options[:years]
29950 d = d >> options[:months] if options[:months]
29951 d = d + options[:weeks] * 7 if options[:weeks]
29952 d = d + options[:days] if options[:days]
29953 ::Date.new(
29954 if other.is_a?(Time)
29955 def to_s(format = "F")
29956 transform_keys!(&:to_s)
29957 each_key do |k|
29958 raise ArgumentError.new("Unknown key: #{k.inspect}. Valid keys are: #{valid_keys.map(&:inspect).join(', ')}")
29959 object.each_with_object({}) do |(key, value), result|
29960 object.map { |e| _deep_transform_keys_in_object(e, &block) }
29961 object.map! { |e| _deep_transform_keys_in_object!(e, &block) }
29962 keys.each { |key| delete(key) }
29963 from_xml xml, []
29964 deep_to_h(@xml)
29965 Hash[params.map { |k, v| [k.to_s.tr("-", "_"), normalize_keys(v)] } ]
29966 params.map { |v| normalize_keys(v) }
29967 if value.include?("type") && !value["type"].is_a?(Hash) && @disallowed_types.include?(value["type"])
29968 _, entries = Array.wrap(value.detect { |k, v| not v.is_a?(String) })
29969 if entries.nil? || value["__content__"].try(:empty?)
29970 entries.collect { |v| deep_to_h(v) }
29971 [deep_to_h(entries)]
29972 xml_value = value.transform_values { |v| deep_to_h(v) }
29973 xml_value["file"].is_a?(StringIO) ? xml_value["file"] : xml_value
29974 value["type"] == "file" || (value["__content__"] && (value.keys.size == 1 || value["__content__"].present?))
29975 value["type"] == "array"
29976 value["type"] == "string" && value["nil"] != "true"
29977 !nothing?(value) && !garbage?(value)
29978 value.blank? || value["nil"] == "true"
29979 value["type"] && !value["type"].is_a?(::Hash) && value.size == 1
29980 content = value["__content__"]
29981 value.map! { |i| deep_to_h(i) }
29982 if this_val.is_a?(Hash) && other_val.is_a?(Hash)
29983 omit = slice(*self.keys - keys)
29984 hash = slice(*keys)
29985 keys.each_with_object(self.class.new) { |key, result| result[key] = delete(key) if has_key?(key) }
29986 object.map { |e| _deep_transform_values_in_object(e, &block) }
29987 object.map! { |e| _deep_transform_values_in_object!(e, &block) }
29988 location.delete_suffix(".rb") == path.to_s.delete_suffix(".rb")
29989 Tempfile.open(".#{basename(file_name)}", temp_dir) do |temp_file|
29990 basename = [
29991 ].join(".")
29992 class_methods, methods = [], []
29993 unless name.is_a?(Symbol) || name.is_a?(String)
29994 defined?(@#{name}) ? @#{name} : self.class.#{name}
29995 class_methods << <<~RUBY
29996 attr_writer :#{name}
29997 class_methods << "silence_redefinition_of_method def #{name}?; !!self.#{name}; end"
29998 methods << "silence_redefinition_of_method def #{name}?; !!self.#{name}; end"
29999 class_eval(["class << self", *class_methods, "end", *methods].join(";").tr("
", ";"), location.path, location.lineno)
30000 attrs.each { |name| public_send("#{name}=", default) }
30001 k.singleton_class? || k == self
30002 @digest = digest || "SHA1" unless aead_mode?
30003 cipher.auth_data = "" if aead_mode?
30004 blob = "#{blob}--#{::Base64.strict_encode64 cipher.auth_tag}" if aead_mode?
30005 encrypted_data, iv, auth_tag = encrypted_message.split("--").map { |v| ::Base64.strict_decode64(v) }
30006 cipher.auth_data = ""
30007 def raw_state(&block) # :nodoc:
30008 @_autoloads = {}
30009 @_under_path = nil
30010 @_at_path = nil
30011 full = [name, @_under_path, const_name.to_s].compact.join("::")
30012 @_under_path, old_path = path, @_under_path
30013 @_under_path = old_path
30014 @_at_path, old_path = path, @_at_path
30015 @_at_path = old_path
30016 cpath = object.is_a?(Module) ? real_mod_name(object) : object.to_s
30017 l = verbose ? logger || Rails.logger : nil
30018 :no_op
30019 @overrides = {}
30020 @filters, @silencers = [], []
30021 @silencers = []
30022 @filters = []
30023 gems_paths = (Gem.path | [Gem.default_dir]).map { |p| Regexp.escape(p) }
30024 gems_regexp = %r{\A(#{gems_paths.join('|')})/(bundler/)?gems/([^/]+)-([\w.]+)/(.*)}
30025 gems_result = '\3 (\4) \5'
30026 @filters.each do |f|
30027 backtrace = backtrace.map { |line| f.call(line) }
30028 @silencers.any? do |s|
30029 node_type_map = {}
30030 raise "Document too deep!" if depth == 0
30031 (0...child_nodes.length).each do |i|
30032 hash[key] << value
30033 hash[key] = [hash[key], value]
30034 hash[key] = [value]
30035 attribute_hash = {}
30036 (0...attributes.length).each do |i|
30037 texts = []
30038 text = +""
30039 @hash = {}
30040 @hash_stack = [@hash]
30041 def start_element(name, attrs = [])
30042 data = StringIO.new(data || "")
30043 def to_hash(hash = {})
30044 node_hash = {}
30045 elsif c.text? || c.cdata?
30046 attribute_nodes.each { |a| node_hash[a.node_name] = a.value }
30047 texts = +""
30048 element.texts.each { |t| texts << t.value }
30049 attributes = {}
30050 element.attributes.each { |n, v| attributes[n] = v }
30051 @hash = @hash_stack.pop
30052 def on_start_element(name, attrs = {})
30053 each_attr { |a| node_hash[a.name] = a.value }
30054 delegate :<=>, :=~, :match?, :acts_like_string?, to: :wrapped_string
30055 result = @wrapped_string.__send__(method, *args, &block)
30056 if method.end_with?("!")
30057 @wrapped_string.split(*args).map { |i| self.class.new(i) }
30058 chars(downcase.to_s.gsub(/\b('?\S)/u) { $1.upcase })
30059 define_method("#{method}!") do |*args|
30060 _, _, _, error_bytes, _ = reader.primitive_errinfo
30061 mod = nil
30062 mod ||= Module.new
30063 notification_name = "deprecation.#{gem_name.underscore.tr('/', '_')}"
30064 if behavior.arity == 4 || behavior.arity == -1
30065 -> message, callstack, _, _ { behavior.call(message, callstack) }
30066 when String then "#{warning} (#{message})"
30067 } || callstack.first
30068 if md = offending_line.match(/^(.+?):(\d+)(?::in `(.*?)')?/)
30069 @disallowed_warnings ||= []
30070 instance_methods.each { |m| undef_method m unless /^__|^object_id$/.match?(m) }
30071 target.__send__(called, *args, &block)
30072 @var = var
30073 @instance.__send__(@method)
30074 @deprecator.warn("#{@var} is deprecated! Call #{@method}.#{called} instead of #{@var}.#{called}. Args: #{args.inspect}", callstack)
30075 def self.new(*args, **options, &block)
30076 k = "#{k}="
30077 name.end_with?("?") || super
30078 if name.end_with?("?")
30079 any?(name[0..-2])
30080 when ActionableError, -> it { Class === it && it < ActionableError }
30081 tags.reject!(&:blank?)
30082 def pop_tags(size = 1)
30083 Thread.current[thread_key] ||= []
30084 tags.collect { |tag| "[#{tag}] " }.join
30085 base.current_tags = []
30086 options[:level] ||= :info
30087 ms = Benchmark.ms { result = options[:silence] ? logger.silence { yield } : yield }
30088 logger.public_send(options[:level], "%s (%.1fms)" % [ message, ms ])
30089 @cpu_time_start = 0
30090 @cpu_time_finish = 0
30091 @time = now
30092 @end = now
30093 (@cpu_time_finish - @cpu_time_start) * 1000
30094 1000.0 * (self.end - time)
30095 def <<(event)
30096 @string_subscribers = Hash.new { |h, k| h[k] = [] }
30097 @other_subscribers = []
30098 listeners_for(name).each { |s| s.start(name, id, payload) }
30099 listeners.each { |s| s.finish(name, id, payload) }
30100 listeners_for(name).each { |s| s.publish(name, *args) }
30101 @listeners_for[name] ||=
30102 if params.length == 1 && params.first.first == :opt
30103 exclusions << -name if pattern === name
30104 def ===(name)
30105 pattern === name && !exclusions.include?(name)
30106 pattern === name
30107 pattern && pattern === name
30108 timestack = Thread.current[:_timestack] ||= []
30109 stack = Thread.current[:_event_stack] ||= []
30110 alias :matches? :===
30111 '\1ews' '\1ews' '\1ews' '\1ews' '\1ews' '\1ews' '\1ews' '\1ews' '\1ews' '\1ews' '\1ews' '\1ews' '\1ews' '\1ews' '\1ews'
30112 (op[:exp]) (op[:exp]) (op[:exp]) (op[:exp]) (op[:exp]) (op[:exp]) (op[:exp]) (op[:exp]) (op[:exp]) (op[:exp]) (op[:exp])
30113 :nodoc: :nodoc: :nodoc: :nodoc: :nodoc: :nodoc: :nodoc: :nodoc: :nodoc: :nodoc: :nodoc: :nodoc: :nodoc: :nodoc: :nodoc: *
30114 sub(/\A\.?/) sub(/\A\.?/) sub(/\A\.?/) sub(/\A\.?/) sub(/\A\.?/) sub(/\A\.?/) sub(/\A\.?/) sub(/\A\.?/) sub(/\A\.?/) sub(/\A\.?/)
30115 /^(m|l)$/i /^(m|l)$/i /^(m|l)$/i /^(m|l)$/i /^(m|l)$/i /^(m|l)$/i /^(m|l)$/i /^(m|l)$/i /^(m|l)$/i /^(m|l)$/i /^(m|l)$/i
30116 q > w, w < q, u < y, y > u, q > w, w < q, u < y, y > u, q > w, w < q, u < y, y > u, q > w, w < q, u < y, y > u
30117 { p: @p } { p: @p } { p: @p } { p: @p } { p: @p } { p: @p } { p: @p } { p: @p } { p: @p } { p: @p } { p: @p } { p: @p } { p: @p }
30118 z >= 0 z >= 0 z >= 0 z >= 0 z >= 0 z >= 0 z >= 0 z >= 0 z >= 0 z >= 0 z >= 0 z >= 0 z >= 0 z >= 0 z >= 0 z >= 0 z >= 0
30119 m <= 7 m <= 7 m <= 7 m <= 7 m <= 7 m <= 7 m <= 7 m <= 7 m <= 7 m <= 7 m <= 7 m <= 7 m <= 7 m <= 7 m <= 7 m <= 7 m <= 7

Связаться
Выделить
Выделите фрагменты страницы, относящиеся к вашему сообщению
Скрыть сведения
Скрыть всю личную информацию
Отмена