[rubygems/rubygems] Use a constant empty tar header to avoid extra allocations
[ruby.git] / test / test_trick.rb
blobc5c19d079e7198167bd0aa9d2e972befe60f46e2
1 # frozen_string_literal: false
3 require "test/unit"
4 require "ripper"
5 require "envutil"
6 require "stringio"
8 # This is a test suite for TRICK entries, joke Ruby program contest.
9 # The programs are very unusual, and not practical.
10 # Feel free to comment them out if they bother you.
11 # I'll appreciate it if you could notify mame <mame@ruby-lang.org>
13 class TestTRICK2013 < Test::Unit::TestCase
14   def test_kinaba
15     src = File.join(__dir__, "../sample/trick2013/kinaba/entry.rb")
16     expected = [*" ".."~"].join("") # all ASCII printables
17     assert_in_out_err(["-W0", "--disable-frozen-string-literal", src], "", [expected])
18     assert_equal(expected, File.read(src).chomp.chars.sort.join)
19   end
21   def test_mame
22     src = File.join(__dir__, "../sample/trick2013/mame/entry.rb")
23     ignore_dsp = "def open(_file, _mode); s = ''; def s.flush; self;end; yield s; end;"
24     assert_in_out_err(["-W0", "--disable-frozen-string-literal"], ignore_dsp + File.read(src), File.read(src).lines(chomp: true), timeout: 60)
25   end
27   def test_shinh
28     src = File.join(__dir__, "../sample/trick2013/shinh/entry.rb")
29     assert_in_out_err(["-W0", "--disable-frozen-string-literal", src], "", [])
30   end
32   def test_yhara
33     src = File.join(__dir__, "../sample/trick2013/yhara/entry.rb")
34     assert_in_out_err(["-W0", "--disable-frozen-string-literal", src], "", ["JUST ANOTHER RUBY HACKER"])
35   end
36 end
38 class TestTRICK2015 < Test::Unit::TestCase
39   def test_kinaba
40     src = File.join(__dir__, "../sample/trick2015/kinaba/entry.rb")
42     # calculate the first 10000 digits of Pi
43     n = 10000
44     a = b = 10 ** n
45     (n * 8 + 1).step(3, -2) do |i|
46         a = (i / 2) * (a + b * 2) / i
47     end
48     pi = "3#{ a - b }"
50     assert_in_out_err(["-W0", "--disable-frozen-string-literal", src], "", [pi], timeout: 60)
51     assert_equal(pi[0, 242], Ripper.tokenize(File.read(src)).grep(/\S/).map{|t|t.size%10}.join)
52   end
54   def test_ksk_1
55     src = File.join(__dir__, "../sample/trick2015/ksk_1/entry.rb")
57     # calculate Collatz sequence
58     s = ["27"]
59     n = 27
60     until n == 1
61       n = n.even? ? n / 2 : n * 3 + 1
62       s << n.to_s
63     end
65     assert_in_out_err(["-W0", "--disable-frozen-string-literal", src, "27"], "", s)
66   end
68   def test_monae
69     src = File.join(__dir__, "../sample/trick2015/monae/entry.rb")
71     code = File.read(src)
72     expected = code.lines(chomp: true) + (0..15).map { "" }
73     code.lines.each_with_index do |s, y|
74       y += 16
75       s.chomp.chars.each_with_index do |c, x|
76         x += 16
77         expected[y] << " " while expected[y].size < x
78         expected[y][x] = c if c != " "
79       end
80     end
81     expected = /\A#{ expected.map {|s| "#{ Regexp.quote(s) }\s*\n" }.join }\z/
83     assert_in_out_err(["-W0", "--disable-frozen-string-literal", src], "", expected)
84   end
86   def test_eregon
87     src = File.join(__dir__, "../sample/trick2015/eregon/entry.rb")
89     assert_in_out_err(["-W0", "--disable-frozen-string-literal", src], "", <<END.lines(chomp: true))
90 1 9 4 2 3 8 7 6 5
91 3 7 2 6 5 1 4 8 9
92 8 5 6 7 4 9 2 3 1
93 7 8 1 3 6 4 5 9 2
94 4 2 3 9 7 5 8 1 6
95 5 6 9 8 1 2 3 7 4
96 6 4 8 1 2 7 9 5 3
97 9 3 5 4 8 6 1 2 7
98 2 1 7 5 9 3 6 4 8
100 1 9 7 2 3 8 4 6 5
101 3 4 2 6 5 1 7 8 9
102 8 5 6 7 4 9 2 3 1
103 7 1 8 3 6 4 5 9 2
104 4 2 3 9 7 5 8 1 6
105 5 6 9 8 1 2 3 7 4
106 6 8 4 1 2 7 9 5 3
107 9 3 5 4 8 6 1 2 7
108 2 7 1 5 9 3 6 4 8
111   end
113   def test_ksk_2
114     src = File.join(__dir__, "../sample/trick2015/ksk_2/entry.rb")
116     inp = <<END
118 c This is a sample input file.
120 p cnf 3 5
121  1 -2  3 0
122 -1  2 0
123 -2 -3 0
124  1  2 -3 0
125  1  3 0
128     assert_in_out_err(["-W0", "--disable-frozen-string-literal", src], inp, ["s SATISFIABLE", "v 1 2 -3"])
129   end
132 class TestTRICK2018 < Test::Unit::TestCase
133   def test_01_kinaba
134     src = File.join(__dir__, "../sample/trick2018/01-kinaba/entry.rb")
136     assert_in_out_err(["-W0", "--disable-frozen-string-literal", src], "", [])
137   end
139   def test_02_mame
140     src = File.join(__dir__, "../sample/trick2018/02-mame/entry.rb")
142     ignore_sleep = "def sleep(_); end;"
143     assert_in_out_err(["-W0", "--disable-frozen-string-literal"], ignore_sleep + File.read(src)) do |stdout, _stderr, _status|
144       code = stdout.join("\n") + "\n"
145       expected = code.lines(chomp: true)
146       assert_in_out_err(["-W0", "--disable-frozen-string-literal"], ignore_sleep + code, expected)
147     end
148   end
150   def test_03_tompng
151     src = File.join(__dir__, "../sample/trick2018/03-tompng/entry.rb")
153     # only syntax check because it requires chunky_png
154     assert_in_out_err(["-W0", "--disable-frozen-string-literal", "-c", src], "", ["Syntax OK"])
155   end
157   def test_04_colin
158     src = File.join(__dir__, "../sample/trick2018/04-colin/entry.rb")
160     code = "# encoding: UTF-8\n" + File.read(src, encoding: "UTF-8") + <<END
161 \u{1F914} "Math" do
162   \u{1F914} "Addition" do
163     \u{1F914} "One plus one equals two.",
164       1+1 == 2
165     \u{1F914} "One plus one equals eleven. (This should fail.)",
166       1+1 == 11
167   end
169   \u{1F914} "Subtraction" do
170     \u{1F914} "One minus one equals zero.",
171       1-1 == 0
172     \u{1F914} "Ten minus one equal nine.",
173       10-1 == 9
174   end
177     assert_in_out_err(["-W0", "--disable-frozen-string-literal"], code, <<END.lines(chomp: true), encoding: "UTF-8")
178 Math
179     Addition
180         One plus one equals two.
181         \u{1F6AB} One plus one equals eleven. (This should fail.)
182     Subtraction
183         One minus one equals zero.
184         Ten minus one equal nine.
186   end
188   def test_05_tompng
189     src = File.join(__dir__, "../sample/trick2018/05-tompng/entry.rb")
191     # only syntax check because it generates 3D model data
192     assert_in_out_err(["-W0", "--disable-frozen-string-literal", "-c", src], "", ["Syntax OK"])
193   end
196 class TestTRICK2022 < Test::Unit::TestCase
197   def test_01_tompng
198     src = File.join(__dir__, "../sample/trick2022/01-tompng/entry.rb")
200     # only syntax check because it requires matrix
201     assert_in_out_err(["-W0", "--disable-frozen-string-literal", "-c", src], "", ["Syntax OK"])
202   end
204   def test_02_tompng
205     src = File.join(__dir__, "../sample/trick2022/02-tompng/entry.rb")
207     # only syntax check because it works as a web server
208     assert_in_out_err(["-W0", "--disable-frozen-string-literal", "-c", src], "", ["Syntax OK"])
209   end
211   def test_03_mame
212     src = File.join(__dir__, "../sample/trick2022/03-mame/entry.rb")
214     # TODO
215     assert_in_out_err(["-W0", "--disable-frozen-string-literal", "-c", src], "", ["Syntax OK"])
216   end
219 class TestRubyKaigi2023🥢 < Test::Unit::TestCase
220   CHOPSTICKS = [<<~'0', <<~'1'] # by mame
221   BEGIN{q=:Ruby};p||=:Enjoy;END{puts p,q||2023}
222   0
223   q=print(q||"/:|}\n")||p&&:@Matsumoto;p=:Kaigi
224   1
226   def test_chopsticks_0
227     assert_in_out_err(%w[-W0], CHOPSTICKS[0], %w[Enjoy Ruby])
228   end
230   def test_chopsticks_1
231     assert_in_out_err(%w[-W0], CHOPSTICKS[1], %w[/:|}])
232   end
234   def test_chopsticks_0_1
235     assert_in_out_err(%w[-W0], "#{CHOPSTICKS[0]}\n#{CHOPSTICKS[1]}", %w[RubyKaigi @Matsumoto])
236   end
238   def test_chopsticks_1_0
239     assert_in_out_err(%w[-W0], "#{CHOPSTICKS[1]}\n#{CHOPSTICKS[0]}", %w[RubyKaigi 2023])
240   end
243 # https://github.com/mame/all-ruby-quine
244 class TestAllRubyQuine < Test::Unit::TestCase
245   def test_all_ruby_quine
246     stdout_bak = $stdout
247     $stdout = StringIO.new
248     verbose_bak = $VERBOSE
249     $VERBOSE = nil
250     src = File.read(File.join(__dir__, "../sample/all-ruby-quine.rb"))
252     eval(src)
254     out = $stdout.string.lines(chomp: true)
255     $stdout = stdout_bak
257     # cheat OCR
258     font = {
259       "-" => 0x7ffffffffffe03fffffffffff, "." => 0x7fffffffffffffffffffc7f8f, "_" => 0x7fffffffffffffffffffff800,
260       "0" => 0x6030e03e07c0f81f03e038603, "1" => 0x70fc1f23fc7f8ff1fe3fc7c01, "2" => 0x4011f1fe3fc7e1f0f87c3f800,
261       "3" => 0x4031e3fe3f8e03fe3fe078c03, "4" => 0x783e0788e318e31c6003f1fe3, "5" => 0x0001fe3fc7f801fe1fe078401,
262       "6" => 0x78083e3fc7f8011e03e038401, "7" => 0x000fe1fc3f0fc3f0fc3f0fc3f, "8" => 0x4011f03e238e038e23e07c401,
263       "9" => 0x4010e03e03c400ff1fe078401, "a" => 0x7fffff00c787f88003e078408, "b" => 0x0ff1fe3fc408701f03e078001,
264       "c" => 0x7fffff8063c0ff1fe3fe3c601, "d" => 0x7f8ff1fe3004781f03e038408,
265     }.invert
266     out = (0...out.first.size / 15).map do |i|
267       font[(3..11).map {|j| out[j][i * 15 + 5, 11] }.join.gsub(/\S/, "#").tr("# ", "10").to_i(2)]
268     end.join
270     assert_equal(RUBY_VERSION, out)
271   ensure
272     $stdout = stdout_bak
273     $VERBOSE = verbose_bak
274   end