fluentd 0.14.17-x64-mingw32 → 1.3.1-x64-mingw32

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of fluentd might be problematic. Click here for more details.

Files changed (159) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +16 -5
  3. data/ADOPTERS.md +5 -0
  4. data/{ChangeLog → CHANGELOG.md} +495 -6
  5. data/CONTRIBUTING.md +5 -2
  6. data/GOVERNANCE.md +55 -0
  7. data/LICENSE +202 -0
  8. data/MAINTAINERS.md +7 -5
  9. data/README.md +17 -10
  10. data/bin/fluent-ca-generate +6 -0
  11. data/example/counter.conf +18 -0
  12. data/example/secondary_file.conf +3 -2
  13. data/fluentd.gemspec +3 -3
  14. data/lib/fluent/agent.rb +1 -1
  15. data/lib/fluent/command/binlog_reader.rb +11 -2
  16. data/lib/fluent/command/ca_generate.rb +181 -0
  17. data/lib/fluent/command/cat.rb +28 -15
  18. data/lib/fluent/command/debug.rb +4 -4
  19. data/lib/fluent/command/fluentd.rb +2 -2
  20. data/lib/fluent/command/plugin_config_formatter.rb +24 -2
  21. data/lib/fluent/command/plugin_generator.rb +26 -8
  22. data/lib/fluent/config/configure_proxy.rb +7 -1
  23. data/lib/fluent/config/dsl.rb +8 -5
  24. data/lib/fluent/config/element.rb +5 -0
  25. data/lib/fluent/config/literal_parser.rb +7 -1
  26. data/lib/fluent/config/types.rb +28 -2
  27. data/lib/fluent/config/v1_parser.rb +1 -2
  28. data/lib/fluent/configurable.rb +1 -0
  29. data/lib/fluent/counter.rb +23 -0
  30. data/lib/fluent/counter/base_socket.rb +46 -0
  31. data/lib/fluent/counter/client.rb +297 -0
  32. data/lib/fluent/counter/error.rb +86 -0
  33. data/lib/fluent/counter/mutex_hash.rb +163 -0
  34. data/lib/fluent/counter/server.rb +273 -0
  35. data/lib/fluent/counter/store.rb +205 -0
  36. data/lib/fluent/counter/validator.rb +145 -0
  37. data/lib/fluent/env.rb +1 -0
  38. data/lib/fluent/event_router.rb +1 -1
  39. data/lib/fluent/log.rb +119 -29
  40. data/lib/fluent/plugin/base.rb +12 -0
  41. data/lib/fluent/plugin/buf_file.rb +20 -16
  42. data/lib/fluent/plugin/buffer.rb +130 -32
  43. data/lib/fluent/plugin/buffer/file_chunk.rb +23 -4
  44. data/lib/fluent/plugin/compressable.rb +1 -1
  45. data/lib/fluent/plugin/filter_grep.rb +135 -21
  46. data/lib/fluent/plugin/filter_parser.rb +13 -2
  47. data/lib/fluent/plugin/filter_record_transformer.rb +16 -14
  48. data/lib/fluent/plugin/formatter_stdout.rb +3 -2
  49. data/lib/fluent/plugin/formatter_tsv.rb +5 -1
  50. data/lib/fluent/plugin/in_debug_agent.rb +8 -1
  51. data/lib/fluent/plugin/in_forward.rb +1 -1
  52. data/lib/fluent/plugin/in_http.rb +84 -3
  53. data/lib/fluent/plugin/in_monitor_agent.rb +7 -1
  54. data/lib/fluent/plugin/in_syslog.rb +31 -10
  55. data/lib/fluent/plugin/in_tail.rb +142 -53
  56. data/lib/fluent/plugin/in_tcp.rb +5 -6
  57. data/lib/fluent/plugin/in_udp.rb +6 -2
  58. data/lib/fluent/plugin/in_unix.rb +1 -1
  59. data/lib/fluent/plugin/multi_output.rb +1 -0
  60. data/lib/fluent/plugin/out_copy.rb +25 -2
  61. data/lib/fluent/plugin/out_file.rb +26 -7
  62. data/lib/fluent/plugin/out_forward.rb +81 -42
  63. data/lib/fluent/plugin/out_secondary_file.rb +2 -2
  64. data/lib/fluent/plugin/out_stdout.rb +0 -1
  65. data/lib/fluent/plugin/out_stream.rb +1 -1
  66. data/lib/fluent/plugin/output.rb +221 -57
  67. data/lib/fluent/plugin/parser_apache.rb +1 -1
  68. data/lib/fluent/plugin/parser_apache2.rb +5 -1
  69. data/lib/fluent/plugin/parser_apache_error.rb +1 -1
  70. data/lib/fluent/plugin/parser_json.rb +10 -3
  71. data/lib/fluent/plugin/parser_ltsv.rb +7 -0
  72. data/lib/fluent/plugin/parser_multiline.rb +2 -1
  73. data/lib/fluent/plugin/parser_nginx.rb +1 -1
  74. data/lib/fluent/plugin/parser_none.rb +1 -0
  75. data/lib/fluent/plugin/parser_regexp.rb +15 -14
  76. data/lib/fluent/plugin/parser_syslog.rb +9 -5
  77. data/lib/fluent/plugin_helper.rb +2 -0
  78. data/lib/fluent/plugin_helper/cert_option.rb +28 -9
  79. data/lib/fluent/plugin_helper/compat_parameters.rb +3 -1
  80. data/lib/fluent/plugin_helper/counter.rb +51 -0
  81. data/lib/fluent/plugin_helper/event_loop.rb +9 -0
  82. data/lib/fluent/plugin_helper/record_accessor.rb +210 -0
  83. data/lib/fluent/plugin_helper/retry_state.rb +15 -7
  84. data/lib/fluent/plugin_helper/server.rb +87 -25
  85. data/lib/fluent/plugin_helper/socket_option.rb +5 -2
  86. data/lib/fluent/plugin_helper/timer.rb +8 -7
  87. data/lib/fluent/root_agent.rb +18 -9
  88. data/lib/fluent/supervisor.rb +63 -23
  89. data/lib/fluent/system_config.rb +30 -2
  90. data/lib/fluent/test/helpers.rb +1 -1
  91. data/lib/fluent/time.rb +15 -7
  92. data/lib/fluent/timezone.rb +26 -2
  93. data/lib/fluent/version.rb +1 -1
  94. data/templates/new_gem/README.md.erb +2 -2
  95. data/templates/new_gem/lib/fluent/plugin/filter.rb.erb +1 -1
  96. data/templates/new_gem/lib/fluent/plugin/input.rb.erb +1 -1
  97. data/templates/new_gem/lib/fluent/plugin/output.rb.erb +1 -1
  98. data/templates/new_gem/lib/fluent/plugin/parser.rb.erb +4 -4
  99. data/test/command/test_ca_generate.rb +70 -0
  100. data/test/command/test_fluentd.rb +2 -2
  101. data/test/command/test_plugin_config_formatter.rb +8 -7
  102. data/test/command/test_plugin_generator.rb +65 -39
  103. data/test/config/test_config_parser.rb +7 -2
  104. data/test/config/test_configurable.rb +7 -2
  105. data/test/config/test_configure_proxy.rb +41 -3
  106. data/test/config/test_dsl.rb +10 -10
  107. data/test/config/test_element.rb +10 -0
  108. data/test/config/test_literal_parser.rb +8 -0
  109. data/test/config/test_plugin_configuration.rb +56 -0
  110. data/test/config/test_system_config.rb +19 -1
  111. data/test/config/test_types.rb +37 -0
  112. data/test/counter/test_client.rb +559 -0
  113. data/test/counter/test_error.rb +44 -0
  114. data/test/counter/test_mutex_hash.rb +179 -0
  115. data/test/counter/test_server.rb +589 -0
  116. data/test/counter/test_store.rb +258 -0
  117. data/test/counter/test_validator.rb +137 -0
  118. data/test/plugin/test_buf_file.rb +124 -0
  119. data/test/plugin/test_buffer.rb +3 -2
  120. data/test/plugin/test_filter_grep.rb +580 -2
  121. data/test/plugin/test_filter_parser.rb +33 -2
  122. data/test/plugin/test_filter_record_transformer.rb +22 -1
  123. data/test/plugin/test_formatter_ltsv.rb +3 -0
  124. data/test/plugin/test_formatter_tsv.rb +68 -0
  125. data/test/plugin/test_in_debug_agent.rb +21 -0
  126. data/test/plugin/test_in_exec.rb +3 -5
  127. data/test/plugin/test_in_http.rb +178 -0
  128. data/test/plugin/test_in_monitor_agent.rb +1 -1
  129. data/test/plugin/test_in_syslog.rb +64 -0
  130. data/test/plugin/test_in_tail.rb +116 -6
  131. data/test/plugin/test_in_tcp.rb +21 -0
  132. data/test/plugin/test_in_udp.rb +78 -0
  133. data/test/plugin/test_metadata.rb +89 -0
  134. data/test/plugin/test_out_copy.rb +31 -0
  135. data/test/plugin/test_out_file.rb +108 -2
  136. data/test/plugin/test_out_forward.rb +195 -2
  137. data/test/plugin/test_out_secondary_file.rb +14 -0
  138. data/test/plugin/test_output.rb +159 -45
  139. data/test/plugin/test_output_as_buffered.rb +19 -0
  140. data/test/plugin/test_output_as_buffered_backup.rb +307 -0
  141. data/test/plugin/test_output_as_buffered_retries.rb +70 -0
  142. data/test/plugin/test_output_as_buffered_secondary.rb +1 -1
  143. data/test/plugin/test_parser_apache2.rb +1 -0
  144. data/test/plugin/test_parser_labeled_tsv.rb +17 -0
  145. data/test/plugin/test_parser_nginx.rb +40 -0
  146. data/test/plugin/test_parser_regexp.rb +6 -7
  147. data/test/plugin/test_parser_syslog.rb +155 -5
  148. data/test/plugin_helper/test_child_process.rb +4 -4
  149. data/test/plugin_helper/test_compat_parameters.rb +22 -0
  150. data/test/plugin_helper/test_record_accessor.rb +197 -0
  151. data/test/plugin_helper/test_retry_state.rb +20 -0
  152. data/test/plugin_helper/test_server.rb +30 -2
  153. data/test/test_config.rb +3 -3
  154. data/test/test_configdsl.rb +2 -2
  155. data/test/test_log.rb +51 -1
  156. data/test/test_root_agent.rb +33 -0
  157. data/test/test_supervisor.rb +105 -0
  158. metadata +68 -8
  159. data/COPYING +0 -14
