Skip to content

Commit

Permalink
With the memcache-client gem installed, the Rails tests fail to start…
Browse files Browse the repository at this point in the history
…up as memcache does TCPSocket.new(addr, port, 0) and we were not handling the third argument
  • Loading branch information
Shri Borde committed Apr 30, 2009
1 parent 1f5d8cb commit 8c00011
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 20 deletions.
@@ -1,3 +1,5 @@
fails:TCPSocket.new refuses the connection when there is no server to connect to
fails:TCPSocket.new connects to a listening server
critical:TCPSocket.new has an address once it has connected to a listening server
critical:TCPSocket.new allows local_port to be 0 when local_host is not specified
critical:TCPSocket.new requires local_port to be 0 when local_host is not specified
@@ -1,3 +1,5 @@
fails:TCPSocket.open refuses the connection when there is no server to connect to
fails:TCPSocket.open connects to a listening server
critical:TCPSocket.open has an address once it has connected to a listening server
critical:TCPSocket.open allows local_port to be 0 when local_host is not specified
critical:TCPSocket.open requires local_port to be 0 when local_host is not specified
Expand Up @@ -17,11 +17,30 @@ def self.port
40001
end

def self.local_port
40002
end

def self.sockaddr_in(port, host)
Socket::SockAddr_In.new(Socket.sockaddr_in(port, host))
end

def self.socket_path
"/tmp/unix_server_spec.socket"
end

def self.start_tcp_server(remote_host = nil)
thread = Thread.new do
if remote_host
server = TCPServer.new(remote_host, SocketSpecs.port)
else
server = TCPServer.new(SocketSpecs.port)
end
server.accept
server.close
end
Thread.pass until thread.status == 'sleep' or thread.status == nil
thread.status.should_not be_nil
thread
end
end
Expand Up @@ -4,7 +4,13 @@
describe :tcpsocket_new, :shared => true do
before :each do
@hostname = Socket.getaddrinfo("127.0.0.1", nil)[0][2]
@thread = nil
end

after :each do
@thread.join if @thread
end

it "requires a hostname and a port as arguments" do
lambda { TCPSocket.new }.should raise_error(ArgumentError)
end
Expand All @@ -14,28 +20,15 @@
end

it "connects to a listening server" do
thread = Thread.new do
server = TCPServer.new(SocketSpecs.port)
server.accept
server.close
end
Thread.pass until thread.status == 'sleep' or thread.status == nil
thread.status.should_not be_nil
@thread = SocketSpecs.start_tcp_server
lambda {
sock = TCPSocket.new(@hostname, SocketSpecs.port)
sock.close
}.should_not raise_error(Errno::ECONNREFUSED)
thread.join
end

it "has an address once it has connected to a listening server" do
thread = Thread.new do
server = TCPServer.new('127.0.0.1', SocketSpecs.port)
server.accept
server.close
end
Thread.pass until thread.status == 'sleep' or thread.status == nil
thread.status.should_not be_nil
@thread = SocketSpecs.start_tcp_server('127.0.0.1')
sock = TCPSocket.new('127.0.0.1', SocketSpecs.port)
sock.addr[0].should == "AF_INET"
sock.addr[1].should be_kind_of(Fixnum)
Expand All @@ -46,6 +39,17 @@
sock.addr[2].should =~ /^#{@hostname}/
sock.addr[3].should == "127.0.0.1"
sock.close
thread.join
end

it "allows local_port to be 0 when local_host is not specified" do
@thread = SocketSpecs.start_tcp_server('127.0.0.1')
sock = TCPSocket.new('127.0.0.1', SocketSpecs.port, 0)
sock.addr[0].should == "AF_INET"
sock.close
end

