PageRenderTime 94ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/spec/mongo/address_spec.rb

http://github.com/mongodb/mongo-ruby-driver
Ruby | 337 lines | 250 code | 86 blank | 1 comment | 6 complexity | 83bd1e7760822ad61eed08551b4cf552 MD5 | raw file
Possible License(s): Apache-2.0
  1. require 'spec_helper'
  2. describe Mongo::Address do
  3. describe '#==' do
  4. context 'when the other host and port are the same' do
  5. let(:address) do
  6. described_class.new('127.0.0.1:27017')
  7. end
  8. let(:other) do
  9. described_class.new('127.0.0.1:27017')
  10. end
  11. it 'returns true' do
  12. expect(address).to eq(other)
  13. end
  14. end
  15. context 'when the other port is different' do
  16. let(:address) do
  17. described_class.new('127.0.0.1:27017')
  18. end
  19. let(:other) do
  20. described_class.new('127.0.0.1:27018')
  21. end
  22. it 'returns false' do
  23. expect(address).to_not eq(other)
  24. end
  25. end
  26. context 'when the other host is different' do
  27. let(:address) do
  28. described_class.new('127.0.0.1:27017')
  29. end
  30. let(:other) do
  31. described_class.new('127.0.0.2:27017')
  32. end
  33. it 'returns false' do
  34. expect(address).to_not eq(other)
  35. end
  36. end
  37. context 'when the other object is not an address' do
  38. let(:address) do
  39. described_class.new('127.0.0.1:27017')
  40. end
  41. it 'returns false' do
  42. expect(address).to_not eq('test')
  43. end
  44. end
  45. context 'when the addresses are identical unix sockets' do
  46. let(:address) do
  47. described_class.new('/path/to/socket.sock')
  48. end
  49. let(:other) do
  50. described_class.new('/path/to/socket.sock')
  51. end
  52. it 'returns true' do
  53. expect(address).to eq(other)
  54. end
  55. end
  56. end
  57. describe '#hash' do
  58. let(:address) do
  59. described_class.new('127.0.0.1:27017')
  60. end
  61. it 'hashes on the host and port' do
  62. expect(address.hash).to eq([ '127.0.0.1', 27017 ].hash)
  63. end
  64. end
  65. describe '#initialize' do
  66. context 'when providing an ipv4 host' do
  67. context 'when a port is provided' do
  68. let(:address) do
  69. described_class.new('127.0.0.1:27017')
  70. end
  71. it 'sets the port' do
  72. expect(address.port).to eq(27017)
  73. end
  74. it 'sets the host' do
  75. expect(address.host).to eq('127.0.0.1')
  76. end
  77. end
  78. context 'when no port is provided' do
  79. let(:address) do
  80. described_class.new('127.0.0.1')
  81. end
  82. it 'sets the port to 27017' do
  83. expect(address.port).to eq(27017)
  84. end
  85. it 'sets the host' do
  86. expect(address.host).to eq('127.0.0.1')
  87. end
  88. end
  89. end
  90. context 'when providing an ipv6 host' do
  91. context 'when a port is provided' do
  92. let(:address) do
  93. described_class.new('[::1]:27017')
  94. end
  95. it 'sets the port' do
  96. expect(address.port).to eq(27017)
  97. end
  98. it 'sets the host' do
  99. expect(address.host).to eq('::1')
  100. end
  101. end
  102. context 'when no port is provided' do
  103. let(:address) do
  104. described_class.new('[::1]')
  105. end
  106. it 'sets the port to 27017' do
  107. expect(address.port).to eq(27017)
  108. end
  109. it 'sets the host' do
  110. expect(address.host).to eq('::1')
  111. end
  112. end
  113. end
  114. context 'when providing a DNS entry' do
  115. context 'when a port is provided' do
  116. let(:address) do
  117. described_class.new('localhost:27017')
  118. end
  119. it 'sets the port' do
  120. expect(address.port).to eq(27017)
  121. end
  122. it 'sets the host' do
  123. expect(address.host).to eq('localhost')
  124. end
  125. end
  126. context 'when a port is not provided' do
  127. let(:address) do
  128. described_class.new('localhost')
  129. end
  130. it 'sets the port to 27017' do
  131. expect(address.port).to eq(27017)
  132. end
  133. it 'sets the host' do
  134. expect(address.host).to eq('localhost')
  135. end
  136. end
  137. end
  138. context 'when providing a socket path' do
  139. let(:address) do
  140. described_class.new('/path/to/socket.sock')
  141. end
  142. it 'sets the port to nil' do
  143. expect(address.port).to be_nil
  144. end
  145. it 'sets the host' do
  146. expect(address.host).to eq('/path/to/socket.sock')
  147. end
  148. end
  149. end
  150. describe "#socket" do
  151. let(:address) do
  152. default_address
  153. end
  154. let(:host) do
  155. address.host
  156. end
  157. let(:addr_info) do
  158. family = (host == 'localhost') ? ::Socket::AF_INET : ::Socket::AF_UNSPEC
  159. ::Socket.getaddrinfo(host, nil, family, ::Socket::SOCK_STREAM)
  160. end
  161. let(:socket_address_or_host) do
  162. (host == 'localhost') ? addr_info.first[3] : host
  163. end
  164. context 'when providing a DNS entry that resolves to both IPv6 and IPv4' do
  165. let(:custom_hostname) do
  166. 'not_localhost'
  167. end
  168. let(:ip) do
  169. '127.0.0.1'
  170. end
  171. let(:address) do
  172. Mongo::Address.new(custom_hostname)
  173. end
  174. before do
  175. allow(::Socket).to receive(:getaddrinfo).and_return(
  176. [ ["AF_INET6", 0, '::2', '::2', ::Socket::AF_INET6, 1, 6],
  177. ["AF_INET", 0, custom_hostname, ip, ::Socket::AF_INET, 1, 6]]
  178. )
  179. end
  180. it "attempts to use IPv6 and fallbacks to IPv4" do
  181. expect(address.socket(0.0).host).to eq(ip)
  182. end
  183. end
  184. context 'when creating a socket' do
  185. it 'uses the host, not the IP address' do
  186. expect(address.socket(0.0).host).to eq(socket_address_or_host)
  187. end
  188. let(:socket) do
  189. if SpecConfig.instance.ssl?
  190. address.socket(0.0, SpecConfig.instance.ssl_options).instance_variable_get(:@tcp_socket)
  191. else
  192. address.socket(0.0).instance_variable_get(:@socket)
  193. end
  194. end
  195. if Socket.const_defined?(:TCP_KEEPINTVL)
  196. it 'sets the socket TCP_KEEPINTVL option' do
  197. expect(socket.getsockopt(Socket::IPPROTO_TCP, Socket::TCP_KEEPINTVL).int).to be <= 10
  198. end
  199. end
  200. if Socket.const_defined?(:TCP_KEEPCNT)
  201. it 'sets the socket TCP_KEEPCNT option' do
  202. expect(socket.getsockopt(Socket::IPPROTO_TCP, Socket::TCP_KEEPCNT).int).to be <= 9
  203. end
  204. end
  205. if Socket.const_defined?(:TCP_KEEPIDLE)
  206. it 'sets the socket TCP_KEEPIDLE option' do
  207. expect(socket.getsockopt(Socket::IPPROTO_TCP, Socket::TCP_KEEPIDLE).int).to be <= 300
  208. end
  209. end
  210. end
  211. describe ':connect_timeout option' do
  212. clean_slate
  213. let(:address) { Mongo::Address.new('127.0.0.1') }
  214. it 'defaults to 10' do
  215. RSpec::Mocks.with_temporary_scope do
  216. resolved_address = double('address')
  217. # This test's expectation
  218. expect(resolved_address).to receive(:socket).with(0, {}, connect_timeout: 10)
  219. expect(Mongo::Address::IPv4).to receive(:new).and_return(resolved_address)
  220. address.socket(0)
  221. end
  222. end
  223. end
  224. end
  225. describe '#to_s' do
  226. context 'address with ipv4 host only' do
  227. let(:address) { Mongo::Address.new('127.0.0.1') }
  228. it 'is host with port' do
  229. expect(address.to_s).to eql('127.0.0.1:27017')
  230. end
  231. end
  232. context 'address with ipv4 host and port' do
  233. let(:address) { Mongo::Address.new('127.0.0.1:27000') }
  234. it 'is host with port' do
  235. expect(address.to_s).to eql('127.0.0.1:27000')
  236. end
  237. end
  238. context 'address with ipv6 host only' do
  239. let(:address) { Mongo::Address.new('::1') }
  240. it 'is host with port' do
  241. expect(address.to_s).to eql('[::1]:27017')
  242. end
  243. end
  244. context 'address with ipv6 host and port' do
  245. let(:address) { Mongo::Address.new('[::1]:27000') }
  246. it 'is host with port' do
  247. expect(address.to_s).to eql('[::1]:27000')
  248. end
  249. end
  250. end
  251. end