protobuffy 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|