it "requires local_port to be 0 when local_host is not specified" do
# The requested address is not valid in its context
lambda { sock = TCPSocket.new('127.0.0.1', SocketSpecs.port, 1) }.should raise_error(Errno::EADDRNOTAVAIL)
end
end
Expand Up @@ -31,7 +31,7 @@
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<OutputPath>..\..\..\Bin\Release\</OutputPath>
<DefineConstants>TRACE;$(SignedSym)</DefineConstants>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
Expand Down
Expand Up @@ -6180,7 +6180,9 @@ public sealed class SocketsLibraryInitializer : IronRuby.Builtins.LibraryInitial
#endif
#if !SILVERLIGHT
IronRuby.Builtins.RubyClass def4 = DefineGlobalClass("TCPSocket", typeof(IronRuby.StandardLibrary.Sockets.TCPSocket), true, def5, null, LoadTCPSocket_Class, null, IronRuby.Builtins.RubyModule.EmptyArray,
new System.Func<IronRuby.Runtime.ConversionStorage<IronRuby.Builtins.MutableString>, IronRuby.Runtime.ConversionStorage<System.Int32>, IronRuby.Builtins.RubyClass, IronRuby.Builtins.MutableString, System.Object, IronRuby.StandardLibrary.Sockets.TCPSocket>(IronRuby.StandardLibrary.Sockets.TCPSocket.CreateTCPSocket)
new System.Func<IronRuby.Runtime.ConversionStorage<IronRuby.Builtins.MutableString>, IronRuby.Runtime.ConversionStorage<System.Int32>, IronRuby.Builtins.RubyClass, IronRuby.Builtins.MutableString, System.Object, IronRuby.StandardLibrary.Sockets.TCPSocket>(IronRuby.StandardLibrary.Sockets.TCPSocket.CreateTCPSocket),
new System.Func<IronRuby.Runtime.ConversionStorage<IronRuby.Builtins.MutableString>, IronRuby.Runtime.ConversionStorage<System.Int32>, IronRuby.Builtins.RubyClass, IronRuby.Builtins.MutableString, System.Object, System.Int32, IronRuby.StandardLibrary.Sockets.TCPSocket>(IronRuby.StandardLibrary.Sockets.TCPSocket.CreateTCPSocket),
new System.Func<IronRuby.Runtime.ConversionStorage<IronRuby.Builtins.MutableString>, IronRuby.Runtime.ConversionStorage<System.Int32>, IronRuby.Builtins.RubyClass, IronRuby.Builtins.MutableString, System.Object, IronRuby.Builtins.MutableString, IronRuby.Builtins.MutableString, IronRuby.StandardLibrary.Sockets.TCPSocket>(IronRuby.StandardLibrary.Sockets.TCPSocket.CreateTCPSocket)
);
#endif
#if !SILVERLIGHT
Expand Down
Expand Up @@ -19,6 +19,8 @@
using Microsoft.Scripting.Runtime;
using IronRuby.Builtins;
using IronRuby.Runtime;
using System.Runtime.InteropServices;
using System.Net;

namespace IronRuby.StandardLibrary.Sockets {
[RubyClass("TCPSocket", BuildConfig = "!SILVERLIGHT")]
Expand All @@ -33,15 +35,58 @@ public TCPSocket(RubyContext/*!*/ context, Socket/*!*/ socket)
}

[RubyConstructor]
public static TCPSocket/*!*/ CreateTCPSocket(ConversionStorage<MutableString>/*!*/ stringCast, ConversionStorage<int>/*!*/ fixnumCast,
RubyClass/*!*/ self, [DefaultProtocol, NotNull]MutableString/*!*/ remoteHost, object remotePort) {
public static TCPSocket/*!*/ CreateTCPSocket(
ConversionStorage<MutableString>/*!*/ stringCast,
ConversionStorage<int>/*!*/ fixnumCast,
RubyClass/*!*/ self,
[DefaultProtocol, NotNull]MutableString/*!*/ remoteHost,
object remotePort) {

int port = ConvertToPortNum(stringCast, fixnumCast, remotePort);

Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Connect(remoteHost.ConvertToString(), port);

return new TCPSocket(self.Context, socket);
}

[RubyConstructor]
public static TCPSocket/*!*/ CreateTCPSocket(
ConversionStorage<MutableString>/*!*/ stringCast,
ConversionStorage<int>/*!*/ fixnumCast,
RubyClass/*!*/ self,
[DefaultProtocol, NotNull]MutableString/*!*/ remoteHost,
object remotePort,
int localPort) {

if (localPort == 0) {
// Not sure what the semantics should be in this case but we make sure not to blow up.
// Real-world code (Server.connect_to in memcache.rb in the memcache-client gem) does do "TCPSocket.new(host, port, 0)"
return CreateTCPSocket(stringCast, fixnumCast, self, remoteHost, remotePort);
}

throw new NotImplementedError();
}

[RubyConstructor]
public static TCPSocket/*!*/ CreateTCPSocket(
ConversionStorage<MutableString>/*!*/ stringCast,
ConversionStorage<int>/*!*/ fixnumCast,
RubyClass/*!*/ self,
[DefaultProtocol, NotNull]MutableString/*!*/ remoteHost,
object remotePort,
[DefaultProtocol, NotNull]MutableString/*!*/ localHost,
[DefaultProtocol, NotNull]MutableString/*!*/ localPort) {

TCPSocket/*!*/ socket = CreateTCPSocket(stringCast, fixnumCast, self, remoteHost, remotePort);

IPAddress localIPAddress = GetHostAddress(localHost.ConvertToString());
int localPortNum = ConvertToPortNum(stringCast, fixnumCast, localPort);
IPEndPoint localEndPoint = new IPEndPoint(localIPAddress, localPortNum);
socket.Socket.Bind(localEndPoint);

return socket;
}
}
}
#endif

0 comments on commit 8c00011

Please sign in to comment.