Skip to content

Commit d67029a

Browse files
committed
Add test for data method mismatches.
1 parent eade6da commit d67029a

File tree

2 files changed

+115
-7
lines changed

2 files changed

+115
-7
lines changed

src/main/java/org/cojen/dirmi/core/StubMaker.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,9 @@ private void addStubMethods() {
390390
RemoteMethod method = serverMethod;
391391
int methodId = serverMethodId;
392392

393-
if (method == null) {
393+
if (method == null ||
394+
(clientMethod != null && !clientMethod.isData() && serverMethod.isData()))
395+
{
394396
// If the server method isn't implemented, use the client definition as a best
395397
// guess for now.
396398
method = clientMethod;
@@ -459,6 +461,12 @@ private void addStubMethods() {
459461
mStubMaker.addField(mType, "data");
460462
}
461463

464+
if (clientMethod == null) {
465+
// Only exists on the server side, and so it will be skipped.
466+
mm.new_(DataUnavailableException.class, method.name()).throw_();
467+
continue;
468+
}
469+
462470
var resultVar = mm.field("data").getAcquire().invoke(methodName);
463471
if (resultVar != null) {
464472
mm.return_(resultVar);
@@ -671,6 +679,10 @@ private static boolean isVoid(Object returnType) {
671679
private void writeParams(MethodMaker mm, Variable pipeVar,
672680
RemoteMethod method, int methodId, Object[] ptypes)
673681
{
682+
if (methodId < 0) {
683+
throw new AssertionError();
684+
}
685+
674686
String writeName = "writeMethodId";
675687

676688
if (methodId >= mServerInfo.remoteMethods().size()) {

src/test/java/org/cojen/dirmi/DataTest.java

Lines changed: 102 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020

2121
import java.util.function.BiPredicate;
2222

23+
import org.cojen.maker.ClassMaker;
24+
import org.cojen.maker.MethodMaker;
25+
2326
import org.junit.*;
2427
import static org.junit.Assert.*;
2528

@@ -33,15 +36,26 @@ public static void main(String[] args) throws Exception {
3336
org.junit.runner.JUnitCore.main(DataTest.class.getName());
3437
}
3538

39+
private Environment mEnv;
40+
41+
@Before
42+
public void setup() {
43+
mEnv = Environment.create();
44+
}
45+
46+
@After
47+
public void tearDown() throws Exception {
48+
mEnv.close();
49+
}
50+
3651
@Test
3752
public void basic() throws Exception {
38-
var env = Environment.create();
39-
env.reconnectDelayMillis(0);
53+
mEnv.reconnectDelayMillis(0);
4054
var server = new MainServer(false);
4155
assertFalse(server.nothing);
42-
env.export("main", server);
43-
env.connector(Connector.local(env));
44-
var session = env.connect(Main.class, "main", null);
56+
mEnv.export("main", server);
57+
mEnv.connector(Connector.local(mEnv));
58+
var session = mEnv.connect(Main.class, "main", null);
4559

4660
var main = session.root();
4761

@@ -128,8 +142,90 @@ public synchronized void awaitConnected() throws InterruptedException {
128142
main.uninstallHandler();
129143

130144
assertEquals("broken", server.error.getMessage());
145+
}
146+
147+
@Test
148+
public void mismatch() throws Exception {
149+
// Launch the server with a different set of data methods.
150+
151+
Class<?> iface, server;
152+
{
153+
ClassMaker cm = ClassMaker.beginExplicit(Main.class.getName(), new Loader(), null)
154+
.public_().interface_().implement(Remote.class);
155+
cm.addMethod(int.class, "id").public_().abstract_()
156+
.addAnnotation(Data.class, true);
157+
cm.addMethod(String.class, "name").public_().abstract_()
158+
.addAnnotation(Data.class, true);
159+
cm.addMethod(String.class, "message").public_().abstract_()
160+
.addAnnotation(Data.class, true);
161+
cm.addMethod(Object.class, "obj").public_().abstract_().throws_(RemoteException.class);
162+
cm.addMethod(cm, "same").public_().abstract_().throws_(RemoteException.class);
163+
cm.addMethod(null, "installHandler").public_().abstract_()
164+
.addAnnotation(Data.class, true);
165+
iface = cm.finish();
166+
167+
cm = ClassMaker.begin(null, iface.getClassLoader()).implement(iface).public_();
168+
cm.addConstructor().public_();
169+
cm.addMethod(int.class, "id").public_().return_(123);
170+
cm.addMethod(String.class, "name").public_().return_("myname");
171+
cm.addMethod(String.class, "message").public_().return_("message");
172+
cm.addMethod(Object.class, "obj").public_().return_("obj");
173+
MethodMaker mm = cm.addMethod(iface, "same").public_();
174+
mm.return_(mm.this_());
175+
cm.addMethod(null, "installHandler").public_();
176+
server = cm.finish();
177+
}
178+
179+
mEnv.export("main", server.getConstructor().newInstance());
131180

132-
env.close();
181+
mEnv.connector(Connector.local(mEnv));
182+
var session = mEnv.connect(Main.class, "main", null);
183+
var main = session.root();
184+
185+
try {
186+
main.id();
187+
fail();
188+
} catch (DataUnavailableException e) {
189+
// Return type differs.
190+
}
191+
192+
assertEquals("myname", main.name());
193+
194+
try {
195+
main.value();
196+
fail();
197+
} catch (DataUnavailableException e) {
198+
// Isn't defined on the server.
199+
}
200+
201+
try {
202+
main.nothing();
203+
fail();
204+
} catch (DataUnavailableException e) {
205+
// Isn't defined on the server.
206+
}
207+
208+
try {
209+
main.obj();
210+
fail();
211+
} catch (DataUnavailableException e) {
212+
// Isn't a data method on the server.
213+
}
214+
215+
assertEquals(main, main.same());
216+
217+
try {
218+
main.installHandler();
219+
fail();
220+
} catch (UnimplementedException e) {
221+
// The client expects a true remote call, but the server provides data.
222+
}
223+
}
224+
225+
private static class Loader extends ClassLoader {
226+
Loader() {
227+
super(DataTest.class.getClassLoader());
228+
}
133229
}
134230

135231
public static interface Main extends Remote {

0 commit comments

Comments
 (0)