// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.command;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.openstreetmap.josm.command.CommandTest.CommandTestData;
import org.openstreetmap.josm.data.osm.DataSet;
import org.openstreetmap.josm.data.osm.Node;
import org.openstreetmap.josm.data.osm.OsmPrimitive;
import org.openstreetmap.josm.data.osm.Relation;
import org.openstreetmap.josm.data.osm.TagMap;
import org.openstreetmap.josm.data.osm.User;
import org.openstreetmap.josm.data.osm.Way;
import org.openstreetmap.josm.gui.layer.OsmDataLayer;
import org.openstreetmap.josm.testutils.JOSMTestRules;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import nl.jqno.equalsverifier.EqualsVerifier;
import nl.jqno.equalsverifier.Warning;
/**
* Unit tests of {@link ChangePropertyCommand} class.
*/
public class ChangePropertyCommandTest {
/**
* We need prefs for nodes.
*/
@Rule
@SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
public JOSMTestRules test = new JOSMTestRules().preferences().i18n();
private CommandTestData testData;
/**
* Set up the test data.
*/
@Before
public void createTestData() {
testData = new CommandTestData();
}
/**
* Checks that the short constructors create the right {@link ChangePropertyCommand}
*/
@Test
public void testShortConstructor() {
ChangePropertyCommand command = new ChangePropertyCommand(Arrays.asList(testData.existingNode), "a", "b");
assertEquals("b", command.getTags().get("a"));
assertEquals(1, command.getTags().size());
assertEquals(1, command.getObjectsNumber());
command = new ChangePropertyCommand(testData.existingNode, "a", "b");
assertEquals("b", command.getTags().get("a"));
assertEquals(1, command.getTags().size());
assertEquals(1, command.getObjectsNumber());
}
/**
* Checks that {@link ChangePropertyCommand} adds/updates a property
*/
@Test
public void testUpdateSingleProperty() {
Node node1 = testData.createNode(14);
Node node2 = testData.createNode(15);
node2.removeAll();
TagMap tags = new TagMap();
tags.put("existing", "new");
new ChangePropertyCommand(Arrays.<OsmPrimitive>asList(node1, node2), tags).executeCommand();
assertEquals("new", node1.get("existing"));
assertEquals("new", node2.get("existing"));
assertTrue(node1.isModified());
assertTrue(node2.isModified());
}
/**
* Checks that {@link ChangePropertyCommand} removes a property
*/
@Test
public void testRemoveProperty() {
Node node1 = testData.createNode(14);
Node node2 = testData.createNode(15);
node2.removeAll();
HashMap<String, String> tags = new HashMap<>();
tags.put("existing", "");
new ChangePropertyCommand(Arrays.<OsmPrimitive>asList(node1, node2), tags).executeCommand();
assertNull(node1.get("existing"));
assertNull(node2.get("existing"));
assertTrue(node1.isModified());
assertFalse(node2.isModified());
}
/**
* Checks that {@link ChangePropertyCommand} adds/updates multiple properties
*/
@Test
public void testUpdateMultipleProperties() {
Node node1 = testData.createNode(14);
Node node2 = testData.createNode(15);
node2.removeAll();
node2.put("test", "xx");
node2.put("remove", "xx");
HashMap<String, String> tags = new HashMap<>();
tags.put("existing", "existing");
tags.put("test", "test");
tags.put("remove", "");
new ChangePropertyCommand(Arrays.<OsmPrimitive>asList(node1, node2), tags).executeCommand();
assertEquals("existing", node1.get("existing"));
assertEquals("existing", node2.get("existing"));
assertEquals("test", node1.get("test"));
assertEquals("test", node2.get("test"));
assertNull(node1.get("remove"));
assertNull(node2.get("remove"));
assertTrue(node1.isModified());
assertTrue(node2.isModified());
}
/**
* Checks that {@link ChangePropertyCommand} adds/updates a property
*/
@Test
public void testUpdateIgnoresExistingProperty() {
Node node1 = testData.createNode(14);
Node node2 = testData.createNode(15);
node2.removeAll();
TagMap tags = new TagMap();
tags.put("existing", "existing");
new ChangePropertyCommand(Arrays.<OsmPrimitive>asList(node1, node2), tags).executeCommand();
assertEquals("existing", node1.get("existing"));
assertEquals("existing", node2.get("existing"));
assertFalse(node1.isModified());
assertTrue(node2.isModified());
}
/**
* Tests {@link ChangePropertyCommand#fillModifiedData(java.util.Collection, java.util.Collection, java.util.Collection)}
* and {@link ChangePropertyCommand#getObjectsNumber()}
*/
@Test
public void testFillModifiedData() {
Node node1 = testData.createNode(14);
Node node2 = testData.createNode(15);
node2.put("existing", "new");
TagMap tags = new TagMap();
tags.put("existing", "new");
ArrayList<OsmPrimitive> modified = new ArrayList<>();
ArrayList<OsmPrimitive> deleted = new ArrayList<>();
ArrayList<OsmPrimitive> added = new ArrayList<>();
new ChangePropertyCommand(Arrays.asList(node1, node2), tags).fillModifiedData(modified, deleted, added);
assertArrayEquals(new Object[] {node1}, modified.toArray());
assertArrayEquals(new Object[] {}, deleted.toArray());
assertArrayEquals(new Object[] {}, added.toArray());
assertEquals(1, new ChangePropertyCommand(Arrays.asList(node1, node2), tags).getObjectsNumber());
tags.clear();
assertEquals(0, new ChangePropertyCommand(Arrays.asList(node1, node2), tags).getObjectsNumber());
tags.put("a", "b");
assertEquals(2, new ChangePropertyCommand(Arrays.asList(node1, node2), tags).getObjectsNumber());
}
/**
* Test {@link ChangePropertyCommand#getDescriptionText()}
*/
@Test
public void testDescription() {
Node node1 = testData.createNode(14);
Node node2 = testData.createNode(15);
Node node3 = testData.createNode(16);
node1.put("name", "xy");
node2.put("existing", "new");
node3.put("existing", null);
TagMap tags = new TagMap();
tags.put("existing", "new");
HashMap<String, String> tagsRemove = new HashMap<>();
tagsRemove.put("existing", "");
Way way = new Way();
way.addNode(node1);
way.put("name", "xy");
way.put("existing", "existing");
Relation relation = new Relation();
relation.put("name", "xy");
relation.put("existing", "existing");
// nop
assertTrue(new ChangePropertyCommand(Arrays.asList(node2), tags).getDescriptionText()
.matches("Set.*tags for 0 objects"));
// change 1 key on 1 element.
assertTrue(new ChangePropertyCommand(Arrays.asList(node1, node2), tags).getDescriptionText()
.matches("Set existing=new for node.*xy.*"));
assertTrue(new ChangePropertyCommand(Arrays.asList(way, node2), tags).getDescriptionText()
.matches("Set existing=new for way.*xy.*"));
assertTrue(new ChangePropertyCommand(Arrays.asList(relation, node2), tags).getDescriptionText()
.matches("Set existing=new for relation.*xy.*"));
// remove 1 key on 1 element
assertTrue(new ChangePropertyCommand(Arrays.asList(node1, node3), tagsRemove).getDescriptionText()
.matches("Remove \"existing\" for node.*xy.*"));
assertTrue(new ChangePropertyCommand(Arrays.asList(way, node3), tagsRemove).getDescriptionText()
.matches("Remove \"existing\" for way.*xy.*"));
assertTrue(new ChangePropertyCommand(Arrays.asList(relation, node3), tagsRemove).getDescriptionText()
.matches("Remove \"existing\" for relation.*xy.*"));
// change 1 key on 3 elements
assertEquals("Set existing=new for 3 objects",
new ChangePropertyCommand(Arrays.asList(node1, node2, way, relation), tags).getDescriptionText());
// remove 1 key on 3 elements
assertEquals("Remove \"existing\" for 3 objects",
new ChangePropertyCommand(Arrays.asList(node1, node3, way, relation), tagsRemove).getDescriptionText());
// add 2 keys on 3 elements
tags.put("name", "a");
node2.put("name", "a");
assertEquals("Set 2 tags for 3 objects",
new ChangePropertyCommand(Arrays.asList(node1, node2, way, relation), tags).getDescriptionText());
tagsRemove.put("name", "");
// remove 2 key on 3 elements
assertEquals("Deleted 2 tags for 3 objects",
new ChangePropertyCommand(Arrays.asList(node1, node3, way, relation), tagsRemove).getDescriptionText());
}
/**
* Test {@link ChangePropertyCommand#getChildren()}
*/
@Test
public void testChildren() {
Node node1 = testData.createNode(15);
Node node2 = testData.createNode(16);
node1.put("name", "node1");
node2.put("name", "node2");
assertNull(new ChangePropertyCommand(Arrays.asList(node1), "a", "b").getChildren());
Collection<PseudoCommand> children = new ChangePropertyCommand(Arrays.asList(node1, node2), "a", "b").getChildren();
assertEquals(2, children.size());
List<Node> nodesToExpect = new ArrayList<>(Arrays.asList(node1, node2));
for (PseudoCommand c : children) {
assertNull(c.getChildren());
Collection<? extends OsmPrimitive> part = c.getParticipatingPrimitives();
assertEquals(1, part.size());
OsmPrimitive node = part.iterator().next();
assertTrue(nodesToExpect.remove(node));
assertTrue(c.getDescriptionText().matches(".*" + node.get("name") + ".*"));
}
}
/**
* Unit test of methods {@link ChangePropertyCommand#equals} and {@link ChangePropertyCommand#hashCode}.
*/
@Test
public void testEqualsContract() {
EqualsVerifier.forClass(ChangePropertyCommand.class).usingGetClass()
.withPrefabValues(DataSet.class,
new DataSet(), new DataSet())
.withPrefabValues(User.class,
User.createOsmUser(1, "foo"), User.createOsmUser(2, "bar"))
.withPrefabValues(OsmDataLayer.class,
new OsmDataLayer(new DataSet(), "1", null), new OsmDataLayer(new DataSet(), "2", null))
.suppress(Warning.NONFINAL_FIELDS)
.verify();
}
}