@@ -2,6 +2,7 @@ require_relative '../helper'
2
2
  require 'fluent/config/element'
3
3
  require 'fluent/config/configure_proxy'
4
4
  require 'fluent/configurable'
5
+ require 'pp'
5
6
 
6
7
  class TestConfigElement < ::Test::Unit::TestCase
7
8
  def element(name = 'ROOT', arg = '', attrs = {}, elements = [], unused = nil)
@@ -463,4 +464,13 @@ CONF
463
464
  assert_false e.for_another_worker?
464
465
  end
465
466
  end
467
+
468
+ sub_test_case '#pretty_print' do
469
+ test 'prints inspect to pp object' do
470
+ q = PP.new
471
+ e = element()
472
+ e.pretty_print(q)
473
+ assert_equal e.inspect, q.output
474
+ end
475
+ end
466
476
  end
@@ -232,6 +232,14 @@ module Fluent::Config
232
232
  test("\"\#{\n=begin\n}\"") { assert_parse_error("\"\#{\n=begin\n}\"") } # error in embedded ruby code
233
233
  test('"#{v1}foo#{v2}"') { assert_text_parsed_as("#{v1}foo#{v2}", '"#{v1}foo#{v2}"') }
234
234
  test('"#{1+1}foo#{2+2}bar"') { assert_text_parsed_as("#{1+1}foo#{2+2}bar", '"#{1+1}foo#{2+2}bar"') }
