1#
2# Licensed to the Apache Software Foundation (ASF) under one
3# or more contributor license agreements. See the NOTICE file
4# distributed with this work for additional information
5# regarding copyright ownership. The ASF licenses this file
6# to you under the Apache License, Version 2.0 (the
7# "License"); you may not use this file except in compliance
8# with the License. You may obtain a copy of the License at
9#
10#   http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing,
13# software distributed under the License is distributed on an
14# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15# KIND, either express or implied. See the License for the
16# specific language governing permissions and limitations
17# under the License.
18#
19
20require 'spec_helper'
21require 'rack/test'
22require 'thrift/server/thin_http_server'
23
24describe Thrift::ThinHTTPServer do
25
26  let(:processor) { double('processor') }
27
28  describe "#initialize" do
29
30    context "when using the defaults" do
31
32      it "binds to port 80, with host 0.0.0.0, a path of '/'" do
33        expect(Thin::Server).to receive(:new).with('0.0.0.0', 80, an_instance_of(Rack::Builder))
34        Thrift::ThinHTTPServer.new(processor)
35      end
36
37      it 'creates a ThinHTTPServer::RackApplicationContext' do
38        expect(Thrift::ThinHTTPServer::RackApplication).to receive(:for).with("/", processor, an_instance_of(Thrift::BinaryProtocolFactory)).and_return(anything)
39        Thrift::ThinHTTPServer.new(processor)
40      end
41
42      it "uses the BinaryProtocolFactory" do
43        expect(Thrift::BinaryProtocolFactory).to receive(:new)
44        Thrift::ThinHTTPServer.new(processor)
45      end
46
47    end
48
49    context "when using the options" do
50
51      it 'accepts :ip, :port, :path' do
52        ip = "192.168.0.1"
53        port = 3000
54        path = "/thin"
55        expect(Thin::Server).to receive(:new).with(ip, port, an_instance_of(Rack::Builder))
56        Thrift::ThinHTTPServer.new(processor,
57                           :ip => ip,
58                           :port => port,
59                           :path => path)
60      end
61
62      it 'creates a ThinHTTPServer::RackApplicationContext with a different protocol factory' do
63        expect(Thrift::ThinHTTPServer::RackApplication).to receive(:for).with("/", processor, an_instance_of(Thrift::JsonProtocolFactory)).and_return(anything)
64        Thrift::ThinHTTPServer.new(processor,
65                           :protocol_factory => Thrift::JsonProtocolFactory.new)
66      end
67
68    end
69
70  end
71
72  describe "#serve" do
73
74    it 'starts the Thin server' do
75      underlying_thin_server = double('thin server', :start => true)
76      allow(Thin::Server).to receive(:new).and_return(underlying_thin_server)
77
78      thin_thrift_server = Thrift::ThinHTTPServer.new(processor)
79
80      expect(underlying_thin_server).to receive(:start)
81      thin_thrift_server.serve
82    end
83  end
84
85end
86
87describe Thrift::ThinHTTPServer::RackApplication do
88  include Rack::Test::Methods
89
90  let(:processor) { double('processor') }
91  let(:protocol_factory) { double('protocol factory') }
92
93  def app
94    Thrift::ThinHTTPServer::RackApplication.for("/", processor, protocol_factory)
95  end
96
97  context "404 response" do
98
99    it 'receives a non-POST' do
100      header('Content-Type', "application/x-thrift")
101      get "/"
102      expect(last_response.status).to be 404
103    end
104
105    it 'receives a header other than application/x-thrift' do
106      header('Content-Type', "application/json")
107      post "/"
108      expect(last_response.status).to be 404
109    end
110
111  end
112
113  context "200 response" do
114
115    before do
116      allow(protocol_factory).to receive(:get_protocol)
117      allow(processor).to receive(:process)
118    end
119
120    it 'creates an IOStreamTransport' do
121      header('Content-Type', "application/x-thrift")
122      expect(Thrift::IOStreamTransport).to receive(:new).with(an_instance_of(Rack::Lint::InputWrapper), an_instance_of(Rack::Response))
123      post "/"
124    end
125
126    it 'fetches the right protocol based on the Transport' do
127      header('Content-Type', "application/x-thrift")
128      expect(protocol_factory).to receive(:get_protocol).with(an_instance_of(Thrift::IOStreamTransport))
129      post "/"
130    end
131
132    it 'status code 200' do
133      header('Content-Type', "application/x-thrift")
134      post "/"
135      expect(last_response.ok?).to be_truthy
136    end
137
138  end
139
140end
141
142