#region Copyright notice and license | |
// Protocol Buffers - Google's data interchange format | |
// Copyright 2008 Google Inc. All rights reserved. | |
// http://github.com/jskeet/dotnet-protobufs/ | |
// Original C++/Java/Python code: | |
// http://code.google.com/p/protobuf/ | |
// | |
// Redistribution and use in source and binary forms, with or without | |
// modification, are permitted provided that the following conditions are | |
// met: | |
// | |
// * Redistributions of source code must retain the above copyright | |
// notice, this list of conditions and the following disclaimer. | |
// * Redistributions in binary form must reproduce the above | |
// copyright notice, this list of conditions and the following disclaimer | |
// in the documentation and/or other materials provided with the | |
// distribution. | |
// * Neither the name of Google Inc. nor the names of its | |
// contributors may be used to endorse or promote products derived from | |
// this software without specific prior written permission. | |
// | |
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
#endregion | |
using System; | |
using Google.ProtocolBuffers.Descriptors; | |
using Google.ProtocolBuffers.TestProtos; | |
using NUnit.Framework; | |
using Rhino.Mocks; | |
using Rhino.Mocks.Constraints; | |
namespace Google.ProtocolBuffers | |
{ | |
/// <summary> | |
/// Tests for generated service classes. | |
/// TODO(jonskeet): Convert the mocking tests using Rhino.Mocks. | |
/// </summary> | |
[TestFixture] | |
public class ServiceTest | |
{ | |
private delegate void Action<T1, T2>(T1 t1, T2 t2); | |
private static readonly MethodDescriptor FooDescriptor = TestGenericService.Descriptor.Methods[0]; | |
private static readonly MethodDescriptor BarDescriptor = TestGenericService.Descriptor.Methods[1]; | |
[Test] | |
public void GetRequestPrototype() | |
{ | |
TestGenericService service = new TestServiceImpl(); | |
Assert.AreSame(service.GetRequestPrototype(FooDescriptor), FooRequest.DefaultInstance); | |
Assert.AreSame(service.GetRequestPrototype(BarDescriptor), BarRequest.DefaultInstance); | |
} | |
[Test] | |
public void GetResponsePrototype() | |
{ | |
TestGenericService service = new TestServiceImpl(); | |
Assert.AreSame(service.GetResponsePrototype(FooDescriptor), FooResponse.DefaultInstance); | |
Assert.AreSame(service.GetResponsePrototype(BarDescriptor), BarResponse.DefaultInstance); | |
} | |
[Test] | |
public void CallMethodFoo() | |
{ | |
MockRepository mocks = new MockRepository(); | |
FooRequest fooRequest = FooRequest.CreateBuilder().Build(); | |
FooResponse fooResponse = FooResponse.CreateBuilder().Build(); | |
IRpcController controller = mocks.StrictMock<IRpcController>(); | |
bool fooCalled = false; | |
TestGenericService service = new TestServiceImpl((request, responseAction) => | |
{ | |
Assert.AreSame(fooRequest, request); | |
fooCalled = true; | |
responseAction(fooResponse); | |
}, null, controller); | |
bool doneHandlerCalled = false; | |
Action<IMessage> doneHandler = (response => | |
{ | |
Assert.AreSame(fooResponse, response); | |
doneHandlerCalled = true; | |
}); | |
using (mocks.Record()) | |
{ | |
// No mock interactions to record | |
} | |
service.CallMethod(FooDescriptor, controller, fooRequest, doneHandler); | |
Assert.IsTrue(doneHandlerCalled); | |
Assert.IsTrue(fooCalled); | |
mocks.VerifyAll(); | |
} | |
private delegate void CallFooDelegate(MethodDescriptor descriptor, IRpcController controller, | |
IMessage request, IMessage response, Action<IMessage> doneHandler); | |
/// <summary> | |
/// Tests the generated stub handling of Foo. By this stage we're reasonably confident | |
/// that the choice between Foo and Bar is arbitrary, hence the lack of a corresponding Bar | |
/// test. | |
/// </summary> | |
[Test] | |
[Ignore("Crashes Mono - needs further investigation")] | |
public void GeneratedStubFooCall() | |
{ | |
FooRequest fooRequest = FooRequest.CreateBuilder().Build(); | |
MockRepository mocks = new MockRepository(); | |
IRpcChannel mockChannel = mocks.StrictMock<IRpcChannel>(); | |
IRpcController mockController = mocks.StrictMock<IRpcController>(); | |
TestGenericService service = TestGenericService.CreateStub(mockChannel); | |
Action<FooResponse> doneHandler = mocks.StrictMock<Action<FooResponse>>(); | |
using (mocks.Record()) | |
{ | |
// Nasty way of mocking out "the channel calls the done handler". | |
Expect.Call(() => mockChannel.CallMethod(null, null, null, null, null)) | |
.IgnoreArguments() | |
.Constraints(Is.Same(FooDescriptor), Is.Same(mockController), Is.Same(fooRequest), | |
Is.Same(FooResponse.DefaultInstance), Is.Anything()) | |
.Do((CallFooDelegate) ((p1, p2, p3, response, done) => done(response))); | |
doneHandler(FooResponse.DefaultInstance); | |
} | |
service.Foo(mockController, fooRequest, doneHandler); | |
mocks.VerifyAll(); | |
} | |
[Test] | |
public void CallMethodBar() | |
{ | |
MockRepository mocks = new MockRepository(); | |
BarRequest barRequest = BarRequest.CreateBuilder().Build(); | |
BarResponse barResponse = BarResponse.CreateBuilder().Build(); | |
IRpcController controller = mocks.StrictMock<IRpcController>(); | |
bool barCalled = false; | |
TestGenericService service = new TestServiceImpl(null, (request, responseAction) => | |
{ | |
Assert.AreSame(barRequest, request); | |
barCalled = true; | |
responseAction(barResponse); | |
}, controller); | |
bool doneHandlerCalled = false; | |
Action<IMessage> doneHandler = (response => | |
{ | |
Assert.AreSame(barResponse, response); | |
doneHandlerCalled = true; | |
}); | |
using (mocks.Record()) | |
{ | |
// No mock interactions to record | |
} | |
service.CallMethod(BarDescriptor, controller, barRequest, doneHandler); | |
Assert.IsTrue(doneHandlerCalled); | |
Assert.IsTrue(barCalled); | |
mocks.VerifyAll(); | |
} | |
private class TestServiceImpl : TestGenericService | |
{ | |
private readonly Action<FooRequest, Action<FooResponse>> fooHandler; | |
private readonly Action<BarRequest, Action<BarResponse>> barHandler; | |
private readonly IRpcController expectedController; | |
internal TestServiceImpl() | |
{ | |
} | |
internal TestServiceImpl(Action<FooRequest, Action<FooResponse>> fooHandler, | |
Action<BarRequest, Action<BarResponse>> barHandler, | |
IRpcController expectedController) | |
{ | |
this.fooHandler = fooHandler; | |
this.barHandler = barHandler; | |
this.expectedController = expectedController; | |
} | |
public override void Foo(IRpcController controller, FooRequest request, Action<FooResponse> done) | |
{ | |
Assert.AreSame(expectedController, controller); | |
fooHandler(request, done); | |
} | |
public override void Bar(IRpcController controller, BarRequest request, Action<BarResponse> done) | |
{ | |
Assert.AreSame(expectedController, controller); | |
barHandler(request, done); | |
} | |
} | |
} | |
} |