/*
* Copyright 2010-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.core.query;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import java.util.Collections;
import java.util.Date;
import java.util.Map;
import org.bson.Document;
import org.joda.time.DateTime;
import org.junit.Test;
import org.springframework.data.mongodb.core.DocumentTestUtils;
/**
* Test cases for {@link Update}.
*
* @author Oliver Gierke
* @author Thomas Risberg
* @author Becca Gaspard
* @author Christoph Strobl
* @author Thomas Darimont
* @author Alexey Plotnik
*/
public class UpdateTests {
@Test
public void testSet() {
Update u = new Update().set("directory", "/Users/Test/Desktop");
assertThat(u.getUpdateObject(), is(Document.parse("{ \"$set\" : { \"directory\" : \"/Users/Test/Desktop\"}}")));
}
@Test
public void testSetSet() {
Update u = new Update().set("directory", "/Users/Test/Desktop").set("size", 0);
assertThat(u.getUpdateObject(),
is(Document.parse("{ \"$set\" : { \"directory\" : \"/Users/Test/Desktop\" , \"size\" : 0}}")));
}
@Test
public void testInc() {
Update u = new Update().inc("size", 1);
assertThat(u.getUpdateObject(), is(Document.parse("{ \"$inc\" : { \"size\" : 1}}")));
}
@Test
public void testIncInc() {
Update u = new Update().inc("size", 1).inc("count", 1);
assertThat(u.getUpdateObject(), is(Document.parse("{ \"$inc\" : { \"size\" : 1 , \"count\" : 1}}")));
}
@Test
public void testIncAndSet() {
Update u = new Update().inc("size", 1).set("directory", "/Users/Test/Desktop");
assertThat(u.getUpdateObject(),
is(Document.parse("{ \"$inc\" : { \"size\" : 1} , \"$set\" : { \"directory\" : \"/Users/Test/Desktop\"}}")));
}
@Test
public void testUnset() {
Update u = new Update().unset("directory");
assertThat(u.getUpdateObject(), is(Document.parse("{ \"$unset\" : { \"directory\" : 1}}")));
}
@Test
public void testPush() {
Update u = new Update().push("authors", Collections.singletonMap("name", "Sven"));
assertThat(u.getUpdateObject(), is(Document.parse("{ \"$push\" : { \"authors\" : { \"name\" : \"Sven\"}}}")));
}
@Test
public void testPushAll() {
Map<String, String> m1 = Collections.singletonMap("name", "Sven");
Map<String, String> m2 = Collections.singletonMap("name", "Maria");
Update u = new Update().pushAll("authors", new Object[] { m1, m2 });
assertThat(u.getUpdateObject(),
is(Document.parse("{ \"$pushAll\" : { \"authors\" : [ { \"name\" : \"Sven\"} , { \"name\" : \"Maria\"}]}}")));
}
@Test // DATAMONGO-354
public void testMultiplePushAllShouldBePossibleWhenUsingDifferentFields() {
Map<String, String> m1 = Collections.singletonMap("name", "Sven");
Map<String, String> m2 = Collections.singletonMap("name", "Maria");
Update u = new Update().pushAll("authors", new Object[] { m1, m2 });
u.pushAll("books", new Object[] { "Spring in Action" });
assertThat(u.getUpdateObject(), is(Document.parse(
"{ \"$pushAll\" : { \"authors\" : [ { \"name\" : \"Sven\"} , { \"name\" : \"Maria\"}] , \"books\" : [ \"Spring in Action\"]}}")));
}
@Test
public void testAddToSet() {
Update u = new Update().addToSet("authors", Collections.singletonMap("name", "Sven"));
assertThat(u.getUpdateObject(), is(Document.parse("{ \"$addToSet\" : { \"authors\" : { \"name\" : \"Sven\"}}}")));
}
@Test
public void testPop() {
Update u = new Update().pop("authors", Update.Position.FIRST);
assertThat(u.getUpdateObject(), is(Document.parse("{ \"$pop\" : { \"authors\" : -1}}")));
u = new Update().pop("authors", Update.Position.LAST);
assertThat(u.getUpdateObject(), is(Document.parse("{ \"$pop\" : { \"authors\" : 1}}")));
}
@Test
public void testPull() {
Update u = new Update().pull("authors", Collections.singletonMap("name", "Sven"));
assertThat(u.getUpdateObject(), is(Document.parse("{ \"$pull\" : { \"authors\" : { \"name\" : \"Sven\"}}}")));
}
@Test
public void testPullAll() {
Map<String, String> m1 = Collections.singletonMap("name", "Sven");
Map<String, String> m2 = Collections.singletonMap("name", "Maria");
Update u = new Update().pullAll("authors", new Object[] { m1, m2 });
assertThat(u.getUpdateObject(),
is(Document.parse("{ \"$pullAll\" : { \"authors\" : [ { \"name\" : \"Sven\"} , { \"name\" : \"Maria\"}]}}")));
}
@Test
public void testRename() {
Update u = new Update().rename("directory", "folder");
assertThat(u.getUpdateObject(), is(Document.parse("{ \"$rename\" : { \"directory\" : \"folder\"}}")));
}
@Test
public void testBasicUpdateInc() {
Update u = new Update().inc("size", 1);
assertThat(u.getUpdateObject(), is(Document.parse("{ \"$inc\" : { \"size\" : 1}}")));
}
@Test
public void testBasicUpdateIncAndSet() {
Update u = new BasicUpdate("{ \"$inc\" : { \"size\" : 1}}").set("directory", "/Users/Test/Desktop");
assertThat(u.getUpdateObject(),
is(Document.parse("{ \"$inc\" : { \"size\" : 1} , \"$set\" : { \"directory\" : \"/Users/Test/Desktop\"}}")));
}
@Test // DATAMONGO-630
public void testSetOnInsert() {
Update u = new Update().setOnInsert("size", 1);
assertThat(u.getUpdateObject(), is(Document.parse("{ \"$setOnInsert\" : { \"size\" : 1}}")));
}
@Test // DATAMONGO-630
public void testSetOnInsertSetOnInsert() {
Update u = new Update().setOnInsert("size", 1).setOnInsert("count", 1);
assertThat(u.getUpdateObject(), is(Document.parse("{ \"$setOnInsert\" : { \"size\" : 1 , \"count\" : 1}}")));
}
@Test // DATAMONGO-852
public void testUpdateAffectsFieldShouldReturnTrueWhenMultiFieldOperationAddedForField() {
Update update = new Update().set("foo", "bar");
assertThat(update.modifies("foo"), is(true));
}
@Test // DATAMONGO-852
public void testUpdateAffectsFieldShouldReturnFalseWhenMultiFieldOperationAddedForField() {
Update update = new Update().set("foo", "bar");
assertThat(update.modifies("oof"), is(false));
}
@Test // DATAMONGO-852
public void testUpdateAffectsFieldShouldReturnTrueWhenSingleFieldOperationAddedForField() {
Update update = new Update().pullAll("foo", new Object[] { "bar" });
assertThat(update.modifies("foo"), is(true));
}
@Test // DATAMONGO-852
public void testUpdateAffectsFieldShouldReturnFalseWhenSingleFieldOperationAddedForField() {
Update update = new Update().pullAll("foo", new Object[] { "bar" });
assertThat(update.modifies("oof"), is(false));
}
@Test // DATAMONGO-852
public void testUpdateAffectsFieldShouldReturnFalseWhenCalledOnEmptyUpdate() {
assertThat(new Update().modifies("foo"), is(false));
}
@Test // DATAMONGO-852
public void testUpdateAffectsFieldShouldReturnTrueWhenUpdateWithKeyCreatedFromDocument() {
Update update = new Update().set("foo", "bar");
Update clone = Update.fromDocument(update.getUpdateObject());
assertThat(clone.modifies("foo"), is(true));
}
@Test // DATAMONGO-852
public void testUpdateAffectsFieldShouldReturnFalseWhenUpdateWithoutKeyCreatedFromDocument() {
Update update = new Update().set("foo", "bar");
Update clone = Update.fromDocument(update.getUpdateObject());
assertThat(clone.modifies("oof"), is(false));
}
@Test(expected = IllegalArgumentException.class) // DATAMONGO-853
public void testAddingMultiFieldOperationThrowsExceptionWhenCalledWithNullKey() {
new Update().addMultiFieldOperation("$op", null, "exprected to throw IllegalArgumentException.");
}
@Test(expected = IllegalArgumentException.class) // DATAMONGO-853
public void testAddingSingleFieldOperationThrowsExceptionWhenCalledWithNullKey() {
new Update().addFieldOperation("$op", null, "exprected to throw IllegalArgumentException.");
}
@Test(expected = IllegalArgumentException.class) // DATAMONGO-853
public void testCreatingUpdateWithNullKeyThrowsException() {
Update.update(null, "value");
}
@Test // DATAMONGO-953
public void testEquality() {
Update actualUpdate = new Update() //
.inc("size", 1) //
.set("nl", null) //
.set("directory", "/Users/Test/Desktop") //
.push("authors", Collections.singletonMap("name", "Sven")) //
.pop("authors", Update.Position.FIRST) //
.set("foo", "bar");
Update expectedUpdate = new Update() //
.inc("size", 1) //
.set("nl", null) //
.set("directory", "/Users/Test/Desktop") //
.push("authors", Collections.singletonMap("name", "Sven")) //
.pop("authors", Update.Position.FIRST) //
.set("foo", "bar");
assertThat(actualUpdate, is(equalTo(actualUpdate)));
assertThat(actualUpdate.hashCode(), is(equalTo(actualUpdate.hashCode())));
assertThat(actualUpdate, is(equalTo(expectedUpdate)));
assertThat(actualUpdate.hashCode(), is(equalTo(expectedUpdate.hashCode())));
}
@Test // DATAMONGO-953
public void testToString() {
Update actualUpdate = new Update() //
.inc("size", 1) //
.set("nl", null) //
.set("directory", "/Users/Test/Desktop") //
.push("authors", Collections.singletonMap("name", "Sven")) //
.pop("authors", Update.Position.FIRST) //
.set("foo", "bar");
Update expectedUpdate = new Update() //
.inc("size", 1) //
.set("nl", null) //
.set("directory", "/Users/Test/Desktop") //
.push("authors", Collections.singletonMap("name", "Sven")) //
.pop("authors", Update.Position.FIRST) //
.set("foo", "bar");
assertThat(actualUpdate.toString(), is(equalTo(expectedUpdate.toString())));
assertThat(actualUpdate.getUpdateObject(),
is(Document.parse("{ \"$inc\" : { \"size\" : 1} ," //
+ " \"$set\" : { \"nl\" : null , \"directory\" : \"/Users/Test/Desktop\" , \"foo\" : \"bar\"} , " //
+ "\"$push\" : { \"authors\" : { \"name\" : \"Sven\"}} " //
+ ", \"$pop\" : { \"authors\" : -1}}"))); //
}
@Test // DATAMONGO-944
public void getUpdateObjectShouldReturnCurrentDateCorrectlyForSingleFieldWhenUsingDate() {
Update update = new Update().currentDate("foo");
assertThat(update.getUpdateObject(), equalTo(new Document().append("$currentDate", new Document("foo", true))));
}
@Test // DATAMONGO-944
public void getUpdateObjectShouldReturnCurrentDateCorrectlyForMultipleFieldsWhenUsingDate() {
Update update = new Update().currentDate("foo").currentDate("bar");
assertThat(update.getUpdateObject(),
equalTo(new Document().append("$currentDate", new Document("foo", true).append("bar", true))));
}
@Test // DATAMONGO-944
public void getUpdateObjectShouldReturnCurrentDateCorrectlyForSingleFieldWhenUsingTimestamp() {
Update update = new Update().currentTimestamp("foo");
assertThat(update.getUpdateObject(),
equalTo(new Document().append("$currentDate", new Document("foo", new Document("$type", "timestamp")))));
}
@Test // DATAMONGO-944
public void getUpdateObjectShouldReturnCurrentDateCorrectlyForMultipleFieldsWhenUsingTimestamp() {
Update update = new Update().currentTimestamp("foo").currentTimestamp("bar");
assertThat(update.getUpdateObject(), equalTo(new Document().append("$currentDate",
new Document("foo", new Document("$type", "timestamp")).append("bar", new Document("$type", "timestamp")))));
}
@Test // DATAMONGO-944
public void getUpdateObjectShouldReturnCurrentDateCorrectlyWhenUsingMixedDateAndTimestamp() {
Update update = new Update().currentDate("foo").currentTimestamp("bar");
assertThat(update.getUpdateObject(), equalTo(new Document().append("$currentDate",
new Document("foo", true).append("bar", new Document("$type", "timestamp")))));
}
@Test // DATAMONGO-1002
public void toStringWorksForUpdateWithComplexObject() {
Update update = new Update().addToSet("key", new DateTime());
assertThat(update.toString(), is(notNullValue()));
}
@Test(expected = IllegalArgumentException.class) // DATAMONGO-1097
public void multiplyShouldThrowExceptionForNullMultiplier() {
new Update().multiply("key", null);
}
@Test // DATAMONGO-1097
public void multiplyShouldAddMultiplierAsItsDoubleValue() {
Update update = new Update().multiply("key", 10);
assertThat(update.getUpdateObject(), equalTo(new Document().append("$mul", new Document("key", 10D))));
}
@Test // DATAMONGO-1101
public void getUpdateObjectShouldReturnCorrectRepresentationForBitwiseAnd() {
Update update = new Update().bitwise("key").and(10L);
assertThat(update.getUpdateObject(),
equalTo(new Document().append("$bit", new Document("key", new Document("and", 10L)))));
}
@Test // DATAMONGO-1101
public void getUpdateObjectShouldReturnCorrectRepresentationForBitwiseOr() {
Update update = new Update().bitwise("key").or(10L);
assertThat(update.getUpdateObject(),
equalTo(new Document().append("$bit", new Document("key", new Document("or", 10L)))));
}
@Test // DATAMONGO-1101
public void getUpdateObjectShouldReturnCorrectRepresentationForBitwiseXor() {
Update update = new Update().bitwise("key").xor(10L);
assertThat(update.getUpdateObject(),
equalTo(new Document().append("$bit", new Document("key", new Document("xor", 10L)))));
}
@Test(expected = IllegalArgumentException.class) // DATAMONGO-943
public void pushShouldThrowExceptionWhenGivenNegativePosition() {
new Update().push("foo").atPosition(-1).each("booh");
}
@Test // DATAMONGO-1346
public void registersMultiplePullAllClauses() {
Update update = new Update();
update.pullAll("field1", new String[] { "foo" });
update.pullAll("field2", new String[] { "bar" });
Document updateObject = update.getUpdateObject();
Document pullAll = DocumentTestUtils.getAsDocument(updateObject, "$pullAll");
assertThat(pullAll.get("field1"), is(notNullValue()));
assertThat(pullAll.get("field2"), is(notNullValue()));
}
@Test(expected = IllegalArgumentException.class) // DATAMONGO-1404
public void maxShouldThrowExceptionForNullMultiplier() {
new Update().max("key", null);
}
@Test(expected = IllegalArgumentException.class) // DATAMONGO-1404
public void minShouldThrowExceptionForNullMultiplier() {
new Update().min("key", null);
}
@Test // DATAMONGO-1404
public void getUpdateObjectShouldReturnCorrectRepresentationForMax() {
Update update = new Update().max("key", 10);
assertThat(update.getUpdateObject(),
equalTo(new Document("$max", new Document("key", 10))));
}
@Test // DATAMONGO-1404
public void getUpdateObjectShouldReturnCorrectRepresentationForMin() {
Update update = new Update().min("key", 10);
assertThat(update.getUpdateObject(),
equalTo(new Document("$min", new Document("key", 10))));
}
@Test // DATAMONGO-1404
public void shouldSuppressPreviousValueForMax() {
Update update = new Update().max("key", 10);
update.max("key", 99);
assertThat(update.getUpdateObject(),
equalTo(new Document("$max", new Document("key", 99))));
}
@Test // DATAMONGO-1404
public void shouldSuppressPreviousValueForMin() {
Update update = new Update().min("key", 10);
update.min("key", 99);
assertThat(update.getUpdateObject(),
equalTo(new Document("$min", new Document("key", 99))));
}
@Test // DATAMONGO-1404
public void getUpdateObjectShouldReturnCorrectDateRepresentationForMax() {
Date date = new Date();
Update update = new Update().max("key", date);
assertThat(update.getUpdateObject(),
equalTo(new Document("$max", new Document("key", date))));
}
@Test // DATAMONGO-1404
public void getUpdateObjectShouldReturnCorrectDateRepresentationForMin() {
Date date = new Date();
Update update = new Update().min("key", date);
assertThat(update.getUpdateObject(),
equalTo(new Document("$min", new Document("key", date))));
}
}