235
+ test('"foo#{hostname}"') { assert_text_parsed_as("foo#{Socket.gethostname}", '"foo#{hostname}"') }
236
+ test('"foo#{worker_id}"') {
237
+ ENV.delete('SERVERENGINE_WORKER_ID')
238
+ assert_text_parsed_as("foo", '"foo#{worker_id}"')
239
+ ENV['SERVERENGINE_WORKER_ID'] = '1'
240
+ assert_text_parsed_as("foo1", '"foo#{worker_id}"')
241
+ ENV.delete('SERVERENGINE_WORKER_ID')
242
+ }
235
243
  end
236
244
 
237
245
  sub_test_case 'array parsing' do
@@ -0,0 +1,56 @@
1
+ require_relative '../helper'
2
+ require 'fluent/plugin/input'
3
+ require 'fluent/test/driver/input'
4
+
5
+ module ConfigurationForPlugins
6
+ class AllBooleanParams < Fluent::Plugin::Input
7
+ config_param :flag1, :bool, default: true
8
+ config_param :flag2, :bool, default: true
9
+ config_param :flag3, :bool, default: false
10
+ config_param :flag4, :bool, default: false
11
+
12
+ config_section :child, param_name: :children, multi: true, required: true do
13
+ config_param :flag1, :bool, default: true
14
+ config_param :flag2, :bool, default: true
15
+ config_param :flag3, :bool, default: false
16
+ config_param :flag4, :bool, default: false
17
+ end
18
+ end
19
+
20
+ class BooleanParamsWithoutValue < ::Test::Unit::TestCase
21
+ CONFIG = <<CONFIG
22
+ flag1
23
+ flag2 # yaaaaaaaaaay
24
+ flag3
25
+ flag4 # yaaaaaaaaaay
26
+ <child>
27
+ flag1
28
+ flag2 # yaaaaaaaaaay
29
+ flag3
30
+ flag4 # yaaaaaaaaaay
31
+ </child>
32
+ <child>
33
+ flag1 # yaaaaaaaaaay
34
+ flag2
35
+ flag3 # yaaaaaaaaaay
36
+ flag4
37
+ </child>
38
+ # with following whitespace
39
+ <child>
40
+ flag1
41
+ flag2
42
+ flag3
43
+ flag4
44
+ </child>
45
+ CONFIG
46
+
47
+ test 'create plugin via driver' do
48
+ d = Fluent::Test::Driver::Input.new(AllBooleanParams)
49
+ d.configure(CONFIG)
50
+ assert_equal([true] * 4, [d.instance.flag1, d.instance.flag2, d.instance.flag3, d.instance.flag4])
51
+ num_of_sections = 3
52
+ assert_equal num_of_sections, d.instance.children.size
53
+ assert_equal([true] * (num_of_sections * 4), d.instance.children.map{|c| [c.flag1, c.flag2, c.flag3, c.flag4]}.flatten)
54
+ end
55
+ end
56
+ end
@@ -7,7 +7,7 @@ require 'fluent/system_config'
7
7
  module Fluent::Config
8
8
  class FakeLoggerInitializer
9
9
  attr_accessor :level
10
- def initalize
10
+ def initialize
11
11
  @level = nil
12
12
  end
13
13
  end
@@ -55,6 +55,8 @@ module Fluent::Config
55
55
  assert_nil(sc.emit_error_log_interval)
56
56
  assert_nil(sc.suppress_config_dump)
57
57
  assert_nil(sc.without_source)
