/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* 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.bson.codecs;
import org.bson.BsonBinaryReader;
import org.bson.BsonBinarySubType;
import org.bson.BsonBinaryWriter;
import org.bson.BsonInt32;
import org.bson.BsonObjectId;
import org.bson.ByteBufNIO;
import org.bson.Document;
import org.bson.io.BasicOutputBuffer;
import org.bson.io.BsonInput;
import org.bson.io.ByteBufferBsonInput;
import org.bson.types.Binary;
import org.bson.types.Code;
import org.bson.types.CodeWithScope;
import org.bson.types.Decimal128;
import org.bson.types.MaxKey;
import org.bson.types.MinKey;
import org.bson.types.ObjectId;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import static java.util.Arrays.asList;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class DocumentCodecTest {
private BasicOutputBuffer buffer;
private BsonBinaryWriter writer;
@Before
public void setUp() throws Exception {
buffer = new BasicOutputBuffer();
writer = new BsonBinaryWriter(buffer);
}
@After
public void tearDown() {
writer.close();
}
@Test
public void testPrimitiveBSONTypeCodecs() throws IOException {
DocumentCodec documentCodec = new DocumentCodec();
Document doc = new Document();
doc.put("oid", new ObjectId());
doc.put("integer", 1);
doc.put("long", 2L);
doc.put("string", "hello");
doc.put("double", 3.2);
doc.put("decimal", Decimal128.parse("0.100"));
doc.put("binary", new Binary(BsonBinarySubType.USER_DEFINED, new byte[]{0, 1, 2, 3}));
doc.put("date", new Date(1000));
doc.put("boolean", true);
doc.put("code", new Code("var i = 0"));
doc.put("minkey", new MinKey());
doc.put("maxkey", new MaxKey());
// doc.put("pattern", Pattern.compile("^hello")); // TODO: Pattern doesn't override equals method!
doc.put("null", null);
documentCodec.encode(writer, doc, EncoderContext.builder().build());
BsonInput bsonInput = createInputBuffer();
Document decodedDocument = documentCodec.decode(new BsonBinaryReader(bsonInput), DecoderContext.builder().build());
assertEquals(doc, decodedDocument);
}
@Test
public void testIterableEncoding() throws IOException {
DocumentCodec documentCodec = new DocumentCodec();
Document doc = new Document()
.append("list", asList(1, 2, 3, 4, 5))
.append("set", new HashSet<Integer>(asList(1, 2, 3, 4)));
documentCodec.encode(writer, doc, EncoderContext.builder().build());
BsonInput bsonInput = createInputBuffer();
Document decodedDocument = documentCodec.decode(new BsonBinaryReader(bsonInput), DecoderContext.builder().build());
assertEquals(new Document()
.append("list", asList(1, 2, 3, 4, 5))
.append("set", asList(1, 2, 3, 4)),
decodedDocument);
}
@Test
public void testCodeWithScopeEncoding() throws IOException {
DocumentCodec documentCodec = new DocumentCodec();
Document doc = new Document();
doc.put("theCode", new CodeWithScope("javaScript code", new Document("fieldNameOfScope", "valueOfScope")));
documentCodec.encode(writer, doc, EncoderContext.builder().build());
Document decodedDocument = documentCodec.decode(new BsonBinaryReader(createInputBuffer()), DecoderContext.builder().build());
assertEquals(doc, decodedDocument);
}
@Test
public void testIterableContainingOtherIterableEncoding() throws IOException {
DocumentCodec documentCodec = new DocumentCodec();
Document doc = new Document();
@SuppressWarnings("unchecked")
List<List<Integer>> listOfLists = asList(asList(1), asList(2));
doc.put("array", listOfLists);
documentCodec.encode(writer, doc, EncoderContext.builder().build());
BsonInput bsonInput = createInputBuffer();
Document decodedDocument = documentCodec.decode(new BsonBinaryReader(bsonInput), DecoderContext.builder().build());
assertEquals(doc, decodedDocument);
}
@Test
public void testIterableContainingDocumentsEncoding() throws IOException {
DocumentCodec documentCodec = new DocumentCodec();
Document doc = new Document();
List<Document> listOfDocuments = asList(new Document("intVal", 1), new Document("anotherInt", 2));
doc.put("array", listOfDocuments);
documentCodec.encode(writer, doc, EncoderContext.builder().build());
BsonInput bsonInput = createInputBuffer();
Document decodedDocument = documentCodec.decode(new BsonBinaryReader(bsonInput), DecoderContext.builder().build());
assertEquals(doc, decodedDocument);
}
@Test
public void testNestedDocumentEncoding() throws IOException {
DocumentCodec documentCodec = new DocumentCodec();
Document doc = new Document();
doc.put("nested", new Document("x", 1));
documentCodec.encode(writer, doc, EncoderContext.builder().build());
BsonInput bsonInput = createInputBuffer();
Document decodedDocument = documentCodec.decode(new BsonBinaryReader(bsonInput), DecoderContext.builder().build());
assertEquals(doc, decodedDocument);
}
@Test
public void shouldNotGenerateIdIfPresent() {
DocumentCodec documentCodec = new DocumentCodec();
Document document = new Document("_id", 1);
assertTrue(documentCodec.documentHasId(document));
document = documentCodec.generateIdIfAbsentFromDocument(document);
assertTrue(documentCodec.documentHasId(document));
assertEquals(new BsonInt32(1), documentCodec.getDocumentId(document));
}
@Test
public void shouldGenerateIdIfAbsent() {
DocumentCodec documentCodec = new DocumentCodec();
Document document = new Document();
assertFalse(documentCodec.documentHasId(document));
document = documentCodec.generateIdIfAbsentFromDocument(document);
assertTrue(documentCodec.documentHasId(document));
assertEquals(BsonObjectId.class, documentCodec.getDocumentId(document).getClass());
}
// TODO: factor into common base class;
private BsonInput createInputBuffer() throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
buffer.pipe(baos);
return new ByteBufferBsonInput(new ByteBufNIO(ByteBuffer.wrap(baos.toByteArray())));
}
}