minitest 5.20.0 → 5.25.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/History.rdoc +130 -3
- data/Manifest.txt +3 -0
- data/README.rdoc +16 -13
- data/Rakefile +6 -0
- data/lib/hoe/minitest.rb +2 -1
- data/lib/minitest/assertions.rb +77 -80
- data/lib/minitest/autorun.rb +0 -7
- data/lib/minitest/benchmark.rb +6 -9
- data/lib/minitest/compress.rb +94 -0
- data/lib/minitest/error_on_warning.rb +11 -0
- data/lib/minitest/manual_plugins.rb +16 -0
- data/lib/minitest/mock.rb +17 -15
- data/lib/minitest/parallel.rb +5 -5
- data/lib/minitest/pride_plugin.rb +16 -23
- data/lib/minitest/spec.rb +5 -5
- data/lib/minitest/test.rb +14 -25
- data/lib/minitest/test_task.rb +17 -12
- data/lib/minitest.rb +257 -144
- data/test/minitest/metametameta.rb +32 -18
- data/test/minitest/test_minitest_assertions.rb +159 -140
- data/test/minitest/test_minitest_benchmark.rb +1 -1
- data/test/minitest/test_minitest_mock.rb +80 -75
- data/test/minitest/test_minitest_reporter.rb +111 -16
- data/test/minitest/test_minitest_spec.rb +54 -55
- data/test/minitest/test_minitest_test.rb +191 -117
- data/test/minitest/test_minitest_test_task.rb +18 -7
- data.tar.gz.sig +0 -0
- metadata +17 -13
- metadata.gz.sig +0 -0
data/lib/minitest/assertions.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
1
|
require "rbconfig"
|
4
2
|
require "tempfile"
|
5
3
|
require "stringio"
|
@@ -29,12 +27,12 @@ module Minitest
|
|
29
27
|
def self.diff
|
30
28
|
return @diff if defined? @diff
|
31
29
|
|
32
|
-
@diff = if (RbConfig::CONFIG["host_os"] =~ /mswin|mingw/
|
33
|
-
system
|
30
|
+
@diff = if (RbConfig::CONFIG["host_os"] =~ /mswin|mingw/ and
|
31
|
+
system "diff.exe", __FILE__, __FILE__) then
|
34
32
|
"diff.exe -u"
|
35
|
-
elsif system
|
33
|
+
elsif system "gdiff", __FILE__, __FILE__ then
|
36
34
|
"gdiff -u" # solaris and kin suck
|
37
|
-
elsif system
|
35
|
+
elsif system "diff", __FILE__, __FILE__ then
|
38
36
|
"diff -u"
|
39
37
|
else
|
40
38
|
nil
|
@@ -59,16 +57,16 @@ module Minitest
|
|
59
57
|
def diff exp, act
|
60
58
|
result = nil
|
61
59
|
|
62
|
-
expect, butwas = things_to_diff
|
60
|
+
expect, butwas = things_to_diff exp, act
|
63
61
|
|
64
62
|
return "Expected: #{mu_pp exp}\n Actual: #{mu_pp act}" unless
|
65
63
|
expect
|
66
64
|
|
67
|
-
Tempfile.open
|
65
|
+
Tempfile.open "expect" do |a|
|
68
66
|
a.puts expect
|
69
67
|
a.flush
|
70
68
|
|
71
|
-
Tempfile.open
|
69
|
+
Tempfile.open "butwas" do |b|
|
72
70
|
b.puts butwas
|
73
71
|
b.flush
|
74
72
|
|
@@ -79,10 +77,10 @@ module Minitest
|
|
79
77
|
if result.empty? then
|
80
78
|
klass = exp.class
|
81
79
|
result = [
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
80
|
+
"No visible difference in the #{klass}#inspect output.\n",
|
81
|
+
"You should look at the implementation of #== on ",
|
82
|
+
"#{klass} or its members.\n",
|
83
|
+
expect,
|
86
84
|
].join
|
87
85
|
end
|
88
86
|
end
|
@@ -127,20 +125,15 @@ module Minitest
|
|
127
125
|
# See Minitest::Test.make_my_diffs_pretty!
|
128
126
|
|
129
127
|
def mu_pp obj
|
130
|
-
s = obj.inspect
|
128
|
+
s = obj.inspect.encode Encoding.default_external
|
131
129
|
|
132
|
-
|
133
|
-
|
130
|
+
return s unless String === obj &&
|
131
|
+
(obj.encoding != Encoding.default_external || !obj.valid_encoding?)
|
134
132
|
|
135
|
-
|
136
|
-
|
137
|
-
enc = "# encoding: #{obj.encoding}"
|
138
|
-
val = "# valid: #{obj.valid_encoding?}"
|
139
|
-
s = "#{enc}\n#{val}\n#{s}"
|
140
|
-
end
|
141
|
-
end
|
133
|
+
enc = "# encoding: #{obj.encoding}"
|
134
|
+
val = "# valid: #{obj.valid_encoding?}"
|
142
135
|
|
143
|
-
s
|
136
|
+
[enc, val, s].join "\n"
|
144
137
|
end
|
145
138
|
|
146
139
|
##
|
@@ -153,8 +146,8 @@ module Minitest
|
|
153
146
|
str = mu_pp obj
|
154
147
|
|
155
148
|
# both '\n' & '\\n' (_after_ mu_pp (aka inspect))
|
156
|
-
single =
|
157
|
-
double =
|
149
|
+
single = str.match?(/(?<!\\|^)\\n/)
|
150
|
+
double = str.match?(/(?<=\\|^)\\n/)
|
158
151
|
|
159
152
|
process =
|
160
153
|
if single ^ double then
|
@@ -167,9 +160,9 @@ module Minitest
|
|
167
160
|
:itself # leave it alone
|
168
161
|
end
|
169
162
|
|
170
|
-
str
|
171
|
-
gsub(/\\?\\n/, &process)
|
172
|
-
gsub(/:0x[a-fA-F0-9]{4,}/m, ":0xXXXXXX") # anonymize hex values
|
163
|
+
str
|
164
|
+
.gsub(/\\?\\n/, &process)
|
165
|
+
.gsub(/:0x[a-fA-F0-9]{4,}/m, ":0xXXXXXX") # anonymize hex values
|
173
166
|
end
|
174
167
|
|
175
168
|
##
|
@@ -193,11 +186,16 @@ module Minitest
|
|
193
186
|
# Fails unless +obj+ is empty.
|
194
187
|
|
195
188
|
def assert_empty obj, msg = nil
|
196
|
-
msg = message(msg) { "Expected #{mu_pp
|
189
|
+
msg = message(msg) { "Expected #{mu_pp obj} to be empty" }
|
197
190
|
assert_respond_to obj, :empty?
|
198
191
|
assert obj.empty?, msg
|
199
192
|
end
|
200
193
|
|
194
|
+
def _where # :nodoc:
|
195
|
+
Minitest.filter_backtrace(caller).first
|
196
|
+
.split(":in ", 2).first # clean up noise
|
197
|
+
end
|
198
|
+
|
201
199
|
E = "" # :nodoc:
|
202
200
|
|
203
201
|
##
|
@@ -218,13 +216,10 @@ module Minitest
|
|
218
216
|
result = assert exp == act, msg
|
219
217
|
|
220
218
|
if nil == exp then
|
221
|
-
if Minitest::VERSION
|
219
|
+
if Minitest::VERSION >= "6" then
|
222
220
|
refute_nil exp, "Use assert_nil if expecting nil."
|
223
221
|
else
|
224
|
-
|
225
|
-
where = where.split(/:in /, 2).first # clean up noise
|
226
|
-
|
227
|
-
warn "DEPRECATED: Use assert_nil if expecting nil from #{where}. This will fail in Minitest 6."
|
222
|
+
warn "DEPRECATED: Use assert_nil if expecting nil from #{_where}. This will fail in Minitest 6."
|
228
223
|
end
|
229
224
|
end
|
230
225
|
|
@@ -258,7 +253,7 @@ module Minitest
|
|
258
253
|
|
259
254
|
def assert_includes collection, obj, msg = nil
|
260
255
|
msg = message(msg) {
|
261
|
-
"Expected #{mu_pp
|
256
|
+
"Expected #{mu_pp collection} to include #{mu_pp obj}"
|
262
257
|
}
|
263
258
|
assert_respond_to collection, :include?
|
264
259
|
assert collection.include?(obj), msg
|
@@ -269,7 +264,7 @@ module Minitest
|
|
269
264
|
|
270
265
|
def assert_instance_of cls, obj, msg = nil
|
271
266
|
msg = message(msg) {
|
272
|
-
"Expected #{mu_pp
|
267
|
+
"Expected #{mu_pp obj} to be an instance of #{cls}, not #{obj.class}"
|
273
268
|
}
|
274
269
|
|
275
270
|
assert obj.instance_of?(cls), msg
|
@@ -280,7 +275,8 @@ module Minitest
|
|
280
275
|
|
281
276
|
def assert_kind_of cls, obj, msg = nil
|
282
277
|
msg = message(msg) {
|
283
|
-
"Expected #{mu_pp
|
278
|
+
"Expected #{mu_pp obj} to be a kind of #{cls}, not #{obj.class}"
|
279
|
+
}
|
284
280
|
|
285
281
|
assert obj.kind_of?(cls), msg
|
286
282
|
end
|
@@ -290,7 +286,7 @@ module Minitest
|
|
290
286
|
|
291
287
|
def assert_match matcher, obj, msg = nil
|
292
288
|
msg = message(msg) { "Expected #{mu_pp matcher} to match #{mu_pp obj}" }
|
293
|
-
assert_respond_to matcher,
|
289
|
+
assert_respond_to matcher, :=~
|
294
290
|
matcher = Regexp.new Regexp.escape matcher if String === matcher
|
295
291
|
assert matcher =~ obj, msg
|
296
292
|
|
@@ -301,7 +297,7 @@ module Minitest
|
|
301
297
|
# Fails unless +obj+ is nil
|
302
298
|
|
303
299
|
def assert_nil obj, msg = nil
|
304
|
-
msg = message(msg) { "Expected #{mu_pp
|
300
|
+
msg = message(msg) { "Expected #{mu_pp obj} to be nil" }
|
305
301
|
assert obj.nil?, msg
|
306
302
|
end
|
307
303
|
|
@@ -312,7 +308,7 @@ module Minitest
|
|
312
308
|
|
313
309
|
def assert_operator o1, op, o2 = UNDEFINED, msg = nil
|
314
310
|
return assert_predicate o1, op, msg if UNDEFINED == o2
|
315
|
-
msg = message(msg) { "Expected #{mu_pp
|
311
|
+
msg = message(msg) { "Expected #{mu_pp o1} to be #{op} #{mu_pp o2}" }
|
316
312
|
assert o1.__send__(op, o2), msg
|
317
313
|
end
|
318
314
|
|
@@ -393,7 +389,7 @@ module Minitest
|
|
393
389
|
# str.must_be :empty?
|
394
390
|
|
395
391
|
def assert_predicate o1, op, msg = nil
|
396
|
-
msg = message(msg) { "Expected #{mu_pp
|
392
|
+
msg = message(msg) { "Expected #{mu_pp o1} to be #{op}" }
|
397
393
|
assert o1.__send__(op), msg
|
398
394
|
end
|
399
395
|
|
@@ -438,23 +434,24 @@ module Minitest
|
|
438
434
|
raise
|
439
435
|
rescue Exception => e
|
440
436
|
flunk proc {
|
441
|
-
exception_details(e, "#{msg}#{mu_pp
|
437
|
+
exception_details(e, "#{msg}#{mu_pp exp} exception expected, not")
|
442
438
|
}
|
443
439
|
end
|
444
440
|
|
445
441
|
exp = exp.first if exp.size == 1
|
446
442
|
|
447
|
-
flunk "#{msg}#{mu_pp
|
443
|
+
flunk "#{msg}#{mu_pp exp} expected but nothing was raised."
|
448
444
|
end
|
449
445
|
|
450
446
|
##
|
451
447
|
# Fails unless +obj+ responds to +meth+.
|
448
|
+
# include_all defaults to false to match Object#respond_to?
|
452
449
|
|
453
|
-
def assert_respond_to obj, meth, msg = nil
|
450
|
+
def assert_respond_to obj, meth, msg = nil, include_all: false
|
454
451
|
msg = message(msg) {
|
455
|
-
"Expected #{mu_pp
|
452
|
+
"Expected #{mu_pp obj} (#{obj.class}) to respond to ##{meth}"
|
456
453
|
}
|
457
|
-
assert obj.respond_to?(meth), msg
|
454
|
+
assert obj.respond_to?(meth, include_all), msg
|
458
455
|
end
|
459
456
|
|
460
457
|
##
|
@@ -474,13 +471,12 @@ module Minitest
|
|
474
471
|
# Fails unless the call returns a true value
|
475
472
|
|
476
473
|
def assert_send send_ary, m = nil
|
477
|
-
|
478
|
-
where = where.split(/:in /, 2).first # clean up noise
|
479
|
-
warn "DEPRECATED: assert_send. From #{where}"
|
474
|
+
warn "DEPRECATED: assert_send. From #{_where}"
|
480
475
|
|
481
476
|
recv, msg, *args = send_ary
|
482
477
|
m = message(m) {
|
483
|
-
"Expected #{mu_pp
|
478
|
+
"Expected #{mu_pp recv}.#{msg}(*#{mu_pp args}) to return true"
|
479
|
+
}
|
484
480
|
assert recv.__send__(msg, *args), m
|
485
481
|
end
|
486
482
|
|
@@ -499,15 +495,15 @@ module Minitest
|
|
499
495
|
# Fails unless the block throws +sym+
|
500
496
|
|
501
497
|
def assert_throws sym, msg = nil
|
502
|
-
default = "Expected #{mu_pp
|
498
|
+
default = "Expected #{mu_pp sym} to have been thrown"
|
503
499
|
caught = true
|
504
|
-
value = catch
|
500
|
+
value = catch sym do
|
505
501
|
begin
|
506
502
|
yield
|
507
503
|
rescue ThreadError => e # wtf?!? 1.8 + threads == suck
|
508
|
-
default += ", not
|
504
|
+
default += ", not :#{e.message[/uncaught throw \`(\w+?)\'/, 1]}"
|
509
505
|
rescue ArgumentError => e # 1.9 exception
|
510
|
-
raise e unless e.message.include?
|
506
|
+
raise e unless e.message.include? "uncaught throw"
|
511
507
|
default += ", not #{e.message.split(/ /).last}"
|
512
508
|
rescue NameError => e # 1.8 exception
|
513
509
|
raise e unless e.name == sym
|
@@ -606,12 +602,12 @@ module Minitest
|
|
606
602
|
|
607
603
|
def exception_details e, msg
|
608
604
|
[
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
605
|
+
msg,
|
606
|
+
"Class: <#{e.class}>",
|
607
|
+
"Message: <#{e.message.inspect}>",
|
608
|
+
"---Backtrace---",
|
609
|
+
Minitest.filter_backtrace(e.backtrace),
|
610
|
+
"---------------",
|
615
611
|
].join "\n"
|
616
612
|
end
|
617
613
|
|
@@ -620,7 +616,7 @@ module Minitest
|
|
620
616
|
# you to put time-bombs in your tests if you need to keep
|
621
617
|
# something around until a later date lest you forget about it.
|
622
618
|
|
623
|
-
def fail_after y,m,d,msg
|
619
|
+
def fail_after y, m, d, msg
|
624
620
|
flunk msg if Time.now > Time.local(y, m, d)
|
625
621
|
end
|
626
622
|
|
@@ -654,7 +650,7 @@ module Minitest
|
|
654
650
|
# Fails if +test+ is truthy.
|
655
651
|
|
656
652
|
def refute test, msg = nil
|
657
|
-
msg ||= message { "Expected #{mu_pp
|
653
|
+
msg ||= message { "Expected #{mu_pp test} to not be truthy" }
|
658
654
|
assert !test, msg
|
659
655
|
end
|
660
656
|
|
@@ -662,7 +658,7 @@ module Minitest
|
|
662
658
|
# Fails if +obj+ is empty.
|
663
659
|
|
664
660
|
def refute_empty obj, msg = nil
|
665
|
-
msg = message(msg) { "Expected #{mu_pp
|
661
|
+
msg = message(msg) { "Expected #{mu_pp obj} to not be empty" }
|
666
662
|
assert_respond_to obj, :empty?
|
667
663
|
refute obj.empty?, msg
|
668
664
|
end
|
@@ -674,7 +670,7 @@ module Minitest
|
|
674
670
|
|
675
671
|
def refute_equal exp, act, msg = nil
|
676
672
|
msg = message(msg) {
|
677
|
-
"Expected #{mu_pp
|
673
|
+
"Expected #{mu_pp act} to not be equal to #{mu_pp exp}"
|
678
674
|
}
|
679
675
|
refute exp == act, msg
|
680
676
|
end
|
@@ -705,7 +701,7 @@ module Minitest
|
|
705
701
|
|
706
702
|
def refute_includes collection, obj, msg = nil
|
707
703
|
msg = message(msg) {
|
708
|
-
"Expected #{mu_pp
|
704
|
+
"Expected #{mu_pp collection} to not include #{mu_pp obj}"
|
709
705
|
}
|
710
706
|
assert_respond_to collection, :include?
|
711
707
|
refute collection.include?(obj), msg
|
@@ -716,7 +712,7 @@ module Minitest
|
|
716
712
|
|
717
713
|
def refute_instance_of cls, obj, msg = nil
|
718
714
|
msg = message(msg) {
|
719
|
-
"Expected #{mu_pp
|
715
|
+
"Expected #{mu_pp obj} to not be an instance of #{cls}"
|
720
716
|
}
|
721
717
|
refute obj.instance_of?(cls), msg
|
722
718
|
end
|
@@ -725,7 +721,7 @@ module Minitest
|
|
725
721
|
# Fails if +obj+ is a kind of +cls+.
|
726
722
|
|
727
723
|
def refute_kind_of cls, obj, msg = nil
|
728
|
-
msg = message(msg) { "Expected #{mu_pp
|
724
|
+
msg = message(msg) { "Expected #{mu_pp obj} to not be a kind of #{cls}" }
|
729
725
|
refute obj.kind_of?(cls), msg
|
730
726
|
end
|
731
727
|
|
@@ -734,7 +730,7 @@ module Minitest
|
|
734
730
|
|
735
731
|
def refute_match matcher, obj, msg = nil
|
736
732
|
msg = message(msg) { "Expected #{mu_pp matcher} to not match #{mu_pp obj}" }
|
737
|
-
assert_respond_to matcher,
|
733
|
+
assert_respond_to matcher, :=~
|
738
734
|
matcher = Regexp.new Regexp.escape matcher if String === matcher
|
739
735
|
refute matcher =~ obj, msg
|
740
736
|
end
|
@@ -743,7 +739,7 @@ module Minitest
|
|
743
739
|
# Fails if +obj+ is nil.
|
744
740
|
|
745
741
|
def refute_nil obj, msg = nil
|
746
|
-
msg = message(msg) { "Expected #{mu_pp
|
742
|
+
msg = message(msg) { "Expected #{mu_pp obj} to not be nil" }
|
747
743
|
refute obj.nil?, msg
|
748
744
|
end
|
749
745
|
|
@@ -765,7 +761,7 @@ module Minitest
|
|
765
761
|
|
766
762
|
begin
|
767
763
|
yield
|
768
|
-
flunk
|
764
|
+
flunk "NoMatchingPatternError expected, but nothing was raised."
|
769
765
|
rescue NoMatchingPatternError
|
770
766
|
pass
|
771
767
|
end
|
@@ -779,7 +775,7 @@ module Minitest
|
|
779
775
|
|
780
776
|
def refute_operator o1, op, o2 = UNDEFINED, msg = nil
|
781
777
|
return refute_predicate o1, op, msg if UNDEFINED == o2
|
782
|
-
msg = message(msg) { "Expected #{mu_pp
|
778
|
+
msg = message(msg) { "Expected #{mu_pp o1} to not be #{op} #{mu_pp o2}" }
|
783
779
|
refute o1.__send__(op, o2), msg
|
784
780
|
end
|
785
781
|
|
@@ -801,17 +797,18 @@ module Minitest
|
|
801
797
|
# str.wont_be :empty?
|
802
798
|
|
803
799
|
def refute_predicate o1, op, msg = nil
|
804
|
-
msg = message(msg) { "Expected #{mu_pp
|
800
|
+
msg = message(msg) { "Expected #{mu_pp o1} to not be #{op}" }
|
805
801
|
refute o1.__send__(op), msg
|
806
802
|
end
|
807
803
|
|
808
804
|
##
|
809
805
|
# Fails if +obj+ responds to the message +meth+.
|
806
|
+
# include_all defaults to false to match Object#respond_to?
|
810
807
|
|
811
|
-
def refute_respond_to obj, meth, msg = nil
|
812
|
-
msg = message(msg) { "Expected #{mu_pp
|
808
|
+
def refute_respond_to obj, meth, msg = nil, include_all: false
|
809
|
+
msg = message(msg) { "Expected #{mu_pp obj} to not respond to #{meth}" }
|
813
810
|
|
814
|
-
refute obj.respond_to?(meth), msg
|
811
|
+
refute obj.respond_to?(meth, include_all), msg
|
815
812
|
end
|
816
813
|
|
817
814
|
##
|
@@ -830,10 +827,10 @@ module Minitest
|
|
830
827
|
# gets listed at the end of the run but doesn't cause a failure
|
831
828
|
# exit code.
|
832
829
|
|
833
|
-
def skip msg = nil,
|
830
|
+
def skip msg = nil, _ignored = nil
|
834
831
|
msg ||= "Skipped, no message given"
|
835
832
|
@skip = true
|
836
|
-
raise Minitest::Skip, msg
|
833
|
+
raise Minitest::Skip, msg
|
837
834
|
end
|
838
835
|
|
839
836
|
##
|
@@ -842,9 +839,9 @@ module Minitest
|
|
842
839
|
# date, but still holds you accountable and prevents you from
|
843
840
|
# forgetting it.
|
844
841
|
|
845
|
-
def skip_until y,m,d,msg
|
842
|
+
def skip_until y, m, d, msg
|
846
843
|
skip msg if Time.now < Time.local(y, m, d)
|
847
|
-
where = caller.first.rpartition(
|
844
|
+
where = caller(1..1).first.rpartition(":in").reject(&:empty?).first
|
848
845
|
warn "Stale skip_until %p at %s" % [msg, where]
|
849
846
|
end
|
850
847
|
|
data/lib/minitest/autorun.rb
CHANGED
data/lib/minitest/benchmark.rb
CHANGED
@@ -47,8 +47,6 @@ module Minitest
|
|
47
47
|
|
48
48
|
def self.bench_linear min, max, step = 10
|
49
49
|
(min..max).step(step).to_a
|
50
|
-
rescue LocalJumpError # 1.8.6
|
51
|
-
r = []; (min..max).step(step) { |n| r << n }; r
|
52
50
|
end
|
53
51
|
|
54
52
|
##
|
@@ -83,7 +81,7 @@ module Minitest
|
|
83
81
|
def assert_performance validation, &work
|
84
82
|
range = self.class.bench_range
|
85
83
|
|
86
|
-
io.print
|
84
|
+
io.print self.name
|
87
85
|
|
88
86
|
times = []
|
89
87
|
|
@@ -236,7 +234,7 @@ module Minitest
|
|
236
234
|
|
237
235
|
def fit_exponential xs, ys
|
238
236
|
n = xs.size
|
239
|
-
xys = xs.zip
|
237
|
+
xys = xs.zip ys
|
240
238
|
sxlny = sigma(xys) { |x, y| x * Math.log(y) }
|
241
239
|
slny = sigma(xys) { |_, y| Math.log(y) }
|
242
240
|
sx2 = sigma(xys) { |x, _| x * x }
|
@@ -258,7 +256,7 @@ module Minitest
|
|
258
256
|
|
259
257
|
def fit_logarithmic xs, ys
|
260
258
|
n = xs.size
|
261
|
-
xys = xs.zip
|
259
|
+
xys = xs.zip ys
|
262
260
|
slnx2 = sigma(xys) { |x, _| Math.log(x) ** 2 }
|
263
261
|
slnx = sigma(xys) { |x, _| Math.log(x) }
|
264
262
|
sylnx = sigma(xys) { |x, y| y * Math.log(x) }
|
@@ -280,7 +278,7 @@ module Minitest
|
|
280
278
|
|
281
279
|
def fit_linear xs, ys
|
282
280
|
n = xs.size
|
283
|
-
xys = xs.zip
|
281
|
+
xys = xs.zip ys
|
284
282
|
sx = sigma xs
|
285
283
|
sy = sigma ys
|
286
284
|
sx2 = sigma(xs) { |x| x ** 2 }
|
@@ -302,7 +300,7 @@ module Minitest
|
|
302
300
|
|
303
301
|
def fit_power xs, ys
|
304
302
|
n = xs.size
|
305
|
-
xys = xs.zip
|
303
|
+
xys = xs.zip ys
|
306
304
|
slnxlny = sigma(xys) { |x, y| Math.log(x) * Math.log(y) }
|
307
305
|
slnx = sigma(xs) { |x | Math.log(x) }
|
308
306
|
slny = sigma(ys) { | y| Math.log(y) }
|
@@ -323,7 +321,7 @@ module Minitest
|
|
323
321
|
|
324
322
|
def sigma enum, &block
|
325
323
|
enum = enum.map(&block) if block
|
326
|
-
enum.
|
324
|
+
enum.sum
|
327
325
|
end
|
328
326
|
|
329
327
|
##
|
@@ -419,7 +417,6 @@ module Minitest
|
|
419
417
|
end
|
420
418
|
end
|
421
419
|
|
422
|
-
|
423
420
|
##
|
424
421
|
# Create a benchmark that verifies that the performance is logarithmic.
|
425
422
|
#
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Minitest
|
2
|
+
##
|
3
|
+
# Compresses backtraces.
|
4
|
+
|
5
|
+
module Compress
|
6
|
+
|
7
|
+
##
|
8
|
+
# Takes a backtrace (array of strings) and compresses repeating
|
9
|
+
# cycles in it to make it more readable.
|
10
|
+
|
11
|
+
def compress orig
|
12
|
+
ary = orig
|
13
|
+
|
14
|
+
eswo = ->(a, n, off) { # each_slice_with_offset
|
15
|
+
if off.zero? then
|
16
|
+
a.each_slice n
|
17
|
+
else
|
18
|
+
# [ ...off... [...n...] [...n...] ... ]
|
19
|
+
front, back = a.take(off), a.drop(off)
|
20
|
+
[front].chain back.each_slice n
|
21
|
+
end
|
22
|
+
}
|
23
|
+
|
24
|
+
3.times do # maybe don't use loop do here?
|
25
|
+
index = ary # [ a b c b c b c d ]
|
26
|
+
.size
|
27
|
+
.times # 0...size
|
28
|
+
.group_by { |i| ary[i] } # { a: [0] b: [1 3 5], c: [2 4 6], d: [7] }
|
29
|
+
|
30
|
+
order = index
|
31
|
+
.reject { |k, v| v.size == 1 } # { b: [1 3 5], c: [2 4 6] }
|
32
|
+
.sort_by { |k, a1| ### sort by max dist + min offset
|
33
|
+
d = a1.each_cons(2).sum { |a2, b| b-a2 }
|
34
|
+
[-d, a1.first]
|
35
|
+
} # b: [1 3 5] c: [2 4 6]
|
36
|
+
|
37
|
+
ranges = order
|
38
|
+
.map { |k, a1| # [[1..2 3..4] [2..3 4..5]]
|
39
|
+
a1
|
40
|
+
.each_cons(2)
|
41
|
+
.map { |a2, b| a2..b-1 }
|
42
|
+
}
|
43
|
+
|
44
|
+
big_ranges = ranges
|
45
|
+
.flat_map { |a| # [1..2 3..4 2..3 4..5]
|
46
|
+
a.sort_by { |r| [-r.size, r.first] }.first 5
|
47
|
+
}
|
48
|
+
.first(100)
|
49
|
+
|
50
|
+
culprits = big_ranges
|
51
|
+
.map { |r|
|
52
|
+
eswo[ary, r.size, r.begin] # [o1 s1 s1 s2 s2]
|
53
|
+
.chunk_while { |a, b| a == b } # [[o1] [s1 s1] [s2 s2]]
|
54
|
+
.map { |a| [a.size, a.first] } # [[1 o1] [2 s1] [2 s2]]
|
55
|
+
}
|
56
|
+
.select { |chunks|
|
57
|
+
chunks.any? { |a| a.first > 1 } # compressed anything?
|
58
|
+
}
|
59
|
+
|
60
|
+
min = culprits
|
61
|
+
.min_by { |a| a.flatten.size } # most compressed
|
62
|
+
|
63
|
+
break unless min
|
64
|
+
|
65
|
+
ary = min.flat_map { |(n, lines)|
|
66
|
+
if n > 1 then
|
67
|
+
[[n, compress(lines)]] # [o1 [2 s1] [2 s2]]
|
68
|
+
else
|
69
|
+
lines
|
70
|
+
end
|
71
|
+
}
|
72
|
+
end
|
73
|
+
|
74
|
+
format = ->(lines) {
|
75
|
+
lines.flat_map { |line|
|
76
|
+
case line
|
77
|
+
when Array then
|
78
|
+
n, lines = line
|
79
|
+
lines = format[lines]
|
80
|
+
[
|
81
|
+
" +->> #{n} cycles of #{lines.size} lines:",
|
82
|
+
*lines.map { |s| " | #{s}" },
|
83
|
+
" +-<<",
|
84
|
+
]
|
85
|
+
else
|
86
|
+
line
|
87
|
+
end
|
88
|
+
}
|
89
|
+
}
|
90
|
+
|
91
|
+
format[ary]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|