58
+ assert_equal(:text, sc.log.format)
59
+ assert_equal('%Y-%m-%d %H:%M:%S %z', sc.log.time_format)
58
60
  assert_equal(1, s.instance_variable_get(:@workers))
59
61
  assert_nil(s.instance_variable_get(:@root_dir))
60
62
  assert_equal(Fluent::Log::LEVEL_INFO, s.instance_variable_get(:@log_level))
@@ -91,6 +93,22 @@ module Fluent::Config
91
93
  assert_not_nil(s.instance_variable_get("@#{key}"))
92
94
  end
93
95
 
96
+ test "log parameters" do
97
+ conf = parse_text(<<-EOS)
98
+ <system>
99
+ <log>
100
+ format json
101
+ time_format %Y
102
+ </log>
103
+ </system>
104
+ EOS
105
+ s = FakeSupervisor.new
106
+ sc = Fluent::SystemConfig.new(conf)
107
+ sc.apply(s)
108
+ assert_equal(:json, sc.log.format)
109
+ assert_equal('%Y', sc.log.time_format)
110
+ end
111
+
94
112
  data(
95
113
  'foo' => ['foo', 'bar'],
96
114
  'hoge' => ['hoge', 'fuga'],
@@ -61,6 +61,34 @@ class TestConfigTypes < ::Test::Unit::TestCase
61
61
  end
62
62
  end
63
63
 
64
+ sub_test_case 'Config.regexp_value' do
65
+ data("empty" => [//, "//"],
66
+ "plain" => [/regexp/, "/regexp/"],
67
+ "zero width" => [/^$/, "/^$/"],
68
+ "character classes" => [/[a-z]/, "/[a-z]/"],
69
+ "meta charactersx" => [/.+.*?\d\w\s\S/, '/.+.*?\d\w\s\S/'])
70
+ test 'normal case' do |(expected, str)|
71
+ assert_equal(expected, Config.regexp_value(str))
72
+ end
73
+
74
+ data("empty" => [//, ""],
75
+ "plain" => [/regexp/, "regexp"],
76
+ "zero width" => [/^$/, "^$"],
77
+ "character classes" => [/[a-z]/, "[a-z]"],
78
+ "meta charactersx" => [/.+.*?\d\w\s\S/, '.+.*?\d\w\s\S'])
79
+ test 'w/o slashes' do |(expected, str)|
80
+ assert_equal(expected, Config.regexp_value(str))
81
+ end
82
+
83
+ data("missing right slash" => "/regexp",
84
+ "too many options" => "/regexp/imx",)
85
+ test 'invalid regexp' do |(str)|
86
+ assert_raise(Fluent::ConfigError.new("invalid regexp: missing right slash: #{str}")) do
87
+ Config.regexp_value(str)
88
+ end
89
+ end
90
+ end
91
+
64
92
  sub_test_case 'type converters for config_param definitions' do
65
93
  test 'string' do
66
94
  assert_equal 'test', Config::STRING_TYPE.call('test', {})
@@ -134,6 +162,15 @@ class TestConfigTypes < ::Test::Unit::TestCase
134
162
  assert_equal 86400, Config::TIME_TYPE.call('1d', {})
135
163
  end
136
164
 
165
+ data("empty" => [//, "//"],
166
+ "plain" => [/regexp/, "/regexp/"],
167
+ "zero width" => [/^$/, "/^$/"],
168
+ "character classes" => [/[a-z]/, "/[a-z]/"],
169
+ "meta charactersx" => [/.+.*?\d\w\s\S/, '/.+.*?\d\w\s\S/'])
170
+ test 'regexp' do |(expected, str)|
171
+ assert_equal(expected, Config::REGEXP_TYPE.call(str, {}))
172
+ end
173
+
137
174
  test 'hash' do
138
175
  assert_equal({"x"=>"v","k"=>1}, Config::HASH_TYPE.call('{"x":"v","k":1}', {}))
139
176
  assert_equal({"x"=>"v","k"=>"1"}, Config::HASH_TYPE.call('x:v,k:1', {}))
@@ -0,0 +1,559 @@
1
+ require_relative '../helper'
2
+ require 'fluent/counter/client'
3
+ require 'fluent/counter/store'
4
+ require 'fluent/counter/server'
5
+ require 'flexmock/test_unit'
6
+ require 'timecop'
7
+
8
+ class CounterClientTest < ::Test::Unit::TestCase
9
+ TEST_ADDR = '127.0.0.1'
10
+ TEST_PORT = '8277'
11
+
12
+ setup do
13
+ # timecop isn't compatible with EventTime
14
+ t = Time.parse('2016-09-22 16:59:59 +0900')
15
+ Timecop.freeze(t)
16
+ @now = Fluent::EventTime.now
17
+
18
+ @options = {
19
+ addr: TEST_ADDR,
20
+ port: TEST_PORT,
21
+ log: $log,
22
+ }
23
+
24
+ @server_name = 'server1'
25
+ @scope = "worker1\tplugin1"
26
+ @loop = Coolio::Loop.new
27
+ @server = Fluent::Counter::Server.new(@server_name, @options).start
28
+ @client = Fluent::Counter::Client.new(@loop, @options).start
29
+ end
30
+
31
+ teardown do
32
+ Timecop.return
33
+ @server.stop
34
+ @client.stop
35
+ end
36
+
37
+ test 'Callable API' do
38
+ [:establish, :init, :delete, :inc, :reset, :get].each do |m|
39
+ assert_true @client.respond_to?(m)
40
+ end
41
+ end
42
+
43
+ sub_test_case 'on_message' do
44
+ setup do
45
+ @future = flexmock('future')
46
+ @client.instance_variable_set(:@responses, { 1 => @future })
47
+ end
48
+
49
+ test 'call a set method to a corresponding object' do
50
+ @future.should_receive(:set).once.with(Hash)
51
+ @client.send(:on_message, { 'id' => 1 })
52
+ end
53
+
54
+ test "output a warning log when passed id doesn't exist" do
55
+ data = { 'id' => 2 }
56
+ mock($log).warn("Receiving missing id data: #{data}")
57
+ @client.send(:on_message, data)
58
+ end
59
+ end
60
+
61
+ def extract_value_from_server(server, scope, name)
62
+ store = server.instance_variable_get(:@store).instance_variable_get(:@storage).instance_variable_get(:@store)
63
+ key = Fluent::Counter::Store.gen_key(scope, name)
64
+ store[key]
65
+ end
66
+
67
+ def travel(sec)
68
+ # Since Timecop.travel() causes test failures on Windows/AppVeyor by inducing
69
+ # rounding errors to Time.now, we need to use Timecop.freeze() instead.
70
+ Timecop.freeze(Time.now + sec)
71
+ end
72
+
73
+ sub_test_case 'establish' do
74
+ test 'establish a scope' do
75
+ @client.establish(@scope)
76
+ assert_equal "#{@server_name}\t#{@scope}", @client.instance_variable_get(:@scope)
77
+ end
78
+
79
+ data(
80
+ empty: '',
81
+ invalid_string: '_scope',
82
+ invalid_string2: 'Scope'
83
+ )
84
+ test 'raise an error when passed scope is invalid' do |scope|
85
+ assert_raise do
86
+ @client.establish(scope)
87
+ end
88
+ end
89
+ end
90
+
91
+ sub_test_case 'init' do
92
+ setup do
93
+ @client.instance_variable_set(:@scope, @scope)
94
+ end
95
+
96
+ data(
97
+ numeric_type: [
98
+ { name: 'key', reset_interval: 20, type: 'numeric' }, 0
99
+ ],
100
+ float_type: [
101
+ { name: 'key', reset_interval: 20, type: 'float' }, 0.0
102
+ ],
103
+ integer_type: [
104
+ { name: 'key', reset_interval: 20, type: 'integer' }, 0
105
+ ]
106
+ )
107
+ test 'create a value' do |(param, initial_value)|
108
+ assert_nil extract_value_from_server(@server, @scope, param[:name])
109
+
110
+ response = @client.init(param).get
111
+ data = response.data.first
112
+
113
+ assert_nil response.errors
114
+ assert_equal param[:name], data['name']
115
+ assert_equal param[:reset_interval], data['reset_interval']
116
+ assert_equal param[:type], data['type']
117
+ assert_equal initial_value, data['current']
118
+ assert_equal initial_value, data['total']
119
+
120
+ v = extract_value_from_server(@server, @scope, param[:name])
121
+ assert_equal param[:name], v['name']
122
+ assert_equal param[:reset_interval], v['reset_interval']
123
+ assert_equal param[:type], v['type']
124
+ assert_equal initial_value, v['total']
125
+ assert_equal initial_value, v['current']
126
+ end
127
+
128
+ test 'raise an error when @scope is nil' do
129
+ @client.instance_variable_set(:@scope, nil)
130
+ assert_raise 'Call `establish` method to get a `scope` before calling this method' do
131
+ @client.init(name: 'key1', reset_interval: 10).get
132
+ end
133
+ end
134
+
135
+ data(
136
+ already_exist_key: [
137
+ { name: 'key1', reset_interval: 10 },
138
+ { 'code' => 'invalid_params', 'message' => "worker1\tplugin1\tkey1 already exists in counter" }
139
+ ],
140
+ missing_name: [
141
+ { reset_interval: 10 },
142
+ { 'code' => 'invalid_params', 'message' => '`name` is required' },
143
+ ],
144
+ missing_reset_interval: [
145
+ { name: 'key' },
146
+ { 'code' => 'invalid_params', 'message' => '`reset_interval` is required' },
147
+ ],
148
+ invalid_name: [
149
+ { name: '\tkey' },
150
+ { 'code' => 'invalid_params', 'message' => '`name` is the invalid format' }
151
+ ]
152
+ )
153
+ test 'return an error object' do |(param, expected_error)|
154
+ @client.init(:name => 'key1', :reset_interval => 10).get
155
+ response = @client.init(param).get
156
+ errors = response.errors.first
157
+
158
+ assert_empty response.data
159
+ assert_equal expected_error, errors
160
+
161
+ assert_raise {
162
+ @client.init(param).wait
163
+ }
164
+ end
165
+
166
+ test 'return an existing value when passed key already exists and ignore option is true' do
167
+ res1 = @client.init(name: 'key1', reset_interval: 10).get
168
+ res2 = nil
169
+ assert_nothing_raised do
170
+ res2 = @client.init({ name: 'key1', reset_interval: 10 }, options: { ignore: true }).get
171
+ end
172
+ assert_equal res1.data, res2.data
173
+ end
174
+
175
+ test 'return an error object and data object' do
176
+ param = { name: 'key1', reset_interval: 10 }
177
+ param2 = { name: 'key2', reset_interval: 10 }
178
+ @client.init(param).get
179
+
180
+ response = @client.init([param2, param]).get
181
+ data = response.data.first
182
+ error = response.errors.first
183
+
184
+ assert_equal param2[:name], data['name']
185
+ assert_equal param2[:reset_interval], data['reset_interval']
186
+
187
+ assert_equal 'invalid_params', error['code']
188
+ assert_equal "#{@scope}\t#{param[:name]} already exists in counter", error['message']
189
+ end
190
+
191
+ test 'return a future object when async call' do
192
+ param = { name: 'key', reset_interval: 10 }
193
+ r = @client.init(param)
194
+ assert_true r.is_a?(Fluent::Counter::Future)
195
+ assert_nil r.errors
196
+ end
197
+ end
198
+
199
+ sub_test_case 'delete' do
200
+ setup do
201
+ @client.instance_variable_set(:@scope, @scope)
202
+ @name = 'key'
203
+ @key = Fluent::Counter::Store.gen_key(@scope, @name)
204
+
205
+ @init_obj = { name: @name, reset_interval: 20, type: 'numeric' }
206
+ @client.init(@init_obj).get
207
+ end
208
+
209
+ test 'delete a value' do
210
+ assert extract_value_from_server(@server, @scope, @name)
211
+
212
+ response = @client.delete(@name).get
213
+ v = response.data.first
214
+
215
+ assert_nil response.errors
216
+ assert_equal @init_obj[:name], v['name']
217
+ assert_equal @init_obj[:type], v['type']
218
+ assert_equal @init_obj[:reset_interval], v['reset_interval']
219
+
220
+ assert_nil extract_value_from_server(@server, @scope, @name)
221
+ end
222
+
223
+ test 'raise an error when @scope is nil' do
224
+ @client.instance_variable_set(:@scope, nil)
225
+ assert_raise 'Call `establish` method to get a `scope` before calling this method' do
226
+ @client.delete(@name).get
227
+ end
228
+ end
229
+
230
+ data(
231
+ key_not_found: [
232
+ 'key2',
233
+ { 'code' => 'unknown_key', 'message' => "`worker1\tplugin1\tkey2` doesn't exist in counter" }
234
+ ],
235
+ invalid_key: [
236
+ '\tkey',
237
+ { 'code' => 'invalid_params', 'message' => '`key` is the invalid format' }
238
+ ]
239
+ )
240
+ test 'return an error object' do |(param, expected_error)|
241
+ response = @client.delete(param).get
242
+ errors = response.errors.first
243
+
244
+ assert_empty response.data
245
+ assert_equal expected_error, errors
246
+ end
247
+
248
+ test 'return an error object and data object' do
249
+ unknown_name = 'key2'
250
+
251
+ response = @client.delete(@name, unknown_name).get
252
+ data = response.data.first
253
+ error = response.errors.first
254
+
255
+ assert_equal @name, data['name']
256
+ assert_equal @init_obj[:reset_interval], data['reset_interval']
257
+
258
+ assert_equal 'unknown_key', error['code']
259
+ assert_equal "`#{@scope}\t#{unknown_name}` doesn't exist in counter", error['message']
260
+
261
+ assert_nil extract_value_from_server(@server, @scope, @name)
262
+ end
263
+
264
+ test 'return a future object when async call' do
265
+ r = @client.delete(@name)
266
+ assert_true r.is_a?(Fluent::Counter::Future)
267
+ assert_nil r.errors
268
+ end
269
+ end
270
+
271
+ sub_test_case 'inc' do
272
+ setup do
273
+ @client.instance_variable_set(:@scope, @scope)
274
+ @name = 'key'
275
+ @key = Fluent::Counter::Store.gen_key(@scope, @name)
276
+
277
+ @init_obj = { name: @name, reset_interval: 20, type: 'numeric' }
278
+ @client.init(@init_obj).get
279
+ end
280
+
281
+ test 'increment a value' do
282
+ v = extract_value_from_server(@server, @scope, @name)
283
+ assert_equal 0, v['total']
284
+ assert_equal 0, v['current']
285
+
286
+ travel(1)
287
+ inc_obj = { name: @name, value: 10 }
288
+ @client.inc(inc_obj).get
289
+
290
+ v = extract_value_from_server(@server, @scope, @name)
291
+ assert_equal inc_obj[:value], v['total']
292
+ assert_equal inc_obj[:value], v['current']
293
+ assert_equal (@now + 1), Fluent::EventTime.new(*v['last_modified_at'])
294
+ end
295
+
296
+ test 'create and increment a value when force option is true' do
297
+ name = 'new_key'
298
+ param = { name: name, value: 11, reset_interval: 1 }
299
+
300
+ assert_nil extract_value_from_server(@server, @scope, name)
301
+
302
+ @client.inc(param, options: { force: true }).get
303
+
304
+ v = extract_value_from_server(@server, @scope, name)
305
+ assert v
306
+ assert_equal param[:name], v['name']
307
+ assert_equal 1, v['reset_interval']
308
+ assert_equal param[:value], v['current']
309
+ assert_equal param[:value], v['total']
310
+ end
311
+
312
+ test 'raise an error when @scope is nil' do
313
+ @client.instance_variable_set(:@scope, nil)
314
+ assert_raise 'Call `establish` method to get a `scope` before calling this method' do
315
+ @client.inc(name: 'name', value: 1).get
316
+ end
317
+ end
318
+
319
+ data(
320
+ not_exist_key: [
321
+ { name: 'key2', value: 10 },
322
+ { 'code' => 'unknown_key', 'message' => "`worker1\tplugin1\tkey2` doesn't exist in counter" }
323
+ ],
324
+ missing_name: [
325
+ { value: 10 },
326
+ { 'code' => 'invalid_params', 'message' => '`name` is required' },
327
+ ],
328
+ missing_value: [
329
+ { name: 'key' },
330
+ { 'code' => 'invalid_params', 'message' => '`value` is required' },
331
+ ],
332
+ invalid_name: [
333
+ { name: '\tkey' },
334
+ { 'code' => 'invalid_params', 'message' => '`name` is the invalid format' }
335
+ ]
336
+ )
337
+ test 'return an error object' do |(param, expected_error)|
338
+ response = @client.inc(param).get
339
+ errors = response.errors.first
340
+ assert_empty response.data
341
+ assert_equal expected_error, errors
342
+ end
343
+
344
+ test 'return an error object and data object' do
345
+ parmas = [
346
+ { name: @name, value: 10 },
347
+ { name: 'unknown_key', value: 9 },
348
+ ]
349
+ response = @client.inc(parmas).get
350
+
351
+ data = response.data.first
352
+ error = response.errors.first
353
+
354
+ assert_equal @name, data['name']
355
+ assert_equal 10, data['current']
356
+ assert_equal 10, data['total']
357
+
358
+ assert_equal 'unknown_key', error['code']
359
+ assert_equal "`#{@scope}\tunknown_key` doesn't exist in counter", error['message']
360
+ end
361
+
362
+ test 'return a future object when async call' do
363
+ param = { name: 'key', value: 10 }
364
+ r = @client.inc(param)
365
+ assert_true r.is_a?(Fluent::Counter::Future)
366
+ assert_nil r.errors
367
+ end
368
+ end
369
+
370
+ sub_test_case 'get' do
371
+ setup do
372
+ @client.instance_variable_set(:@scope, @scope)
373
+ @name = 'key'
374
+
375
+ @init_obj = { name: @name, reset_interval: 20, type: 'numeric' }
376
+ @client.init(@init_obj).get
377
+ end
378
+
379
+ test 'get a value' do
380
+ v1 = extract_value_from_server(@server, @scope, @name)
381
+ v2 = @client.get(@name).data.first
382
+
383
+ assert_equal v1['name'], v2['name']
384
+ assert_equal v1['current'], v2['current']
385
+ assert_equal v1['total'], v2['total']
386
+ assert_equal v1['type'], v2['type']
387
+ end
388
+
389
+ test 'raise an error when @scope is nil' do
390
+ @client.instance_variable_set(:@scope, nil)
391
+ assert_raise 'Call `establish` method to get a `scope` before calling this method' do
392
+ @client.get(@name).get
393
+ end
394
+ end
395
+
396
+ data(
397
+ key_not_found: [
398
+ 'key2',
399
+ { 'code' => 'unknown_key', 'message' => "`worker1\tplugin1\tkey2` doesn't exist in counter" }
400
+ ],
401
+ invalid_key: [
402
+ '\tkey',
403
+ { 'code' => 'invalid_params', 'message' => '`key` is the invalid format' }
404
+ ]
405
+ )
406
+ test 'return an error object' do |(param, expected_error)|
407
+ response = @client.get(param).get
408
+ errors = response.errors.first
409
+ assert_empty response.data
410
+ assert_equal expected_error, errors
411
+ end
412
+
413
+ test 'return an error object and data object' do
414
+ unknown_name = 'key2'
415
+
416
+ response = @client.get(@name, unknown_name).get
417
+ data = response.data.first
418
+ error = response.errors.first
419
+
420
+ assert_equal @name, data['name']
421
+ assert_equal @init_obj[:reset_interval], data['reset_interval']
422
+
423
+ assert_equal 'unknown_key', error['code']
424
+ assert_equal "`#{@scope}\t#{unknown_name}` doesn't exist in counter", error['message']
425
+ end
426
+
427
+ test 'return a future object when async call' do
428
+ r = @client.get(@name)
429
+ assert_true r.is_a?(Fluent::Counter::Future)
430
+ assert_nil r.errors
431
+ end
432
+ end
433
+
434
+ sub_test_case 'reset' do
435
+ setup do
436
+ @client.instance_variable_set(:@scope, @scope)
437
+ @name = 'key'
438
+ @key = Fluent::Counter::Store.gen_key(@scope, @name)
439
+
440
+ @init_obj = { name: @name, reset_interval: 5, type: 'numeric' }
441
+ @client.init(@init_obj).get
442
+ @inc_obj = { name: @name, value: 10 }
443
+ @client.inc(@inc_obj).get
444
+ end
445
+
446
+ test 'reset a value after `reset_interval` passed' do
447
+ v1 = extract_value_from_server(@server, @scope, @name)
448
+ assert_equal @inc_obj[:value], v1['total']
449
+ assert_equal @inc_obj[:value], v1['current']
450
+ assert_equal @now, Fluent::EventTime.new(*v1['last_reset_at'])
451
+
452
+ travel_sec = 6 # greater than reset_interval
453
+ travel(travel_sec)
454
+
455
+ v2 = @client.reset(@name).get
456
+ data = v2.data.first
457
+
458
+ c = data['counter_data']
459
+
460
+ assert_equal travel_sec, data['elapsed_time']
461
+ assert_true data['success']
462
+
463
+ assert_equal @inc_obj[:value], c['current']
464
+ assert_equal @inc_obj[:value], c['total']
465
+ assert_equal @now, c['last_reset_at']
466
+
467
+ v1 = extract_value_from_server(@server, @scope, @name)
468
+ assert_equal 0, v1['current']
469
+ assert_equal @inc_obj[:value], v1['total']
470
+ assert_equal (@now + travel_sec), Fluent::EventTime.new(*v1['last_reset_at'])
471
+ assert_equal (@now + travel_sec), Fluent::EventTime.new(*v1['last_modified_at'])
472
+ end
473
+
474
+ test 'areturn a value object before `reset_interval` passed' do
475
+ v1 = extract_value_from_server(@server, @scope, @name)
476
+ assert_equal @inc_obj[:value], v1['total']
477
+ assert_equal @inc_obj[:value], v1['current']
478
+ assert_equal @now, Fluent::EventTime.new(*v1['last_reset_at'])
479
+
480
+ travel_sec = 4 # less than reset_interval
481
+ travel(travel_sec)
482
+
483
+ v2 = @client.reset(@name).get
484
+ data = v2.data.first
485
+
486
+ c = data['counter_data']
487
+
488
+ assert_equal travel_sec, data['elapsed_time']
489
+ assert_equal false, data['success']
490
+
491
+ assert_equal @inc_obj[:value], c['current']
492
+ assert_equal @inc_obj[:value], c['total']
493
+ assert_equal @now, c['last_reset_at']
494
+
495
+ v1 = extract_value_from_server(@server, @scope, @name)
496
+ assert_equal @inc_obj[:value], v1['current']
497
+ assert_equal @inc_obj[:value], v1['total']
498
+ assert_equal @now, Fluent::EventTime.new(*v1['last_reset_at'])
499
+ end
500
+
501
+ test 'raise an error when @scope is nil' do
502
+ @client.instance_variable_set(:@scope, nil)
503
+ assert_raise 'Call `establish` method to get a `scope` before calling this method' do
504
+ @client.reset(@name).get
505
+ end
506
+ end
507
+
508
+ data(
509
+ key_not_found: [
510
+ 'key2',
511
+ { 'code' => 'unknown_key', 'message' => "`worker1\tplugin1\tkey2` doesn't exist in counter" }
512
+ ],
513
+ invalid_key: [
514
+ '\tkey',
515
+ { 'code' => 'invalid_params', 'message' => '`key` is the invalid format' }
516
+ ]
517
+ )
518
+ test 'return an error object' do |(param, expected_error)|
519
+ response = @client.reset(param).get
520
+ errors = response.errors.first
521
+ assert_empty response.data
522
+ assert_equal expected_error, errors
523
+ end
524
+
525
+ test 'return an error object and data object' do
526
+ unknown_name = 'key2'
527
+
528
+ travel_sec = 6 # greater than reset_interval
529
+ travel(travel_sec)
530
+
531
+ response = @client.reset(@name, unknown_name).get
532
+ data = response.data.first
533
+ error = response.errors.first
534
+ counter = data['counter_data']
535
+
536
+ assert_true data['success']
537
+ assert_equal travel_sec, data['elapsed_time']
538
+ assert_equal @name, counter['name']
539
+ assert_equal @init_obj[:reset_interval], counter['reset_interval']
540
+ assert_equal @inc_obj[:value], counter['total']
541
+ assert_equal @inc_obj[:value], counter['current']
542
+
543
+ assert_equal 'unknown_key', error['code']
544
+ assert_equal "`#{@scope}\t#{unknown_name}` doesn't exist in counter", error['message']
545
+
546
+ v1 = extract_value_from_server(@server, @scope, @name)
547
+ assert_equal 0, v1['current']
548
+ assert_equal @inc_obj[:value], v1['total']
549
+ assert_equal (@now + travel_sec), Fluent::EventTime.new(*v1['last_reset_at'])
550
+ assert_equal (@now + travel_sec), Fluent::EventTime.new(*v1['last_modified_at'])
551
+ end
552
+
553
+ test 'return a future object when async call' do
554
+ r = @client.reset(@name)
555
+ assert_true r.is_a?(Fluent::Counter::Future)
556
+ assert_nil r.errors
557
+ end
558
+ end
559
+ end