001 package sysModel.env;
002
003 import junit.framework.TestCase;
004 import model.ILambda;
005 import model.fish.GenericFish;
006 import sysModel.ICmdFactory;
007 import sysModel.ISecurityAdapter;
008 import sysModel.NoOpLambda;
009 import sysModel.fish.IFishFactory;
010 import sysModel.fish.AFish;
011 import sysModel.parser.DefaultTokenVisitor;
012 import sysModel.parser.Lexer;
013 import sysModel.parser.ParserException;
014
015 import javax.swing.*;
016 import java.awt.*;
017 import java.awt.event.MouseEvent;
018 import java.util.LinkedList;
019
020 /**
021 * Implementation of a square wrapping environment.
022 *
023 * @author Mathias G. Ricken
024 */
025 public class WrappingEnv extends BoundedEnv {
026
027 /**
028 * Factory method for overridden Location.
029 *
030 * @param x x coordinate
031 * @param y y coordinate
032 * @return new WrappingEnv.Location at (x, y)
033 */
034 public ASquareEnv.Location makeLocation(double x, double y) {
035 return new Location(x, y);
036 }
037
038 /**
039 * Overridden location class that does wrapping.
040 *
041 * @author Mathias G. Ricken
042 */
043 public class Location extends ASquareEnv.Location {
044 /**
045 * Ctor for location.
046 *
047 * @param x x position
048 * @param y y position
049 */
050 public Location(double x, double y) {
051 super(x, y);
052 }
053
054 /**
055 * Return the location of a neighbor in the given direction.
056 *
057 * @param dir the direction of the neighbor to be returned
058 * @return neighbor in that direction
059 */
060 public ASquareEnv.Location getNeighbor(Direction dir) {
061 double newX = getX() + dir.getDeltaX();
062 double newY = getY() + dir.getDeltaY();
063 if (0 > newX) {
064 newX = _width + newX;
065 }
066 else if (newX >= _width) {
067 newX = newX - _width;
068 }
069 if (0 > newY) {
070 newY = _height + newY;
071 }
072 else if (newY >= _height) {
073 newY = newY - _height;
074 }
075 return makeLocation(newX, newY);
076 }
077 }
078
079 /**
080 * Construct a new square wrapping environment. Does not set this object up for actual use. Note: This constructor
081 * needs to exist and be public for the "environment selection" dialog to work.
082 *
083 * @param cmdFactory command factory to use
084 * @param sm security manager to control fish action
085 */
086 public WrappingEnv(ICmdFactory cmdFactory, ISecurityAdapter sm) {
087 super(cmdFactory, sm);
088 }
089
090 /**
091 * Construct a new square wrapping environment.
092 *
093 * @param cmdFactory command factory to use
094 * @param sm security manager to control fish actions
095 * @param width width of environment
096 * @param height height of environment
097 */
098 public WrappingEnv(ICmdFactory cmdFactory, ISecurityAdapter sm, int width, int height) {
099 super(cmdFactory, sm, width, height);
100 }
101
102 /**
103 * Get the environment settings class.
104 *
105 * @return environment settings class
106 */
107 public AEnvFactory makeEnvFactory() {
108 return new AEnvFactory() {
109 private JTextField _rowField;
110 private JTextField _colField;
111
112 {
113 setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
114 add(new JLabel("rows: "));
115 add(_rowField = new JTextField("10"));
116 add(new JLabel(" cols: "));
117 add(_colField = new JTextField("10"));
118 }
119
120 public AGlobalEnv create() {
121 return new WrappingEnv(_cmdFactory,
122 _securityAdapter,
123 Integer.parseInt(_colField.getText()),
124 Integer.parseInt(_rowField.getText()));
125 }
126
127 public String toString() {
128 return WrappingEnv.class.getName();
129 }
130 };
131 }
132
133 /**
134 * Factory method for parsing a stream of tokens and creating a global environment from it.
135 *
136 * @param l lexer
137 * @return new global environment
138 */
139 protected AGlobalEnv parseEnvironment(final Lexer l) {
140 // have to read size of environment
141 return (AGlobalEnv) l.nextToken().execute(new DefaultTokenVisitor() {
142 public Object defaultCase() {
143 throw new ParserException("Invalid token");
144 }
145
146 public Object numCase(final double width) {
147 // width was read
148 return (AGlobalEnv) l.nextToken().execute(new DefaultTokenVisitor() {
149 public Object defaultCase() {
150 throw new ParserException("Invalid token");
151 }
152
153 public Object numCase(double height) {
154 // height was read
155 BoundedEnv env = new WrappingEnv(_cmdFactory, _securityAdapter, (int) width, (int) height);
156
157 // parse fish
158 env.parseFish(l);
159
160 return env;
161 }
162 });
163 }
164 });
165 }
166
167 /*****************************************************************************************************************
168 * Tests follow
169 *****************************************************************************************************************/
170
171 /**
172 * Test cases for WrappingEnv.
173 *
174 * @author Mathias Ricken
175 */
176 public static class Test_WrappingEnv extends TestCase {
177 private ICmdFactory _cmdFactory;
178 private ISecurityAdapter _sm;
179 private WrappingEnv _env;
180 private IFishFactory _fishFactory;
181
182 private static final ILambda _notify = new ILambda() {
183 public Object apply(Object param) {
184 return "notifyCmd";
185 }
186 };
187 private static final ILambda _delete = new ILambda() {
188 public Object apply(Object param) {
189 return "deleteCmd";
190 }
191 };
192 private static final ILambda _add = new ILambda() {
193 public Object apply(Object param) {
194 return "addCmd";
195 }
196 };
197
198 public void setUp() throws Exception {
199 super.setUp();
200 _cmdFactory = new ICmdFactory() {
201 public ILambda makeNotifyCmd(ILambda lambda) {
202 return _notify;
203 }
204
205 public ILambda makeDeleteCmd(ALocalEnv env) {
206 return _delete;
207 }
208
209 public ILambda makeAddCmd(AFish fish) {
210 return _add;
211 }
212 };
213 _sm = new ISecurityAdapter() {
214 public void setProtected(boolean _protected) {
215 }
216 public ThreadGroup getFishThreadGroup() {
217 return null;
218 }
219 public ClassLoader getClassLoader() {
220 return null;
221 }
222 public void handleException(Throwable t) {
223 }
224 };
225
226 _env = new WrappingEnv(_cmdFactory, _sm, 10, 10);
227
228 _fishFactory = new IFishFactory() {
229 /**
230 * Create a new fish.
231 *
232 * @return new fish
233 */
234 public AFish createFish() {
235 return new GenericFish(Color.RED);
236 }
237 };
238 }
239
240 int countNonEmpty() {
241 int count = 0;
242 WrappingEnv.IField[][] map = _env._fieldMap;
243 IFieldVisitor countVisitor = new IFieldVisitor() {
244 public Object emptyCase(EmptyField host, Object param) {
245 return new Integer(0);
246 }
247
248 public Object nonEmptyCase(NonEmptyField host, Object param) {
249 return new Integer(1);
250 }
251 };
252 for (int i = 0; i < map.length; i++) {
253 WrappingEnv.IField[] iFields = map[i];
254 for (int j = 0; j < iFields.length; j++) {
255 WrappingEnv.IField iField = iFields[j];
256 count += ((Integer) iField.execute(countVisitor, null)).intValue();
257 }
258 }
259 return count;
260 }
261
262 /**
263 * Test addFishToInternalData.
264 */
265 public void testAddFish() {
266 assertEquals(0, countNonEmpty());
267
268 ALocalEnv lTop = _env.makeLocalEnv(new Point.Double(1.0, 1.0));
269 GenericFish fTop = new GenericFish(Color.RED);
270 fTop.setLocalEnvironment(lTop);
271 _env.addFishToInternalData(lTop, fTop);
272
273 assertEquals(1, countNonEmpty());
274
275 ALocalEnv lBottom = _env.makeLocalEnv(new Point.Double(1.0, 2.0));
276 GenericFish fBottom = new GenericFish(Color.RED);
277 fBottom.setLocalEnvironment(lBottom);
278 _env.addFishToInternalData(lBottom, fBottom);
279
280 assertEquals(2, countNonEmpty());
281 }
282
283 /**
284 * Test editFish.
285 */
286 public void testEditFish() {
287 assertEquals(0, countNonEmpty());
288
289 ASquareLocalEnvironment l = (ASquareLocalEnvironment) _env.makeLocalEnv(new Point.Double(1.0, 1.0));
290 GenericFish f = new GenericFish(Color.RED);
291 f.setLocalEnvironment(l);
292 _env.addFishToInternalData(l, f);
293 WrappingEnv.Direction d = l.direction();
294
295 assertEquals(1, countNonEmpty());
296 assertEquals(0.0, d.getAngle(), 0.01);
297
298 ILambda lambda = _env.editFish(l, _fishFactory, MouseEvent.BUTTON1);
299 assertEquals(1, countNonEmpty());
300 assertEquals(Math.PI / 2.0, d.getAngle(), 0.01);
301 assertEquals(NoOpLambda.instance(), lambda);
302
303 lambda = _env.editFish(l, _fishFactory, MouseEvent.BUTTON1);
304 assertEquals(1, countNonEmpty());
305 assertEquals(Math.PI, d.getAngle(), 0.01);
306 assertEquals(NoOpLambda.instance(), lambda);
307
308 lambda = _env.editFish(l, _fishFactory, MouseEvent.BUTTON1);
309 assertEquals(1, countNonEmpty());
310 assertEquals(3 * Math.PI / 2.0, d.getAngle(), 0.01);
311 assertEquals(NoOpLambda.instance(), lambda);
312
313 lambda = _env.editFish(l, _fishFactory, MouseEvent.BUTTON1);
314 assertEquals(0, countNonEmpty());
315 assertEquals(0, d.getAngle(), 0.01);
316 assertEquals(_delete, lambda);
317 }
318
319 /**
320 * Test getViewPosition.
321 */
322 public void testGetViewPosition() {
323 assertTrue(_env.getViewPosition(new Point.Double(0, 0)).equals(new Point.Double(0, 0)));
324 assertTrue(_env.getViewPosition(new Point.Double(1.0, 0)).equals(new Point.Double(1.0, 0)));
325 assertTrue(_env.getViewPosition(new Point.Double(1.2, 0)).equals(new Point.Double(1.2, 0)));
326 assertTrue(_env.getViewPosition(new Point.Double(0, 1.0)).equals(new Point.Double(0, 1.0)));
327 assertTrue(_env.getViewPosition(new Point.Double(0, 1.3)).equals(new Point.Double(0, 1.3)));
328 assertTrue(_env.getViewPosition(new Point.Double(-2.5, 0)).equals(new Point.Double(-2.5, 0)));
329 assertTrue(_env.getViewPosition(new Point.Double(-3.0, 0)).equals(new Point.Double(-3.0, 0)));
330 assertTrue(_env.getViewPosition(new Point.Double(0, -2.5)).equals(new Point.Double(0, -2.5)));
331 assertTrue(_env.getViewPosition(new Point.Double(0, -3.0)).equals(new Point.Double(0, -3.0)));
332 assertTrue(_env.getViewPosition(new Point.Double(2.0, 1.0)).equals(new Point.Double(2.0, 1.0)));
333 assertTrue(_env.getViewPosition(new Point.Double(-4.0, -2.3)).equals(new Point.Double(-4.0, -2.3)));
334 }
335
336 /**
337 * Test getPanDelta.
338 */
339 public void testGetPanDelta() {
340 assertTrue(_env.getPanDelta(new Point.Double(0, 0)).equals(new Point.Double(0, 0)));
341 assertTrue(_env.getPanDelta(new Point.Double(1.0, 0)).equals(new Point.Double(0, 0)));
342 assertTrue(_env.getPanDelta(new Point.Double(1.2, 0)).equals(new Point.Double(0, 0)));
343 assertTrue(_env.getPanDelta(new Point.Double(0, 1.0)).equals(new Point.Double(0, 0)));
344 assertTrue(_env.getPanDelta(new Point.Double(0, 1.3)).equals(new Point.Double(0, 0)));
345 assertTrue(_env.getPanDelta(new Point.Double(-2.5, 0)).equals(new Point.Double(0, 0)));
346 assertTrue(_env.getPanDelta(new Point.Double(-3.0, 0)).equals(new Point.Double(0, 0)));
347 assertTrue(_env.getPanDelta(new Point.Double(0, -2.5)).equals(new Point.Double(0, 0)));
348 assertTrue(_env.getPanDelta(new Point.Double(0, -3.0)).equals(new Point.Double(0, 0)));
349 assertTrue(_env.getPanDelta(new Point.Double(2.0, 1.0)).equals(new Point.Double(0, 0)));
350 assertTrue(_env.getPanDelta(new Point.Double(-4.0, -2.3)).equals(new Point.Double(0, 0)));
351 }
352 }
353
354 /**
355 * Test cases for WrappingEnv.LocalEnv.
356 *
357 * @author Mathias Ricken
358 */
359 public static class Test_WrappingEnv_LocalEnv extends TestCase {
360 private ICmdFactory _cmdFactory;
361 private ISecurityAdapter _sm;
362 private WrappingEnv _env;
363
364 private static class SuccessException extends RuntimeException {
365 public SuccessException() {
366 super();
367 }
368 }
369
370 private static final ILambda _notify = new ILambda() {
371 public Object apply(Object param) {
372 return "notifyCmd";
373 }
374 };
375 private static final ILambda _delete = new ILambda() {
376 public Object apply(Object param) {
377 return "deleteCmd";
378 }
379 };
380 private static final ILambda _add = new ILambda() {
381 public Object apply(Object param) {
382 return "addCmd";
383 }
384 };
385
386 public void setUp() throws Exception {
387 super.setUp();
388 _cmdFactory = new ICmdFactory() {
389 public ILambda makeNotifyCmd(ILambda lambda) {
390 return _notify;
391 }
392
393 public ILambda makeDeleteCmd(ALocalEnv env) {
394 return _delete;
395 }
396
397 public ILambda makeAddCmd(AFish fish) {
398 return _add;
399 }
400 };
401 _sm = new ISecurityAdapter() {
402 public void setProtected(boolean _protected) {
403 }
404 public ThreadGroup getFishThreadGroup() {
405 return null;
406 }
407 public ClassLoader getClassLoader() {
408 return null;
409 }
410 public void handleException(Throwable t) {
411 }
412 };
413
414 _env = new WrappingEnv(_cmdFactory, _sm, 10, 10);
415 }
416
417 /**
418 * Test local environment's execute.
419 */
420 public void testExecute() {
421 ALocalEnv l = _env.makeLocalEnv(new Point.Double(1, 1));
422
423 try {
424 l.execute(new AGlobalEnv.ILocalEnvVisitor() {
425 public Object emptyCase(ALocalEnv host, Object param) {
426 // ok
427 throw new SuccessException();
428 }
429
430 public Object nonEmptyCase(ALocalEnv host, Object param) {
431 throw new RuntimeException("Should be empty");
432 }
433 }, null);
434 fail("emptyCase should have been called --");
435 }
436 catch (SuccessException e) {
437 }
438
439
440 GenericFish f = new GenericFish(Color.RED);
441 f.setLocalEnvironment(l);
442 _env.addFish(l, f);
443 l.setState(NonEmptyLocalEnvState.Singleton);
444 try {
445 l.execute(new AGlobalEnv.ILocalEnvVisitor() {
446 public Object emptyCase(ALocalEnv host, Object param) {
447 throw new RuntimeException("Should be non-empty");
448 }
449
450 public Object nonEmptyCase(ALocalEnv host, Object param) {
451 // ok
452 throw new SuccessException();
453 }
454 }, null);
455 fail("nonEmptyCase should have been called --");
456 }
457 catch (SuccessException e) {
458 }
459
460 ALocalEnv l2 = _env.makeLocalEnv(new Point.Double(1, 1));
461 try {
462 l2.execute(new AGlobalEnv.ILocalEnvVisitor() {
463 public Object emptyCase(ALocalEnv host, Object param) {
464 throw new RuntimeException("Should be non-empty");
465 }
466
467 public Object nonEmptyCase(ALocalEnv host, Object param) {
468 // ok
469 throw new SuccessException();
470 }
471 }, null);
472 fail("nonEmptyCase should have been called --");
473 }
474 catch (SuccessException e) {
475 }
476
477 ALocalEnv l3 = _env.makeLocalEnv(new Point.Double(1.4, 1.6));
478 try {
479 l3.execute(new AGlobalEnv.ILocalEnvVisitor() {
480 public Object emptyCase(ALocalEnv host, Object param) {
481 throw new RuntimeException("Should be non-empty");
482 }
483
484 public Object nonEmptyCase(ALocalEnv host, Object param) {
485 // ok
486 throw new SuccessException();
487 }
488 }, null);
489 fail("nonEmptyCase should have been called --");
490 }
491 catch (SuccessException e) {
492 }
493
494 ALocalEnv l4 = _env.makeLocalEnv(new Point.Double(1.0, 2.0));
495 try {
496 l4.execute(new AGlobalEnv.ILocalEnvVisitor() {
497 public Object emptyCase(ALocalEnv host, Object param) {
498 // ok
499 throw new SuccessException();
500 }
501
502 public Object nonEmptyCase(ALocalEnv host, Object param) {
503 throw new RuntimeException("Should be empty");
504 }
505 }, null);
506 fail("emptyCase should have been called --");
507 }
508 catch (SuccessException e) {
509 }
510
511 GenericFish f4 = new GenericFish(Color.RED);
512 f4.setLocalEnvironment(l4);
513 _env.addFish(l4, f4);
514 l4.setState(NonEmptyLocalEnvState.Singleton);
515 try {
516 l4.execute(new AGlobalEnv.ILocalEnvVisitor() {
517 public Object emptyCase(ALocalEnv host, Object param) {
518 throw new RuntimeException("Should be non-empty");
519 }
520
521 public Object nonEmptyCase(ALocalEnv host, Object param) {
522 // ok
523 throw new SuccessException();
524 }
525 }, null);
526 fail("nonEmptyCase should have been called --");
527 }
528 catch (SuccessException e) {
529 }
530 }
531
532 /**
533 * Test local environment's tryMoveFwd.
534 */
535 public void testTryMoveFwd() {
536 ALocalEnv lTop = _env.makeLocalEnv(new Point.Double(1.0, 1.0));
537 GenericFish fTop = new GenericFish(Color.RED);
538 fTop.setLocalEnvironment(lTop);
539 _env.addFish(lTop, fTop);
540 lTop.setState(NonEmptyLocalEnvState.Singleton);
541
542 ALocalEnv lBottom = _env.makeLocalEnv(new Point.Double(1.0, 2.0));
543 GenericFish fBottom = new GenericFish(Color.RED);
544 fBottom.setLocalEnvironment(lBottom);
545 _env.addFish(lBottom, fBottom);
546 lBottom.setState(NonEmptyLocalEnvState.Singleton);
547
548 // move lBottom into lTop --> blocked
549 Integer i = (Integer) lBottom.tryMoveFwd(fBottom, new IBlockedCommand() {
550 public Object apply(Object param) {
551 // ok
552 return new Integer(456);
553 }
554 }, new IOpenCommand() {
555 public Object apply(Object param) {
556 throw new RuntimeException("Should be blocked");
557 }
558 });
559 assertEquals("Error in delegation, blockedCmd not called, or incorrect return value --",
560 new Integer(456),
561 i);
562
563 // move lTop --> open, don't move
564 i = (Integer) lTop.tryMoveFwd(fTop, new IBlockedCommand() {
565 public Object apply(Object param) {
566 throw new RuntimeException("Should be open");
567 }
568 }, new IOpenCommand() {
569 public Object apply(Object param) {
570 assertNotNull("Error, deactivatable move lambda needs to be passed to openCmd --", param);
571 assertEquals("Error, deactivatable move lambda needs to be passed to openCmd --",
572 DeactivatableLambda.class,
573 param.getClass());
574 // ok
575 return new Integer(123);
576 }
577 });
578 assertEquals("Error in delegation, openCmd not called, or incorrect return value --", new Integer(123), i);
579
580 // move lBottom into lTop --> blocked
581 i = (Integer) lBottom.tryMoveFwd(fBottom, new IBlockedCommand() {
582 public Object apply(Object param) {
583 // ok
584 return new Integer(789);
585 }
586 }, new IOpenCommand() {
587 public Object apply(Object param) {
588 throw new RuntimeException("Should be blocked");
589 }
590 });
591 assertEquals("Error in delegation, blockedCmd not called, or incorrect return value --",
592 new Integer(789),
593 i);
594
595 // move lTop --> open, move
596 i = (Integer) lTop.tryMoveFwd(fTop, new IBlockedCommand() {
597 public Object apply(Object param) {
598 throw new RuntimeException("Should be open");
599 }
600 }, new IOpenCommand() {
601 public Object apply(Object param) {
602 assertNotNull("Error, deactivatable move lambda needs to be passed to openCmd --", param);
603 assertEquals("Error, deactivatable move lambda needs to be passed to openCmd --",
604 DeactivatableLambda.class,
605 param.getClass());
606 // ok, make move
607 ((ILambda) param).apply(null);
608 return new Integer(111);
609 }
610 });
611 assertEquals("Error in delegation, openCmd not called, or incorrect return value --", new Integer(111), i);
612
613 // move lBottom --> open
614 i = (Integer) lBottom.tryMoveFwd(fBottom, new IBlockedCommand() {
615 public Object apply(Object param) {
616 throw new RuntimeException("Should be open");
617 }
618 }, new IOpenCommand() {
619 public Object apply(Object param) {
620 assertNotNull("Error, deactivatable move lambda needs to be passed to openCmd --", param);
621 assertEquals("Error, deactivatable move lambda needs to be passed to openCmd --",
622 DeactivatableLambda.class,
623 param.getClass());
624 // ok
625 return new Integer(222);
626 }
627 });
628 assertEquals("Error in delegation, openCmd not called, or incorrect return value --", new Integer(222), i);
629
630 // move lTop into edge, wrap --> open
631 i = (Integer) lTop.tryMoveFwd(fTop, new IBlockedCommand() {
632 public Object apply(Object param) {
633 throw new RuntimeException("Should be open");
634 }
635 }, new IOpenCommand() {
636 public Object apply(Object param) {
637 assertNotNull("Error, deactivatable move lambda needs to be passed to openCmd --", param);
638 assertEquals("Error, deactivatable move lambda needs to be passed to openCmd --",
639 DeactivatableLambda.class,
640 param.getClass());
641 // ok
642 return new Integer(333);
643 }
644 });
645 assertEquals("Error in delegation, openCmd not called, or incorrect return value --", new Integer(333), i);
646
647 // turn and move lTop --> open
648 lTop.turnRight(fTop, Math.PI / 2.0);
649 i = (Integer) lTop.tryMoveFwd(fTop, new IBlockedCommand() {
650 public Object apply(Object param) {
651 throw new RuntimeException("Should be open");
652 }
653 }, new IOpenCommand() {
654 public Object apply(Object param) {
655 assertNotNull("Error, deactivatable move lambda needs to be passed to openCmd --", param);
656 assertEquals("Error, deactivatable move lambda needs to be passed to openCmd --",
657 DeactivatableLambda.class,
658 param.getClass());
659 // ok
660 return new Integer(444);
661 }
662 });
663 assertEquals("Error in delegation, openCmd not called, or incorrect return value --", new Integer(444), i);
664 }
665
666 int countNonEmpty() {
667 int count = 0;
668 WrappingEnv.IField[][] map = _env._fieldMap;
669 IFieldVisitor countVisitor = new IFieldVisitor() {
670 public Object emptyCase(EmptyField host, Object param) {
671 return new Integer(0);
672 }
673
674 public Object nonEmptyCase(NonEmptyField host, Object param) {
675 return new Integer(1);
676 }
677 };
678 for (int i = 0; i < map.length; i++) {
679 WrappingEnv.IField[] iFields = map[i];
680 for (int j = 0; j < iFields.length; j++) {
681 WrappingEnv.IField iField = iFields[j];
682 count += ((Integer) iField.execute(countVisitor, null)).intValue();
683 }
684 }
685 return count;
686 }
687
688 /**
689 * Test local environment's tryBreedFwd.
690 */
691 public void testTryBreedFwd() {
692 assertEquals(0, countNonEmpty());
693
694 ALocalEnv lTop = _env.makeLocalEnv(new Point.Double(1.0, 1.0));
695 GenericFish fTop = new GenericFish(Color.RED);
696 fTop.setLocalEnvironment(lTop);
697 _env.addFish(lTop, fTop);
698 lTop.setState(NonEmptyLocalEnvState.Singleton);
699
700 assertEquals(1, countNonEmpty());
701
702 ALocalEnv lBottom = _env.makeLocalEnv(new Point.Double(1.0, 2.0));
703 GenericFish fBottom = new GenericFish(Color.RED);
704 fBottom.setLocalEnvironment(lBottom);
705 _env.addFish(lBottom, fBottom);
706 lBottom.setState(NonEmptyLocalEnvState.Singleton);
707
708 assertEquals(2, countNonEmpty());
709
710 // breed lBottom into lTop --> blocked
711 Integer i = (Integer) lBottom.tryBreedFwd(fBottom, new IBlockedCommand() {
712 public Object apply(Object param) {
713 // ok
714 return new Integer(456);
715 }
716 }, new IOpenCommand() {
717 public Object apply(Object param) {
718 throw new RuntimeException("Should be blocked");
719 }
720 });
721 assertEquals("Error in delegation, blockedCmd not called, or incorrect return value --",
722 new Integer(456),
723 i);
724
725 // breed lTop --> open, don't breed
726 i = (Integer) lTop.tryBreedFwd(fTop, new IBlockedCommand() {
727 public Object apply(Object param) {
728 throw new RuntimeException("Should be open");
729 }
730 }, new IOpenCommand() {
731 public Object apply(Object param) {
732 assertNotNull("Error, deactivatable breed lambda needs to be passed to openCmd --", param);
733 assertEquals("Error, deactivatable breed lambda needs to be passed to openCmd --",
734 DeactivatableLambda.class,
735 param.getClass());
736 // ok
737 return new Integer(123);
738 }
739 });
740 assertEquals("Error in delegation, openCmd not called, or incorrect return value --", new Integer(123), i);
741
742 assertEquals(2, countNonEmpty());
743
744 // breed lBottom into lTop --> blocked
745 i = (Integer) lBottom.tryBreedFwd(fBottom, new IBlockedCommand() {
746 public Object apply(Object param) {
747 // ok
748 return new Integer(456);
749 }
750 }, new IOpenCommand() {
751 public Object apply(Object param) {
752 throw new RuntimeException("Should be blocked");
753 }
754 });
755 assertEquals("Error in delegation, blockedCmd not called, or incorrect return value --",
756 new Integer(456),
757 i);
758
759 // breed lTop --> open, breed
760 i = (Integer) lTop.tryBreedFwd(fTop, new IBlockedCommand() {
761 public Object apply(Object param) {
762 throw new RuntimeException("Should be open");
763 }
764 }, new IOpenCommand() {
765 public Object apply(Object param) {
766 assertNotNull("Error, deactivatable breed lambda needs to be passed to openCmd --", param);
767 assertEquals("Error, deactivatable breed lambda needs to be passed to openCmd --",
768 DeactivatableLambda.class,
769 param.getClass());
770 // ok, breed
771 ((ILambda) param).apply(null);
772 return new Integer(123);
773 }
774 });
775 assertEquals("Error in delegation, openCmd not called, or incorrect return value --", new Integer(123), i);
776
777 assertEquals(3, countNonEmpty());
778
779 // breed lBottom into lTop --> blocked
780 i = (Integer) lBottom.tryBreedFwd(fBottom, new IBlockedCommand() {
781 public Object apply(Object param) {
782 // ok
783 return new Integer(456);
784 }
785 }, new IOpenCommand() {
786 public Object apply(Object param) {
787 throw new RuntimeException("Should be blocked");
788 }
789 });
790 assertEquals("Error in delegation, blockedCmd not called, or incorrect return value --",
791 new Integer(456),
792 i);
793
794 // breed lTop --> blocked
795 i = (Integer) lTop.tryBreedFwd(fTop, new IBlockedCommand() {
796 public Object apply(Object param) {
797 // ok
798 return new Integer(456);
799 }
800 }, new IOpenCommand() {
801 public Object apply(Object param) {
802 throw new RuntimeException("Should be blocked");
803 }
804 });
805 assertEquals("Error in delegation, blockedCmd not called, or incorrect return value --",
806 new Integer(456),
807 i);
808
809 // turn and breed lTop --> open, don't breed
810 lTop.turnRight(fTop, Math.PI / 2.0);
811 i = (Integer) lTop.tryBreedFwd(fTop, new IBlockedCommand() {
812 public Object apply(Object param) {
813 throw new RuntimeException("Should be open");
814 }
815 }, new IOpenCommand() {
816 public Object apply(Object param) {
817 assertNotNull("Error, deactivatable breed lambda needs to be passed to openCmd --", param);
818 assertEquals("Error, deactivatable breed lambda needs to be passed to openCmd --",
819 DeactivatableLambda.class,
820 param.getClass());
821 // ok
822 return new Integer(789);
823 }
824 });
825 assertEquals("Error in delegation, openCmd not called, or incorrect return value --", new Integer(789), i);
826
827 assertEquals(3, countNonEmpty());
828
829 // turn and breed lTop --> open, breed
830 i = (Integer) lTop.tryBreedFwd(fTop, new IBlockedCommand() {
831 public Object apply(Object param) {
832 throw new RuntimeException("Should be open");
833 }
834 }, new IOpenCommand() {
835 public Object apply(Object param) {
836 assertNotNull("Error, deactivatable breed lambda needs to be passed to openCmd --", param);
837 assertEquals("Error, deactivatable breed lambda needs to be passed to openCmd --",
838 DeactivatableLambda.class,
839 param.getClass());
840 // ok, breed
841 ((ILambda) param).apply(null);
842 return new Integer(789);
843 }
844 });
845 assertEquals("Error in delegation, openCmd not called, or incorrect return value --", new Integer(789), i);
846
847 assertEquals(4, countNonEmpty());
848
849 // turn and breed lTop --> blocked
850 i = (Integer) lTop.tryBreedFwd(fTop, new IBlockedCommand() {
851 public Object apply(Object param) {
852 // ok
853 return new Integer(789);
854 }
855 }, new IOpenCommand() {
856 public Object apply(Object param) {
857 throw new RuntimeException("Should be blocked");
858 }
859 });
860 assertEquals("Error in delegation, blockedCmd not called, or incorrect return value --",
861 new Integer(789),
862 i);
863
864 assertEquals(4, countNonEmpty());
865 }
866
867 /**
868 * Test local environment's turnRight.
869 */
870 public void testTurnRight() {
871 ASquareLocalEnvironment l = (ASquareLocalEnvironment) _env.makeLocalEnv(new Point.Double(1.0, 1.0));
872 GenericFish f = new GenericFish(Color.RED);
873 f.setLocalEnvironment(l);
874 _env.addFish(l, f);
875 l.setState(NonEmptyLocalEnvState.Singleton);
876 WrappingEnv.Direction d = l.direction();
877
878 assertEquals(0.0, d.getAngle(), 0.01);
879 l.turnRight(f, Math.PI / 2);
880 assertEquals(Math.PI / 2.0, d.getAngle(), 0.01);
881 l.turnRight(f, Math.PI / 2);
882 assertEquals(Math.PI, d.getAngle(), 0.01);
883 l.turnRight(f, Math.PI / 2);
884 assertEquals(3 * Math.PI / 2.0, d.getAngle(), 0.01);
885 l.turnRight(f, Math.PI / 2);
886 assertEquals(0, d.getAngle(), 0.01);
887 }
888
889 /**
890 * Test local environment's removeFish.
891 */
892 public void testRemoveFish() {
893 assertEquals(0, countNonEmpty());
894
895 ALocalEnv lTop = _env.makeLocalEnv(new Point.Double(1.0, 1.0));
896 GenericFish fTop = new GenericFish(Color.RED);
897 fTop.setLocalEnvironment(lTop);
898 _env.addFish(lTop, fTop);
899 lTop.setState(NonEmptyLocalEnvState.Singleton);
900
901 assertEquals(1, countNonEmpty());
902
903 ALocalEnv lBottom = _env.makeLocalEnv(new Point.Double(1.0, 2.0));
904 GenericFish fBottom = new GenericFish(Color.RED);
905 fBottom.setLocalEnvironment(lBottom);
906 _env.addFish(lBottom, fBottom);
907 lBottom.setState(NonEmptyLocalEnvState.Singleton);
908
909 assertEquals(2, countNonEmpty());
910
911 lTop.removeFish(fTop);
912
913 assertEquals(1, countNonEmpty());
914
915 lBottom.removeFish(fBottom);
916
917 assertEquals(0, countNonEmpty());
918 }
919
920 /**
921 * Test to make sure only one move lambda can be executed.
922 */
923 public void testOnlyOneMove() {
924 ASquareLocalEnvironment l = (ASquareLocalEnvironment) _env.makeLocalEnv(new Point.Double(5.0, 5.0));
925 GenericFish f = new GenericFish(Color.RED);
926 f.setLocalEnvironment(l);
927 _env.addFish(l, f);
928 l.setState(NonEmptyLocalEnvState.Singleton);
929
930 final LinkedList<ILambda> lambdas = new LinkedList<ILambda>();
931 l.tryMoveFwd(f, new IBlockedCommand() {
932 public Object apply(Object param) {
933 throw new RuntimeException("Should be open");
934 }
935 }, new IOpenCommand() {
936 public Object apply(Object param) {
937 lambdas.add((ILambda)param);
938 return null;
939 }
940 });
941 f.turnRight();
942 l.tryMoveFwd(f, new IBlockedCommand() {
943 public Object apply(Object param) {
944 throw new RuntimeException("Should be open");
945 }
946 }, new IOpenCommand() {
947 public Object apply(Object param) {
948 lambdas.add((ILambda)param);
949 return null;
950 }
951 });
952
953 assertEquals(2, lambdas.size());
954
955 lambdas.get(0).apply(null);
956 Location loc = (Location) l.location();
957 assertTrue(loc.same(_env.makeLocation(5.0, 4.0)));
958
959 lambdas.get(1).apply(null);
960 loc = (Location) l.location();
961 assertTrue(loc.same(_env.makeLocation(5.0, 4.0)));
962
963 lambdas.clear();
964 l.tryMoveFwd(f, new IBlockedCommand() {
965 public Object apply(Object param) {
966 throw new RuntimeException("Should be open");
967 }
968 }, new IOpenCommand() {
969 public Object apply(Object param) {
970 lambdas.add((ILambda)param);
971 return null;
972 }
973 });
974 f.turnRight();
975 l.tryMoveFwd(f, new IBlockedCommand() {
976 public Object apply(Object param) {
977 throw new RuntimeException("Should be open");
978 }
979 }, new IOpenCommand() {
980 public Object apply(Object param) {
981 lambdas.add((ILambda)param);
982 return null;
983 }
984 });
985
986 assertEquals(2, lambdas.size());
987
988 lambdas.get(1).apply(null);
989 loc = (Location) l.location();
990 assertTrue(loc.same(_env.makeLocation(6.0, 4.0)));
991
992 lambdas.get(0).apply(null);
993 loc = (Location) l.location();
994 assertTrue(loc.same(_env.makeLocation(6.0, 4.0)));
995 }
996
997 }
998
999 /**
1000 * Test cases for WrappingEnv.Location.
1001 *
1002 * @author Mathias Ricken
1003 */
1004 public static class Test_WrappingEnv_Location extends TestCase {
1005 private ICmdFactory _cmdFactory;
1006 private ISecurityAdapter _sm;
1007 private WrappingEnv _env;
1008
1009 private static final ILambda _notify = new ILambda() {
1010 public Object apply(Object param) {
1011 return "notifyCmd";
1012 }
1013 };
1014 private static final ILambda _delete = new ILambda() {
1015 public Object apply(Object param) {
1016 return "deleteCmd";
1017 }
1018 };
1019 private static final ILambda _add = new ILambda() {
1020 public Object apply(Object param) {
1021 return "addCmd";
1022 }
1023 };
1024
1025 public void setUp() throws Exception {
1026 super.setUp();
1027 _cmdFactory = new ICmdFactory() {
1028 public ILambda makeNotifyCmd(ILambda lambda) {
1029 return _notify;
1030 }
1031
1032 public ILambda makeDeleteCmd(ALocalEnv env) {
1033 return _delete;
1034 }
1035
1036 public ILambda makeAddCmd(AFish fish) {
1037 return _add;
1038 }
1039 };
1040 _sm = new ISecurityAdapter() {
1041 public void setProtected(boolean _protected) {
1042 }
1043 public ThreadGroup getFishThreadGroup() {
1044 return null;
1045 }
1046 public ClassLoader getClassLoader() {
1047 return null;
1048 }
1049 public void handleException(Throwable t) {
1050 }
1051 };
1052
1053 _env = new WrappingEnv(_cmdFactory, _sm, 50, 50);
1054 }
1055
1056 /**
1057 * Test getters, setters, and ctor.
1058 */
1059 public void testGetSet() {
1060 ASquareEnv.Location l = _env.makeLocation(5, 7);
1061 assertEquals(5.0, l.getX(), 0.01);
1062 assertEquals(7.0, l.getY(), 0.01);
1063
1064 l.setX(11);
1065 assertEquals(11.0, l.getX(), 0.01);
1066 assertEquals(7.0, l.getY(), 0.01);
1067
1068 l.setY(13);
1069 assertEquals(11.0, l.getX(), 0.01);
1070 assertEquals(13.0, l.getY(), 0.01);
1071 }
1072
1073 /**
1074 * Test same.
1075 */
1076 public void testSame() {
1077 ASquareEnv.Location l = _env.makeLocation(17, 23);
1078 ASquareEnv.Location l1 = _env.makeLocation(17, 23);
1079 ASquareEnv.Location l2 = _env.makeLocation(31, 37);
1080 assertEquals(true, l.same(l1));
1081 assertEquals(false, l.same(l2));
1082 assertEquals(true, l1.same(l));
1083 assertEquals(false, l2.same(l));
1084 assertEquals(false, l2.same(l1));
1085 assertEquals(false, l1.same(l2));
1086 }
1087
1088 /**
1089 * Test inField.
1090 */
1091 public void testInField() {
1092 ASquareEnv.Location l = _env.makeLocation(17, 23);
1093 ASquareEnv.Location l1 = _env.makeLocation(17, 23);
1094 ASquareEnv.Location l2 = _env.makeLocation(17.13, 23.53);
1095 ASquareEnv.Location l3 = _env.makeLocation(17.49, 23.77);
1096 ASquareEnv.Location l4 = _env.makeLocation(31, 37);
1097 ASquareEnv.Location l5 = _env.makeLocation(31.81, 37.51);
1098 assertEquals(true, l.inField(l1));
1099 assertEquals(true, l1.inField(l));
1100 assertEquals(true, l.inField(l2));
1101 assertEquals(true, l2.inField(l));
1102 assertEquals(true, l.inField(l3));
1103 assertEquals(true, l3.inField(l));
1104 assertEquals(false, l.inField(l4));
1105 assertEquals(false, l4.inField(l));
1106 assertEquals(false, l.inField(l5));
1107 assertEquals(false, l5.inField(l));
1108 }
1109
1110 /**
1111 * Test getNeighbor.
1112 */
1113 public void testNeighbor() {
1114 ASquareEnv.Location l = _env.makeLocation(17, 23);
1115 ASquareEnv.Location l1 = _env.makeLocation(17, 22);
1116 ASquareEnv.Location l2 = _env.makeLocation(18, 22);
1117 ASquareEnv.Location l3 = _env.makeLocation(18, 23);
1118 ASquareEnv.Location l4 = _env.makeLocation(17, 23);
1119 l = l.getNeighbor(_env.makeDirection(0, -1));
1120 assertEquals(true, l.same(l1));
1121 l = l.getNeighbor(_env.makeDirection(1, 0));
1122 assertEquals(true, l.same(l2));
1123 l = l.getNeighbor(_env.makeDirection(0, 1));
1124 assertEquals(true, l.same(l3));
1125 l = l.getNeighbor(_env.makeDirection(-1, 0));
1126 assertEquals(true, l.same(l4));
1127
1128 // test wrapping
1129 ASquareEnv.Location w = _env.makeLocation(0, 0);
1130 ASquareEnv.Location w1 = _env.makeLocation(0, 49);
1131 ASquareEnv.Location w2 = _env.makeLocation(49, 49);
1132 ASquareEnv.Location w3 = _env.makeLocation(49, 0);
1133 ASquareEnv.Location w4 = _env.makeLocation(0, 0);
1134 w = w.getNeighbor(_env.makeDirection(0, -1));
1135 assertEquals(true, w.same(w1));
1136 w = w.getNeighbor(_env.makeDirection(-1, 0));
1137 assertEquals(true, w.same(w2));
1138 w = w.getNeighbor(_env.makeDirection(0, 1));
1139 assertEquals(true, w.same(w3));
1140 w = w.getNeighbor(_env.makeDirection(1, 0));
1141 assertEquals(true, w.same(w4));
1142 }
1143 }
1144 }