source: josm/trunk/test/unit/org/openstreetmap/josm/command/SequenceCommandTest.java@ 16682

Last change on this file since 16682 was 16682, checked in by simon04, 4 years ago

see #19407 - Add SequenceCommandTest.testCreateReportedException

File size: 12.9 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.command;
3
4import static org.junit.Assert.assertArrayEquals;
5import static org.junit.Assert.assertEquals;
6import static org.junit.Assert.assertFalse;
7import static org.junit.Assert.assertNotSame;
8import static org.junit.Assert.assertNull;
9import static org.junit.Assert.assertSame;
10import static org.junit.Assert.assertTrue;
11import static org.junit.Assert.fail;
12import static org.junit.jupiter.api.Assertions.assertThrows;
13
14import java.io.PrintWriter;
15import java.io.StringWriter;
16import java.util.ArrayList;
17import java.util.Arrays;
18import java.util.Collection;
19import java.util.Collections;
20
21import org.junit.Before;
22import org.junit.Rule;
23import org.junit.Test;
24import org.openstreetmap.josm.TestUtils;
25import org.openstreetmap.josm.command.CommandTest.CommandTestDataWithRelation;
26import org.openstreetmap.josm.data.osm.DataSet;
27import org.openstreetmap.josm.data.osm.Node;
28import org.openstreetmap.josm.data.osm.OsmPrimitive;
29import org.openstreetmap.josm.data.osm.User;
30import org.openstreetmap.josm.gui.layer.OsmDataLayer;
31import org.openstreetmap.josm.testutils.JOSMTestRules;
32import org.openstreetmap.josm.tools.bugreport.ReportedException;
33
34import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
35import nl.jqno.equalsverifier.EqualsVerifier;
36import nl.jqno.equalsverifier.Warning;
37
38/**
39 * Unit tests of {@link SequenceCommand} class.
40 */
41public class SequenceCommandTest {
42
43 /**
44 * We need prefs for nodes.
45 */
46 @Rule
47 @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
48 public JOSMTestRules test = new JOSMTestRules().preferences();
49 private CommandTestDataWithRelation testData;
50
51 /**
52 * Set up the test data.
53 */
54 @Before
55 public void createTestData() {
56 testData = new CommandTestDataWithRelation();
57 }
58
59 /**
60 * Test {@link SequenceCommand#executeCommand()}
61 */
62 @Test
63 public void testExecute() {
64 DataSet ds = new DataSet();
65 final TestCommand command1 = new TestCommand(ds, Arrays.<OsmPrimitive>asList(testData.existingNode));
66 TestCommand command2 = new TestCommand(ds, Arrays.<OsmPrimitive>asList(testData.existingNode2)) {
67 @Override
68 public boolean executeCommand() {
69 assertTrue(command1.executed);
70 return super.executeCommand();
71 }
72 };
73 SequenceCommand command = new SequenceCommand("seq", Arrays.<Command>asList(command1, command2));
74
75 command.executeCommand();
76
77 assertTrue(command1.executed);
78 assertTrue(command2.executed);
79 }
80
81 /**
82 * Test {@link SequenceCommand#undoCommand()}
83 */
84 @Test
85 public void testUndo() {
86 DataSet ds = new DataSet();
87 final TestCommand command2 = new TestCommand(ds, Arrays.<OsmPrimitive>asList(testData.existingNode2));
88 TestCommand command1 = new TestCommand(ds, Arrays.<OsmPrimitive>asList(testData.existingNode)) {
89 @Override
90 public void undoCommand() {
91 assertFalse(command2.executed);
92 super.undoCommand();
93 }
94 };
95 SequenceCommand command = new SequenceCommand("seq", Arrays.<Command>asList(command1, command2));
96
97 command.executeCommand();
98
99 command.undoCommand();
100
101 assertFalse(command1.executed);
102 assertFalse(command2.executed);
103
104 command.executeCommand();
105
106 assertTrue(command1.executed);
107 assertTrue(command2.executed);
108 }
109
110 /**
111 * Test {@link SequenceCommand#executeCommand()} rollback if case of subcommand failure.
112 */
113 @Test
114 public void testExecuteRollback() {
115 DataSet ds = new DataSet();
116 TestCommand command1 = new TestCommand(ds, null);
117 FailingCommand command2 = new FailingCommand(ds);
118 TestCommand command3 = new TestCommand(ds, null);
119 SequenceCommand command = new SequenceCommand("seq", Arrays.<Command>asList(command1, command2, command3));
120 assertFalse(command.executeCommand());
121 assertFalse(command1.executed);
122 // Don't check command2 executed state as it's possible but not necessary to undo failed commands
123 assertFalse(command3.executed);
124 command.undoCommand();
125 }
126
127 /**
128 * Test {@link SequenceCommand#executeCommand()} with continueOnError = true
129 */
130 @Test
131 public void testContinueOnErrors() {
132 DataSet ds = new DataSet();
133 TestCommand command1 = new TestCommand(ds, null);
134 FailingCommand command2 = new FailingCommand(ds);
135 TestCommand command3 = new TestCommand(ds, null);
136 SequenceCommand command = new SequenceCommand("seq", Arrays.<Command>asList(command1, command2, command3), true);
137 assertTrue(command.executeCommand());
138 assertTrue(command1.executed);
139 assertTrue(command3.executed);
140 command.undoCommand();
141 assertFalse(command1.executed);
142 // Don't check command2 executed state as it's possible but not necessary to undo failed commands
143 assertFalse(command3.executed);
144 }
145
146 /**
147 * Test {@link SequenceCommand#undoCommand()}
148 */
149 @Test
150 public void testGetLastCommand() {
151 DataSet ds = new DataSet();
152 final TestCommand command1 = new TestCommand(ds, Arrays.<OsmPrimitive>asList(testData.existingNode));
153 final TestCommand command2 = new TestCommand(ds, Arrays.<OsmPrimitive>asList(testData.existingNode2));
154
155 assertEquals(command2, new SequenceCommand(ds, "seq", Arrays.asList(command1, command2), false).getLastCommand());
156 assertNull(new SequenceCommand(ds, "seq", Collections.emptyList(), false).getLastCommand());
157 }
158
159 /**
160 * Tests {@link SequenceCommand#fillModifiedData(java.util.Collection, java.util.Collection, java.util.Collection)}
161 */
162 @Test
163 public void testFillModifiedData() {
164 DataSet ds = new DataSet();
165 Command command1 = new TestCommand(ds, Arrays.<OsmPrimitive>asList(testData.existingNode));
166 Command command2 = new TestCommand(ds, Arrays.<OsmPrimitive>asList(testData.existingNode2));
167 Command command3 = new TestCommand(ds, Arrays.<OsmPrimitive>asList(testData.existingWay)) {
168 @Override
169 public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted,
170 Collection<OsmPrimitive> added) {
171 deleted.addAll(primitives);
172 }
173 };
174 Command command4 = new TestCommand(ds, Arrays.<OsmPrimitive>asList(testData.existingRelation)) {
175 @Override
176 public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted,
177 Collection<OsmPrimitive> added) {
178 added.addAll(primitives);
179 }
180 };
181
182 ArrayList<OsmPrimitive> modified = new ArrayList<>();
183 ArrayList<OsmPrimitive> deleted = new ArrayList<>();
184 ArrayList<OsmPrimitive> added = new ArrayList<>();
185 SequenceCommand command = new SequenceCommand("seq", command1, command2, command3, command4);
186 command.fillModifiedData(modified, deleted, added);
187 assertArrayEquals(new Object[] {testData.existingNode, testData.existingNode2}, modified.toArray());
188 assertArrayEquals(new Object[] {testData.existingWay}, deleted.toArray());
189 assertArrayEquals(new Object[] {testData.existingRelation}, added.toArray());
190 }
191
192 /**
193 * Tests {@link SequenceCommand#getParticipatingPrimitives()}
194 */
195 @Test
196 public void testGetParticipatingPrimitives() {
197 DataSet ds = new DataSet();
198 Command command1 = new TestCommand(ds, Arrays.<OsmPrimitive>asList(testData.existingNode));
199 Command command2 = new TestCommand(ds, Arrays.<OsmPrimitive>asList(testData.existingNode2));
200
201 SequenceCommand command = new SequenceCommand("seq", command1, command2);
202 command.executeCommand();
203 Collection<? extends OsmPrimitive> primitives = command.getParticipatingPrimitives();
204 assertEquals(2, primitives.size());
205 assertTrue(primitives.contains(testData.existingNode));
206 assertTrue(primitives.contains(testData.existingNode2));
207 }
208
209 /**
210 * Test {@link SequenceCommand#getDescriptionText()}
211 */
212 @Test
213 public void testDescription() {
214 assertTrue(new SequenceCommand(new DataSet(), "test", Collections.emptyList(), false).getDescriptionText().matches("Sequence: test"));
215 }
216
217 /**
218 * Unit test of methods {@link SequenceCommand#equals} and {@link SequenceCommand#hashCode}.
219 */
220 @Test
221 public void testEqualsContract() {
222 DataSet ds = new DataSet();
223 TestUtils.assumeWorkingEqualsVerifier();
224 EqualsVerifier.forClass(SequenceCommand.class).usingGetClass()
225 .withPrefabValues(Command.class,
226 new AddCommand(ds, new Node(1)), new AddCommand(ds, new Node(2)))
227 .withPrefabValues(DataSet.class,
228 new DataSet(), new DataSet())
229 .withPrefabValues(User.class,
230 User.createOsmUser(1, "foo"), User.createOsmUser(2, "bar"))
231 .withPrefabValues(OsmDataLayer.class,
232 new OsmDataLayer(new DataSet(), "1", null), new OsmDataLayer(new DataSet(), "2", null))
233 .suppress(Warning.NONFINAL_FIELDS)
234 .verify();
235 }
236
237 private static class TestCommand extends Command {
238 protected final Collection<? extends OsmPrimitive> primitives;
239 protected boolean executed;
240
241 TestCommand(DataSet ds, Collection<? extends OsmPrimitive> primitives) {
242 super(ds);
243 this.primitives = primitives;
244 }
245
246 @Override
247 public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted,
248 Collection<OsmPrimitive> added) {
249 modified.addAll(primitives);
250 }
251
252 @Override
253 public String getDescriptionText() {
254 fail("Should not be called");
255 return "";
256 }
257
258 @Override
259 public Collection<? extends OsmPrimitive> getParticipatingPrimitives() {
260 return primitives;
261 }
262
263 @Override
264 public boolean executeCommand() {
265 assertFalse("Cannot execute twice", executed);
266 executed = true;
267 return true;
268 }
269
270 @Override
271 public void undoCommand() {
272 assertTrue("Cannot undo without execute", executed);
273 executed = false;
274 }
275
276 @Override
277 public String toString() {
278 return "TestCommand [primitives=" + primitives + "]";
279 }
280
281 }
282
283 private static class FailingCommand extends TestCommand {
284
285 FailingCommand(DataSet ds) {
286 super(ds, null);
287 }
288
289 @Override
290 public boolean executeCommand() {
291 executed = true;
292 return false;
293 }
294
295 @Override
296 public void undoCommand() {
297 assertTrue("Cannot undo without execute", executed);
298 executed = false;
299 }
300
301 @Override
302 public String toString() {
303 return "FailingCommand";
304 }
305 }
306
307 /**
308 * Test {@link SequenceCommand#wrapIfNeeded}
309 */
310 @Test
311 public void testWrapIfNeeded() {
312 DataSet ds = new DataSet();
313 TestCommand command1 = new TestCommand(ds, Collections.<OsmPrimitive>singletonList(testData.existingNode));
314 TestCommand command2 = new TestCommand(ds, Collections.<OsmPrimitive>singletonList(testData.existingNode2));
315 assertSame(command1, SequenceCommand.wrapIfNeeded("foo", command1));
316 assertNotSame(command1, SequenceCommand.wrapIfNeeded("foo", command1, command2));
317 assertEquals(new SequenceCommand("foo", command1, command2), SequenceCommand.wrapIfNeeded("foo", command1, command2));
318 }
319
320 /**
321 * Test SequenceCommand#createReportedException
322 */
323 @Test
324 public void testCreateReportedException() {
325 DataSet ds = new DataSet();
326 Command c1 = new TestCommand(ds, Collections.emptyList()) {
327 @Override
328 public boolean executeCommand() {
329 fail("foo");
330 return false;
331 }
332
333 @Override
334 public String getDescriptionText() {
335 return "foo command";
336 }
337 };
338 SequenceCommand command = new SequenceCommand("test", c1);
339 ReportedException reportedException = assertThrows(ReportedException.class, command::executeCommand);
340 StringWriter stringWriter = new StringWriter();
341 reportedException.printReportDataTo(new PrintWriter(stringWriter));
342 assertEquals("=== REPORTED CRASH DATA ===\n" +
343 "sequence_information:\n" +
344 " - sequence_name: Sequence: test\n" +
345 " - sequence_command: foo command\n" +
346 " - sequence_index: 0\n" +
347 " - sequence_commands: [null]\n" +
348 " - sequence_commands_descriptions: [foo command]\n" +
349 "\n", stringWriter.toString());
350 }
351}
Note: See TracBrowser for help on using the repository browser.