OLD | NEW |
(Empty) | |
| 1 # Copyright 2015-2016, Google Inc. |
| 2 # All rights reserved. |
| 3 # |
| 4 # Redistribution and use in source and binary forms, with or without |
| 5 # modification, are permitted provided that the following conditions are |
| 6 # met: |
| 7 # |
| 8 # * Redistributions of source code must retain the above copyright |
| 9 # notice, this list of conditions and the following disclaimer. |
| 10 # * Redistributions in binary form must reproduce the above |
| 11 # copyright notice, this list of conditions and the following disclaimer |
| 12 # in the documentation and/or other materials provided with the |
| 13 # distribution. |
| 14 # * Neither the name of Google Inc. nor the names of its |
| 15 # contributors may be used to endorse or promote products derived from |
| 16 # this software without specific prior written permission. |
| 17 # |
| 18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 19 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 20 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 21 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 22 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 23 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 24 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 |
| 30 require 'grpc' |
| 31 require 'grpc/health/v1/health' |
| 32 require 'grpc/health/checker' |
| 33 require 'open3' |
| 34 require 'tmpdir' |
| 35 |
| 36 def can_run_codegen_check |
| 37 system('which grpc_ruby_plugin') && system('which protoc') |
| 38 end |
| 39 |
| 40 describe 'Health protobuf code generation' do |
| 41 context 'the health service file used by grpc/health/checker' do |
| 42 if !can_run_codegen_check |
| 43 skip 'protoc || grpc_ruby_plugin missing, cannot verify health code-gen' |
| 44 else |
| 45 it 'should already be loaded indirectly i.e, used by the other specs' do |
| 46 expect(require('grpc/health/v1/health_services')).to be(false) |
| 47 end |
| 48 |
| 49 it 'should have the same content as created by code generation' do |
| 50 root_dir = File.join(File.dirname(__FILE__), '..', '..', '..', '..') |
| 51 pb_dir = File.join(root_dir, 'proto') |
| 52 |
| 53 # Get the current content |
| 54 service_path = File.join(root_dir, 'ruby', 'pb', 'grpc', |
| 55 'health', 'v1', 'health_services.rb') |
| 56 want = nil |
| 57 File.open(service_path) { |f| want = f.read } |
| 58 |
| 59 # Regenerate it |
| 60 plugin, = Open3.capture2('which', 'grpc_ruby_plugin') |
| 61 plugin = plugin.strip |
| 62 got = nil |
| 63 Dir.mktmpdir do |tmp_dir| |
| 64 gen_out = File.join(tmp_dir, 'grpc', 'health', 'v1', |
| 65 'health_services.rb') |
| 66 pid = spawn( |
| 67 'protoc', |
| 68 '-I.', |
| 69 'grpc/health/v1/health.proto', |
| 70 "--grpc_out=#{tmp_dir}", |
| 71 "--plugin=protoc-gen-grpc=#{plugin}", |
| 72 chdir: pb_dir) |
| 73 Process.wait(pid) |
| 74 File.open(gen_out) { |f| got = f.read } |
| 75 end |
| 76 expect(got).to eq(want) |
| 77 end |
| 78 end |
| 79 end |
| 80 end |
| 81 |
| 82 describe Grpc::Health::Checker do |
| 83 StatusCodes = GRPC::Core::StatusCodes |
| 84 ServingStatus = Grpc::Health::V1::HealthCheckResponse::ServingStatus |
| 85 HCResp = Grpc::Health::V1::HealthCheckResponse |
| 86 HCReq = Grpc::Health::V1::HealthCheckRequest |
| 87 success_tests = |
| 88 [ |
| 89 { |
| 90 desc: 'the service is not specified', |
| 91 service: '' |
| 92 }, { |
| 93 desc: 'the service is specified', |
| 94 service: 'fake-service-1' |
| 95 } |
| 96 ] |
| 97 |
| 98 context 'initialization' do |
| 99 it 'can be constructed with no args' do |
| 100 expect(subject).to_not be(nil) |
| 101 end |
| 102 end |
| 103 |
| 104 context 'method `add_status` and `check`' do |
| 105 success_tests.each do |t| |
| 106 it "should succeed when #{t[:desc]}" do |
| 107 subject.add_status(t[:service], ServingStatus::NOT_SERVING) |
| 108 got = subject.check(HCReq.new(service: t[:service]), nil) |
| 109 want = HCResp.new(status: ServingStatus::NOT_SERVING) |
| 110 expect(got).to eq(want) |
| 111 end |
| 112 end |
| 113 end |
| 114 |
| 115 context 'method `check`' do |
| 116 success_tests.each do |t| |
| 117 it "should fail with NOT_FOUND when #{t[:desc]}" do |
| 118 blk = proc do |
| 119 subject.check(HCReq.new(service: t[:service]), nil) |
| 120 end |
| 121 expected_msg = /#{StatusCodes::NOT_FOUND}/ |
| 122 expect(&blk).to raise_error GRPC::BadStatus, expected_msg |
| 123 end |
| 124 end |
| 125 end |
| 126 |
| 127 context 'method `clear_status`' do |
| 128 success_tests.each do |t| |
| 129 it "should fail after clearing status when #{t[:desc]}" do |
| 130 subject.add_status(t[:service], ServingStatus::NOT_SERVING) |
| 131 got = subject.check(HCReq.new(service: t[:service]), nil) |
| 132 want = HCResp.new(status: ServingStatus::NOT_SERVING) |
| 133 expect(got).to eq(want) |
| 134 |
| 135 subject.clear_status(t[:service]) |
| 136 blk = proc do |
| 137 subject.check(HCReq.new(service: t[:service]), nil) |
| 138 end |
| 139 expected_msg = /#{StatusCodes::NOT_FOUND}/ |
| 140 expect(&blk).to raise_error GRPC::BadStatus, expected_msg |
| 141 end |
| 142 end |
| 143 end |
| 144 |
| 145 context 'method `clear_all`' do |
| 146 it 'should return NOT_FOUND after being invoked' do |
| 147 success_tests.each do |t| |
| 148 subject.add_status(t[:service], ServingStatus::NOT_SERVING) |
| 149 got = subject.check(HCReq.new(service: t[:service]), nil) |
| 150 want = HCResp.new(status: ServingStatus::NOT_SERVING) |
| 151 expect(got).to eq(want) |
| 152 end |
| 153 |
| 154 subject.clear_all |
| 155 |
| 156 success_tests.each do |t| |
| 157 blk = proc do |
| 158 subject.check(HCReq.new(service: t[:service]), nil) |
| 159 end |
| 160 expected_msg = /#{StatusCodes::NOT_FOUND}/ |
| 161 expect(&blk).to raise_error GRPC::BadStatus, expected_msg |
| 162 end |
| 163 end |
| 164 end |
| 165 |
| 166 describe 'running on RpcServer' do |
| 167 RpcServer = GRPC::RpcServer |
| 168 CheckerStub = Grpc::Health::Checker.rpc_stub_class |
| 169 |
| 170 before(:each) do |
| 171 @server_queue = GRPC::Core::CompletionQueue.new |
| 172 server_host = '0.0.0.0:0' |
| 173 @server = GRPC::Core::Server.new(@server_queue, nil) |
| 174 server_port = @server.add_http2_port(server_host, :this_port_is_insecure) |
| 175 @host = "localhost:#{server_port}" |
| 176 @ch = GRPC::Core::Channel.new(@host, nil, :this_channel_is_insecure) |
| 177 @client_opts = { channel_override: @ch } |
| 178 server_opts = { |
| 179 server_override: @server, |
| 180 completion_queue_override: @server_queue, |
| 181 poll_period: 1 |
| 182 } |
| 183 @srv = RpcServer.new(**server_opts) |
| 184 end |
| 185 |
| 186 after(:each) do |
| 187 @srv.stop |
| 188 end |
| 189 |
| 190 it 'should receive the correct status', server: true do |
| 191 @srv.handle(subject) |
| 192 subject.add_status('', ServingStatus::NOT_SERVING) |
| 193 t = Thread.new { @srv.run } |
| 194 @srv.wait_till_running |
| 195 |
| 196 stub = CheckerStub.new(@host, :this_channel_is_insecure, **@client_opts) |
| 197 got = stub.check(HCReq.new) |
| 198 want = HCResp.new(status: ServingStatus::NOT_SERVING) |
| 199 expect(got).to eq(want) |
| 200 @srv.stop |
| 201 t.join |
| 202 end |
| 203 |
| 204 it 'should fail on unknown services', server: true do |
| 205 @srv.handle(subject) |
| 206 t = Thread.new { @srv.run } |
| 207 @srv.wait_till_running |
| 208 blk = proc do |
| 209 stub = CheckerStub.new(@host, :this_channel_is_insecure, **@client_opts) |
| 210 stub.check(HCReq.new(service: 'unknown')) |
| 211 end |
| 212 expected_msg = /#{StatusCodes::NOT_FOUND}/ |
| 213 expect(&blk).to raise_error GRPC::BadStatus, expected_msg |
| 214 @srv.stop |
| 215 t.join |
| 216 end |
| 217 end |
| 218 end |
OLD | NEW |