protobuffy 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +21 -0
- data/.travis.yml +12 -0
- data/.yardopts +5 -0
- data/CHANGES.md +261 -0
- data/CONTRIBUTING.md +16 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +14 -0
- data/README.md +58 -0
- data/Rakefile +61 -0
- data/bin/protoc-gen-ruby +17 -0
- data/bin/rpc_server +4 -0
- data/examples/bin/reverse-client-http +4 -0
- data/examples/bin/reverse-client-socket +4 -0
- data/examples/bin/reverse-client-zmq +4 -0
- data/examples/config.ru +6 -0
- data/examples/definitions/example/reverse.proto +12 -0
- data/examples/lib/example/reverse-client.rb +23 -0
- data/examples/lib/example/reverse-service.rb +9 -0
- data/examples/lib/example/reverse.pb.rb +36 -0
- data/lib/protobuf.rb +106 -0
- data/lib/protobuf/cli.rb +249 -0
- data/lib/protobuf/code_generator.rb +41 -0
- data/lib/protobuf/decoder.rb +74 -0
- data/lib/protobuf/deprecator.rb +42 -0
- data/lib/protobuf/descriptors.rb +3 -0
- data/lib/protobuf/descriptors/google/protobuf/compiler/plugin.pb.rb +52 -0
- data/lib/protobuf/descriptors/google/protobuf/descriptor.pb.rb +249 -0
- data/lib/protobuf/encoder.rb +62 -0
- data/lib/protobuf/enum.rb +319 -0
- data/lib/protobuf/exceptions.rb +9 -0
- data/lib/protobuf/field.rb +74 -0
- data/lib/protobuf/field/base_field.rb +280 -0
- data/lib/protobuf/field/bool_field.rb +53 -0
- data/lib/protobuf/field/bytes_field.rb +81 -0
- data/lib/protobuf/field/double_field.rb +26 -0
- data/lib/protobuf/field/enum_field.rb +57 -0
- data/lib/protobuf/field/field_array.rb +86 -0
- data/lib/protobuf/field/fixed32_field.rb +25 -0
- data/lib/protobuf/field/fixed64_field.rb +29 -0
- data/lib/protobuf/field/float_field.rb +38 -0
- data/lib/protobuf/field/int32_field.rb +22 -0
- data/lib/protobuf/field/int64_field.rb +22 -0
- data/lib/protobuf/field/integer_field.rb +24 -0
- data/lib/protobuf/field/message_field.rb +66 -0
- data/lib/protobuf/field/sfixed32_field.rb +28 -0
- data/lib/protobuf/field/sfixed64_field.rb +29 -0
- data/lib/protobuf/field/signed_integer_field.rb +30 -0
- data/lib/protobuf/field/sint32_field.rb +22 -0
- data/lib/protobuf/field/sint64_field.rb +22 -0
- data/lib/protobuf/field/string_field.rb +35 -0
- data/lib/protobuf/field/uint32_field.rb +22 -0
- data/lib/protobuf/field/uint64_field.rb +22 -0
- data/lib/protobuf/field/varint_field.rb +68 -0
- data/lib/protobuf/generators/base.rb +71 -0
- data/lib/protobuf/generators/enum_generator.rb +42 -0
- data/lib/protobuf/generators/extension_generator.rb +28 -0
- data/lib/protobuf/generators/field_generator.rb +132 -0
- data/lib/protobuf/generators/file_generator.rb +140 -0
- data/lib/protobuf/generators/group_generator.rb +113 -0
- data/lib/protobuf/generators/message_generator.rb +99 -0
- data/lib/protobuf/generators/printable.rb +161 -0
- data/lib/protobuf/generators/service_generator.rb +27 -0
- data/lib/protobuf/http.rb +20 -0
- data/lib/protobuf/lifecycle.rb +46 -0
- data/lib/protobuf/logger.rb +86 -0
- data/lib/protobuf/message.rb +182 -0
- data/lib/protobuf/message/fields.rb +122 -0
- data/lib/protobuf/message/serialization.rb +84 -0
- data/lib/protobuf/optionable.rb +23 -0
- data/lib/protobuf/rpc/buffer.rb +79 -0
- data/lib/protobuf/rpc/client.rb +168 -0
- data/lib/protobuf/rpc/connector.rb +21 -0
- data/lib/protobuf/rpc/connectors/base.rb +54 -0
- data/lib/protobuf/rpc/connectors/common.rb +172 -0
- data/lib/protobuf/rpc/connectors/http.rb +90 -0
- data/lib/protobuf/rpc/connectors/socket.rb +73 -0
- data/lib/protobuf/rpc/connectors/zmq.rb +205 -0
- data/lib/protobuf/rpc/dynamic_discovery.pb.rb +47 -0
- data/lib/protobuf/rpc/env.rb +58 -0
- data/lib/protobuf/rpc/error.rb +28 -0
- data/lib/protobuf/rpc/error/client_error.rb +31 -0
- data/lib/protobuf/rpc/error/server_error.rb +43 -0
- data/lib/protobuf/rpc/middleware.rb +25 -0
- data/lib/protobuf/rpc/middleware/exception_handler.rb +36 -0
- data/lib/protobuf/rpc/middleware/logger.rb +91 -0
- data/lib/protobuf/rpc/middleware/request_decoder.rb +83 -0
- data/lib/protobuf/rpc/middleware/response_encoder.rb +88 -0
- data/lib/protobuf/rpc/middleware/runner.rb +18 -0
- data/lib/protobuf/rpc/rpc.pb.rb +53 -0
- data/lib/protobuf/rpc/server.rb +39 -0
- data/lib/protobuf/rpc/servers/http/server.rb +101 -0
- data/lib/protobuf/rpc/servers/http_runner.rb +34 -0
- data/lib/protobuf/rpc/servers/socket/server.rb +113 -0
- data/lib/protobuf/rpc/servers/socket/worker.rb +56 -0
- data/lib/protobuf/rpc/servers/socket_runner.rb +34 -0
- data/lib/protobuf/rpc/servers/zmq/broker.rb +155 -0
- data/lib/protobuf/rpc/servers/zmq/server.rb +313 -0
- data/lib/protobuf/rpc/servers/zmq/util.rb +47 -0
- data/lib/protobuf/rpc/servers/zmq/worker.rb +105 -0
- data/lib/protobuf/rpc/servers/zmq_runner.rb +51 -0
- data/lib/protobuf/rpc/service.rb +179 -0
- data/lib/protobuf/rpc/service_directory.rb +245 -0
- data/lib/protobuf/rpc/service_dispatcher.rb +46 -0
- data/lib/protobuf/rpc/service_filters.rb +273 -0
- data/lib/protobuf/rpc/stat.rb +148 -0
- data/lib/protobuf/socket.rb +22 -0
- data/lib/protobuf/tasks.rb +1 -0
- data/lib/protobuf/tasks/compile.rake +61 -0
- data/lib/protobuf/version.rb +3 -0
- data/lib/protobuf/wire_type.rb +10 -0
- data/lib/protobuf/zmq.rb +21 -0
- data/proto/dynamic_discovery.proto +44 -0
- data/proto/google/protobuf/compiler/plugin.proto +147 -0
- data/proto/google/protobuf/descriptor.proto +620 -0
- data/proto/rpc.proto +62 -0
- data/protobuffy.gemspec +37 -0
- data/spec/benchmark/tasks.rb +113 -0
- data/spec/bin/protoc-gen-ruby_spec.rb +18 -0
- data/spec/data/data.bin +3 -0
- data/spec/data/types.bin +0 -0
- data/spec/encoding/all_types_spec.rb +91 -0
- data/spec/encoding/extreme_values_spec.rb +0 -0
- data/spec/functional/socket_server_spec.rb +59 -0
- data/spec/functional/zmq_server_spec.rb +103 -0
- data/spec/lib/protobuf/cli_spec.rb +267 -0
- data/spec/lib/protobuf/code_generator_spec.rb +60 -0
- data/spec/lib/protobuf/enum_spec.rb +239 -0
- data/spec/lib/protobuf/field/int32_field_spec.rb +7 -0
- data/spec/lib/protobuf/field/string_field_spec.rb +46 -0
- data/spec/lib/protobuf/field_spec.rb +194 -0
- data/spec/lib/protobuf/generators/base_spec.rb +87 -0
- data/spec/lib/protobuf/generators/enum_generator_spec.rb +68 -0
- data/spec/lib/protobuf/generators/extension_generator_spec.rb +43 -0
- data/spec/lib/protobuf/generators/field_generator_spec.rb +99 -0
- data/spec/lib/protobuf/generators/file_generator_spec.rb +29 -0
- data/spec/lib/protobuf/generators/message_generator_spec.rb +0 -0
- data/spec/lib/protobuf/generators/service_generator_spec.rb +43 -0
- data/spec/lib/protobuf/lifecycle_spec.rb +89 -0
- data/spec/lib/protobuf/logger_spec.rb +136 -0
- data/spec/lib/protobuf/message_spec.rb +368 -0
- data/spec/lib/protobuf/optionable_spec.rb +46 -0
- data/spec/lib/protobuf/rpc/client_spec.rb +66 -0
- data/spec/lib/protobuf/rpc/connector_spec.rb +26 -0
- data/spec/lib/protobuf/rpc/connectors/base_spec.rb +50 -0
- data/spec/lib/protobuf/rpc/connectors/common_spec.rb +170 -0
- data/spec/lib/protobuf/rpc/connectors/connector_spec.rb +13 -0
- data/spec/lib/protobuf/rpc/connectors/http_spec.rb +61 -0
- data/spec/lib/protobuf/rpc/connectors/socket_spec.rb +24 -0
- data/spec/lib/protobuf/rpc/connectors/zmq_spec.rb +129 -0
- data/spec/lib/protobuf/rpc/middleware/exception_handler_spec.rb +62 -0
- data/spec/lib/protobuf/rpc/middleware/logger_spec.rb +49 -0
- data/spec/lib/protobuf/rpc/middleware/request_decoder_spec.rb +115 -0
- data/spec/lib/protobuf/rpc/middleware/response_encoder_spec.rb +75 -0
- data/spec/lib/protobuf/rpc/servers/http/server_spec.rb +104 -0
- data/spec/lib/protobuf/rpc/servers/socket_server_spec.rb +38 -0
- data/spec/lib/protobuf/rpc/servers/zmq/server_spec.rb +41 -0
- data/spec/lib/protobuf/rpc/servers/zmq/util_spec.rb +55 -0
- data/spec/lib/protobuf/rpc/servers/zmq/worker_spec.rb +35 -0
- data/spec/lib/protobuf/rpc/service_directory_spec.rb +295 -0
- data/spec/lib/protobuf/rpc/service_dispatcher_spec.rb +52 -0
- data/spec/lib/protobuf/rpc/service_filters_spec.rb +484 -0
- data/spec/lib/protobuf/rpc/service_spec.rb +161 -0
- data/spec/lib/protobuf/rpc/stat_spec.rb +151 -0
- data/spec/lib/protobuf_spec.rb +78 -0
- data/spec/spec_helper.rb +57 -0
- data/spec/support/all.rb +7 -0
- data/spec/support/packed_field.rb +22 -0
- data/spec/support/server.rb +94 -0
- data/spec/support/test/all_types.data.bin +0 -0
- data/spec/support/test/all_types.data.txt +119 -0
- data/spec/support/test/defaults.pb.rb +25 -0
- data/spec/support/test/defaults.proto +9 -0
- data/spec/support/test/enum.pb.rb +59 -0
- data/spec/support/test/enum.proto +34 -0
- data/spec/support/test/extended.pb.rb +22 -0
- data/spec/support/test/extended.proto +10 -0
- data/spec/support/test/extreme_values.data.bin +0 -0
- data/spec/support/test/google_unittest.pb.rb +543 -0
- data/spec/support/test/google_unittest.proto +713 -0
- data/spec/support/test/google_unittest_import.pb.rb +37 -0
- data/spec/support/test/google_unittest_import.proto +64 -0
- data/spec/support/test/google_unittest_import_public.pb.rb +8 -0
- data/spec/support/test/google_unittest_import_public.proto +38 -0
- data/spec/support/test/multi_field_extensions.pb.rb +56 -0
- data/spec/support/test/multi_field_extensions.proto +33 -0
- data/spec/support/test/resource.pb.rb +117 -0
- data/spec/support/test/resource.proto +94 -0
- data/spec/support/test/resource_service.rb +26 -0
- data/spec/support/test_app_file.rb +2 -0
- data/spec/support/tolerance_matcher.rb +40 -0
- metadata +367 -0
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'protobuf/generators/field_generator'
|
4
|
+
|
5
|
+
describe ::Protobuf::Generators::FieldGenerator do
|
6
|
+
|
7
|
+
let(:label_enum) { :LABEL_OPTIONAL }
|
8
|
+
let(:name) { 'foo_bar' }
|
9
|
+
let(:number) { 3 }
|
10
|
+
let(:type_enum) { :TYPE_STRING }
|
11
|
+
let(:type_name) { nil }
|
12
|
+
let(:default_value) { nil }
|
13
|
+
let(:extendee) { nil }
|
14
|
+
let(:field_options) { {} }
|
15
|
+
|
16
|
+
let(:field_fields) { { :label => label_enum,
|
17
|
+
:name => name,
|
18
|
+
:number => number,
|
19
|
+
:type => type_enum,
|
20
|
+
:type_name => type_name,
|
21
|
+
:default_value => default_value,
|
22
|
+
:extendee => extendee,
|
23
|
+
:options => field_options } }
|
24
|
+
|
25
|
+
let(:field) { ::Google::Protobuf::FieldDescriptorProto.new(field_fields) }
|
26
|
+
|
27
|
+
describe '#compile' do
|
28
|
+
subject { described_class.new(field).to_s }
|
29
|
+
|
30
|
+
it { should eq "optional :string, :foo_bar, 3\n" }
|
31
|
+
|
32
|
+
context 'when the type is another message' do
|
33
|
+
let(:type_enum) { :TYPE_MESSAGE }
|
34
|
+
let(:type_name) { '.foo.bar.Baz' }
|
35
|
+
|
36
|
+
it { should eq "optional ::Foo::Bar::Baz, :foo_bar, 3\n" }
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'when a default value is used' do
|
40
|
+
let(:type_enum) { :TYPE_INT32 }
|
41
|
+
let(:default_value) { '42' }
|
42
|
+
it { should eq "optional :int32, :foo_bar, 3, :default => 42\n" }
|
43
|
+
|
44
|
+
context 'when type is an enum' do
|
45
|
+
let(:type_enum) { :TYPE_ENUM }
|
46
|
+
let(:type_name) { '.foo.bar.Baz' }
|
47
|
+
let(:default_value) { 'QUUX' }
|
48
|
+
|
49
|
+
it { should eq "optional ::Foo::Bar::Baz, :foo_bar, 3, :default => ::Foo::Bar::Baz::QUUX\n" }
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'when the type is a string' do
|
53
|
+
let(:type_enum) { :TYPE_STRING }
|
54
|
+
let(:default_value) { "a default \"string\"" }
|
55
|
+
|
56
|
+
it { should eq %Q{optional :string, :foo_bar, 3, :default => "a default \"string\""\n} }
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'when float or double field type' do
|
60
|
+
let(:type_enum) { :TYPE_DOUBLE }
|
61
|
+
|
62
|
+
context 'when the default value is "nan"' do
|
63
|
+
let(:default_value) { 'nan' }
|
64
|
+
it { should match(/::Float::NAN/) }
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'when the default value is "inf"' do
|
68
|
+
let(:default_value) { 'inf' }
|
69
|
+
it { should match(/::Float::INFINITY/) }
|
70
|
+
end
|
71
|
+
|
72
|
+
context 'when the default value is "-inf"' do
|
73
|
+
let(:default_value) { '-inf' }
|
74
|
+
it { should match(/-::Float::INFINITY/) }
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'when the field is an extension' do
|
80
|
+
let(:extendee) { 'foo.bar.Baz' }
|
81
|
+
|
82
|
+
it { should eq "optional :string, :foo_bar, 3, :extension => true\n" }
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'when field is packed' do
|
86
|
+
let(:field_options) { { :packed => true } }
|
87
|
+
|
88
|
+
it { should eq "optional :string, :foo_bar, 3, :packed => true\n" }
|
89
|
+
end
|
90
|
+
|
91
|
+
context 'when field is deprecated' do
|
92
|
+
let(:field_options) { { :deprecated => true } }
|
93
|
+
|
94
|
+
it { should eq "optional :string, :foo_bar, 3, :deprecated => true\n" }
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'protobuf/generators/file_generator'
|
4
|
+
|
5
|
+
describe ::Protobuf::Generators::FileGenerator do
|
6
|
+
|
7
|
+
let(:base_descriptor_fields) { { :name => 'test/foo.proto' } }
|
8
|
+
let(:descriptor_fields) { base_descriptor_fields }
|
9
|
+
let(:file_descriptor) { ::Google::Protobuf::FileDescriptorProto.new(descriptor_fields) }
|
10
|
+
|
11
|
+
subject { described_class.new(file_descriptor) }
|
12
|
+
its(:file_name) { should eq 'test/foo.pb.rb' }
|
13
|
+
|
14
|
+
describe '#print_import_requires' do
|
15
|
+
let(:descriptor_fields) do
|
16
|
+
base_descriptor_fields.merge!({ :dependency => [ 'test/bar.proto',
|
17
|
+
'test/baz.proto' ] })
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'prints a ruby require for each dependency' do
|
21
|
+
subject.should_receive(:print_require).with('test/bar.pb')
|
22
|
+
subject.should_receive(:print_require).with('test/baz.pb')
|
23
|
+
subject.print_import_requires
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
File without changes
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'protobuf/generators/service_generator'
|
4
|
+
|
5
|
+
describe ::Protobuf::Generators::ServiceGenerator do
|
6
|
+
|
7
|
+
let(:methods) {
|
8
|
+
[
|
9
|
+
{ :name => 'Search', :input_type => 'FooRequest', :output_type => 'FooResponse' },
|
10
|
+
{ :name => 'FooBar', :input_type => '.foo.Request', :output_type => '.bar.Response' }
|
11
|
+
]
|
12
|
+
}
|
13
|
+
let(:service_fields) { { :name => 'TestService',
|
14
|
+
:method => methods } }
|
15
|
+
|
16
|
+
let(:service) { ::Google::Protobuf::ServiceDescriptorProto.new(service_fields) }
|
17
|
+
|
18
|
+
subject { described_class.new(service) }
|
19
|
+
|
20
|
+
describe '#compile' do
|
21
|
+
let(:compiled) {
|
22
|
+
%q{class TestService < ::Protobuf::Rpc::Service
|
23
|
+
rpc :search, FooRequest, FooResponse
|
24
|
+
rpc :foo_bar, ::Foo::Request, ::Bar::Response
|
25
|
+
end
|
26
|
+
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
it 'compiles the service and it\'s rpc methods' do
|
31
|
+
subject.compile
|
32
|
+
subject.to_s.should eq(compiled)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '#build_method' do
|
37
|
+
it 'returns a string identifying the given method descriptor' do
|
38
|
+
subject.build_method(service.method.first).should eq("rpc :search, FooRequest, FooResponse")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'protobuf/lifecycle'
|
3
|
+
|
4
|
+
describe ::Protobuf::Lifecycle do
|
5
|
+
subject { described_class }
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
::ActiveSupport::Notifications.notifier = ::ActiveSupport::Notifications::Fanout.new
|
9
|
+
end
|
10
|
+
|
11
|
+
it "registers a string as the event_name" do
|
12
|
+
::ActiveSupport::Notifications.should_receive(:subscribe).with("something")
|
13
|
+
subject.register("something") { true }
|
14
|
+
end
|
15
|
+
|
16
|
+
it "only registers blocks for event callbacks" do
|
17
|
+
expect {
|
18
|
+
subject.register("something")
|
19
|
+
}.to raise_error( /block/ )
|
20
|
+
end
|
21
|
+
|
22
|
+
it "calls the registered block when triggered" do
|
23
|
+
this = nil
|
24
|
+
subject.register("this") do
|
25
|
+
this = "not nil"
|
26
|
+
end
|
27
|
+
|
28
|
+
subject.trigger("this")
|
29
|
+
this.should_not be_nil
|
30
|
+
this.should eq("not nil")
|
31
|
+
end
|
32
|
+
|
33
|
+
it "calls multiple registered blocks when triggered" do
|
34
|
+
this = nil
|
35
|
+
that = nil
|
36
|
+
|
37
|
+
subject.register("this") do
|
38
|
+
this = "not nil"
|
39
|
+
end
|
40
|
+
|
41
|
+
subject.register("this") do
|
42
|
+
that = "not nil"
|
43
|
+
end
|
44
|
+
|
45
|
+
subject.trigger("this")
|
46
|
+
this.should_not be_nil
|
47
|
+
this.should eq("not nil")
|
48
|
+
that.should_not be_nil
|
49
|
+
that.should eq("not nil")
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'when the registered block has arity' do
|
53
|
+
context 'and the triggered event does not have args' do
|
54
|
+
it 'does not pass the args' do
|
55
|
+
outer_bar = nil
|
56
|
+
|
57
|
+
subject.register('foo') do |bar|
|
58
|
+
bar.should be_nil
|
59
|
+
outer_bar = 'triggered'
|
60
|
+
end
|
61
|
+
|
62
|
+
subject.trigger('foo')
|
63
|
+
outer_bar.should eq 'triggered'
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'and the triggered event has arguments' do
|
68
|
+
it 'does not pass the args' do
|
69
|
+
outer_bar = nil
|
70
|
+
|
71
|
+
subject.register('foo') do |bar|
|
72
|
+
bar.should_not be_nil
|
73
|
+
outer_bar = bar
|
74
|
+
end
|
75
|
+
|
76
|
+
subject.trigger('foo', 'baz')
|
77
|
+
outer_bar.should eq 'baz'
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context "normalized event names" do
|
83
|
+
specify { subject.normalized_event_name(:derp).should eq("derp") }
|
84
|
+
specify { subject.normalized_event_name(:Derp).should eq("derp") }
|
85
|
+
specify { subject.normalized_event_name("DERP").should eq("derp") }
|
86
|
+
specify { subject.normalized_event_name("derp").should eq("derp") }
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
require 'protobuf/logger'
|
2
|
+
require 'stringio'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
describe Protobuf::Logger do
|
6
|
+
|
7
|
+
subject { Protobuf::Logger }
|
8
|
+
|
9
|
+
before(:each) do
|
10
|
+
Protobuf::Logger.reset_device!
|
11
|
+
Protobuf::Logger.file = '/dev/null'
|
12
|
+
Protobuf::Logger.level = ::Logger::INFO
|
13
|
+
end
|
14
|
+
|
15
|
+
after(:all) do
|
16
|
+
::FileUtils.rm_f('myfile.log')
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '.instance' do
|
20
|
+
|
21
|
+
it 'doesn\'t create a logger if the file was not set' do
|
22
|
+
subject.file = nil
|
23
|
+
subject.instance.should be_nil
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'doesn\'t create a logger if the level was not set' do
|
27
|
+
subject.level = nil
|
28
|
+
subject.instance.should be_nil
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'gets a new instance of the logger when file and level are set' do
|
32
|
+
subject.file.should_not be_nil
|
33
|
+
subject.level.should_not be_nil
|
34
|
+
subject.instance.should_not be_nil
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'keeps the same object from multiple calls to instance' do
|
38
|
+
subject.instance === subject.instance
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '.configure' do
|
44
|
+
before(:each) { subject.reset_device! }
|
45
|
+
it 'sets the file and level in one call' do
|
46
|
+
subject.file.should_not be
|
47
|
+
subject.level.should_not be
|
48
|
+
subject.instance.should_not be
|
49
|
+
subject.configure :file => 'myfile.log', :level => ::Logger::WARN
|
50
|
+
subject.file.should == 'myfile.log'
|
51
|
+
subject.level.should == ::Logger::WARN
|
52
|
+
subject.instance.level.should == ::Logger::WARN
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
describe '.reset_device!' do
|
58
|
+
|
59
|
+
it 'resets the logger instance, file, and level' do
|
60
|
+
subject.instance.should be
|
61
|
+
subject.file.should be
|
62
|
+
subject.level.should be
|
63
|
+
subject.reset_device!
|
64
|
+
subject.instance.should_not be
|
65
|
+
subject.file.should_not be
|
66
|
+
subject.level.should_not be
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'when logging' do
|
72
|
+
|
73
|
+
it 'doesn\'t raise errors when log instance is nil' do
|
74
|
+
subject.reset_device!
|
75
|
+
subject.instance.should be_nil
|
76
|
+
expect {
|
77
|
+
subject.debug 'No errors here'
|
78
|
+
subject.info 'No errors here'
|
79
|
+
subject.warn 'No errors here'
|
80
|
+
subject.error 'No errors here'
|
81
|
+
subject.fatal 'No errors here'
|
82
|
+
subject.add 'No errors here'
|
83
|
+
subject.log 'No errors here'
|
84
|
+
}.to_not raise_error
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'logs correctly when instance is valid' do
|
88
|
+
subject.instance.should_not be_nil
|
89
|
+
subject.instance.should_receive(:info).with('Should log great')
|
90
|
+
subject.info 'Should log great'
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
describe Protobuf::Logger::LogMethods do
|
96
|
+
|
97
|
+
context 'when included in another class' do
|
98
|
+
|
99
|
+
before(:all) do
|
100
|
+
class MyTestClass
|
101
|
+
include Protobuf::Logger::LogMethods
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
subject { MyTestClass.new }
|
106
|
+
|
107
|
+
it { should respond_to(:log_debug) }
|
108
|
+
it { should respond_to(:log_info) }
|
109
|
+
it { should respond_to(:log_warn) }
|
110
|
+
it { should respond_to(:log_error) }
|
111
|
+
it { should respond_to(:log_fatal) }
|
112
|
+
it { should respond_to(:log_add) }
|
113
|
+
it { should respond_to(:log_log) }
|
114
|
+
|
115
|
+
context '#log_exception' do
|
116
|
+
it 'logs the exception message as an error and backtrace as debug' do
|
117
|
+
subject.should_receive(:log_error).twice
|
118
|
+
subject.should_receive(:log_debug)
|
119
|
+
subject.log_exception(RuntimeError.new('this is an exception'))
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
its(:log_signature) { should eq "[MyTestClass]" }
|
124
|
+
describe '#sign_message' do
|
125
|
+
specify { subject.sign_message("this is a test").should eq "[MyTestClass] this is a test" }
|
126
|
+
specify { subject.class.sign_message("this is a test").should eq "[MyTestClass] this is a test" }
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'passes all embedded log calls to Logger instance' do
|
130
|
+
Protobuf::Logger.instance.should_receive(:debug).with('[MyTestClass] log this')
|
131
|
+
subject.log_debug('log this')
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,368 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Protobuf::Message do
|
4
|
+
|
5
|
+
describe '.decode' do
|
6
|
+
let(:message) { ::Test::Resource.new(:name => "Jim") }
|
7
|
+
|
8
|
+
it 'creates a new message object decoded from the given bytes' do
|
9
|
+
::Test::Resource.decode(message.encode).should eq message
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe 'defining a new field' do
|
14
|
+
context 'when defining a field with a tag that has already been used' do
|
15
|
+
it 'raises a TagCollisionError' do
|
16
|
+
expect {
|
17
|
+
Class.new(Protobuf::Message) do
|
18
|
+
optional ::Protobuf::Field::Int32Field, :foo, 1
|
19
|
+
optional ::Protobuf::Field::Int32Field, :bar, 1
|
20
|
+
end
|
21
|
+
}.to raise_error(Protobuf::TagCollisionError, /Field number 1 has already been used/)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'when defining an extension field with a tag that has already been used' do
|
26
|
+
it 'raises a TagCollisionError' do
|
27
|
+
expect {
|
28
|
+
Class.new(Protobuf::Message) do
|
29
|
+
extensions 100...110
|
30
|
+
optional ::Protobuf::Field::Int32Field, :foo, 100
|
31
|
+
optional ::Protobuf::Field::Int32Field, :bar, 100, :extension => true
|
32
|
+
end
|
33
|
+
}.to raise_error(Protobuf::TagCollisionError, /Field number 100 has already been used/)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'when defining a field with a name that has already been used' do
|
38
|
+
it 'raises a DuplicateFieldNameError' do
|
39
|
+
expect {
|
40
|
+
Class.new(Protobuf::Message) do
|
41
|
+
optional ::Protobuf::Field::Int32Field, :foo, 1
|
42
|
+
optional ::Protobuf::Field::Int32Field, :foo, 2
|
43
|
+
end
|
44
|
+
}.to raise_error(Protobuf::DuplicateFieldNameError, /Field name foo has already been used/)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'when defining an extension field with a name that has already been used' do
|
49
|
+
it 'raises a DuplicateFieldNameError' do
|
50
|
+
expect {
|
51
|
+
Class.new(Protobuf::Message) do
|
52
|
+
extensions 100...110
|
53
|
+
optional ::Protobuf::Field::Int32Field, :foo, 1
|
54
|
+
optional ::Protobuf::Field::Int32Field, :foo, 100, :extension => true
|
55
|
+
end
|
56
|
+
}.to raise_error(Protobuf::DuplicateFieldNameError, /Field name foo has already been used/)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe '.encode' do
|
62
|
+
let(:values) { { :name => "Jim" } }
|
63
|
+
|
64
|
+
it 'creates a new message object with the given values and returns the encoded bytes' do
|
65
|
+
::Test::Resource.encode(values).should eq ::Test::Resource.new(values).encode
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe '#initialize' do
|
70
|
+
it "initializes the enum getter to 0" do
|
71
|
+
test_enum = Test::EnumTestMessage.new
|
72
|
+
test_enum.non_default_enum.should eq(0)
|
73
|
+
end
|
74
|
+
|
75
|
+
it "exposes the enum getter raw value through ! method" do
|
76
|
+
test_enum = Test::EnumTestMessage.new
|
77
|
+
test_enum.non_default_enum!.should be_nil
|
78
|
+
end
|
79
|
+
|
80
|
+
it "exposes the enum getter raw value through ! method (when set)" do
|
81
|
+
test_enum = Test::EnumTestMessage.new
|
82
|
+
test_enum.non_default_enum = 1
|
83
|
+
test_enum.non_default_enum!.should eq(1)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "does not try to set attributes which have nil values" do
|
87
|
+
Test::EnumTestMessage.any_instance.should_not_receive("non_default_enum=")
|
88
|
+
Test::EnumTestMessage.new(:non_default_enum => nil)
|
89
|
+
end
|
90
|
+
|
91
|
+
it "takes a hash as an initialization argument" do
|
92
|
+
test_enum = Test::EnumTestMessage.new(:non_default_enum => 2)
|
93
|
+
test_enum.non_default_enum.should eq(2)
|
94
|
+
end
|
95
|
+
|
96
|
+
it "initializes with an object that responds to #to_hash" do
|
97
|
+
hashie_object = OpenStruct.new(:to_hash => { :non_default_enum => 2 })
|
98
|
+
test_enum = Test::EnumTestMessage.new(hashie_object)
|
99
|
+
test_enum.non_default_enum.should eq(2)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe '#encode' do
|
104
|
+
context "encoding" do
|
105
|
+
it "accepts UTF-8 strings into string fields" do
|
106
|
+
message = ::Test::Resource.new(:name => "Kyle Redfearn\u0060s iPad")
|
107
|
+
|
108
|
+
expect { message.encode }.to_not raise_error
|
109
|
+
end
|
110
|
+
|
111
|
+
it "keeps utf-8 when utf-8 is input for string fields" do
|
112
|
+
name = "my name\xC3"
|
113
|
+
name.force_encoding("UTF-8")
|
114
|
+
|
115
|
+
message = ::Test::Resource.new(:name => name)
|
116
|
+
new_message = ::Test::Resource.decode(message.encode)
|
117
|
+
(new_message.name == name).should be_true
|
118
|
+
end
|
119
|
+
|
120
|
+
it "trims binary when binary is input for string fields" do
|
121
|
+
name = "my name\xC3"
|
122
|
+
name.force_encoding("ASCII-8BIT")
|
123
|
+
|
124
|
+
message = ::Test::Resource.new(:name => name)
|
125
|
+
new_message = ::Test::Resource.decode(message.encode)
|
126
|
+
(new_message.name == "my name").should be_true
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
context "when there's no value for a required field" do
|
131
|
+
let(:message) { ::Test::ResourceWithRequiredField.new }
|
132
|
+
|
133
|
+
it "raises a 'message not initialized' error" do
|
134
|
+
expect {
|
135
|
+
message.encode
|
136
|
+
}.to raise_error(Protobuf::SerializationError, /required/i)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
context "repeated fields" do
|
141
|
+
let(:message) { ::Test::Resource.new(:name => "something") }
|
142
|
+
|
143
|
+
it "does not raise an error when repeated fields are []" do
|
144
|
+
expect {
|
145
|
+
message.repeated_enum = []
|
146
|
+
message.encode
|
147
|
+
}.to_not raise_error
|
148
|
+
end
|
149
|
+
|
150
|
+
it "sets the value to nil when empty array is passed" do
|
151
|
+
message.repeated_enum = []
|
152
|
+
message.instance_variable_get("@values")[:repeated_enum].should be_nil
|
153
|
+
end
|
154
|
+
|
155
|
+
it "does not compact the edit original array" do
|
156
|
+
a = [nil].freeze
|
157
|
+
message.repeated_enum = a
|
158
|
+
message.repeated_enum.should eq([])
|
159
|
+
a.should eq([nil].freeze)
|
160
|
+
end
|
161
|
+
|
162
|
+
it "compacts the set array" do
|
163
|
+
message.repeated_enum = [nil]
|
164
|
+
message.repeated_enum.should eq([])
|
165
|
+
end
|
166
|
+
|
167
|
+
it "raises TypeError when a non-array replaces it" do
|
168
|
+
expect {
|
169
|
+
message.repeated_enum = 2
|
170
|
+
}.to raise_error(/value of type/)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
describe "boolean predicate methods" do
|
176
|
+
subject { Test::ResourceFindRequest.new(:name => "resource") }
|
177
|
+
|
178
|
+
it { should respond_to(:active?) }
|
179
|
+
|
180
|
+
it "sets the predicate to true when the boolean value is true" do
|
181
|
+
subject.active = true
|
182
|
+
subject.active?.should be_true
|
183
|
+
end
|
184
|
+
|
185
|
+
it "sets the predicate to false when the boolean value is false" do
|
186
|
+
subject.active = false
|
187
|
+
subject.active?.should be_false
|
188
|
+
end
|
189
|
+
|
190
|
+
it "does not put predicate methods on non-boolean fields" do
|
191
|
+
Test::ResourceFindRequest.new(:name => "resource").should_not respond_to(:name?)
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
describe "#respond_to_and_has?" do
|
196
|
+
subject { Test::EnumTestMessage.new(:non_default_enum => 2) }
|
197
|
+
|
198
|
+
it "is false when the message does not have the field" do
|
199
|
+
subject.respond_to_and_has?(:other_field).should be_false
|
200
|
+
end
|
201
|
+
|
202
|
+
it "is true when the message has the field" do
|
203
|
+
subject.respond_to_and_has?(:non_default_enum).should be_true
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
describe "#respond_to_has_and_present?" do
|
208
|
+
subject { Test::EnumTestMessage.new(:non_default_enum => 2) }
|
209
|
+
|
210
|
+
it "is false when the message does not have the field" do
|
211
|
+
subject.respond_to_and_has_and_present?(:other_field).should be_false
|
212
|
+
end
|
213
|
+
|
214
|
+
it "is false when the field is repeated and a value is not present" do
|
215
|
+
subject.respond_to_and_has_and_present?(:repeated_enums).should be_false
|
216
|
+
end
|
217
|
+
|
218
|
+
it "is false when the field is repeated and the value is empty array" do
|
219
|
+
subject.repeated_enums = []
|
220
|
+
subject.respond_to_and_has_and_present?(:repeated_enums).should be_false
|
221
|
+
end
|
222
|
+
|
223
|
+
it "is true when the field is repeated and a value is present" do
|
224
|
+
subject.repeated_enums = [2]
|
225
|
+
subject.respond_to_and_has_and_present?(:repeated_enums).should be_true
|
226
|
+
end
|
227
|
+
|
228
|
+
it "is true when the message has the field" do
|
229
|
+
subject.respond_to_and_has_and_present?(:non_default_enum).should be_true
|
230
|
+
end
|
231
|
+
|
232
|
+
context "#API" do
|
233
|
+
subject { Test::EnumTestMessage.new(:non_default_enum => 2) }
|
234
|
+
|
235
|
+
it { should respond_to(:respond_to_and_has_and_present?) }
|
236
|
+
it { should respond_to(:responds_to_and_has_and_present?) }
|
237
|
+
it { should respond_to(:responds_to_has?) }
|
238
|
+
it { should respond_to(:respond_to_has?) }
|
239
|
+
it { should respond_to(:respond_to_has_present?) }
|
240
|
+
it { should respond_to(:responds_to_has_present?) }
|
241
|
+
it { should respond_to(:respond_to_and_has_present?) }
|
242
|
+
it { should respond_to(:responds_to_and_has_present?) }
|
243
|
+
end
|
244
|
+
|
245
|
+
end
|
246
|
+
|
247
|
+
describe '#to_hash' do
|
248
|
+
context 'generating values for an ENUM field' do
|
249
|
+
it 'converts the enum to its tag representation' do
|
250
|
+
hash = Test::EnumTestMessage.new(:non_default_enum => :TWO).to_hash
|
251
|
+
hash.should eq({ :non_default_enum => 2 })
|
252
|
+
end
|
253
|
+
|
254
|
+
it 'does not populate default values' do
|
255
|
+
hash = Test::EnumTestMessage.new.to_hash
|
256
|
+
hash.should eq(Hash.new)
|
257
|
+
end
|
258
|
+
|
259
|
+
it 'converts repeated enum fields to an array of the tags' do
|
260
|
+
hash = Test::EnumTestMessage.new(:repeated_enums => [ :ONE, :TWO, :TWO, :ONE ]).to_hash
|
261
|
+
hash.should eq({ :repeated_enums => [ 1, 2, 2, 1 ] })
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
context 'generating values for a Message field' do
|
266
|
+
it 'recursively hashes field messages' do
|
267
|
+
hash = Test::Nested.new({ :resource => { :name => 'Nested' } }).to_hash
|
268
|
+
hash.should eq({ :resource => { :name => 'Nested' } })
|
269
|
+
end
|
270
|
+
|
271
|
+
it 'recursively hashes a repeated set of messages' do
|
272
|
+
proto = Test::Nested.new(:multiple_resources => [
|
273
|
+
Test::Resource.new(:name => 'Resource 1'),
|
274
|
+
Test::Resource.new(:name => 'Resource 2')
|
275
|
+
])
|
276
|
+
|
277
|
+
proto.to_hash.should eq({ :multiple_resources => [ { :name => 'Resource 1' },
|
278
|
+
{ :name => 'Resource 2' } ] })
|
279
|
+
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
describe '#to_json' do
|
285
|
+
subject do
|
286
|
+
::Test::ResourceFindRequest.new({ :name => 'Test Name', :active => false })
|
287
|
+
end
|
288
|
+
|
289
|
+
its(:to_json) { should eq '{"name":"Test Name","active":false}' }
|
290
|
+
end
|
291
|
+
|
292
|
+
describe '.to_json' do
|
293
|
+
it 'returns the class name of the message for use in json encoding' do
|
294
|
+
expect {
|
295
|
+
::Timeout.timeout(0.1) do
|
296
|
+
expect(::Test::Resource.to_json).to eq("Test::Resource")
|
297
|
+
end
|
298
|
+
}.not_to raise_error
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
describe "#define_setter" do
|
303
|
+
subject { ::Test::Resource.new }
|
304
|
+
|
305
|
+
it "allows string fields to be set to nil" do
|
306
|
+
expect { subject.name = nil }.to_not raise_error
|
307
|
+
end
|
308
|
+
|
309
|
+
it "does not allow string fields to be set to Numeric" do
|
310
|
+
expect { subject.name = 1}.to raise_error(/name/)
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
describe '.get_extension_field' do
|
315
|
+
it 'fetches an extension field by its tag' do
|
316
|
+
field = ::Test::Resource.get_extension_field(100)
|
317
|
+
expect(field).to be_a(::Protobuf::Field::BoolField)
|
318
|
+
expect(field.tag).to eq(100)
|
319
|
+
expect(field.name).to eq(:ext_is_searchable)
|
320
|
+
expect(field).to be_extension
|
321
|
+
end
|
322
|
+
|
323
|
+
it 'fetches an extension field by its symbolized name' do
|
324
|
+
expect(::Test::Resource.get_extension_field(:ext_is_searchable)).to be_a(::Protobuf::Field::BoolField)
|
325
|
+
expect(::Test::Resource.get_extension_field('ext_is_searchable')).to be_a(::Protobuf::Field::BoolField)
|
326
|
+
end
|
327
|
+
|
328
|
+
it 'returns nil when attempting to get a non-extension field' do
|
329
|
+
expect(::Test::Resource.get_extension_field(1)).to be_nil
|
330
|
+
end
|
331
|
+
|
332
|
+
it 'returns nil when field is not found' do
|
333
|
+
::Test::Resource.get_extension_field(-1).should be_nil
|
334
|
+
::Test::Resource.get_extension_field(nil).should be_nil
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
describe '.get_field' do
|
339
|
+
it 'fetches a non-extension field by its tag' do
|
340
|
+
field = ::Test::Resource.get_field(1)
|
341
|
+
expect(field).to be_a(::Protobuf::Field::StringField)
|
342
|
+
expect(field.tag).to eq(1)
|
343
|
+
expect(field.name).to eq(:name)
|
344
|
+
expect(field).not_to be_extension
|
345
|
+
end
|
346
|
+
|
347
|
+
it 'fetches a non-extension field by its symbolized name' do
|
348
|
+
expect(::Test::Resource.get_field(:name)).to be_a(::Protobuf::Field::StringField)
|
349
|
+
expect(::Test::Resource.get_field('name')).to be_a(::Protobuf::Field::StringField)
|
350
|
+
end
|
351
|
+
|
352
|
+
it 'fetches an extension field when forced' do
|
353
|
+
expect(::Test::Resource.get_field(100, true)).to be_a(::Protobuf::Field::BoolField)
|
354
|
+
expect(::Test::Resource.get_field(:ext_is_searchable, true)).to be_a(::Protobuf::Field::BoolField)
|
355
|
+
expect(::Test::Resource.get_field('ext_is_searchable', true)).to be_a(::Protobuf::Field::BoolField)
|
356
|
+
end
|
357
|
+
|
358
|
+
it 'returns nil when attempting to get an extension field' do
|
359
|
+
expect(::Test::Resource.get_field(100)).to be_nil
|
360
|
+
end
|
361
|
+
|
362
|
+
it 'returns nil when field is not defined' do
|
363
|
+
::Test::Resource.get_field(-1).should be_nil
|
364
|
+
::Test::Resource.get_field(nil).should be_nil
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
end
|