diff options
| author | Amir Rajan <[email protected]> | 2020-09-11 02:02:01 -0500 |
|---|---|---|
| committer | Amir Rajan <[email protected]> | 2020-09-11 02:02:57 -0500 |
| commit | 33ec37b141e896b47ed642923fd33b0c658ae9fb (patch) | |
| tree | a40d3e5d41beeb06508200078f6f26b0ee57d6a4 /samples/10_advanced_debugging | |
| parent | 958cf43779d2bf528869e80511c4c4f2a433b2db (diff) | |
| download | dragonruby-game-toolkit-contrib-33ec37b141e896b47ed642923fd33b0c658ae9fb.tar.gz dragonruby-game-toolkit-contrib-33ec37b141e896b47ed642923fd33b0c658ae9fb.zip | |
synced samples
Diffstat (limited to 'samples/10_advanced_debugging')
12 files changed, 490 insertions, 0 deletions
diff --git a/samples/10_advanced_debugging/01_trace_debugging/app/main.rb b/samples/10_advanced_debugging/01_trace_debugging/app/main.rb new file mode 100644 index 0000000..33f15b3 --- /dev/null +++ b/samples/10_advanced_debugging/01_trace_debugging/app/main.rb @@ -0,0 +1,53 @@ +class Game + attr_gtk + + def method1 num + method2 num + end + + def method2 num + method3 num + end + + def method3 num + method4 num + end + + def method4 num + if num == 1 + puts "UNLUCKY #{num}." + state.unlucky_count += 1 + if state.unlucky_count > 3 + raise "NAT 1 finally occurred. Check app/trace.txt for all method invocation history." + end + else + puts "LUCKY #{num}." + end + end + + def tick + state.roll_history ||= [] + state.roll_history << rand(20) + 1 + state.countdown ||= 600 + state.countdown -= 1 + state.unlucky_count ||= 0 + outputs.labels << [640, 360, "A dice roll of 1 will cause an exception.", 0, 1] + if state.countdown > 0 + outputs.labels << [640, 340, "Dice roll countdown: #{state.countdown}", 0, 1] + else + state.attempts ||= 0 + state.attempts += 1 + outputs.labels << [640, 340, "ROLLING! #{state.attempts}", 0, 1] + end + return if state.countdown > 0 + method1 state.roll_history[-1] + end +end + +$game = Game.new + +def tick args + trace! $game # <------------------- TRACING ENABLED FOR THIS OBJECT + $game.args = args + $game.tick +end diff --git a/samples/10_advanced_debugging/01_trace_debugging/license-for-sample.txt b/samples/10_advanced_debugging/01_trace_debugging/license-for-sample.txt new file mode 100644 index 0000000..100dcec --- /dev/null +++ b/samples/10_advanced_debugging/01_trace_debugging/license-for-sample.txt @@ -0,0 +1,9 @@ +Copyright 2019 DragonRuby LLC + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/samples/10_advanced_debugging/02_trace_debugging_classes/app/main.rb b/samples/10_advanced_debugging/02_trace_debugging_classes/app/main.rb new file mode 100644 index 0000000..a6804ae --- /dev/null +++ b/samples/10_advanced_debugging/02_trace_debugging_classes/app/main.rb @@ -0,0 +1,22 @@ +class Foobar + def initialize + trace! # Trace is added to the constructor. + end + + def clicky args + return unless args.inputs.mouse.click + try_rand rand + end + + def try_rand num + return if num < 0.9 + raise "Exception finally occurred. Take a look at logs/trace.txt #{num}." + end +end + +def tick args + args.labels << [640, 360, "Start clicking. Eventually an exception will be thrown. Then look at logs/trace.txt.", 0, 1] + args.state.foobar = Foobar.new if args.tick_count + return unless args.state.foobar + args.state.foobar.clicky args +end diff --git a/samples/10_advanced_debugging/03_unit_tests/exception_raising_tests.rb b/samples/10_advanced_debugging/03_unit_tests/exception_raising_tests.rb new file mode 100644 index 0000000..57efdb2 --- /dev/null +++ b/samples/10_advanced_debugging/03_unit_tests/exception_raising_tests.rb @@ -0,0 +1,21 @@ +begin :shared + class ExceptionalClass + def initialize exception_to_throw = nil + raise exception_to_throw if exception_to_throw + end + end +end + +def test_exception_in_newing_object args, assert + begin + ExceptionalClass.new TypeError + raise "Exception wasn't thrown!" + rescue Exception => e + assert.equal! e.class, TypeError, "Exceptions within constructor should be retained." + end +end + +puts "running tests" +$gtk.reset 100 +$gtk.log_level = :off +$gtk.tests.start diff --git a/samples/10_advanced_debugging/03_unit_tests/gen_docs.rb b/samples/10_advanced_debugging/03_unit_tests/gen_docs.rb new file mode 100644 index 0000000..0e41326 --- /dev/null +++ b/samples/10_advanced_debugging/03_unit_tests/gen_docs.rb @@ -0,0 +1,2 @@ +# sh ./amir-build-and-run.sh --eval samples/99_zz_gtk_unit_tests/gen_docs.rb --no-tick +Kernel.export_docs! diff --git a/samples/10_advanced_debugging/03_unit_tests/geometry_tests.rb b/samples/10_advanced_debugging/03_unit_tests/geometry_tests.rb new file mode 100644 index 0000000..d823d78 --- /dev/null +++ b/samples/10_advanced_debugging/03_unit_tests/geometry_tests.rb @@ -0,0 +1,116 @@ +begin :shared + def primitive_representations x, y, w, h + [ + [x, y, w, h], + { x: x, y: y, w: w, h: h }, + RectForTest.new(x, y, w, h) + ] + end + + class RectForTest + attr_sprite + + def initialize x, y, w, h + @x = x + @y = y + @w = w + @h = h + end + + def to_s + "RectForTest: #{[x, y, w, h]}" + end + end +end + +begin :intersect_rect? + def test_intersect_rect_point args, assert + assert.true! [16, 13].intersect_rect?([13, 12, 4, 4]), "point intersects with rect." + end + + def test_intersect_rect args, assert + intersecting = primitive_representations(0, 0, 100, 100) + + primitive_representations(20, 20, 20, 20) + + intersecting.product(intersecting).each do |rect_one, rect_two| + assert.true! rect_one.intersect_rect?(rect_two), + "intersect_rect? assertion failed for #{rect_one}, #{rect_two} (expected true)." + end + + not_intersecting = [ + [ 0, 0, 5, 5], + { x: 10, y: 10, w: 5, h: 5 }, + RectForTest.new(20, 20, 5, 5) + ] + + not_intersecting.product(not_intersecting) + .reject { |rect_one, rect_two| rect_one == rect_two } + .each do |rect_one, rect_two| + assert.false! rect_one.intersect_rect?(rect_two), + "intersect_rect? assertion failed for #{rect_one}, #{rect_two} (expected false)." + end + end +end + +begin :inside_rect? + def assert_inside_rect outer: nil, inner: nil, expected: nil, assert: nil + assert.true! inner.inside_rect?(outer) == expected, + "inside_rect? assertion failed for outer: #{outer} inner: #{inner} (expected #{expected})." + end + + def test_inside_rect args, assert + outer_rects = primitive_representations(0, 0, 10, 10) + inner_rects = primitive_representations(1, 1, 5, 5) + primitive_representations(0, 0, 10, 10).product(primitive_representations(1, 1, 5, 5)) + .each do |outer, inner| + assert_inside_rect outer: outer, inner: inner, + expected: true, assert: assert + end + end +end + +begin :angle_to + def test_angle_to args, assert + origins = primitive_representations(0, 0, 0, 0) + rights = primitive_representations(1, 0, 0, 0) + aboves = primitive_representations(0, 1, 0, 0) + + origins.product(aboves).each do |origin, above| + assert.equal! origin.angle_to(above), 90, + "A point directly above should be 90 degrees." + + assert.equal! above.angle_from(origin), 90, + "A point coming from above should be 90 degrees." + end + + origins.product(rights).each do |origin, right| + assert.equal! origin.angle_to(right) % 360, 0, + "A point directly to the right should be 0 degrees." + + assert.equal! right.angle_from(origin) % 360, 0, + "A point coming from the right should be 0 degrees." + + end + end +end + +begin :scale_rect + def test_scale_rect args, assert + assert.equal! [0, 0, 100, 100].scale_rect(0.5, 0.5), + [25.0, 25.0, 50.0, 50.0] + + assert.equal! [0, 0, 100, 100].scale_rect(0.5), + [0.0, 0.0, 50.0, 50.0] + + assert.equal! [0, 0, 100, 100].scale_rect_extended(percentage_x: 0.5, percentage_y: 0.5, anchor_x: 0.5, anchor_y: 0.5), + [25.0, 25.0, 50.0, 50.0] + + assert.equal! [0, 0, 100, 100].scale_rect_extended(percentage_x: 0.5, percentage_y: 0.5, anchor_x: 0, anchor_y: 0), + [0.0, 0.0, 50.0, 50.0] + end +end + +puts "running tests" +$gtk.reset 100 +$gtk.log_level = :off +$gtk.tests.start diff --git a/samples/10_advanced_debugging/03_unit_tests/http_tests.rb b/samples/10_advanced_debugging/03_unit_tests/http_tests.rb new file mode 100644 index 0000000..1132f85 --- /dev/null +++ b/samples/10_advanced_debugging/03_unit_tests/http_tests.rb @@ -0,0 +1,24 @@ +def try_assert_or_schedule args, assert + if $result[:complete] + log_info "Request completed! Verifying." + if $result[:http_response_code] != 200 + log_info "The request yielded a result of #{$result[:http_response_code]} instead of 200." + exit + end + log_info ":try_assert_or_schedule succeeded!" + else + args.gtk.schedule_callback Kernel.tick_count + 10 do + try_assert_or_schedule args, assert + end + end +end + +def test_http args, assert + $result = $gtk.http_get 'http://dragonruby.org' + try_assert_or_schedule args, assert +end + +puts "running tests" +$gtk.reset 100 +$gtk.log_level = :off +$gtk.tests.start diff --git a/samples/10_advanced_debugging/03_unit_tests/object_to_primitive_tests.rb b/samples/10_advanced_debugging/03_unit_tests/object_to_primitive_tests.rb new file mode 100644 index 0000000..4686c6e --- /dev/null +++ b/samples/10_advanced_debugging/03_unit_tests/object_to_primitive_tests.rb @@ -0,0 +1,17 @@ +class PlayerSpriteForTest +end + +def test_array_to_sprite args, assert + array = [[0, 0, 100, 100, "test.png"]].sprites + puts "No exception was thrown. Sweet!" +end + +def test_class_to_sprite args, assert + array = [PlayerSprite.new].sprites + assert.true! array.first.is_a?(PlayerSprite) + puts "No exception was thrown. Sweet!" +end + +$gtk.reset 100 +$gtk.log_level = :off +$gtk.tests.start diff --git a/samples/10_advanced_debugging/03_unit_tests/parsing_tests.rb b/samples/10_advanced_debugging/03_unit_tests/parsing_tests.rb new file mode 100644 index 0000000..4dede2b --- /dev/null +++ b/samples/10_advanced_debugging/03_unit_tests/parsing_tests.rb @@ -0,0 +1,29 @@ +def test_parse_json args, assert + result = args.gtk.parse_json '{ "name": "John Doe", "aliases": ["JD"] }' + assert.equal! result, { "name"=>"John Doe", "aliases"=>["JD"] }, "Parsing JSON failed." +end + +def test_parse_xml args, assert + result = args.gtk.parse_xml <<-S +<Person id="100"> + <Name>John Doe</Name> +</Person> +S + + expected = {:type=>:element, + :name=>nil, + :children=>[{:type=>:element, + :name=>"Person", + :children=>[{:type=>:element, + :name=>"Name", + :children=>[{:type=>:content, + :data=>"John Doe"}]}], + :attributes=>{"id"=>"100"}}]} + + assert.equal! result, expected, "Parsing xml failed." +end + +puts "running tests" +$gtk.reset 100 +$gtk.log_level = :off +$gtk.tests.start diff --git a/samples/10_advanced_debugging/03_unit_tests/run-bash.sh b/samples/10_advanced_debugging/03_unit_tests/run-bash.sh new file mode 100644 index 0000000..005077b --- /dev/null +++ b/samples/10_advanced_debugging/03_unit_tests/run-bash.sh @@ -0,0 +1,4 @@ +sh ./amir-build-and-run.sh --eval samples/99_zz_gtk_unit_tests/geometry_tests.rb --no-tick +sh ./amir-build-and-run.sh --eval samples/99_zz_gtk_unit_tests/parsing_tests.rb --no-tick +sh ./amir-build-and-run.sh --eval samples/99_zz_gtk_unit_tests/http_tests.rb --no-tick +sh ./amir-build-and-run.sh --eval samples/99_zz_gtk_unit_tests/array_to_primitive_tests.rb --no-tick diff --git a/samples/10_advanced_debugging/03_unit_tests/serialize_deserialize_tests.rb b/samples/10_advanced_debugging/03_unit_tests/serialize_deserialize_tests.rb new file mode 100644 index 0000000..22fa862 --- /dev/null +++ b/samples/10_advanced_debugging/03_unit_tests/serialize_deserialize_tests.rb @@ -0,0 +1,86 @@ +def test_serialize args, assert + GTK::Entity.__reset_id__! + args.state.player_one = "test" + result = args.gtk.serialize_state args.state + assert.equal! result, "{:entity_id=>3, :tick_count=>-1, :player_one=>\"test\"}" + + GTK::Entity.__reset_id__! + args.gtk.write_file 'state.txt', '' + result = args.gtk.serialize_state 'state.txt', args.state + assert.equal! result, "{:entity_id=>3, :tick_count=>-1, :player_one=>\"test\"}" +end + +def test_deserialize args, assert + GTK::Entity.__reset_id__! + result = args.gtk.deserialize_state '{:entity_id=>3, :tick_count=>-1, :player_one=>"test"}' + assert.equal! result.player_one, "test" + + GTK::Entity.__reset_id__! + args.gtk.write_file 'state.txt', '{:entity_id=>3, :tick_count=>-1, :player_one=>"test"}' + result = args.gtk.deserialize_state 'state.txt' + assert.equal! result.player_one, "test" +end + +def test_very_large_serialization args, assert + GTK::Entity.__reset_id__! + size = 3000 + size.map_with_index do |i| + args.state.send("k#{i}=".to_sym, i) + end + + result = args.gtk.serialize_state args.state + assert.true! (args.gtk.console.log.join.include? "unlikely a string this large will deserialize correctly") +end + +def test_strict_entity_serialization args, assert + GTK::Entity.__reset_id__! + args.state.player_one = args.state.new_entity(:player, name: "Ryu") + args.state.player_two = args.state.new_entity_strict(:player_strict, name: "Ken") + + serialized_state = args.gtk.serialize_state args.state + assert.equal! serialized_state, '{:entity_id=>1, :tick_count=>-1, :player_one=>{:entity_id=>1, :entity_name=>:player, :entity_type=>:player, :created_at=>-1, :global_created_at=>-1, :name=>"Ryu"}, :player_two=>{:entity_id=>3, :entity_name=>:player_strict, :created_at=>-1, :global_created_at_elapsed=>-1, :entity_strict=>true, :name=>"Ken"}}' + + deserialize_state = args.gtk.deserialize_state serialized_state + + assert.equal! args.state.player_one.name, deserialize_state.player_one.name + assert.true! args.state.player_one.is_a? GTK::OpenEntity + + assert.equal! args.state.player_two.name, deserialize_state.player_two.name + assert.true! args.state.player_two.is_a? GTK::StrictEntity +end + +def test_strict_entity_serialization_with_nil args, assert + GTK::Entity.__reset_id__! + args.state.player_one = args.state.new_entity(:player, name: "Ryu") + args.state.player_two = args.state.new_entity_strict(:player_strict, name: "Ken", blood_type: nil) + + serialized_state = args.gtk.serialize_state args.state + assert.equal! serialized_state, '{:entity_id=>3, :tick_count=>-1, :player_one=>{:entity_id=>1, :entity_name=>:player, :entity_type=>:player, :created_at=>-1, :global_created_at=>-1, :name=>"Ryu"}, :player_two=>{:entity_id=>3, :entity_name=>:player_strict, :created_at=>-1, :global_created_at_elapsed=>-1, :entity_strict=>true, :name=>"Ken", :blood_type=>nil}}' + + deserialized_state = args.gtk.deserialize_state serialized_state + + assert.equal! args.state.player_one.name, deserialized_state.player_one.name + assert.true! args.state.player_one.is_a? GTK::OpenEntity + + assert.equal! args.state.player_two.name, deserialized_state.player_two.name + assert.equal! args.state.player_two.blood_type, deserialized_state.player_two.blood_type + assert.equal! deserialized_state.player_two.blood_type, nil + assert.true! args.state.player_two.is_a? GTK::StrictEntity + + deserialized_state.player_two.blood_type = :O + assert.equal! deserialized_state.player_two.blood_type, :O +end + +def test_multiple_strict_entities args, assert + GTK::Entity.__reset_id__! + args.state.player = args.state.new_entity_strict(:player_one, name: "Ryu") + args.state.enemy = args.state.new_entity_strict(:enemy, name: "Bison", other_property: 'extra mean') + + serialized_state = args.gtk.serialize_state args.state + deserialized_state = args.gtk.deserialize_state serialized_state + + assert.equal! deserialized_state.player.name, "Ryu" + assert.equal! deserialized_state.enemy.other_property, "extra mean" +end + +$tests.start diff --git a/samples/10_advanced_debugging/03_unit_tests/state_serialization_experimental_tests.rb b/samples/10_advanced_debugging/03_unit_tests/state_serialization_experimental_tests.rb new file mode 100644 index 0000000..ffd8064 --- /dev/null +++ b/samples/10_advanced_debugging/03_unit_tests/state_serialization_experimental_tests.rb @@ -0,0 +1,107 @@ +MAX_CODE_GEN_LENGTH = 50 + +# NOTE: This is experimental/advanced stuff. +def needs_partitioning? target + target[:value].to_s.length > MAX_CODE_GEN_LENGTH +end + +def partition target + return [] unless needs_partitioning? target + if target[:value].is_a? GTK::OpenEntity + target[:value] = target[:value].hash + end + + results = [] + idx = 0 + left, right = target[:value].partition do + idx += 1 + idx.even? + end + left, right = Hash[left], Hash[right] + left = { value: left } + right = { value: right} + [left, right] +end + +def add_partition target, path, aggregate, final_result + partitions = partition target + partitions.each do |part| + if needs_partitioning? part + if part[:value].keys.length == 1 + first_key = part[:value].keys[0] + new_part = { value: part[:value][first_key] } + path.push first_key + add_partition new_part, path, aggregate, final_result + path.pop + else + add_partition part, path, aggregate, final_result + end + else + final_result << { value: { __path__: [*path] } } + final_result << { value: part[:value] } + end + end +end + +def state_to_string state + parts_queue = [] + final_queue = [] + add_partition({ value: state.hash }, + [], + parts_queue, + final_queue) + final_queue.reject {|i| i[:value].keys.length == 0}.map do |i| + i[:value].to_s + end.join("\n#==================================================#\n") +end + +def state_from_string string + Kernel.eval("$load_data = {}") + lines = string.split("\n#==================================================#\n") + lines.each do |l| + puts "todo: #{l}" + end + + GTK::OpenEntity.parse_from_hash $load_data +end + +def test_save_and_load args, assert + args.state.item_1.name = "Jane" + string = state_to_string args.state + state = state_from_string string + assert.equal! args.state.item_1.name, state.item_1.name +end + +def test_save_and_load_big args, assert + size = 1000 + size.map_with_index do |i| + args.state.send("k#{i}=".to_sym, i) + end + + string = state_to_string args.state + state = state_from_string string + size.map_with_index do |i| + assert.equal! args.state.send("k#{i}".to_sym), state.send("k#{i}".to_sym) + assert.equal! args.state.send("k#{i}".to_sym), i + assert.equal! state.send("k#{i}".to_sym), i + end +end + +def test_save_and_load_big_nested args, assert + args.state.player_one.friend.nested_hash.k0 = 0 + args.state.player_one.friend.nested_hash.k1 = 1 + args.state.player_one.friend.nested_hash.k2 = 2 + args.state.player_one.friend.nested_hash.k3 = 3 + args.state.player_one.friend.nested_hash.k4 = 4 + args.state.player_one.friend.nested_hash.k5 = 5 + args.state.player_one.friend.nested_hash.k6 = 6 + args.state.player_one.friend.nested_hash.k7 = 7 + args.state.player_one.friend.nested_hash.k8 = 8 + args.state.player_one.friend.nested_hash.k9 = 9 + string = state_to_string args.state + state = state_from_string string +end + +$gtk.reset 100 +$gtk.log_level = :off +$gtk.tests.start |
