fluentd 0.12.40 → 1.6.2
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.
- checksums.yaml +5 -5
- data/.github/ISSUE_TEMPLATE/bug_report.md +39 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +23 -0
- data/.github/ISSUE_TEMPLATE.md +17 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +13 -0
- data/.gitignore +5 -0
- data/.gitlab/cicd-template.yaml +10 -0
- data/.gitlab-ci.yml +147 -0
- data/.travis.yml +56 -20
- data/ADOPTERS.md +5 -0
- data/CHANGELOG.md +1369 -0
- data/CONTRIBUTING.md +16 -5
- data/GOVERNANCE.md +55 -0
- data/Gemfile +5 -0
- data/GithubWorkflow.md +78 -0
- data/LICENSE +202 -0
- data/MAINTAINERS.md +7 -0
- data/README.md +23 -11
- data/Rakefile +48 -2
- data/Vagrantfile +17 -0
- data/appveyor.yml +37 -0
- data/bin/fluent-binlog-reader +7 -0
- data/bin/fluent-ca-generate +6 -0
- data/bin/fluent-plugin-config-format +5 -0
- data/bin/fluent-plugin-generate +5 -0
- data/bin/fluentd +3 -0
- data/code-of-conduct.md +3 -0
- data/example/copy_roundrobin.conf +39 -0
- data/example/counter.conf +18 -0
- data/example/in_dummy_blocks.conf +17 -0
- data/example/in_dummy_with_compression.conf +23 -0
- data/example/in_forward.conf +7 -0
- data/example/in_forward_client.conf +37 -0
- data/example/in_forward_shared_key.conf +15 -0
- data/example/in_forward_tls.conf +14 -0
- data/example/in_forward_users.conf +24 -0
- data/example/in_forward_workers.conf +21 -0
- data/example/in_http.conf +3 -1
- data/example/in_out_forward.conf +17 -0
- data/example/logevents.conf +25 -0
- data/example/multi_filters.conf +61 -0
- data/example/out_exec_filter.conf +42 -0
- data/example/out_forward.conf +13 -13
- data/example/out_forward_buf_file.conf +23 -0
- data/example/out_forward_client.conf +109 -0
- data/example/out_forward_heartbeat_none.conf +16 -0
- data/example/out_forward_shared_key.conf +36 -0
- data/example/out_forward_tls.conf +18 -0
- data/example/out_forward_users.conf +65 -0
- data/example/out_null.conf +36 -0
- data/example/secondary_file.conf +42 -0
- data/example/suppress_config_dump.conf +7 -0
- data/example/worker_section.conf +36 -0
- data/fluent.conf +29 -0
- data/fluentd.gemspec +21 -11
- data/lib/fluent/agent.rb +67 -90
- data/lib/fluent/clock.rb +62 -0
- data/lib/fluent/command/binlog_reader.rb +244 -0
- data/lib/fluent/command/ca_generate.rb +181 -0
- data/lib/fluent/command/cat.rb +42 -18
- data/lib/fluent/command/debug.rb +12 -10
- data/lib/fluent/command/fluentd.rb +153 -5
- data/lib/fluent/command/plugin_config_formatter.rb +292 -0
- data/lib/fluent/command/plugin_generator.rb +324 -0
- data/lib/fluent/compat/call_super_mixin.rb +67 -0
- data/lib/fluent/compat/detach_process_mixin.rb +33 -0
- data/lib/fluent/compat/exec_util.rb +129 -0
- data/lib/fluent/compat/file_util.rb +54 -0
- data/lib/fluent/compat/filter.rb +68 -0
- data/lib/fluent/compat/formatter.rb +111 -0
- data/lib/fluent/compat/formatter_utils.rb +85 -0
- data/lib/fluent/compat/handle_tag_and_time_mixin.rb +62 -0
- data/lib/fluent/compat/handle_tag_name_mixin.rb +53 -0
- data/lib/fluent/compat/input.rb +49 -0
- data/lib/fluent/compat/output.rb +718 -0
- data/lib/fluent/compat/output_chain.rb +60 -0
- data/lib/fluent/compat/parser.rb +310 -0
- data/lib/fluent/compat/parser_utils.rb +40 -0
- data/lib/fluent/compat/propagate_default.rb +62 -0
- data/lib/fluent/compat/record_filter_mixin.rb +34 -0
- data/lib/fluent/compat/set_tag_key_mixin.rb +50 -0
- data/lib/fluent/compat/set_time_key_mixin.rb +69 -0
- data/lib/fluent/compat/socket_util.rb +165 -0
- data/lib/fluent/compat/string_util.rb +34 -0
- data/lib/fluent/compat/structured_format_mixin.rb +26 -0
- data/lib/fluent/compat/type_converter.rb +90 -0
- data/lib/fluent/config/configure_proxy.rb +210 -62
- data/lib/fluent/config/dsl.rb +12 -5
- data/lib/fluent/config/element.rb +107 -9
- data/lib/fluent/config/literal_parser.rb +9 -3
- data/lib/fluent/config/parser.rb +4 -4
- data/lib/fluent/config/section.rb +51 -14
- data/lib/fluent/config/types.rb +28 -13
- data/lib/fluent/config/v1_parser.rb +3 -5
- data/lib/fluent/config.rb +23 -20
- data/lib/fluent/configurable.rb +79 -21
- data/lib/fluent/counter/base_socket.rb +46 -0
- data/lib/fluent/counter/client.rb +297 -0
- data/lib/fluent/counter/error.rb +86 -0
- data/lib/fluent/counter/mutex_hash.rb +163 -0
- data/lib/fluent/counter/server.rb +273 -0
- data/lib/fluent/counter/store.rb +205 -0
- data/lib/fluent/counter/validator.rb +145 -0
- data/lib/fluent/counter.rb +23 -0
- data/lib/fluent/daemon.rb +15 -0
- data/lib/fluent/engine.rb +102 -65
- data/lib/fluent/env.rb +7 -3
- data/lib/fluent/error.rb +30 -0
- data/lib/fluent/event.rb +197 -21
- data/lib/fluent/event_router.rb +93 -10
- data/lib/fluent/filter.rb +2 -50
- data/lib/fluent/formatter.rb +4 -293
- data/lib/fluent/input.rb +2 -32
- data/lib/fluent/label.rb +10 -2
- data/lib/fluent/load.rb +3 -3
- data/lib/fluent/log.rb +348 -81
- data/lib/fluent/match.rb +37 -36
- data/lib/fluent/mixin.rb +12 -176
- data/lib/fluent/msgpack_factory.rb +62 -0
- data/lib/fluent/output.rb +10 -612
- data/lib/fluent/output_chain.rb +23 -0
- data/lib/fluent/parser.rb +4 -800
- data/lib/fluent/plugin/bare_output.rb +63 -0
- data/lib/fluent/plugin/base.rb +192 -0
- data/lib/fluent/plugin/buf_file.rb +128 -174
- data/lib/fluent/plugin/buf_memory.rb +9 -92
- data/lib/fluent/plugin/buffer/chunk.rb +221 -0
- data/lib/fluent/plugin/buffer/file_chunk.rb +383 -0
- data/lib/fluent/plugin/buffer/memory_chunk.rb +90 -0
- data/lib/fluent/plugin/buffer.rb +779 -0
- data/lib/fluent/plugin/compressable.rb +92 -0
- data/lib/fluent/plugin/exec_util.rb +3 -108
- data/lib/fluent/plugin/file_util.rb +4 -34
- data/lib/fluent/plugin/file_wrapper.rb +120 -0
- data/lib/fluent/plugin/filter.rb +93 -0
- data/lib/fluent/plugin/filter_grep.rb +117 -34
- data/lib/fluent/plugin/filter_parser.rb +85 -62
- data/lib/fluent/plugin/filter_record_transformer.rb +27 -39
- data/lib/fluent/plugin/filter_stdout.rb +15 -12
- data/lib/fluent/plugin/formatter.rb +50 -0
- data/lib/fluent/plugin/formatter_csv.rb +52 -0
- data/lib/fluent/plugin/formatter_hash.rb +33 -0
- data/lib/fluent/plugin/formatter_json.rb +55 -0
- data/lib/fluent/plugin/formatter_ltsv.rb +42 -0
- data/lib/fluent/plugin/formatter_msgpack.rb +33 -0
- data/lib/fluent/plugin/formatter_out_file.rb +51 -0
- data/lib/fluent/plugin/formatter_single_value.rb +34 -0
- data/lib/fluent/plugin/formatter_stdout.rb +76 -0
- data/lib/fluent/plugin/formatter_tsv.rb +38 -0
- data/lib/fluent/plugin/in_debug_agent.rb +17 -6
- data/lib/fluent/plugin/in_dummy.rb +47 -20
- data/lib/fluent/plugin/in_exec.rb +55 -123
- data/lib/fluent/plugin/in_forward.rb +299 -216
- data/lib/fluent/plugin/in_gc_stat.rb +14 -36
- data/lib/fluent/plugin/in_http.rb +204 -91
- data/lib/fluent/plugin/in_monitor_agent.rb +186 -258
- data/lib/fluent/plugin/in_object_space.rb +13 -41
- data/lib/fluent/plugin/in_syslog.rb +112 -134
- data/lib/fluent/plugin/in_tail.rb +408 -745
- data/lib/fluent/plugin/in_tcp.rb +66 -9
- data/lib/fluent/plugin/in_udp.rb +60 -11
- data/lib/fluent/plugin/{in_stream.rb → in_unix.rb} +8 -4
- data/lib/fluent/plugin/input.rb +37 -0
- data/lib/fluent/plugin/multi_output.rb +158 -0
- data/lib/fluent/plugin/out_copy.rb +23 -35
- data/lib/fluent/plugin/out_exec.rb +67 -70
- data/lib/fluent/plugin/out_exec_filter.rb +204 -271
- data/lib/fluent/plugin/out_file.rb +267 -73
- data/lib/fluent/plugin/out_forward.rb +854 -325
- data/lib/fluent/plugin/out_null.rb +42 -9
- data/lib/fluent/plugin/out_relabel.rb +9 -5
- data/lib/fluent/plugin/out_roundrobin.rb +18 -37
- data/lib/fluent/plugin/out_secondary_file.rb +133 -0
- data/lib/fluent/plugin/out_stdout.rb +43 -10
- data/lib/fluent/plugin/out_stream.rb +7 -2
- data/lib/fluent/plugin/output.rb +1498 -0
- data/lib/fluent/plugin/owned_by_mixin.rb +42 -0
- data/lib/fluent/plugin/parser.rb +191 -0
- data/lib/fluent/plugin/parser_apache.rb +28 -0
- data/lib/fluent/plugin/parser_apache2.rb +88 -0
- data/lib/fluent/plugin/parser_apache_error.rb +26 -0
- data/lib/fluent/plugin/parser_csv.rb +39 -0
- data/lib/fluent/plugin/parser_json.rb +94 -0
- data/lib/fluent/plugin/parser_ltsv.rb +49 -0
- data/lib/fluent/plugin/parser_msgpack.rb +50 -0
- data/lib/fluent/plugin/parser_multiline.rb +106 -0
- data/lib/fluent/plugin/parser_nginx.rb +28 -0
- data/lib/fluent/plugin/parser_none.rb +36 -0
- data/lib/fluent/plugin/parser_regexp.rb +68 -0
- data/lib/fluent/plugin/parser_syslog.rb +142 -0
- data/lib/fluent/plugin/parser_tsv.rb +42 -0
- data/lib/fluent/plugin/socket_util.rb +3 -143
- data/lib/fluent/plugin/storage.rb +84 -0
- data/lib/fluent/plugin/storage_local.rb +164 -0
- data/lib/fluent/plugin/string_util.rb +3 -15
- data/lib/fluent/plugin.rb +122 -121
- data/lib/fluent/plugin_helper/cert_option.rb +178 -0
- data/lib/fluent/plugin_helper/child_process.rb +364 -0
- data/lib/fluent/plugin_helper/compat_parameters.rb +333 -0
- data/lib/fluent/plugin_helper/counter.rb +51 -0
- data/lib/fluent/plugin_helper/event_emitter.rb +93 -0
- data/lib/fluent/plugin_helper/event_loop.rb +170 -0
- data/lib/fluent/plugin_helper/extract.rb +104 -0
- data/lib/fluent/plugin_helper/formatter.rb +147 -0
- data/lib/fluent/plugin_helper/http_server/app.rb +79 -0
- data/lib/fluent/plugin_helper/http_server/compat/server.rb +81 -0
- data/lib/fluent/plugin_helper/http_server/compat/webrick_handler.rb +58 -0
- data/lib/fluent/plugin_helper/http_server/methods.rb +35 -0
- data/lib/fluent/plugin_helper/http_server/request.rb +42 -0
- data/lib/fluent/plugin_helper/http_server/router.rb +54 -0
- data/lib/fluent/plugin_helper/http_server/server.rb +87 -0
- data/lib/fluent/plugin_helper/http_server.rb +76 -0
- data/lib/fluent/plugin_helper/inject.rb +151 -0
- data/lib/fluent/plugin_helper/parser.rb +147 -0
- data/lib/fluent/plugin_helper/record_accessor.rb +210 -0
- data/lib/fluent/plugin_helper/retry_state.rb +205 -0
- data/lib/fluent/plugin_helper/server.rb +807 -0
- data/lib/fluent/plugin_helper/socket.rb +250 -0
- data/lib/fluent/plugin_helper/socket_option.rb +80 -0
- data/lib/fluent/plugin_helper/storage.rb +349 -0
- data/lib/fluent/plugin_helper/thread.rb +179 -0
- data/lib/fluent/plugin_helper/timer.rb +92 -0
- data/lib/fluent/plugin_helper.rb +73 -0
- data/lib/fluent/plugin_id.rb +80 -0
- data/lib/fluent/process.rb +3 -489
- data/lib/fluent/registry.rb +52 -10
- data/lib/fluent/root_agent.rb +204 -42
- data/lib/fluent/supervisor.rb +597 -359
- data/lib/fluent/system_config.rb +131 -42
- data/lib/fluent/test/base.rb +6 -54
- data/lib/fluent/test/driver/base.rb +224 -0
- data/lib/fluent/test/driver/base_owned.rb +70 -0
- data/lib/fluent/test/driver/base_owner.rb +135 -0
- data/lib/fluent/test/driver/event_feeder.rb +98 -0
- data/lib/fluent/test/driver/filter.rb +57 -0
- data/lib/fluent/test/driver/formatter.rb +30 -0
- data/lib/fluent/test/driver/input.rb +31 -0
- data/lib/fluent/test/driver/multi_output.rb +53 -0
- data/lib/fluent/test/driver/output.rb +102 -0
- data/lib/fluent/test/driver/parser.rb +30 -0
- data/lib/fluent/test/driver/test_event_router.rb +45 -0
- data/lib/fluent/test/filter_test.rb +0 -1
- data/lib/fluent/test/formatter_test.rb +4 -1
- data/lib/fluent/test/helpers.rb +58 -10
- data/lib/fluent/test/input_test.rb +27 -19
- data/lib/fluent/test/log.rb +79 -0
- data/lib/fluent/test/output_test.rb +28 -39
- data/lib/fluent/test/parser_test.rb +3 -1
- data/lib/fluent/test/startup_shutdown.rb +46 -0
- data/lib/fluent/test.rb +33 -1
- data/lib/fluent/time.rb +450 -1
- data/lib/fluent/timezone.rb +27 -3
- data/lib/fluent/{status.rb → unique_id.rb} +15 -24
- data/lib/fluent/version.rb +1 -1
- data/lib/fluent/winsvc.rb +85 -0
- data/templates/new_gem/Gemfile +3 -0
- data/templates/new_gem/README.md.erb +43 -0
- data/templates/new_gem/Rakefile +13 -0
- data/templates/new_gem/fluent-plugin.gemspec.erb +27 -0
- data/templates/new_gem/lib/fluent/plugin/filter.rb.erb +14 -0
- data/templates/new_gem/lib/fluent/plugin/formatter.rb.erb +14 -0
- data/templates/new_gem/lib/fluent/plugin/input.rb.erb +11 -0
- data/templates/new_gem/lib/fluent/plugin/output.rb.erb +11 -0
- data/templates/new_gem/lib/fluent/plugin/parser.rb.erb +15 -0
- data/templates/new_gem/test/helper.rb.erb +8 -0
- data/templates/new_gem/test/plugin/test_filter.rb.erb +18 -0
- data/templates/new_gem/test/plugin/test_formatter.rb.erb +18 -0
- data/templates/new_gem/test/plugin/test_input.rb.erb +18 -0
- data/templates/new_gem/test/plugin/test_output.rb.erb +18 -0
- data/templates/new_gem/test/plugin/test_parser.rb.erb +18 -0
- data/templates/plugin_config_formatter/param.md-compact.erb +25 -0
- data/templates/plugin_config_formatter/param.md.erb +34 -0
- data/templates/plugin_config_formatter/section.md.erb +12 -0
- data/test/command/test_binlog_reader.rb +346 -0
- data/test/command/test_ca_generate.rb +70 -0
- data/test/command/test_fluentd.rb +901 -0
- data/test/command/test_plugin_config_formatter.rb +276 -0
- data/test/command/test_plugin_generator.rb +92 -0
- data/test/compat/test_calls_super.rb +166 -0
- data/test/compat/test_parser.rb +92 -0
- data/test/config/test_config_parser.rb +126 -2
- data/test/config/test_configurable.rb +946 -187
- data/test/config/test_configure_proxy.rb +424 -74
- data/test/config/test_dsl.rb +11 -11
- data/test/config/test_element.rb +500 -0
- data/test/config/test_literal_parser.rb +8 -0
- data/test/config/test_plugin_configuration.rb +56 -0
- data/test/config/test_section.rb +79 -7
- data/test/config/test_system_config.rb +122 -35
- data/test/config/test_types.rb +38 -0
- data/test/counter/test_client.rb +559 -0
- data/test/counter/test_error.rb +44 -0
- data/test/counter/test_mutex_hash.rb +179 -0
- data/test/counter/test_server.rb +589 -0
- data/test/counter/test_store.rb +258 -0
- data/test/counter/test_validator.rb +137 -0
- data/test/helper.rb +89 -6
- data/test/helpers/fuzzy_assert.rb +89 -0
- data/test/plugin/test_bare_output.rb +118 -0
- data/test/plugin/test_base.rb +115 -0
- data/test/plugin/test_buf_file.rb +823 -460
- data/test/plugin/test_buf_memory.rb +32 -194
- data/test/plugin/test_buffer.rb +1233 -0
- data/test/plugin/test_buffer_chunk.rb +198 -0
- data/test/plugin/test_buffer_file_chunk.rb +844 -0
- data/test/plugin/test_buffer_memory_chunk.rb +338 -0
- data/test/plugin/test_compressable.rb +84 -0
- data/test/plugin/test_filter.rb +357 -0
- data/test/plugin/test_filter_grep.rb +540 -29
- data/test/plugin/test_filter_parser.rb +439 -452
- data/test/plugin/test_filter_record_transformer.rb +123 -166
- data/test/plugin/test_filter_stdout.rb +160 -72
- data/test/plugin/test_formatter_csv.rb +111 -0
- data/test/plugin/test_formatter_hash.rb +35 -0
- data/test/plugin/test_formatter_json.rb +51 -0
- data/test/plugin/test_formatter_ltsv.rb +62 -0
- data/test/plugin/test_formatter_msgpack.rb +28 -0
- data/test/plugin/test_formatter_out_file.rb +95 -0
- data/test/plugin/test_formatter_single_value.rb +38 -0
- data/test/plugin/test_formatter_tsv.rb +68 -0
- data/test/plugin/test_in_debug_agent.rb +24 -1
- data/test/plugin/test_in_dummy.rb +111 -18
- data/test/plugin/test_in_exec.rb +200 -113
- data/test/plugin/test_in_forward.rb +990 -387
- data/test/plugin/test_in_gc_stat.rb +10 -8
- data/test/plugin/test_in_http.rb +600 -224
- data/test/plugin/test_in_monitor_agent.rb +690 -0
- data/test/plugin/test_in_object_space.rb +24 -8
- data/test/plugin/test_in_syslog.rb +154 -215
- data/test/plugin/test_in_tail.rb +1006 -707
- data/test/plugin/test_in_tcp.rb +125 -48
- data/test/plugin/test_in_udp.rb +204 -63
- data/test/plugin/{test_in_stream.rb → test_in_unix.rb} +14 -13
- data/test/plugin/test_input.rb +126 -0
- data/test/plugin/test_metadata.rb +89 -0
- data/test/plugin/test_multi_output.rb +180 -0
- data/test/plugin/test_out_copy.rb +117 -112
- data/test/plugin/test_out_exec.rb +258 -53
- data/test/plugin/test_out_exec_filter.rb +538 -115
- data/test/plugin/test_out_file.rb +865 -178
- data/test/plugin/test_out_forward.rb +998 -210
- data/test/plugin/test_out_null.rb +105 -0
- data/test/plugin/test_out_relabel.rb +28 -0
- data/test/plugin/test_out_roundrobin.rb +36 -29
- data/test/plugin/test_out_secondary_file.rb +458 -0
- data/test/plugin/test_out_stdout.rb +135 -37
- data/test/plugin/test_out_stream.rb +18 -0
- data/test/plugin/test_output.rb +984 -0
- data/test/plugin/test_output_as_buffered.rb +2021 -0
- data/test/plugin/test_output_as_buffered_backup.rb +312 -0
- data/test/plugin/test_output_as_buffered_compress.rb +165 -0
- data/test/plugin/test_output_as_buffered_overflow.rb +250 -0
- data/test/plugin/test_output_as_buffered_retries.rb +911 -0
- data/test/plugin/test_output_as_buffered_secondary.rb +874 -0
- data/test/plugin/test_output_as_standard.rb +374 -0
- data/test/plugin/test_owned_by.rb +35 -0
- data/test/plugin/test_parser.rb +359 -0
- data/test/plugin/test_parser_apache.rb +42 -0
- data/test/plugin/test_parser_apache2.rb +47 -0
- data/test/plugin/test_parser_apache_error.rb +45 -0
- data/test/plugin/test_parser_csv.rb +103 -0
- data/test/plugin/test_parser_json.rb +138 -0
- data/test/plugin/test_parser_labeled_tsv.rb +145 -0
- data/test/plugin/test_parser_multiline.rb +100 -0
- data/test/plugin/test_parser_nginx.rb +88 -0
- data/test/plugin/test_parser_none.rb +52 -0
- data/test/plugin/test_parser_regexp.rb +289 -0
- data/test/plugin/test_parser_syslog.rb +441 -0
- data/test/plugin/test_parser_tsv.rb +122 -0
- data/test/plugin/test_storage.rb +167 -0
- data/test/plugin/test_storage_local.rb +335 -0
- data/test/plugin_helper/data/cert/cert-key.pem +27 -0
- data/test/plugin_helper/data/cert/cert-with-no-newline.pem +19 -0
- data/test/plugin_helper/data/cert/cert.pem +19 -0
- data/test/plugin_helper/http_server/test_app.rb +65 -0
- data/test/plugin_helper/http_server/test_route.rb +32 -0
- data/test/plugin_helper/test_cert_option.rb +16 -0
- data/test/plugin_helper/test_child_process.rb +794 -0
- data/test/plugin_helper/test_compat_parameters.rb +353 -0
- data/test/plugin_helper/test_event_emitter.rb +51 -0
- data/test/plugin_helper/test_event_loop.rb +52 -0
- data/test/plugin_helper/test_extract.rb +194 -0
- data/test/plugin_helper/test_formatter.rb +255 -0
- data/test/plugin_helper/test_http_server_helper.rb +205 -0
- data/test/plugin_helper/test_inject.rb +519 -0
- data/test/plugin_helper/test_parser.rb +264 -0
- data/test/plugin_helper/test_record_accessor.rb +197 -0
- data/test/plugin_helper/test_retry_state.rb +442 -0
- data/test/plugin_helper/test_server.rb +1714 -0
- data/test/plugin_helper/test_storage.rb +542 -0
- data/test/plugin_helper/test_thread.rb +164 -0
- data/test/plugin_helper/test_timer.rb +132 -0
- data/test/scripts/exec_script.rb +0 -6
- data/test/scripts/fluent/plugin/formatter1/formatter_test1.rb +7 -0
- data/test/scripts/fluent/plugin/formatter2/formatter_test2.rb +7 -0
- data/test/scripts/fluent/plugin/out_test.rb +23 -15
- data/test/scripts/fluent/plugin/out_test2.rb +80 -0
- data/test/test_clock.rb +164 -0
- data/test/test_config.rb +16 -7
- data/test/test_configdsl.rb +2 -2
- data/test/test_event.rb +360 -13
- data/test/test_event_router.rb +108 -11
- data/test/test_event_time.rb +199 -0
- data/test/test_filter.rb +48 -6
- data/test/test_formatter.rb +11 -391
- data/test/test_input.rb +1 -1
- data/test/test_log.rb +591 -31
- data/test/test_mixin.rb +1 -1
- data/test/test_output.rb +121 -185
- data/test/test_plugin.rb +251 -0
- data/test/test_plugin_classes.rb +177 -10
- data/test/test_plugin_helper.rb +81 -0
- data/test/test_plugin_id.rb +101 -0
- data/test/test_process.rb +8 -42
- data/test/test_root_agent.rb +766 -21
- data/test/test_supervisor.rb +481 -0
- data/test/test_test_drivers.rb +135 -0
- data/test/test_time_formatter.rb +282 -0
- data/test/test_time_parser.rb +231 -0
- data/test/test_unique_id.rb +47 -0
- metadata +454 -60
- data/COPYING +0 -14
- data/ChangeLog +0 -666
- data/lib/fluent/buffer.rb +0 -365
- data/lib/fluent/plugin/in_status.rb +0 -76
- data/test/plugin/test_in_status.rb +0 -38
- data/test/test_buffer.rb +0 -624
- data/test/test_parser.rb +0 -1305
@@ -0,0 +1,1714 @@
|
|
1
|
+
require_relative '../helper'
|
2
|
+
require 'fluent/plugin_helper/server'
|
3
|
+
require 'fluent/plugin_helper/cert_option' # to create certs for tests
|
4
|
+
require 'fluent/plugin/base'
|
5
|
+
require 'timeout'
|
6
|
+
|
7
|
+
require 'serverengine'
|
8
|
+
require 'fileutils'
|
9
|
+
|
10
|
+
class ServerPluginHelperTest < Test::Unit::TestCase
|
11
|
+
class Dummy < Fluent::Plugin::TestBase
|
12
|
+
helpers :server
|
13
|
+
end
|
14
|
+
|
15
|
+
TMP_DIR = File.expand_path(File.dirname(__FILE__) + "/../tmp/plugin_helper_server")
|
16
|
+
|
17
|
+
PORT = unused_port
|
18
|
+
|
19
|
+
setup do
|
20
|
+
@socket_manager_path = ServerEngine::SocketManager::Server.generate_path
|
21
|
+
if @socket_manager_path.is_a?(String) && File.exist?(@socket_manager_path)
|
22
|
+
FileUtils.rm_f @socket_manager_path
|
23
|
+
end
|
24
|
+
@socket_manager_server = ServerEngine::SocketManager::Server.open(@socket_manager_path)
|
25
|
+
ENV['SERVERENGINE_SOCKETMANAGER_PATH'] = @socket_manager_path.to_s
|
26
|
+
|
27
|
+
@d = Dummy.new
|
28
|
+
@d.start
|
29
|
+
@d.after_start
|
30
|
+
end
|
31
|
+
|
32
|
+
teardown do
|
33
|
+
(@d.stopped? || @d.stop) rescue nil
|
34
|
+
(@d.before_shutdown? || @d.before_shutdown) rescue nil
|
35
|
+
(@d.shutdown? || @d.shutdown) rescue nil
|
36
|
+
(@d.after_shutdown? || @d.after_shutdown) rescue nil
|
37
|
+
(@d.closed? || @d.close) rescue nil
|
38
|
+
(@d.terminated? || @d.terminate) rescue nil
|
39
|
+
|
40
|
+
@socket_manager_server.close
|
41
|
+
if @socket_manager_server.is_a?(String) && File.exist?(@socket_manager_path)
|
42
|
+
FileUtils.rm_f @socket_manager_path
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
sub_test_case 'plugin instance' do
|
47
|
+
test 'can be instantiated to be able to create threads' do
|
48
|
+
d = Dummy.new
|
49
|
+
assert d.respond_to?(:_servers)
|
50
|
+
assert d._servers.empty?
|
51
|
+
|
52
|
+
assert d.respond_to?(:server_wait_until_start)
|
53
|
+
assert d.respond_to?(:server_wait_until_stop)
|
54
|
+
assert d.respond_to?(:server_create_connection)
|
55
|
+
assert d.respond_to?(:server_create)
|
56
|
+
assert d.respond_to?(:server_create_tcp)
|
57
|
+
assert d.respond_to?(:server_create_udp)
|
58
|
+
assert d.respond_to?(:server_create_tls)
|
59
|
+
end
|
60
|
+
|
61
|
+
test 'can be configured' do
|
62
|
+
d = Dummy.new
|
63
|
+
assert_nothing_raised do
|
64
|
+
d.configure(config_element())
|
65
|
+
end
|
66
|
+
assert d.plugin_id
|
67
|
+
assert d.log
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# run tests for tcp, udp, tls and unix
|
72
|
+
sub_test_case '#server_create and #server_create_connection' do
|
73
|
+
methods = {server_create: :server_create, server_create_connection: :server_create_connection}
|
74
|
+
|
75
|
+
data(methods)
|
76
|
+
test 'raise error if title is not specified or not a symbol' do |m|
|
77
|
+
assert_raise(ArgumentError.new("BUG: title must be a symbol")) do
|
78
|
+
@d.__send__(m, nil, PORT){|x| x }
|
79
|
+
end
|
80
|
+
assert_raise(ArgumentError.new("BUG: title must be a symbol")) do
|
81
|
+
@d.__send__(m, "", PORT){|x| x }
|
82
|
+
end
|
83
|
+
assert_raise(ArgumentError.new("BUG: title must be a symbol")) do
|
84
|
+
@d.__send__(m, "title", PORT){|x| x }
|
85
|
+
end
|
86
|
+
assert_nothing_raised do
|
87
|
+
@d.__send__(m, :myserver, PORT){|x| x }
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
data(methods)
|
92
|
+
test 'raise error if port is not specified or not an integer' do |m|
|
93
|
+
assert_raise(ArgumentError.new("BUG: port must be an integer")) do
|
94
|
+
@d.__send__(m, :myserver, nil){|x| x }
|
95
|
+
end
|
96
|
+
assert_raise(ArgumentError.new("BUG: port must be an integer")) do
|
97
|
+
@d.__send__(m, :myserver, "1"){|x| x }
|
98
|
+
end
|
99
|
+
assert_raise(ArgumentError.new("BUG: port must be an integer")) do
|
100
|
+
@d.__send__(m, :myserver, 1.5){|x| x }
|
101
|
+
end
|
102
|
+
assert_nothing_raised do
|
103
|
+
@d.__send__(m, :myserver, PORT){|x| x }
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
data(methods)
|
108
|
+
test 'raise error if block is not specified' do |m|
|
109
|
+
assert_raise(ArgumentError) do
|
110
|
+
@d.__send__(m, :myserver, PORT)
|
111
|
+
end
|
112
|
+
assert_nothing_raised do
|
113
|
+
@d.__send__(m, :myserver, PORT){|x| x }
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
data(methods)
|
118
|
+
test 'creates tcp server, binds 0.0.0.0 in default' do |m|
|
119
|
+
@d.__send__(m, :myserver, PORT){|x| x }
|
120
|
+
|
121
|
+
assert_equal 1, @d._servers.size
|
122
|
+
|
123
|
+
created_server_info = @d._servers.first
|
124
|
+
|
125
|
+
assert_equal :myserver, created_server_info.title
|
126
|
+
assert_equal PORT, created_server_info.port
|
127
|
+
|
128
|
+
assert_equal :tcp, created_server_info.proto
|
129
|
+
assert_equal "0.0.0.0", created_server_info.bind
|
130
|
+
|
131
|
+
created_server = created_server_info.server
|
132
|
+
|
133
|
+
assert created_server.is_a?(Coolio::TCPServer)
|
134
|
+
assert_equal "0.0.0.0", created_server.instance_eval{ @listen_socket }.addr[3]
|
135
|
+
end
|
136
|
+
|
137
|
+
data(methods)
|
138
|
+
test 'creates tcp server if specified in proto' do |m|
|
139
|
+
@d.__send__(m, :myserver, PORT, proto: :tcp){|x| x }
|
140
|
+
|
141
|
+
created_server_info = @d._servers.first
|
142
|
+
assert_equal :tcp, created_server_info.proto
|
143
|
+
created_server = created_server_info.server
|
144
|
+
assert created_server.is_a?(Coolio::TCPServer)
|
145
|
+
end
|
146
|
+
|
147
|
+
data(methods)
|
148
|
+
test 'creates tls server in default if transport section and tcp protocol specified' do |m|
|
149
|
+
@d = d = Dummy.new
|
150
|
+
transport_conf = config_element('transport', 'tcp', {}, [])
|
151
|
+
d.configure(config_element('ROOT', '', {}, [transport_conf]))
|
152
|
+
d.start
|
153
|
+
d.after_start
|
154
|
+
|
155
|
+
d.__send__(m, :myserver, PORT){|x| x }
|
156
|
+
|
157
|
+
created_server_info = @d._servers.first
|
158
|
+
assert_equal :tcp, created_server_info.proto
|
159
|
+
created_server = created_server_info.server
|
160
|
+
assert created_server.is_a?(Coolio::TCPServer)
|
161
|
+
end
|
162
|
+
|
163
|
+
data(methods)
|
164
|
+
test 'creates tls server if specified in proto' do |m|
|
165
|
+
assert_raise(ArgumentError.new("BUG: TLS transport specified, but certification options are not specified")) do
|
166
|
+
@d.__send__(m, :myserver, PORT, proto: :tls){|x| x }
|
167
|
+
end
|
168
|
+
@d.__send__(m, :myserver, PORT, proto: :tls, tls_options: {insecure: true}){|x| x }
|
169
|
+
|
170
|
+
created_server_info = @d._servers.first
|
171
|
+
assert_equal :tls, created_server_info.proto
|
172
|
+
created_server = created_server_info.server
|
173
|
+
assert created_server.is_a?(Coolio::TCPServer) # yes, TCP here
|
174
|
+
end
|
175
|
+
|
176
|
+
data(methods)
|
177
|
+
test 'creates tls server in default if transport section and tls protocol specified' do |m|
|
178
|
+
@d = d = Dummy.new
|
179
|
+
transport_conf = config_element('transport', 'tls', {'insecure' => 'true'}, [])
|
180
|
+
d.configure(config_element('ROOT', '', {}, [transport_conf]))
|
181
|
+
d.start
|
182
|
+
d.after_start
|
183
|
+
|
184
|
+
d.__send__(m, :myserver, PORT){|x| x }
|
185
|
+
|
186
|
+
created_server_info = @d._servers.first
|
187
|
+
assert_equal :tls, created_server_info.proto
|
188
|
+
created_server = created_server_info.server
|
189
|
+
assert created_server.is_a?(Coolio::TCPServer) # OK, it's Coolio::TCPServer
|
190
|
+
end
|
191
|
+
|
192
|
+
data(methods)
|
193
|
+
test 'creates unix server if specified in proto' do |m|
|
194
|
+
# pend "not implemented yet"
|
195
|
+
end
|
196
|
+
|
197
|
+
data(methods)
|
198
|
+
test 'raise error if unknown protocol specified' do |m|
|
199
|
+
assert_raise(ArgumentError.new("BUG: invalid protocol name")) do
|
200
|
+
@d.__send__(m, :myserver, PORT, proto: :quic){|x| x }
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
data(
|
205
|
+
'server_create tcp' => [:server_create, :tcp],
|
206
|
+
'server_create tls' => [:server_create, :tls],
|
207
|
+
# 'server_create unix' => [:server_create, :unix],
|
208
|
+
'server_create_connection tcp' => [:server_create_connection, :tcp],
|
209
|
+
'server_create_connection tls' => [:server_create_connection, :tls],
|
210
|
+
# 'server_create_connection tcp' => [:server_create_connection, :unix],
|
211
|
+
)
|
212
|
+
test 'raise error if udp options specified for tcp/tls/unix' do |(m, proto)|
|
213
|
+
assert_raise ArgumentError do
|
214
|
+
@d.__send__(m, :myserver, PORT, proto: proto, max_bytes: 128){|x| x }
|
215
|
+
end
|
216
|
+
assert_raise ArgumentError do
|
217
|
+
@d.__send__(m, :myserver, PORT, proto: proto, flags: 1){|x| x }
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
data(
|
222
|
+
'server_create udp' => [:server_create, :udp],
|
223
|
+
)
|
224
|
+
test 'raise error if tcp/tls options specified for udp' do |(m, proto)|
|
225
|
+
assert_raise(ArgumentError.new("BUG: linger_timeout is available for tcp/tls")) do
|
226
|
+
@d.__send__(m, :myserver, PORT, proto: proto, linger_timeout: 1, max_bytes: 128){|x| x }
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
data(
|
231
|
+
'server_create udp' => [:server_create, :udp],
|
232
|
+
)
|
233
|
+
test 'raise error if tcp/tls/unix backlog options specified for udp' do |(m, proto)|
|
234
|
+
assert_raise(ArgumentError.new("BUG: backlog is available for tcp/tls")) do
|
235
|
+
@d.__send__(m, :myserver, PORT, proto: proto, backlog: 500){|x| x }
|
236
|
+
end
|
237
|
+
assert_raise(ArgumentError.new("BUG: send_keepalive_packet is available for tcp")) do
|
238
|
+
@d.__send__(m, :myserver, PORT, proto: proto, send_keepalive_packet: true){|x| x }
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
data(
|
243
|
+
'server_create tcp' => [:server_create, :tcp, {}],
|
244
|
+
'server_create udp' => [:server_create, :udp, {max_bytes: 128}],
|
245
|
+
# 'server_create unix' => [:server_create, :unix, {}],
|
246
|
+
'server_create_connection tcp' => [:server_create_connection, :tcp, {}],
|
247
|
+
# 'server_create_connection unix' => [:server_create_connection, :unix, {}],
|
248
|
+
)
|
249
|
+
test 'raise error if tls options specified for tcp/udp/unix' do |(m, proto, kwargs)|
|
250
|
+
assert_raise(ArgumentError.new("BUG: tls_options is available only for tls")) do
|
251
|
+
@d.__send__(m, :myserver, PORT, proto: proto, tls_options: {}, **kwargs){|x| x }
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
data(
|
256
|
+
'server_create tcp' => [:server_create, :tcp, {}],
|
257
|
+
'server_create udp' => [:server_create, :udp, {max_bytes: 128}],
|
258
|
+
'server_create tls' => [:server_create, :tls, {tls_options: {insecure: true}}],
|
259
|
+
'server_create_connection tcp' => [:server_create_connection, :tcp, {}],
|
260
|
+
'server_create_connection tls' => [:server_create_connection, :tls, {tls_options: {insecure: true}}],
|
261
|
+
)
|
262
|
+
test 'can bind specified IPv4 address' do |(m, proto, kwargs)|
|
263
|
+
@d.__send__(m, :myserver, PORT, proto: proto, bind: "127.0.0.1", **kwargs){|x| x }
|
264
|
+
assert_equal "127.0.0.1", @d._servers.first.bind
|
265
|
+
assert_equal "127.0.0.1", @d._servers.first.server.instance_eval{ instance_variable_defined?(:@listen_socket) ? @listen_socket : @_io }.addr[3]
|
266
|
+
end
|
267
|
+
|
268
|
+
data(
|
269
|
+
'server_create tcp' => [:server_create, :tcp, {}],
|
270
|
+
'server_create udp' => [:server_create, :udp, {max_bytes: 128}],
|
271
|
+
'server_create tls' => [:server_create, :tls, {tls_options: {insecure: true}}],
|
272
|
+
'server_create_connection tcp' => [:server_create_connection, :tcp, {}],
|
273
|
+
'server_create_connection tls' => [:server_create_connection, :tls, {tls_options: {insecure: true}}],
|
274
|
+
)
|
275
|
+
test 'can bind specified IPv6 address' do |(m, proto, kwargs)| # if available
|
276
|
+
omit "IPv6 unavailable here" unless ipv6_enabled?
|
277
|
+
@d.__send__(m, :myserver, PORT, proto: proto, bind: "::1", **kwargs){|x| x }
|
278
|
+
assert_equal "::1", @d._servers.first.bind
|
279
|
+
assert_equal "::1", @d._servers.first.server.instance_eval{ instance_variable_defined?(:@listen_socket) ? @listen_socket : @_io }.addr[3]
|
280
|
+
end
|
281
|
+
|
282
|
+
data(
|
283
|
+
'server_create tcp' => [:server_create, :tcp, {}],
|
284
|
+
'server_create udp' => [:server_create, :udp, {max_bytes: 128}],
|
285
|
+
'server_create tls' => [:server_create, :tls, {tls_options: {insecure: true}}],
|
286
|
+
# 'server_create unix' => [:server_create, :unix, {}],
|
287
|
+
'server_create_connection tcp' => [:server_create, :tcp, {}],
|
288
|
+
'server_create_connection tls' => [:server_create, :tls, {tls_options: {insecure: true}}],
|
289
|
+
# 'server_create_connection unix' => [:server_create, :unix, {}],
|
290
|
+
)
|
291
|
+
test 'can create 2 or more servers which share same bind address and port if shared option is true' do |(m, proto, kwargs)|
|
292
|
+
begin
|
293
|
+
d2 = Dummy.new; d2.start; d2.after_start
|
294
|
+
|
295
|
+
assert_nothing_raised do
|
296
|
+
@d.__send__(m, :myserver, PORT, proto: proto, **kwargs){|x| x }
|
297
|
+
d2.__send__(m, :myserver, PORT, proto: proto, **kwargs){|x| x }
|
298
|
+
end
|
299
|
+
ensure
|
300
|
+
d2.stop; d2.before_shutdown; d2.shutdown; d2.after_shutdown; d2.close; d2.terminate
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
data(
|
305
|
+
'server_create tcp' => [:server_create, :tcp, {}],
|
306
|
+
'server_create udp' => [:server_create, :udp, {max_bytes: 128}],
|
307
|
+
'server_create tls' => [:server_create, :tls, {tls_options: {insecure: true}}],
|
308
|
+
# 'server_create unix' => [:server_create, :unix, {}],
|
309
|
+
'server_create_connection tcp' => [:server_create, :tcp, {}],
|
310
|
+
'server_create_connection tls' => [:server_create, :tls, {tls_options: {insecure: true}}],
|
311
|
+
# 'server_create_connection unix' => [:server_create, :unix, {}],
|
312
|
+
)
|
313
|
+
test 'cannot create 2 or more servers using same bind address and port if shared option is false' do |(m, proto, kwargs)|
|
314
|
+
begin
|
315
|
+
d2 = Dummy.new; d2.start; d2.after_start
|
316
|
+
|
317
|
+
assert_nothing_raised do
|
318
|
+
@d.__send__(m, :myserver, PORT, proto: proto, shared: false, **kwargs){|x| x }
|
319
|
+
end
|
320
|
+
assert_raise(Errno::EADDRINUSE, Errno::EACCES) do
|
321
|
+
d2.__send__(m, :myserver, PORT, proto: proto, **kwargs){|x| x }
|
322
|
+
end
|
323
|
+
ensure
|
324
|
+
d2.stop; d2.before_shutdown; d2.shutdown; d2.after_shutdown; d2.close; d2.terminate
|
325
|
+
end
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
sub_test_case '#server_create' do
|
330
|
+
data(
|
331
|
+
'tcp' => [:tcp, {}],
|
332
|
+
'udp' => [:udp, {max_bytes: 128}],
|
333
|
+
'tls' => [:tls, {tls_options: {insecure: true}}],
|
334
|
+
# 'unix' => [:unix, {}],
|
335
|
+
)
|
336
|
+
test 'raise error if block argument is not specified or too many' do |(proto, kwargs)|
|
337
|
+
assert_raise(ArgumentError.new("BUG: block must have 1 or 2 arguments")) do
|
338
|
+
@d.server_create(:myserver, PORT, proto: proto, **kwargs){ 1 }
|
339
|
+
end
|
340
|
+
assert_raise(ArgumentError.new("BUG: block must have 1 or 2 arguments")) do
|
341
|
+
@d.server_create(:myserver, PORT, proto: proto, **kwargs){|sock, conn, what_is_this| 1 }
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
test 'creates udp server if specified in proto' do
|
346
|
+
@d.server_create(:myserver, PORT, proto: :udp, max_bytes: 512){|x| x }
|
347
|
+
|
348
|
+
created_server_info = @d._servers.first
|
349
|
+
assert_equal :udp, created_server_info.proto
|
350
|
+
created_server = created_server_info.server
|
351
|
+
assert created_server.is_a?(Fluent::PluginHelper::Server::EventHandler::UDPServer)
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
sub_test_case '#server_create_tcp' do
|
356
|
+
test 'can accept all keyword arguments valid for tcp server' do
|
357
|
+
assert_nothing_raised do
|
358
|
+
@d.server_create_tcp(:s, PORT, bind: '127.0.0.1', shared: false, resolve_name: true, linger_timeout: 10, backlog: 500, send_keepalive_packet: true) do |data, conn|
|
359
|
+
# ...
|
360
|
+
end
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
test 'creates a tcp server just to read data' do
|
365
|
+
received = ""
|
366
|
+
@d.server_create_tcp(:s, PORT) do |data|
|
367
|
+
received << data
|
368
|
+
end
|
369
|
+
3.times do
|
370
|
+
sock = TCPSocket.new("127.0.0.1", PORT)
|
371
|
+
sock.puts "yay"
|
372
|
+
sock.puts "foo"
|
373
|
+
sock.close
|
374
|
+
end
|
375
|
+
waiting(10){ sleep 0.1 until received.bytesize == 24 }
|
376
|
+
assert_equal "yay\nfoo\nyay\nfoo\nyay\nfoo\n", received
|
377
|
+
end
|
378
|
+
|
379
|
+
test 'creates a tcp server to read and write data' do
|
380
|
+
received = ""
|
381
|
+
responses = []
|
382
|
+
@d.server_create_tcp(:s, PORT) do |data, conn|
|
383
|
+
received << data
|
384
|
+
conn.write "ack\n"
|
385
|
+
end
|
386
|
+
3.times do
|
387
|
+
TCPSocket.open("127.0.0.1", PORT) do |sock|
|
388
|
+
sock.puts "yay"
|
389
|
+
sock.puts "foo"
|
390
|
+
responses << sock.readline
|
391
|
+
end
|
392
|
+
end
|
393
|
+
waiting(10){ sleep 0.1 until received.bytesize == 24 }
|
394
|
+
assert_equal "yay\nfoo\nyay\nfoo\nyay\nfoo\n", received
|
395
|
+
assert_equal ["ack\n","ack\n","ack\n"], responses
|
396
|
+
end
|
397
|
+
|
398
|
+
test 'creates a tcp server to read and write data using IPv6' do
|
399
|
+
omit "IPv6 unavailable here" unless ipv6_enabled?
|
400
|
+
|
401
|
+
received = ""
|
402
|
+
responses = []
|
403
|
+
@d.server_create_tcp(:s, PORT, bind: "::1") do |data, conn|
|
404
|
+
received << data
|
405
|
+
conn.write "ack\n"
|
406
|
+
end
|
407
|
+
3.times do
|
408
|
+
TCPSocket.open("::1", PORT) do |sock|
|
409
|
+
sock.puts "yay"
|
410
|
+
sock.puts "foo"
|
411
|
+
responses << sock.readline
|
412
|
+
end
|
413
|
+
end
|
414
|
+
waiting(10){ sleep 0.1 until received.bytesize == 24 }
|
415
|
+
assert_equal "yay\nfoo\nyay\nfoo\nyay\nfoo\n", received
|
416
|
+
assert_equal ["ack\n","ack\n","ack\n"], responses
|
417
|
+
end
|
418
|
+
|
419
|
+
test 'does not resolve name of client address in default' do
|
420
|
+
received = ""
|
421
|
+
sources = []
|
422
|
+
@d.server_create_tcp(:s, PORT) do |data, conn|
|
423
|
+
received << data
|
424
|
+
sources << conn.remote_host
|
425
|
+
end
|
426
|
+
3.times do
|
427
|
+
TCPSocket.open("127.0.0.1", PORT) do |sock|
|
428
|
+
sock.puts "yay"
|
429
|
+
end
|
430
|
+
end
|
431
|
+
waiting(10){ sleep 0.1 until received.bytesize == 12 }
|
432
|
+
assert_equal "yay\nyay\nyay\n", received
|
433
|
+
assert{ sources.all?{|s| s == "127.0.0.1" } }
|
434
|
+
end
|
435
|
+
|
436
|
+
test 'does resolve name of client address if resolve_name is true' do
|
437
|
+
hostname = Socket.getnameinfo([nil, nil, nil, "127.0.0.1"])[0]
|
438
|
+
|
439
|
+
received = ""
|
440
|
+
sources = []
|
441
|
+
@d.server_create_tcp(:s, PORT, resolve_name: true) do |data, conn|
|
442
|
+
received << data
|
443
|
+
sources << conn.remote_host
|
444
|
+
end
|
445
|
+
3.times do
|
446
|
+
TCPSocket.open("127.0.0.1", PORT) do |sock|
|
447
|
+
sock.puts "yay"
|
448
|
+
end
|
449
|
+
end
|
450
|
+
waiting(10){ sleep 0.1 until received.bytesize == 12 }
|
451
|
+
assert_equal "yay\nyay\nyay\n", received
|
452
|
+
assert{ sources.all?{|s| s == hostname } }
|
453
|
+
end
|
454
|
+
|
455
|
+
test 'can keep connections alive for tcp if keepalive specified' do
|
456
|
+
# pend "not implemented yet"
|
457
|
+
end
|
458
|
+
|
459
|
+
test 'raises error if plugin registers data callback for connection object from #server_create' do
|
460
|
+
received = ""
|
461
|
+
errors = []
|
462
|
+
@d.server_create_tcp(:s, PORT) do |data, conn|
|
463
|
+
received << data
|
464
|
+
begin
|
465
|
+
conn.data{|d| received << d.upcase }
|
466
|
+
rescue => e
|
467
|
+
errors << e
|
468
|
+
end
|
469
|
+
end
|
470
|
+
TCPSocket.open("127.0.0.1", PORT) do |sock|
|
471
|
+
sock.puts "foo"
|
472
|
+
end
|
473
|
+
waiting(10){ sleep 0.1 until received.bytesize == 4 || errors.size == 1 }
|
474
|
+
assert_equal "foo\n", received
|
475
|
+
assert{ errors.size > 0 } # it might be called twice (or more) when connection was accepted, and then data arrived (or more)
|
476
|
+
assert_equal "data callback can be registered just once, but registered twice", errors.first.message
|
477
|
+
end
|
478
|
+
|
479
|
+
test 'can call write_complete callback if registered' do
|
480
|
+
buffer = ""
|
481
|
+
lines = []
|
482
|
+
responses = []
|
483
|
+
response_completes = []
|
484
|
+
@d.server_create_tcp(:s, PORT) do |data, conn|
|
485
|
+
conn.on(:write_complete){|c| response_completes << true }
|
486
|
+
buffer << data
|
487
|
+
if idx = buffer.index("\n")
|
488
|
+
lines << buffer.slice!(0,idx+1)
|
489
|
+
conn.write "ack\n"
|
490
|
+
end
|
491
|
+
end
|
492
|
+
3.times do
|
493
|
+
TCPSocket.open("127.0.0.1", PORT) do |sock|
|
494
|
+
sock.write "yay"
|
495
|
+
sock.write "foo\n"
|
496
|
+
begin
|
497
|
+
responses << sock.readline
|
498
|
+
rescue EOFError, IOError, Errno::ECONNRESET
|
499
|
+
# ignore
|
500
|
+
end
|
501
|
+
sock.close
|
502
|
+
end
|
503
|
+
end
|
504
|
+
waiting(10){ sleep 0.1 until lines.size == 3 && response_completes.size == 3 }
|
505
|
+
assert_equal ["yayfoo\n", "yayfoo\n", "yayfoo\n"], lines
|
506
|
+
assert_equal ["ack\n","ack\n","ack\n"], responses
|
507
|
+
assert_equal [true, true, true], response_completes
|
508
|
+
end
|
509
|
+
|
510
|
+
test 'can call close callback if registered' do
|
511
|
+
buffer = ""
|
512
|
+
lines = []
|
513
|
+
callback_results = []
|
514
|
+
@d.server_create_tcp(:s, PORT) do |data, conn|
|
515
|
+
conn.on(:close){|c| callback_results << "closed" }
|
516
|
+
buffer << data
|
517
|
+
if idx = buffer.index("\n")
|
518
|
+
lines << buffer.slice!(0,idx+1)
|
519
|
+
conn.write "ack\n"
|
520
|
+
end
|
521
|
+
end
|
522
|
+
3.times do
|
523
|
+
TCPSocket.open("127.0.0.1", PORT) do |sock|
|
524
|
+
sock.write "yay"
|
525
|
+
sock.write "foo\n"
|
526
|
+
begin
|
527
|
+
while line = sock.readline
|
528
|
+
if line == "ack\n"
|
529
|
+
sock.close
|
530
|
+
end
|
531
|
+
end
|
532
|
+
rescue EOFError, IOError, Errno::ECONNRESET
|
533
|
+
# ignore
|
534
|
+
end
|
535
|
+
end
|
536
|
+
end
|
537
|
+
waiting(10){ sleep 0.1 until lines.size == 3 && callback_results.size == 3 }
|
538
|
+
assert_equal ["yayfoo\n", "yayfoo\n", "yayfoo\n"], lines
|
539
|
+
assert_equal ["closed", "closed", "closed"], callback_results
|
540
|
+
end
|
541
|
+
end
|
542
|
+
|
543
|
+
sub_test_case '#server_create_udp' do
|
544
|
+
test 'can accept all keyword arguments valid for udp server' do
|
545
|
+
assert_nothing_raised do
|
546
|
+
@d.server_create_udp(:s, PORT, bind: '127.0.0.1', shared: false, resolve_name: true, max_bytes: 100, flags: 1) do |data, conn|
|
547
|
+
# ...
|
548
|
+
end
|
549
|
+
end
|
550
|
+
end
|
551
|
+
|
552
|
+
test 'creates a udp server just to read data' do
|
553
|
+
received = ""
|
554
|
+
@d.server_create_udp(:s, PORT, max_bytes: 128) do |data|
|
555
|
+
received << data
|
556
|
+
end
|
557
|
+
bind_port = unused_port(protocol: :udp, bind: "127.0.0.1")
|
558
|
+
3.times do
|
559
|
+
sock = UDPSocket.new(Socket::AF_INET)
|
560
|
+
sock.bind("127.0.0.1", bind_port)
|
561
|
+
sock.connect("127.0.0.1", PORT)
|
562
|
+
sock.puts "yay"
|
563
|
+
sock.puts "foo"
|
564
|
+
sock.close
|
565
|
+
end
|
566
|
+
waiting(10){ sleep 0.1 until received.bytesize == 24 }
|
567
|
+
assert_equal "yay\nfoo\nyay\nfoo\nyay\nfoo\n", received
|
568
|
+
end
|
569
|
+
|
570
|
+
test 'creates a udp server to read and write data' do
|
571
|
+
received = ""
|
572
|
+
responses = []
|
573
|
+
@d.server_create_udp(:s, PORT, max_bytes: 128) do |data, sock|
|
574
|
+
received << data
|
575
|
+
sock.write "ack\n"
|
576
|
+
end
|
577
|
+
bind_port = unused_port
|
578
|
+
3.times do
|
579
|
+
begin
|
580
|
+
sock = UDPSocket.new(Socket::AF_INET)
|
581
|
+
sock.bind("127.0.0.1", bind_port)
|
582
|
+
sock.connect("127.0.0.1", PORT)
|
583
|
+
th = Thread.new do
|
584
|
+
while true
|
585
|
+
begin
|
586
|
+
in_data, _addr = sock.recvfrom_nonblock(16)
|
587
|
+
if in_data
|
588
|
+
responses << in_data
|
589
|
+
break
|
590
|
+
end
|
591
|
+
rescue IO::WaitReadable
|
592
|
+
IO.select([sock])
|
593
|
+
end
|
594
|
+
end
|
595
|
+
true
|
596
|
+
end
|
597
|
+
sock.write "yay\nfoo\n"
|
598
|
+
th.join(5)
|
599
|
+
ensure
|
600
|
+
sock.close
|
601
|
+
end
|
602
|
+
end
|
603
|
+
waiting(10){ sleep 0.1 until received.bytesize == 24 }
|
604
|
+
assert_equal "yay\nfoo\nyay\nfoo\nyay\nfoo\n", received
|
605
|
+
assert_equal ["ack\n","ack\n","ack\n"], responses
|
606
|
+
end
|
607
|
+
|
608
|
+
test 'creates a udp server to read and write data using IPv6' do
|
609
|
+
omit "IPv6 unavailable here" unless ipv6_enabled?
|
610
|
+
|
611
|
+
received = ""
|
612
|
+
responses = []
|
613
|
+
@d.server_create_udp(:s, PORT, bind: "::1", max_bytes: 128) do |data, sock|
|
614
|
+
received << data
|
615
|
+
sock.write "ack\n"
|
616
|
+
end
|
617
|
+
bind_port = unused_port
|
618
|
+
3.times do
|
619
|
+
begin
|
620
|
+
sock = UDPSocket.new(Socket::AF_INET6)
|
621
|
+
sock.bind("::1", bind_port)
|
622
|
+
th = Thread.new do
|
623
|
+
responses << sock.recv(16)
|
624
|
+
true
|
625
|
+
end
|
626
|
+
sock.connect("::1", PORT)
|
627
|
+
sock.write "yay\nfoo\n"
|
628
|
+
th.join(5)
|
629
|
+
ensure
|
630
|
+
sock.close
|
631
|
+
end
|
632
|
+
end
|
633
|
+
waiting(10){ sleep 0.1 until received.bytesize == 24 }
|
634
|
+
assert_equal "yay\nfoo\nyay\nfoo\nyay\nfoo\n", received
|
635
|
+
assert_equal ["ack\n","ack\n","ack\n"], responses
|
636
|
+
end
|
637
|
+
|
638
|
+
test 'does not resolve name of client address in default' do
|
639
|
+
received = ""
|
640
|
+
sources = []
|
641
|
+
@d.server_create_udp(:s, PORT, max_bytes: 128) do |data, sock|
|
642
|
+
received << data
|
643
|
+
sources << sock.remote_host
|
644
|
+
end
|
645
|
+
3.times do
|
646
|
+
sock = UDPSocket.new(Socket::AF_INET)
|
647
|
+
sock.connect("127.0.0.1", PORT)
|
648
|
+
sock.puts "yay"
|
649
|
+
sock.close
|
650
|
+
end
|
651
|
+
waiting(10){ sleep 0.1 until received.bytesize == 12 }
|
652
|
+
assert_equal "yay\nyay\nyay\n", received
|
653
|
+
assert{ sources.all?{|s| s == "127.0.0.1" } }
|
654
|
+
end
|
655
|
+
|
656
|
+
test 'does resolve name of client address if resolve_name is true' do
|
657
|
+
hostname = Socket.getnameinfo([nil, nil, nil, "127.0.0.1"])[0]
|
658
|
+
|
659
|
+
received = ""
|
660
|
+
sources = []
|
661
|
+
@d.server_create_udp(:s, PORT, resolve_name: true, max_bytes: 128) do |data, sock|
|
662
|
+
received << data
|
663
|
+
sources << sock.remote_host
|
664
|
+
end
|
665
|
+
3.times do
|
666
|
+
sock = UDPSocket.new(Socket::AF_INET)
|
667
|
+
sock.connect("127.0.0.1", PORT)
|
668
|
+
sock.puts "yay"
|
669
|
+
sock.close
|
670
|
+
end
|
671
|
+
waiting(10){ sleep 0.1 until received.bytesize == 12 }
|
672
|
+
assert_equal "yay\nyay\nyay\n", received
|
673
|
+
assert{ sources.all?{|s| s == hostname } }
|
674
|
+
end
|
675
|
+
|
676
|
+
test 'raises error if plugin registers data callback for connection object from #server_create' do
|
677
|
+
received = ""
|
678
|
+
errors = []
|
679
|
+
@d.server_create_udp(:s, PORT, max_bytes: 128) do |data, sock|
|
680
|
+
received << data
|
681
|
+
begin
|
682
|
+
sock.data{|d| received << d.upcase }
|
683
|
+
rescue => e
|
684
|
+
errors << e
|
685
|
+
end
|
686
|
+
end
|
687
|
+
sock = UDPSocket.new(Socket::AF_INET)
|
688
|
+
sock.connect("127.0.0.1", PORT)
|
689
|
+
sock.write "foo\n"
|
690
|
+
sock.close
|
691
|
+
|
692
|
+
waiting(10){ sleep 0.1 until received.bytesize == 4 && errors.size == 1 }
|
693
|
+
assert_equal "foo\n", received
|
694
|
+
assert_equal 1, errors.size
|
695
|
+
assert_equal "BUG: this event is disabled for udp: data", errors.first.message
|
696
|
+
end
|
697
|
+
|
698
|
+
test 'raise error if plugin registers write_complete callback for udp' do
|
699
|
+
received = ""
|
700
|
+
errors = []
|
701
|
+
@d.server_create_udp(:s, PORT, max_bytes: 128) do |data, sock|
|
702
|
+
received << data
|
703
|
+
begin
|
704
|
+
sock.on(:write_complete){|conn| "" }
|
705
|
+
rescue => e
|
706
|
+
errors << e
|
707
|
+
end
|
708
|
+
end
|
709
|
+
sock = UDPSocket.new(Socket::AF_INET)
|
710
|
+
sock.connect("127.0.0.1", PORT)
|
711
|
+
sock.write "foo\n"
|
712
|
+
sock.close
|
713
|
+
|
714
|
+
waiting(10){ sleep 0.1 until received.bytesize == 4 && errors.size == 1 }
|
715
|
+
assert_equal "foo\n", received
|
716
|
+
assert_equal 1, errors.size
|
717
|
+
assert_equal "BUG: this event is disabled for udp: write_complete", errors.first.message
|
718
|
+
end
|
719
|
+
|
720
|
+
test 'raises error if plugin registers close callback for udp' do
|
721
|
+
received = ""
|
722
|
+
errors = []
|
723
|
+
@d.server_create_udp(:s, PORT, max_bytes: 128) do |data, sock|
|
724
|
+
received << data
|
725
|
+
begin
|
726
|
+
sock.on(:close){|d| "" }
|
727
|
+
rescue => e
|
728
|
+
errors << e
|
729
|
+
end
|
730
|
+
end
|
731
|
+
sock = UDPSocket.new(Socket::AF_INET)
|
732
|
+
sock.connect("127.0.0.1", PORT)
|
733
|
+
sock.write "foo\n"
|
734
|
+
sock.close
|
735
|
+
|
736
|
+
waiting(10){ sleep 0.1 until received.bytesize == 4 && errors.size == 1 }
|
737
|
+
assert_equal "foo\n", received
|
738
|
+
assert_equal 1, errors.size
|
739
|
+
assert_equal "BUG: this event is disabled for udp: close", errors.first.message
|
740
|
+
end
|
741
|
+
end
|
742
|
+
|
743
|
+
module CertUtil
|
744
|
+
extend Fluent::PluginHelper::CertOption
|
745
|
+
end
|
746
|
+
|
747
|
+
def create_ca_options
|
748
|
+
{
|
749
|
+
private_key_length: 2048,
|
750
|
+
country: 'US',
|
751
|
+
state: 'CA',
|
752
|
+
locality: 'Mountain View',
|
753
|
+
common_name: 'ca.testing.fluentd.org',
|
754
|
+
expiration: 30 * 86400,
|
755
|
+
digest: :sha256,
|
756
|
+
}
|
757
|
+
end
|
758
|
+
|
759
|
+
def create_server_options
|
760
|
+
{
|
761
|
+
private_key_length: 2048,
|
762
|
+
country: 'US',
|
763
|
+
state: 'CA',
|
764
|
+
locality: 'Mountain View',
|
765
|
+
common_name: 'server.testing.fluentd.org',
|
766
|
+
expiration: 30 * 86400,
|
767
|
+
digest: :sha256,
|
768
|
+
}
|
769
|
+
end
|
770
|
+
|
771
|
+
def write_cert_and_key(cert_path, cert, key_path, key, passphrase)
|
772
|
+
File.open(cert_path, "w"){|f| f.write(cert.to_pem) }
|
773
|
+
# Write the secret key (raw or encrypted by AES256) in PEM format
|
774
|
+
key_str = passphrase ? key.export(OpenSSL::Cipher.new("AES-256-CBC"), passphrase) : key.export
|
775
|
+
File.open(key_path, "w"){|f| f.write(key_str) }
|
776
|
+
File.chmod(0600, cert_path, key_path)
|
777
|
+
end
|
778
|
+
|
779
|
+
def create_server_pair_signed_by_self(cert_path, private_key_path, passphrase)
|
780
|
+
cert, key, _ = CertUtil.cert_option_generate_server_pair_self_signed(create_server_options)
|
781
|
+
write_cert_and_key(cert_path, cert, private_key_path, key, passphrase)
|
782
|
+
return cert
|
783
|
+
end
|
784
|
+
|
785
|
+
def create_ca_pair_signed_by_self(cert_path, private_key_path, passphrase)
|
786
|
+
cert, key, _ = CertUtil.cert_option_generate_ca_pair_self_signed(create_ca_options)
|
787
|
+
write_cert_and_key(cert_path, cert, private_key_path, key, passphrase)
|
788
|
+
end
|
789
|
+
|
790
|
+
def create_server_pair_signed_by_ca(ca_cert_path, ca_key_path, ca_key_passphrase, cert_path, private_key_path, passphrase)
|
791
|
+
cert, key, _ = CertUtil.cert_option_generate_server_pair_by_ca(ca_cert_path, ca_key_path, ca_key_passphrase, create_server_options)
|
792
|
+
write_cert_and_key(cert_path, cert, private_key_path, key, passphrase)
|
793
|
+
return cert
|
794
|
+
end
|
795
|
+
|
796
|
+
def create_server_pair_chained_with_root_ca(ca_cert_path, ca_key_path, ca_key_passphrase, cert_path, private_key_path, passphrase)
|
797
|
+
root_cert, root_key, _ = CertUtil.cert_option_generate_ca_pair_self_signed(create_ca_options)
|
798
|
+
write_cert_and_key(ca_cert_path, root_cert, ca_key_path, root_key, ca_key_passphrase)
|
799
|
+
|
800
|
+
intermediate_ca_options = create_ca_options
|
801
|
+
intermediate_ca_options[:common_name] = 'ca2.testing.fluentd.org'
|
802
|
+
chain_cert, chain_key = CertUtil.cert_option_generate_pair(intermediate_ca_options, root_cert.subject)
|
803
|
+
chain_cert.add_extension OpenSSL::X509::Extension.new('basicConstraints', OpenSSL::ASN1.Sequence([OpenSSL::ASN1::Boolean(true)]))
|
804
|
+
chain_cert.sign(root_key, "sha256")
|
805
|
+
|
806
|
+
server_cert, server_key, _ = CertUtil.cert_option_generate_pair(create_server_options, chain_cert.subject)
|
807
|
+
server_cert.add_extension OpenSSL::X509::Extension.new('basicConstraints', OpenSSL::ASN1.Sequence([OpenSSL::ASN1::Boolean(false)]))
|
808
|
+
server_cert.add_extension OpenSSL::X509::Extension.new('nsCertType', 'server')
|
809
|
+
server_cert.sign(chain_key, "sha256")
|
810
|
+
|
811
|
+
# write chained cert
|
812
|
+
File.open(cert_path, "w") do |f|
|
813
|
+
f.write server_cert.to_pem
|
814
|
+
f.write chain_cert.to_pem
|
815
|
+
end
|
816
|
+
key_str = passphrase ? server_key.export(OpenSSL::Cipher.new("AES-256-CBC"), passphrase) : server_key.export
|
817
|
+
File.open(private_key_path, "w"){|f| f.write(key_str) }
|
818
|
+
File.chmod(0600, cert_path, private_key_path)
|
819
|
+
end
|
820
|
+
|
821
|
+
def open_tls_session(addr, port, verify: true, cert_path: nil, selfsigned: true, hostname: nil)
|
822
|
+
context = OpenSSL::SSL::SSLContext.new
|
823
|
+
context.set_params({})
|
824
|
+
if verify
|
825
|
+
cert_store = OpenSSL::X509::Store.new
|
826
|
+
cert_store.set_default_paths
|
827
|
+
if selfsigned && OpenSSL::X509.const_defined?('V_FLAG_CHECK_SS_SIGNATURE')
|
828
|
+
cert_store.flags = OpenSSL::X509::V_FLAG_CHECK_SS_SIGNATURE
|
829
|
+
end
|
830
|
+
if cert_path
|
831
|
+
cert_store.add_file(cert_path)
|
832
|
+
end
|
833
|
+
context.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
834
|
+
context.cert_store = cert_store
|
835
|
+
if !hostname && context.respond_to?(:verify_hostname=)
|
836
|
+
context.verify_hostname = false # In test code, using hostname to be connected is very difficult
|
837
|
+
end
|
838
|
+
else
|
839
|
+
context.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
840
|
+
end
|
841
|
+
|
842
|
+
sock = OpenSSL::SSL::SSLSocket.new(TCPSocket.new(addr, port), context)
|
843
|
+
sock.hostname = hostname if hostname && sock.respond_to?(:hostname)
|
844
|
+
sock.connect
|
845
|
+
yield sock
|
846
|
+
ensure
|
847
|
+
sock.close rescue nil
|
848
|
+
end
|
849
|
+
|
850
|
+
def assert_certificate(cert, expected_extensions)
|
851
|
+
get_extension = lambda do |oid|
|
852
|
+
cert.extensions.detect { |e| e.oid == oid }
|
853
|
+
end
|
854
|
+
|
855
|
+
assert_true cert.serial > 1
|
856
|
+
assert_equal 2, cert.version
|
857
|
+
|
858
|
+
expected_extensions.each do |ext|
|
859
|
+
expected_oid, expected_value = ext
|
860
|
+
assert_equal expected_value, get_extension.call(expected_oid).value
|
861
|
+
end
|
862
|
+
end
|
863
|
+
|
864
|
+
sub_test_case '#server_create_tls with various certificate options' do
|
865
|
+
setup do
|
866
|
+
@d = Dummy.new # to get plugin not configured/started yet
|
867
|
+
|
868
|
+
@certs_dir = File.join(TMP_DIR, "tls_certs")
|
869
|
+
@server_cert_dir = File.join(@certs_dir, "server")
|
870
|
+
FileUtils.rm_rf @certs_dir
|
871
|
+
FileUtils.mkdir_p @server_cert_dir
|
872
|
+
end
|
873
|
+
|
874
|
+
sub_test_case 'using tls_options arguments to specify cert options' do
|
875
|
+
setup do
|
876
|
+
@d.configure(config_element()); @d.start; @d.after_start
|
877
|
+
end
|
878
|
+
|
879
|
+
test 'create dynamic self-signed cert/key pair (without any verification from clients)' do
|
880
|
+
# insecure
|
881
|
+
tls_options = {
|
882
|
+
protocol: :tls,
|
883
|
+
version: 'TLSv1_2',
|
884
|
+
ciphers: 'ALL:!aNULL:!eNULL:!SSLv2',
|
885
|
+
insecure: true,
|
886
|
+
generate_private_key_length: 2048,
|
887
|
+
generate_cert_country: 'US',
|
888
|
+
generate_cert_state: 'CA',
|
889
|
+
generate_cert_locality: 'Mountain View',
|
890
|
+
generate_cert_common_name: 'myserver.testing.fluentd.org',
|
891
|
+
generate_cert_expiration: 10 * 365 * 86400,
|
892
|
+
generate_cert_digest: :sha256,
|
893
|
+
}
|
894
|
+
|
895
|
+
received = ""
|
896
|
+
@d.server_create_tls(:s, PORT, tls_options: tls_options) do |data, conn|
|
897
|
+
received << data
|
898
|
+
end
|
899
|
+
assert_raise "" do
|
900
|
+
open_tls_session('127.0.0.1', PORT) do |sock|
|
901
|
+
sock.post_connection_check('myserver.testing.fluentd.org')
|
902
|
+
# cannot connect ....
|
903
|
+
end
|
904
|
+
end
|
905
|
+
open_tls_session('127.0.0.1', PORT, verify: false) do |sock|
|
906
|
+
sock.puts "yay"
|
907
|
+
sock.puts "foo"
|
908
|
+
end
|
909
|
+
waiting(10){ sleep 0.1 until received.bytesize == 8 }
|
910
|
+
assert_equal "yay\nfoo\n", received
|
911
|
+
end
|
912
|
+
|
913
|
+
data('with passphrase' => 'yaaaaaaaaaaaaaaaaaaay',
|
914
|
+
'without passphrase' => nil)
|
915
|
+
test 'load self-signed cert/key pair (files), verified from clients using cert files' do |private_key_passphrase|
|
916
|
+
cert_path = File.join(@server_cert_dir, "cert.pem")
|
917
|
+
private_key_path = File.join(@certs_dir, "server.key.pem")
|
918
|
+
cert = create_server_pair_signed_by_self(cert_path, private_key_path, private_key_passphrase)
|
919
|
+
|
920
|
+
assert_certificate(cert,[
|
921
|
+
['basicConstraints', 'CA:FALSE'],
|
922
|
+
['nsCertType', 'SSL Server']
|
923
|
+
])
|
924
|
+
|
925
|
+
tls_options = {
|
926
|
+
protocol: :tls,
|
927
|
+
version: 'TLSv1_2',
|
928
|
+
ciphers: 'ALL:!aNULL:!eNULL:!SSLv2',
|
929
|
+
insecure: false,
|
930
|
+
cert_path: cert_path,
|
931
|
+
private_key_path: private_key_path,
|
932
|
+
}
|
933
|
+
tls_options[:private_key_passphrase] = private_key_passphrase if private_key_passphrase
|
934
|
+
received = ""
|
935
|
+
@d.server_create_tls(:s, PORT, tls_options: tls_options) do |data, conn|
|
936
|
+
received << data
|
937
|
+
end
|
938
|
+
assert_raise "" do
|
939
|
+
open_tls_session('127.0.0.1', PORT) do |sock|
|
940
|
+
sock.post_connection_check('server.testing.fluentd.org')
|
941
|
+
# cannot connect by failing verification without server cert
|
942
|
+
end
|
943
|
+
end
|
944
|
+
open_tls_session('127.0.0.1', PORT, cert_path: cert_path) do |sock|
|
945
|
+
sock.puts "yay"
|
946
|
+
sock.puts "foo"
|
947
|
+
end
|
948
|
+
waiting(10){ sleep 0.1 until received.bytesize == 8 }
|
949
|
+
assert_equal "yay\nfoo\n", received
|
950
|
+
end
|
951
|
+
|
952
|
+
data('with passphrase' => "fooooooooooooooooooooooooo",
|
953
|
+
'without passphrase' => nil)
|
954
|
+
test 'create dynamic server cert by private CA cert file, verified from clients using CA cert file' do |ca_key_passphrase|
|
955
|
+
ca_cert_path = File.join(@certs_dir, "ca_cert.pem")
|
956
|
+
ca_key_path = File.join(@certs_dir, "ca.key.pem")
|
957
|
+
create_ca_pair_signed_by_self(ca_cert_path, ca_key_path, ca_key_passphrase)
|
958
|
+
|
959
|
+
tls_options = {
|
960
|
+
protocol: :tls,
|
961
|
+
version: 'TLSv1_2',
|
962
|
+
ciphers: 'ALL:!aNULL:!eNULL:!SSLv2',
|
963
|
+
insecure: false,
|
964
|
+
ca_cert_path: ca_cert_path,
|
965
|
+
ca_private_key_path: ca_key_path,
|
966
|
+
generate_private_key_length: 2048,
|
967
|
+
}
|
968
|
+
tls_options[:ca_private_key_passphrase] = ca_key_passphrase if ca_key_passphrase
|
969
|
+
received = ""
|
970
|
+
@d.server_create_tls(:s, PORT, tls_options: tls_options) do |data, conn|
|
971
|
+
received << data
|
972
|
+
end
|
973
|
+
open_tls_session('127.0.0.1', PORT, cert_path: ca_cert_path) do |sock|
|
974
|
+
sock.puts "yay"
|
975
|
+
sock.puts "foo"
|
976
|
+
end
|
977
|
+
waiting(10){ sleep 0.1 until received.bytesize == 8 }
|
978
|
+
assert_equal "yay\nfoo\n", received
|
979
|
+
end
|
980
|
+
|
981
|
+
data('with passphrase' => ["foooooooo", "yaaaaaaaaaaaaaaaaaaay"],
|
982
|
+
'without passphrase' => [nil, nil])
|
983
|
+
test 'load static server cert by private CA cert file, verified from clients using CA cert file' do |(ca_key_passphrase, private_key_passphrase)|
|
984
|
+
ca_cert_path = File.join(@certs_dir, "ca_cert.pem")
|
985
|
+
ca_key_path = File.join(@certs_dir, "ca.key.pem")
|
986
|
+
create_ca_pair_signed_by_self(ca_cert_path, ca_key_path, ca_key_passphrase)
|
987
|
+
|
988
|
+
cert_path = File.join(@server_cert_dir, "cert.pem")
|
989
|
+
private_key_path = File.join(@certs_dir, "server.key.pem")
|
990
|
+
cert = create_server_pair_signed_by_ca(ca_cert_path, ca_key_path, ca_key_passphrase, cert_path, private_key_path, private_key_passphrase)
|
991
|
+
|
992
|
+
assert_certificate(cert,[
|
993
|
+
['basicConstraints', 'CA:FALSE'],
|
994
|
+
['nsCertType', 'SSL Server'],
|
995
|
+
['keyUsage', 'Digital Signature, Key Encipherment'],
|
996
|
+
['extendedKeyUsage', 'TLS Web Server Authentication']
|
997
|
+
])
|
998
|
+
|
999
|
+
tls_options = {
|
1000
|
+
protocol: :tls,
|
1001
|
+
version: 'TLSv1_2',
|
1002
|
+
ciphers: 'ALL:!aNULL:!eNULL:!SSLv2',
|
1003
|
+
insecure: false,
|
1004
|
+
cert_path: cert_path,
|
1005
|
+
private_key_path: private_key_path,
|
1006
|
+
}
|
1007
|
+
tls_options[:private_key_passphrase] = private_key_passphrase if private_key_passphrase
|
1008
|
+
received = ""
|
1009
|
+
@d.server_create_tls(:s, PORT, tls_options: tls_options) do |data, conn|
|
1010
|
+
received << data
|
1011
|
+
end
|
1012
|
+
open_tls_session('127.0.0.1', PORT, cert_path: ca_cert_path) do |sock|
|
1013
|
+
sock.puts "yay"
|
1014
|
+
sock.puts "foo"
|
1015
|
+
end
|
1016
|
+
waiting(10){ sleep 0.1 until received.bytesize == 8 }
|
1017
|
+
assert_equal "yay\nfoo\n", received
|
1018
|
+
end
|
1019
|
+
|
1020
|
+
data('with passphrase' => ["foooooooo", "yaaaaaaaaaaaaaaaaaaay"],
|
1021
|
+
'without passphrase' => [nil, nil])
|
1022
|
+
test 'load chained server cert by private CA cert file, verified from clients using CA cert file as root' do |(ca_key_passphrase, private_key_passphrase)|
|
1023
|
+
ca_cert_path = File.join(@certs_dir, "ca_cert.pem")
|
1024
|
+
ca_key_path = File.join(@certs_dir, "ca.key.pem")
|
1025
|
+
cert_path = File.join(@server_cert_dir, "cert.pem")
|
1026
|
+
private_key_path = File.join(@certs_dir, "server.key.pem")
|
1027
|
+
create_server_pair_chained_with_root_ca(ca_cert_path, ca_key_path, ca_key_passphrase, cert_path, private_key_path, private_key_passphrase)
|
1028
|
+
|
1029
|
+
tls_options = {
|
1030
|
+
protocol: :tls,
|
1031
|
+
version: 'TLSv1_2',
|
1032
|
+
ciphers: 'ALL:!aNULL:!eNULL:!SSLv2',
|
1033
|
+
insecure: false,
|
1034
|
+
cert_path: cert_path,
|
1035
|
+
private_key_path: private_key_path,
|
1036
|
+
}
|
1037
|
+
tls_options[:private_key_passphrase] = private_key_passphrase if private_key_passphrase
|
1038
|
+
received = ""
|
1039
|
+
@d.server_create_tls(:s, PORT, tls_options: tls_options) do |data, conn|
|
1040
|
+
received << data
|
1041
|
+
end
|
1042
|
+
open_tls_session('127.0.0.1', PORT, cert_path: ca_cert_path) do |sock|
|
1043
|
+
sock.puts "yay"
|
1044
|
+
sock.puts "foo"
|
1045
|
+
end
|
1046
|
+
waiting(10){ sleep 0.1 until received.bytesize == 8 }
|
1047
|
+
assert_equal "yay\nfoo\n", received
|
1048
|
+
end
|
1049
|
+
end
|
1050
|
+
|
1051
|
+
sub_test_case 'using configurations to specify cert options' do
|
1052
|
+
test 'create dynamic self-signed cert/key pair (without any verification from clients)' do
|
1053
|
+
# insecure
|
1054
|
+
transport_opts = {
|
1055
|
+
'insecure' => 'true',
|
1056
|
+
}
|
1057
|
+
transport_conf = config_element('transport', 'tls', transport_opts)
|
1058
|
+
conf = config_element('match', 'tag.*', {}, [transport_conf])
|
1059
|
+
|
1060
|
+
@d.configure(conf); @d.start; @d.after_start
|
1061
|
+
|
1062
|
+
received = ""
|
1063
|
+
@d.server_create_tls(:s, PORT) do |data, conn|
|
1064
|
+
received << data
|
1065
|
+
end
|
1066
|
+
assert_raise "" do
|
1067
|
+
open_tls_session('127.0.0.1', PORT) do |sock|
|
1068
|
+
sock.post_connection_check('myserver.testing.fluentd.org')
|
1069
|
+
# cannot connect ....
|
1070
|
+
end
|
1071
|
+
end
|
1072
|
+
open_tls_session('127.0.0.1', PORT, verify: false) do |sock|
|
1073
|
+
sock.puts "yay"
|
1074
|
+
sock.puts "foo"
|
1075
|
+
end
|
1076
|
+
waiting(10){ sleep 0.1 until received.bytesize == 8 }
|
1077
|
+
assert_equal "yay\nfoo\n", received
|
1078
|
+
end
|
1079
|
+
|
1080
|
+
data('with passphrase' => "yaaaaaaaaaaaaaaaaaaay",
|
1081
|
+
'without passphrase' => nil)
|
1082
|
+
test 'load self-signed cert/key pair (files), verified from clients using cert files' do |private_key_passphrase|
|
1083
|
+
cert_path = File.join(@server_cert_dir, "cert.pem")
|
1084
|
+
private_key_path = File.join(@certs_dir, "server.key.pem")
|
1085
|
+
create_server_pair_signed_by_self(cert_path, private_key_path, private_key_passphrase)
|
1086
|
+
|
1087
|
+
transport_opts = {
|
1088
|
+
'cert_path' => cert_path,
|
1089
|
+
'private_key_path' => private_key_path,
|
1090
|
+
}
|
1091
|
+
transport_opts['private_key_passphrase'] = private_key_passphrase if private_key_passphrase
|
1092
|
+
transport_conf = config_element('transport', 'tls', transport_opts)
|
1093
|
+
conf = config_element('match', 'tag.*', {}, [transport_conf])
|
1094
|
+
|
1095
|
+
@d.configure(conf); @d.start; @d.after_start
|
1096
|
+
|
1097
|
+
received = ""
|
1098
|
+
@d.server_create_tls(:s, PORT) do |data, conn|
|
1099
|
+
received << data
|
1100
|
+
end
|
1101
|
+
assert_raise "" do
|
1102
|
+
open_tls_session('127.0.0.1', PORT) do |sock|
|
1103
|
+
sock.post_connection_check('server.testing.fluentd.org')
|
1104
|
+
# cannot connect by failing verification without server cert
|
1105
|
+
end
|
1106
|
+
end
|
1107
|
+
open_tls_session('127.0.0.1', PORT, cert_path: cert_path) do |sock|
|
1108
|
+
sock.puts "yay"
|
1109
|
+
sock.puts "foo"
|
1110
|
+
end
|
1111
|
+
waiting(10){ sleep 0.1 until received.bytesize == 8 }
|
1112
|
+
assert_equal "yay\nfoo\n", received
|
1113
|
+
end
|
1114
|
+
|
1115
|
+
data('with passphrase' => "fooooooooooooooooooooooooo",
|
1116
|
+
'without passphrase' => nil)
|
1117
|
+
test 'create dynamic server cert by private CA cert file, verified from clients using CA cert file' do |ca_key_passphrase|
|
1118
|
+
ca_cert_path = File.join(@certs_dir, "ca_cert.pem")
|
1119
|
+
ca_key_path = File.join(@certs_dir, "ca.key.pem")
|
1120
|
+
create_ca_pair_signed_by_self(ca_cert_path, ca_key_path, ca_key_passphrase)
|
1121
|
+
|
1122
|
+
transport_opts = {
|
1123
|
+
'ca_cert_path' => ca_cert_path,
|
1124
|
+
'ca_private_key_path' => ca_key_path,
|
1125
|
+
}
|
1126
|
+
transport_opts['ca_private_key_passphrase'] = ca_key_passphrase if ca_key_passphrase
|
1127
|
+
transport_conf = config_element('transport', 'tls', transport_opts)
|
1128
|
+
conf = config_element('match', 'tag.*', {}, [transport_conf])
|
1129
|
+
|
1130
|
+
@d.configure(conf); @d.start; @d.after_start
|
1131
|
+
|
1132
|
+
received = ""
|
1133
|
+
@d.server_create_tls(:s, PORT) do |data, conn|
|
1134
|
+
received << data
|
1135
|
+
end
|
1136
|
+
open_tls_session('127.0.0.1', PORT, cert_path: ca_cert_path) do |sock|
|
1137
|
+
sock.puts "yay"
|
1138
|
+
sock.puts "foo"
|
1139
|
+
end
|
1140
|
+
waiting(10){ sleep 0.1 until received.bytesize == 8 }
|
1141
|
+
assert_equal "yay\nfoo\n", received
|
1142
|
+
end
|
1143
|
+
|
1144
|
+
data('with passphrase' => ["foooooooo", "yaaaaaaaaaaaaaaaaaaay"],
|
1145
|
+
'without passphrase' => [nil, nil])
|
1146
|
+
test 'load static server cert by private CA cert file, verified from clients using CA cert file' do |(ca_key_passphrase, private_key_passphrase)|
|
1147
|
+
ca_cert_path = File.join(@certs_dir, "ca_cert.pem")
|
1148
|
+
ca_key_path = File.join(@certs_dir, "ca.key.pem")
|
1149
|
+
create_ca_pair_signed_by_self(ca_cert_path, ca_key_path, ca_key_passphrase)
|
1150
|
+
|
1151
|
+
cert_path = File.join(@server_cert_dir, "cert.pem")
|
1152
|
+
private_key_path = File.join(@certs_dir, "server.key.pem")
|
1153
|
+
create_server_pair_signed_by_ca(ca_cert_path, ca_key_path, ca_key_passphrase, cert_path, private_key_path, private_key_passphrase)
|
1154
|
+
|
1155
|
+
transport_opts = {
|
1156
|
+
'cert_path' => cert_path,
|
1157
|
+
'private_key_path' => private_key_path,
|
1158
|
+
}
|
1159
|
+
transport_opts['private_key_passphrase'] = private_key_passphrase if private_key_passphrase
|
1160
|
+
transport_conf = config_element('transport', 'tls', transport_opts)
|
1161
|
+
conf = config_element('match', 'tag.*', {}, [transport_conf])
|
1162
|
+
|
1163
|
+
@d.configure(conf); @d.start; @d.after_start
|
1164
|
+
|
1165
|
+
received = ""
|
1166
|
+
@d.server_create_tls(:s, PORT) do |data, conn|
|
1167
|
+
received << data
|
1168
|
+
end
|
1169
|
+
open_tls_session('127.0.0.1', PORT, cert_path: ca_cert_path) do |sock|
|
1170
|
+
sock.puts "yay"
|
1171
|
+
sock.puts "foo"
|
1172
|
+
end
|
1173
|
+
waiting(10){ sleep 0.1 until received.bytesize == 8 }
|
1174
|
+
assert_equal "yay\nfoo\n", received
|
1175
|
+
end
|
1176
|
+
|
1177
|
+
data('with passphrase' => ["foooooooo", "yaaaaaaaaaaaaaaaaaaay"],
|
1178
|
+
'without passphrase' => [nil, nil])
|
1179
|
+
test 'load chained server cert by private CA cert file, verified from clients using CA cert file as root' do |(ca_key_passphrase, private_key_passphrase)|
|
1180
|
+
ca_cert_path = File.join(@certs_dir, "ca_cert.pem")
|
1181
|
+
ca_key_path = File.join(@certs_dir, "ca.key.pem")
|
1182
|
+
cert_path = File.join(@server_cert_dir, "cert.pem")
|
1183
|
+
private_key_path = File.join(@certs_dir, "server.key.pem")
|
1184
|
+
create_server_pair_chained_with_root_ca(ca_cert_path, ca_key_path, ca_key_passphrase, cert_path, private_key_path, private_key_passphrase)
|
1185
|
+
|
1186
|
+
transport_opts = {
|
1187
|
+
'cert_path' => cert_path,
|
1188
|
+
'private_key_path' => private_key_path,
|
1189
|
+
}
|
1190
|
+
transport_opts['private_key_passphrase'] = private_key_passphrase if private_key_passphrase
|
1191
|
+
transport_conf = config_element('transport', 'tls', transport_opts)
|
1192
|
+
conf = config_element('match', 'tag.*', {}, [transport_conf])
|
1193
|
+
|
1194
|
+
@d.configure(conf); @d.start; @d.after_start
|
1195
|
+
|
1196
|
+
received = ""
|
1197
|
+
@d.server_create_tls(:s, PORT) do |data, conn|
|
1198
|
+
received << data
|
1199
|
+
end
|
1200
|
+
open_tls_session('127.0.0.1', PORT, cert_path: ca_cert_path) do |sock|
|
1201
|
+
sock.puts "yay"
|
1202
|
+
sock.puts "foo"
|
1203
|
+
end
|
1204
|
+
waiting(10){ sleep 0.1 until received.bytesize == 8 }
|
1205
|
+
assert_equal "yay\nfoo\n", received
|
1206
|
+
end
|
1207
|
+
end
|
1208
|
+
end
|
1209
|
+
|
1210
|
+
sub_test_case '#server_create_tls' do
|
1211
|
+
setup do
|
1212
|
+
@certs_dir = File.join(TMP_DIR, "tls_certs")
|
1213
|
+
FileUtils.rm_rf @certs_dir
|
1214
|
+
FileUtils.mkdir_p @certs_dir
|
1215
|
+
|
1216
|
+
@server_cert_dir = File.join(@certs_dir, "server")
|
1217
|
+
FileUtils.mkdir_p @server_cert_dir
|
1218
|
+
|
1219
|
+
@cert_path = File.join(@server_cert_dir, "cert.pem")
|
1220
|
+
private_key_path = File.join(@certs_dir, "server.key.pem")
|
1221
|
+
private_key_passphrase = "yaaaaaaaaaaaaaaaaaaay"
|
1222
|
+
create_server_pair_signed_by_self(@cert_path, private_key_path, private_key_passphrase)
|
1223
|
+
|
1224
|
+
@default_hostname = ::Socket.gethostname
|
1225
|
+
|
1226
|
+
@tls_options = {
|
1227
|
+
protocol: :tls,
|
1228
|
+
version: 'TLSv1_2',
|
1229
|
+
ciphers: 'ALL:!aNULL:!eNULL:!SSLv2',
|
1230
|
+
insecure: false,
|
1231
|
+
cert_path: @cert_path,
|
1232
|
+
private_key_path: private_key_path,
|
1233
|
+
private_key_passphrase: private_key_passphrase,
|
1234
|
+
}
|
1235
|
+
end
|
1236
|
+
|
1237
|
+
test 'can accept all keyword arguments valid for tcp/tls server' do
|
1238
|
+
assert_nothing_raised do
|
1239
|
+
@d.server_create_tls(:s, PORT, bind: '127.0.0.1', shared: false, resolve_name: true, linger_timeout: 10, backlog: 500, tls_options: @tls_options) do |data, conn|
|
1240
|
+
# ...
|
1241
|
+
end
|
1242
|
+
end
|
1243
|
+
end
|
1244
|
+
|
1245
|
+
test 'creates a tls server just to read data' do
|
1246
|
+
received = ""
|
1247
|
+
@d.server_create_tls(:s, PORT, tls_options: @tls_options) do |data, conn|
|
1248
|
+
received << data
|
1249
|
+
end
|
1250
|
+
3.times do
|
1251
|
+
open_tls_session('127.0.0.1', PORT, cert_path: @cert_path) do |sock|
|
1252
|
+
sock.puts "yay"
|
1253
|
+
sock.puts "foo"
|
1254
|
+
end
|
1255
|
+
end
|
1256
|
+
waiting(10){ sleep 0.1 until received.bytesize == 24 }
|
1257
|
+
assert_equal 3, received.scan("yay\n").size
|
1258
|
+
assert_equal 3, received.scan("foo\n").size
|
1259
|
+
end
|
1260
|
+
|
1261
|
+
test 'creates a tls server to read and write data' do
|
1262
|
+
received = ""
|
1263
|
+
responses = []
|
1264
|
+
@d.server_create_tls(:s, PORT, tls_options: @tls_options) do |data, conn|
|
1265
|
+
received << data
|
1266
|
+
conn.write "ack\n"
|
1267
|
+
end
|
1268
|
+
3.times do
|
1269
|
+
# open_tls_session('127.0.0.1', PORT, cert_path: @cert_path, hostname: @default_hostname) do |sock|
|
1270
|
+
open_tls_session('127.0.0.1', PORT, cert_path: @cert_path) do |sock|
|
1271
|
+
sock.puts "yay"
|
1272
|
+
sock.puts "foo"
|
1273
|
+
responses << sock.readline
|
1274
|
+
end
|
1275
|
+
end
|
1276
|
+
waiting(10){ sleep 0.1 until received.bytesize == 24 }
|
1277
|
+
assert_equal 3, received.scan("yay\n").size
|
1278
|
+
assert_equal 3, received.scan("foo\n").size
|
1279
|
+
assert_equal ["ack\n","ack\n","ack\n"], responses
|
1280
|
+
end
|
1281
|
+
|
1282
|
+
test 'creates a tls server to read and write data using IPv6' do
|
1283
|
+
omit "IPv6 unavailable here" unless ipv6_enabled?
|
1284
|
+
|
1285
|
+
received = ""
|
1286
|
+
responses = []
|
1287
|
+
@d.server_create_tls(:s, PORT, bind: "::1", tls_options: @tls_options) do |data, conn|
|
1288
|
+
received << data
|
1289
|
+
conn.write "ack\n"
|
1290
|
+
end
|
1291
|
+
3.times do
|
1292
|
+
# open_tls_session('::1', PORT, cert_path: @cert_path, hostname: @default_hostname) do |sock|
|
1293
|
+
open_tls_session('::1', PORT, cert_path: @cert_path) do |sock|
|
1294
|
+
sock.puts "yay"
|
1295
|
+
sock.puts "foo"
|
1296
|
+
responses << sock.readline
|
1297
|
+
end
|
1298
|
+
end
|
1299
|
+
waiting(10){ sleep 0.1 until received.bytesize == 24 }
|
1300
|
+
assert_equal 3, received.scan("yay\n").size
|
1301
|
+
assert_equal 3, received.scan("foo\n").size
|
1302
|
+
assert_equal ["ack\n","ack\n","ack\n"], responses
|
1303
|
+
end
|
1304
|
+
|
1305
|
+
test 'does not resolve name of client address in default' do
|
1306
|
+
received = ""
|
1307
|
+
sources = []
|
1308
|
+
@d.server_create_tls(:s, PORT, tls_options: @tls_options) do |data, conn|
|
1309
|
+
received << data
|
1310
|
+
sources << conn.remote_host
|
1311
|
+
end
|
1312
|
+
3.times do
|
1313
|
+
# open_tls_session('127.0.0.1', PORT, cert_path: @cert_path, hostname: @default_hostname) do |sock|
|
1314
|
+
open_tls_session('127.0.0.1', PORT, cert_path: @cert_path) do |sock|
|
1315
|
+
sock.puts "yay"
|
1316
|
+
end
|
1317
|
+
end
|
1318
|
+
waiting(10){ sleep 0.1 until received.bytesize == 12 }
|
1319
|
+
assert_equal 3, received.scan("yay\n").size
|
1320
|
+
assert{ sources.all?{|s| s == "127.0.0.1" } }
|
1321
|
+
end
|
1322
|
+
|
1323
|
+
test 'does resolve name of client address if resolve_name is true' do
|
1324
|
+
hostname = Socket.getnameinfo([nil, nil, nil, "127.0.0.1"])[0]
|
1325
|
+
|
1326
|
+
received = ""
|
1327
|
+
sources = []
|
1328
|
+
@d.server_create_tls(:s, PORT, resolve_name: true, tls_options: @tls_options) do |data, conn|
|
1329
|
+
received << data
|
1330
|
+
sources << conn.remote_host
|
1331
|
+
end
|
1332
|
+
3.times do
|
1333
|
+
# open_tls_session('127.0.0.1', PORT, cert_path: @cert_path, hostname: @default_hostname) do |sock|
|
1334
|
+
open_tls_session('127.0.0.1', PORT, cert_path: @cert_path) do |sock|
|
1335
|
+
sock.puts "yay"
|
1336
|
+
end
|
1337
|
+
end
|
1338
|
+
waiting(10){ sleep 0.1 until received.bytesize == 12 }
|
1339
|
+
assert_equal 3, received.scan("yay\n").size
|
1340
|
+
assert{ sources.all?{|s| s == hostname } }
|
1341
|
+
end
|
1342
|
+
|
1343
|
+
test 'can keep connections alive for tls if keepalive specified' do
|
1344
|
+
# pend "not implemented yet"
|
1345
|
+
end
|
1346
|
+
|
1347
|
+
test 'raises error if plugin registers data callback for connection object from #server_create' do
|
1348
|
+
received = ""
|
1349
|
+
errors = []
|
1350
|
+
@d.server_create_tls(:s, PORT, tls_options: @tls_options) do |data, conn|
|
1351
|
+
received << data
|
1352
|
+
begin
|
1353
|
+
conn.data{|d| received << d.upcase }
|
1354
|
+
rescue => e
|
1355
|
+
errors << e
|
1356
|
+
end
|
1357
|
+
end
|
1358
|
+
open_tls_session('127.0.0.1', PORT, cert_path: @cert_path) do |sock|
|
1359
|
+
sock.puts "foo"
|
1360
|
+
end
|
1361
|
+
waiting(10){ sleep 0.1 until received.bytesize == 4 || errors.size == 1 }
|
1362
|
+
assert_equal "foo\n", received
|
1363
|
+
assert_equal 1, errors.size
|
1364
|
+
assert_equal "data callback can be registered just once, but registered twice", errors.first.message
|
1365
|
+
end
|
1366
|
+
|
1367
|
+
test 'can call write_complete callback if registered' do
|
1368
|
+
buffer = ""
|
1369
|
+
lines = []
|
1370
|
+
responses = []
|
1371
|
+
response_completes = []
|
1372
|
+
@d.server_create_tls(:s, PORT, tls_options: @tls_options) do |data, conn|
|
1373
|
+
conn.on(:write_complete){|c| response_completes << true }
|
1374
|
+
buffer << data
|
1375
|
+
if idx = buffer.index("\n")
|
1376
|
+
lines << buffer.slice!(0,idx+1)
|
1377
|
+
conn.write "ack\n"
|
1378
|
+
end
|
1379
|
+
end
|
1380
|
+
3.times do
|
1381
|
+
open_tls_session('127.0.0.1', PORT, cert_path: @cert_path) do |sock|
|
1382
|
+
sock.write "yay"
|
1383
|
+
sock.write "foo\n"
|
1384
|
+
begin
|
1385
|
+
responses << sock.readline
|
1386
|
+
rescue EOFError, IOError, Errno::ECONNRESET
|
1387
|
+
# ignore
|
1388
|
+
end
|
1389
|
+
sock.close
|
1390
|
+
end
|
1391
|
+
end
|
1392
|
+
waiting(10){ sleep 0.1 until lines.size == 3 && response_completes.size == 3 }
|
1393
|
+
assert_equal ["yayfoo\n", "yayfoo\n", "yayfoo\n"], lines
|
1394
|
+
assert_equal ["ack\n","ack\n","ack\n"], responses
|
1395
|
+
assert_equal [true, true, true], response_completes
|
1396
|
+
end
|
1397
|
+
|
1398
|
+
test 'can call close callback if registered' do
|
1399
|
+
buffer = ""
|
1400
|
+
lines = []
|
1401
|
+
callback_results = []
|
1402
|
+
@d.server_create_tls(:s, PORT, tls_options: @tls_options) do |data, conn|
|
1403
|
+
conn.on(:close){|c| callback_results << "closed" }
|
1404
|
+
buffer << data
|
1405
|
+
if idx = buffer.index("\n")
|
1406
|
+
lines << buffer.slice!(0,idx+1)
|
1407
|
+
conn.write "ack\n"
|
1408
|
+
end
|
1409
|
+
end
|
1410
|
+
3.times do
|
1411
|
+
open_tls_session('127.0.0.1', PORT, cert_path: @cert_path) do |sock|
|
1412
|
+
sock.write "yay"
|
1413
|
+
sock.write "foo\n"
|
1414
|
+
begin
|
1415
|
+
while line = sock.readline
|
1416
|
+
if line == "ack\n"
|
1417
|
+
sock.close
|
1418
|
+
end
|
1419
|
+
end
|
1420
|
+
rescue EOFError, IOError, Errno::ECONNRESET
|
1421
|
+
# ignore
|
1422
|
+
end
|
1423
|
+
end
|
1424
|
+
end
|
1425
|
+
waiting(10){ sleep 0.1 until lines.size == 3 && callback_results.size == 3 }
|
1426
|
+
assert_equal ["yayfoo\n", "yayfoo\n", "yayfoo\n"], lines
|
1427
|
+
assert_equal ["closed", "closed", "closed"], callback_results
|
1428
|
+
end
|
1429
|
+
end
|
1430
|
+
|
1431
|
+
sub_test_case '#server_create_unix' do
|
1432
|
+
# not implemented yet
|
1433
|
+
|
1434
|
+
# test 'can accept all keyword arguments valid for unix server'
|
1435
|
+
# test 'creates a unix server just to read data'
|
1436
|
+
# test 'creates a unix server to read and write data'
|
1437
|
+
|
1438
|
+
# test 'raises error if plugin registers data callback for connection object from #server_create'
|
1439
|
+
# test 'can call write_complete callback if registered'
|
1440
|
+
# test 'can call close callback if registered'
|
1441
|
+
end
|
1442
|
+
|
1443
|
+
def open_client(proto, addr, port)
|
1444
|
+
client = case proto
|
1445
|
+
when :tcp
|
1446
|
+
TCPSocket.open(addr, port)
|
1447
|
+
when :tls
|
1448
|
+
c = OpenSSL::SSL::SSLSocket.new(TCPSocket.open(addr, port))
|
1449
|
+
c.sync_close = true
|
1450
|
+
c.connect
|
1451
|
+
else
|
1452
|
+
raise ArgumentError, "unknown proto:#{proto}"
|
1453
|
+
end
|
1454
|
+
yield client
|
1455
|
+
ensure
|
1456
|
+
client.close rescue nil
|
1457
|
+
end
|
1458
|
+
|
1459
|
+
# run tests for tcp, tls and unix
|
1460
|
+
sub_test_case '#server_create_connection' do
|
1461
|
+
test 'raise error if udp is specified in proto' do
|
1462
|
+
assert_raise(ArgumentError.new("BUG: cannot create connection for UDP")) do
|
1463
|
+
@d.server_create_connection(:myserver, PORT, proto: :udp){|c| c }
|
1464
|
+
end
|
1465
|
+
end
|
1466
|
+
|
1467
|
+
# def server_create_connection(title, port, proto: :tcp, bind: '0.0.0.0', shared: true, tls_options: nil, resolve_name: false, linger_timeout: 0, backlog: nil, &block)
|
1468
|
+
protocols = {
|
1469
|
+
'tcp' => [:tcp, {}],
|
1470
|
+
'tls' => [:tls, {tls_options: {insecure: true}}],
|
1471
|
+
# 'unix' => [:unix, {path: ""}],
|
1472
|
+
}
|
1473
|
+
|
1474
|
+
data(protocols)
|
1475
|
+
test 'raise error if block argument is not specified or too many' do |(proto, kwargs)|
|
1476
|
+
empty_block = ->(){}
|
1477
|
+
assert_raise(ArgumentError.new("BUG: block must have just one argument")) do
|
1478
|
+
@d.server_create_connection(:myserver, PORT, proto: proto, **kwargs, &empty_block)
|
1479
|
+
end
|
1480
|
+
assert_raise(ArgumentError.new("BUG: block must have just one argument")) do
|
1481
|
+
@d.server_create_connection(:myserver, PORT, proto: proto, **kwargs){|conn, what_is_this| [conn, what_is_this] }
|
1482
|
+
end
|
1483
|
+
end
|
1484
|
+
|
1485
|
+
data(protocols)
|
1486
|
+
test 'does not resolve name of client address in default' do |(proto, kwargs)|
|
1487
|
+
received = ""
|
1488
|
+
sources = []
|
1489
|
+
@d.server_create_connection(:s, PORT, proto: proto, **kwargs) do |conn|
|
1490
|
+
sources << conn.remote_host
|
1491
|
+
conn.data do |d|
|
1492
|
+
received << d
|
1493
|
+
end
|
1494
|
+
end
|
1495
|
+
3.times do
|
1496
|
+
open_client(proto, "127.0.0.1", PORT) do |sock|
|
1497
|
+
sock.puts "yay"
|
1498
|
+
end
|
1499
|
+
end
|
1500
|
+
waiting(10){ sleep 0.1 until received.bytesize == 12 }
|
1501
|
+
assert_equal "yay\nyay\nyay\n", received
|
1502
|
+
assert{ sources.all?{|s| s == "127.0.0.1" } }
|
1503
|
+
end
|
1504
|
+
|
1505
|
+
data(protocols)
|
1506
|
+
test 'does resolve name of client address if resolve_name is true' do |(proto, kwargs)|
|
1507
|
+
hostname = Socket.getnameinfo([nil, nil, nil, "127.0.0.1"])[0]
|
1508
|
+
|
1509
|
+
received = ""
|
1510
|
+
sources = []
|
1511
|
+
@d.server_create_connection(:s, PORT, proto: proto, resolve_name: true, **kwargs) do |conn|
|
1512
|
+
sources << conn.remote_host
|
1513
|
+
conn.data do |d|
|
1514
|
+
received << d
|
1515
|
+
end
|
1516
|
+
end
|
1517
|
+
3.times do
|
1518
|
+
open_client(proto, "127.0.0.1", PORT) do |sock|
|
1519
|
+
sock.puts "yay"
|
1520
|
+
end
|
1521
|
+
end
|
1522
|
+
waiting(10){ sleep 0.1 until received.bytesize == 12 }
|
1523
|
+
assert_equal "yay\nyay\nyay\n", received
|
1524
|
+
assert{ sources.all?{|s| s == hostname } }
|
1525
|
+
end
|
1526
|
+
|
1527
|
+
data(protocols)
|
1528
|
+
test 'creates a server to provide connection, which can read, write and close' do |(proto, kwargs)|
|
1529
|
+
lines = []
|
1530
|
+
buffer = ""
|
1531
|
+
@d.server_create_connection(:s, PORT, proto: proto, **kwargs) do |conn|
|
1532
|
+
conn.data do |d|
|
1533
|
+
buffer << d
|
1534
|
+
if buffer == "x"
|
1535
|
+
buffer.slice!(0, 1)
|
1536
|
+
conn.close
|
1537
|
+
end
|
1538
|
+
if idx = buffer.index("\n")
|
1539
|
+
lines << buffer.slice!(0, idx + 1)
|
1540
|
+
conn.write "foo!\n"
|
1541
|
+
end
|
1542
|
+
end
|
1543
|
+
end
|
1544
|
+
replied = []
|
1545
|
+
disconnecteds = []
|
1546
|
+
3.times do |i|
|
1547
|
+
open_client(proto, "127.0.0.1", PORT) do |sock|
|
1548
|
+
sock.puts "yay"
|
1549
|
+
while line = sock.readline
|
1550
|
+
replied << line
|
1551
|
+
break
|
1552
|
+
end
|
1553
|
+
sock.write "x"
|
1554
|
+
connection_closed = false
|
1555
|
+
begin
|
1556
|
+
data = sock.read
|
1557
|
+
if data.empty?
|
1558
|
+
connection_closed = true
|
1559
|
+
end
|
1560
|
+
rescue => e
|
1561
|
+
if e.is_a?(Errno::ECONNRESET)
|
1562
|
+
connection_closed = true
|
1563
|
+
end
|
1564
|
+
ensure
|
1565
|
+
disconnecteds << connection_closed
|
1566
|
+
end
|
1567
|
+
end
|
1568
|
+
end
|
1569
|
+
waiting(10){ sleep 0.1 until lines.size == 3 }
|
1570
|
+
waiting(10){ sleep 0.1 until replied.size == 3 }
|
1571
|
+
waiting(10){ sleep 0.1 until disconnecteds.size == 3 }
|
1572
|
+
assert_equal ["yay\n", "yay\n", "yay\n"], lines
|
1573
|
+
assert_equal ["foo!\n", "foo!\n", "foo!\n"], replied
|
1574
|
+
assert_equal [true, true, true], disconnecteds
|
1575
|
+
end
|
1576
|
+
|
1577
|
+
data(protocols)
|
1578
|
+
test 'creates a server to provide connection, which accepts callbacks for data, write_complete, and close' do |(proto, kwargs)|
|
1579
|
+
lines = []
|
1580
|
+
buffer = ""
|
1581
|
+
written = 0
|
1582
|
+
closed = 0
|
1583
|
+
@d.server_create_connection(:s, PORT, proto: proto, **kwargs) do |conn|
|
1584
|
+
conn.on(:write_complete){|_conn| written += 1 }
|
1585
|
+
conn.on(:close){|_conn| closed += 1 }
|
1586
|
+
conn.on(:data) do |d|
|
1587
|
+
buffer << d
|
1588
|
+
if idx = buffer.index("\n")
|
1589
|
+
lines << buffer.slice!(0, idx + 1)
|
1590
|
+
conn.write "foo!\n"
|
1591
|
+
end
|
1592
|
+
end
|
1593
|
+
end
|
1594
|
+
replied = []
|
1595
|
+
3.times do
|
1596
|
+
open_client(proto, "127.0.0.1", PORT) do |sock|
|
1597
|
+
sock.puts "yay"
|
1598
|
+
while line = sock.readline
|
1599
|
+
replied << line
|
1600
|
+
break
|
1601
|
+
end
|
1602
|
+
end # TCP socket is closed here
|
1603
|
+
end
|
1604
|
+
waiting(10){ sleep 0.1 until lines.size == 3 }
|
1605
|
+
waiting(10){ sleep 0.1 until replied.size == 3 }
|
1606
|
+
waiting(10){ sleep 0.1 until closed == 3 }
|
1607
|
+
assert_equal ["yay\n", "yay\n", "yay\n"], lines
|
1608
|
+
assert_equal 3, written
|
1609
|
+
assert_equal 3, closed
|
1610
|
+
assert_equal ["foo!\n", "foo!\n", "foo!\n"], replied
|
1611
|
+
end
|
1612
|
+
|
1613
|
+
data(protocols)
|
1614
|
+
test 'creates a server, and does not leak connections' do |(proto, kwargs)|
|
1615
|
+
buffer = ""
|
1616
|
+
closed = 0
|
1617
|
+
@d.server_create_connection(:s, PORT, proto: proto, **kwargs) do |conn|
|
1618
|
+
conn.on(:close){|_c| closed += 1 }
|
1619
|
+
conn.on(:data) do |d|
|
1620
|
+
buffer << d
|
1621
|
+
end
|
1622
|
+
end
|
1623
|
+
3.times do
|
1624
|
+
open_client(proto, "127.0.0.1", PORT) do |sock|
|
1625
|
+
sock.puts "yay"
|
1626
|
+
end
|
1627
|
+
end
|
1628
|
+
waiting(10){ sleep 0.1 until buffer.bytesize == 12 }
|
1629
|
+
waiting(10){ sleep 0.1 until closed == 3 }
|
1630
|
+
assert_equal 0, @d.instance_eval{ @_server_connections.size }
|
1631
|
+
end
|
1632
|
+
|
1633
|
+
data(protocols)
|
1634
|
+
test 'will refuse more connect requests after stop, but read data from sockets already connected, in non-shared server' do |(proto, kwargs)|
|
1635
|
+
connected = false
|
1636
|
+
begin
|
1637
|
+
open_client(proto, "127.0.0.1", PORT) do |sock|
|
1638
|
+
# expected behavior is connection refused...
|
1639
|
+
connected = true
|
1640
|
+
end
|
1641
|
+
rescue
|
1642
|
+
end
|
1643
|
+
|
1644
|
+
assert_false connected
|
1645
|
+
|
1646
|
+
received = ""
|
1647
|
+
@d.server_create_connection(:s, PORT, proto: proto, shared: false, **kwargs) do |conn|
|
1648
|
+
conn.on(:data) do |data|
|
1649
|
+
received << data
|
1650
|
+
conn.write "ack\n"
|
1651
|
+
end
|
1652
|
+
end
|
1653
|
+
|
1654
|
+
th0 = Thread.new do
|
1655
|
+
open_client(proto, "127.0.0.1", PORT) do |sock|
|
1656
|
+
sock.puts "yay"
|
1657
|
+
sock.readline
|
1658
|
+
end
|
1659
|
+
end
|
1660
|
+
|
1661
|
+
value0 = waiting(5){ th0.value }
|
1662
|
+
assert_equal "ack\n", value0
|
1663
|
+
|
1664
|
+
stopped = false
|
1665
|
+
sleeping = false
|
1666
|
+
ending = false
|
1667
|
+
|
1668
|
+
th1 = Thread.new do
|
1669
|
+
open_client(proto, "127.0.0.1", PORT) do |sock|
|
1670
|
+
sleeping = true
|
1671
|
+
sleep 0.1 until stopped
|
1672
|
+
sock.puts "yay"
|
1673
|
+
res = sock.readline
|
1674
|
+
ending = true
|
1675
|
+
res
|
1676
|
+
end
|
1677
|
+
end
|
1678
|
+
|
1679
|
+
sleep 0.1 until sleeping
|
1680
|
+
|
1681
|
+
@d.stop
|
1682
|
+
assert @d.stopped?
|
1683
|
+
stopped = true
|
1684
|
+
|
1685
|
+
sleep 0.1 until ending
|
1686
|
+
|
1687
|
+
@d.before_shutdown
|
1688
|
+
@d.shutdown
|
1689
|
+
|
1690
|
+
th2 = Thread.new do
|
1691
|
+
begin
|
1692
|
+
open_client(proto, "127.0.0.1", PORT) do |sock|
|
1693
|
+
sock.puts "foo"
|
1694
|
+
end
|
1695
|
+
false # failed
|
1696
|
+
rescue
|
1697
|
+
true # success
|
1698
|
+
end
|
1699
|
+
end
|
1700
|
+
|
1701
|
+
value1 = waiting(5){ th1.value }
|
1702
|
+
value2 = waiting(5){ th2.value }
|
1703
|
+
|
1704
|
+
assert_equal "yay\nyay\n", received
|
1705
|
+
assert_equal "ack\n", value1
|
1706
|
+
assert value2, "should be truthy value to show connection was correctly refused"
|
1707
|
+
end
|
1708
|
+
|
1709
|
+
test 'can keep connections alive for tcp/tls if keepalive specified' do
|
1710
|
+
# pend "not implemented yet"
|
1711
|
+
end
|
1712
|
+
end
|
1713
|
+
|
1714
|
+
end
|