# Copyright 2016 Google Inc. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. require_relative '../helper' require 'fluent/plugin/exception_detector' class ExceptionDetectorTest < Test::Unit::TestCase JAVA_EXC_PART1 = <:3:9) at :6:4 at a_function_name at Object.InjectedScript._evaluateOn (http:///file.js?foo=bar:875:140) at Object.InjectedScript.evaluate () END V8_JS_EXC = <__call('raise', Array) #3 /base/data/home/apps/s~crash-example-php/1.388306779641080894/index.php(36): ErrorEntry->raise() #4 {main} thrown in /base/data/home/apps/s~crash-example-php/1.388306779641080894/errors.php on line 60 END GO_EXC = <:0 at File3.Consolidator_Class.Function5 (System.Collections.Generic.Dictionary`2 names, System.Text.StringBuilder param_4) [0x00007] in /usr/local/google/home/Csharp/another file.csharp:9 at File3.Consolidator_Class.Function4 (System.Text.StringBuilder param_4, System.Double[,,] array) [0x00013] in /usr/local/google/home/Csharp/another file.csharp:23 at File3.Consolidator_Class.Function3 (Int32 param_3) [0x0000f] in /usr/local/google/home/Csharp/another file.csharp:27 at File3.Consolidator_Class.Function3 (System.Text.StringBuilder param_3) [0x00007] in /usr/local/google/home/Csharp/another file.csharp:32 at File2.Processor.Function2 (System.Int32& param_2, System.Collections.Generic.Stack`1& numbers) [0x00003] in /usr/local/google/home/Csharp/File2.csharp:19 at File2.Processor.Random2 () [0x00037] in /usr/local/google/home/Csharp/File2.csharp:28 at File2.Processor.Function1 (Int32 param_1, System.Collections.Generic.Dictionary`2 map) [0x00007] in /usr/local/google/home/Csharp/File2.csharp:34 at Main.Welcome+
c__AnonStorey0.<>m__0 () [0x00006] in /usr/local/google/home/Csharp/hello.csharp:48 at System.Threading.Thread.StartInternal () [0x00000] in :0 END RUBY_EXC = <): app/controllers/books_controller.rb:69:in `recursivewordload' app/controllers/books_controller.rb:75:in `loadword' app/controllers/books_controller.rb:79:in `loadline' app/controllers/books_controller.rb:83:in `loadparagraph' app/controllers/books_controller.rb:87:in `loadpage' app/controllers/books_controller.rb:91:in `onload' app/controllers/books_controller.rb:95:in `loadrecursive' app/controllers/books_controller.rb:99:in `requestload' app/controllers/books_controller.rb:118:in `generror' config/error_reporting_logger.rb:62:in `tagged' END # The whitespace on the second line is significant. # rubocop:disable TrailingWhitespace RAILS_EXC = < line) end buffer.flush end end def expected_json(message_field, messages) messages.collect { |m| { message_field => [m].flatten.join } } end Struct.new('TestJsonScenario', :desc, :configured_field, :actual_field, :input, :output) def json_scenario(desc, configured_field, actual_field, input, output) Struct::TestJsonScenario.new(desc, configured_field, actual_field, input, output) end def test_json_messages [ json_scenario('User-defined message field', 'mydata', 'mydata', [PYTHON_EXC, ARBITRARY_TEXT, GO_EXC], [PYTHON_EXC] + ARBITRARY_TEXT.lines + [GO_EXC]), json_scenario('Default message field "message"', '', 'message', [PYTHON_EXC, ARBITRARY_TEXT, GO_EXC], [PYTHON_EXC] + ARBITRARY_TEXT.lines + [GO_EXC]), json_scenario('Default message field "log"', '', 'log', [PYTHON_EXC, ARBITRARY_TEXT, GO_EXC], [PYTHON_EXC] + ARBITRARY_TEXT.lines + [GO_EXC]), json_scenario('Wrongly defined message field', 'doesnotexist', 'mydata', [PYTHON_EXC, ARBITRARY_TEXT, GO_EXC], PYTHON_EXC.lines + ARBITRARY_TEXT.lines + GO_EXC.lines), json_scenario('Undefined message field', '', 'mydata', [PYTHON_EXC, ARBITRARY_TEXT, GO_EXC], PYTHON_EXC.lines + ARBITRARY_TEXT.lines + GO_EXC.lines) ].each do |s| out = [] buffer = Fluent::TraceAccumulator.new(s.configured_field, [:all]) { |_, m| out << m } feed_json(buffer, s.actual_field, s.input) assert_equal(expected_json(s.actual_field, s.output), out, s.desc) end end def test_max_lines_limit # Limit is equal to the first part of the exception and forces it to be # flushed before the rest of the exception is processed. max_lines = JAVA_EXC_PART1.lines.length out = [] buffer = Fluent::TraceAccumulator.new(nil, [:all], max_lines: max_lines) do |_, m| out << m end feed_lines(buffer, JAVA_EXC) assert_equal([JAVA_EXC_PART1] + JAVA_EXC_PART2.lines, out) end def test_high_max_bytes_limit # Limit is just too small to add one more line to the buffered first part of # the exception. max_bytes = JAVA_EXC_PART1.length + JAVA_EXC_PART2.lines[0].length - 1 out = [] buffer = Fluent::TraceAccumulator.new(nil, [:all], max_bytes: max_bytes) do |_, m| out << m end feed_lines(buffer, JAVA_EXC) # Check that the trace is flushed after the first part. assert_equal([JAVA_EXC_PART1] + JAVA_EXC_PART2.lines, out) end def test_low_max_bytes_limit # Limit is exceeded by the character that follows the buffered first part of # the exception. max_bytes = JAVA_EXC_PART1.length out = [] buffer = Fluent::TraceAccumulator.new(nil, [:all], max_bytes: max_bytes) do |_, m| out << m end feed_lines(buffer, JAVA_EXC) # Check that the trace is flushed after the first part. assert_equal([JAVA_EXC_PART1] + JAVA_EXC_PART2.lines, out) end end