/* * 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. */ // BSONTest.java package org.bson; import org.bson.io.BasicOutputBuffer; import org.bson.io.OutputBuffer; import org.bson.types.CodeWScope; import org.junit.Test; import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Vector; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; public class BSONTest { public BSONTest(){ for ( int x = 8; x<2048; x*=2 ){ StringBuilder buf = new StringBuilder(); while ( buf.length() < x ) buf.append( x ); _data.add( buf.toString() ); } } void _test( BSONObject o , int size , String hash ) throws IOException { BSONEncoder e = new BasicBSONEncoder(); OutputBuffer buf = new BasicOutputBuffer(); e.set( buf ); e.putObject( o ); assertEquals( size , buf.size() ); assertEquals( hash , buf.md5() ); e.done(); BSONDecoder d = new BasicBSONDecoder(); BSONCallback cb = new BasicBSONCallback(); int s = d.decode( new ByteArrayInputStream( buf.toByteArray() ) , cb ); assertEquals( size , s ); OutputBuffer buf2 = new BasicOutputBuffer(); e.set( buf2 ); e.putObject( (BSONObject)cb.get() ); assertEquals( size , buf2.size() ); assertEquals( hash , buf2.md5() ); } @Test public void testBasic1() throws IOException { // BSONObject o = new BasicBSONObject(); _test( new BasicBSONObject( "x" , true ) , 9 , "6fe24623e4efc5cf07f027f9c66b5456" ); _test( new BasicBSONObject( "x" , null ) , 8 , "12d43430ff6729af501faf0638e68888" ); _test( new BasicBSONObject( "x" , 5.2 ) , 16 , "aaeeac4a58e9c30eec6b0b0319d0dff2" ); _test( new BasicBSONObject( "x" , "eliot" ), 18 , "331a3b8b7cbbe0706c80acdb45d4ebbe" ); _test( new BasicBSONObject( "x" , 5.2 ).append( "y" , "truth" ).append( "z" , 1.1 ) , 40 , "7c77b3a6e63e2f988ede92624409da58" ); _test( new BasicBSONObject( "a" , new BasicBSONObject( "b" , 1.1 ) ) , 24 , "31887a4b9d55cd9f17752d6a8a45d51f" ); _test( new BasicBSONObject( "x" , 5.2 ).append( "y" , new BasicBSONObject( "a" , "eliot" ).append( "b" , true ) ).append( "z" , null ) , 44 , "b3de8a0739ab329e7aea138d87235205" ); _test( new BasicBSONObject( "x" , 5.2 ).append( "y" , new Object[]{ "a" , "eliot" , "b" , true } ).append( "z" , null ) , 62 , "cb7bad5697714ba0cbf51d113b6a0ee8" ); _test( new BasicBSONObject( "x" , 4 ) , 12 , "d1ed8dbf79b78fa215e2ded74548d89d" ); } @Test( expected = IllegalArgumentException.class ) public void testNullKeysFail() { BSONEncoder e = new BasicBSONEncoder(); OutputBuffer buf = new BasicOutputBuffer(); e.set( buf ); e.putObject( new BasicBSONObject( "foo\0bar","baz" ) ); } @Test public void testArray() throws IOException { _test( new BasicBSONObject( "x" , new int[]{ 1 , 2 , 3 , 4} ) , 41 , "e63397fe37de1349c50e1e4377a45e2d" ); } @Test public void testOB1(){ BasicOutputBuffer buf = new BasicOutputBuffer(); buf.write( "eliot".getBytes() ); assertEquals( 5 , buf.getPosition() ); assertEquals( 5 , buf.size() ); assertEquals( "eliot" , buf.asString() ); buf.setPosition( 2 ); buf.write( "z".getBytes() ); assertEquals( "elzot" , buf.asString() ); buf.seekEnd(); buf.write( "foo".getBytes() ); assertEquals( "elzotfoo" , buf.asString() ); buf.seekStart(); buf.write( "bar".getBytes() ); assertEquals( "barotfoo" , buf.asString() ); } @Test public void testCode() throws IOException{ BSONObject scope = new BasicBSONObject( "x", 1 ); CodeWScope c = new CodeWScope( "function() { x += 1; }" , scope ); BSONObject code_object = new BasicBSONObject( "map" , c); _test( code_object , 53 , "52918d2367533165bfc617df50335cbb" ); } @Test public void testBinary() throws IOException{ byte[] data = new byte[10000]; for(int i=0; i<10000; i++) { data[i] = 1; } BSONObject binary_object = new BasicBSONObject( "bin" , data); _test( binary_object , 10015 , "1d439ba5b959ecfe297a7862bf95bc10" ); } @Test public void testOBBig1(){ BasicOutputBuffer a = new BasicOutputBuffer(); StringBuilder b = new StringBuilder(); for ( String x : _data ){ a.write( x.getBytes() ); b.append( x ); } assertEquals( a.asString() , b.toString() ); } @Test public void testUTF8() { for (int i = 1; i <= Character.MAX_CODE_POINT; i++) { if (Character.getType(i) == Character.SURROGATE) { continue; } String orig = new String(Character.toChars(i)); BSONObject a = new BasicBSONObject(orig, orig); BSONObject b = BSON.decode(BSON.encode(a)); assertEquals("Could not round trip code point " + i, a, b); } } @Test @SuppressWarnings("unchecked") public void testCustomEncoders() throws IOException{ // If clearEncodingHooks isn't working the first test will fail. Transformer tf = new TestDateTransformer(); BSON.addEncodingHook( TestDate.class, tf ); BSON.clearEncodingHooks(); TestDate td = new TestDate( 2009 , 01 , 23 , 10 , 53 , 42 ); BSONObject o = new BasicBSONObject( "date" , td ); BSONEncoder e = new BasicBSONEncoder(); BSONDecoder d = new BasicBSONDecoder(); BSONCallback cb = new BasicBSONCallback(); OutputBuffer buf = new BasicOutputBuffer(); e.set( buf ); boolean encodeFailed = false; try { e.putObject( o ); } catch ( IllegalArgumentException ieE ) { encodeFailed = true; } assertTrue( encodeFailed); // Reset the buffer buf.seekStart(); assertTrue( tf.transform( td ) instanceof java.util.Date ); BSON.addEncodingHook( TestDate.class, tf ); e.putObject( o ); e.done(); d.decode( new ByteArrayInputStream( buf.toByteArray() ), cb ); Object result = cb.get(); assertTrue( result instanceof BSONObject ); BSONObject bson = (BSONObject) result; assertNotNull( bson.get( "date" ) ); assertTrue( bson.get( "date" ) instanceof java.util.Date ); // Check that the hooks registered assertNotNull( BSON.getEncodingHooks( TestDate.class ) ); Vector expect = new Vector( 1 ); expect.add( tf ); assertEquals( BSON.getEncodingHooks( TestDate.class ), expect ); assertTrue( BSON.getEncodingHooks( TestDate.class ).contains( tf ) ); BSON.removeEncodingHook( TestDate.class, tf ); assertFalse( BSON.getEncodingHooks( TestDate.class ).contains( tf ) ); } @Test @SuppressWarnings({"deprecation", "unchecked"}) public void testCustomDecoders() throws IOException{ // If clearDecodingHooks isn't working this whole test will fail. Transformer tf = new TestDateTransformer(); BSON.addDecodingHook( Date.class, tf ); BSON.clearDecodingHooks(); TestDate td = new TestDate( 2009 , 01 , 23 , 10 , 53 , 42 ); Date dt = new Date( 2009 , 01 , 23 , 10 , 53 , 42 ); BSONObject o = new BasicBSONObject( "date" , dt ); BSONDecoder d = new BasicBSONDecoder(); BSONEncoder e = new BasicBSONEncoder(); BSONCallback cb = new BasicBSONCallback(); OutputBuffer buf = new BasicOutputBuffer(); e.set( buf ); e.putObject( o ); e.done(); d.decode( new ByteArrayInputStream( buf.toByteArray() ), cb ); Object result = cb.get(); assertTrue( result instanceof BSONObject ); BSONObject bson = (BSONObject) result; assertNotNull( bson.get( "date" ) ); assertTrue( bson.get( "date" ) instanceof java.util.Date ); BSON.addDecodingHook( Date.class, tf ); d.decode( new ByteArrayInputStream( buf.toByteArray() ), cb ); bson = (BSONObject) cb.get(); assertNotNull( bson.get( "date" ) ); assertTrue( bson.get( "date" ) instanceof TestDate ); assertEquals( bson.get( "date" ), td ); // Check that the hooks registered assertNotNull( BSON.getDecodingHooks( Date.class ) ); Vector expect = new Vector( 1 ); expect.add( tf ); assertEquals( BSON.getDecodingHooks( Date.class ), expect ); assertTrue( BSON.getDecodingHooks( Date.class ).contains( tf ) ); BSON.removeDecodingHook( Date.class, tf ); assertFalse( BSON.getDecodingHooks( Date.class ).contains( tf ) ); } @Test public void testEquals() { assertNotEquals(new BasicBSONObject("a", 1111111111111111111L), new BasicBSONObject("a", 1111111111111111112L)); assertNotEquals(new BasicBSONObject("a", 100.1D), new BasicBSONObject("a", 100.2D)); assertNotEquals(new BasicBSONObject("a", 100.1F), new BasicBSONObject("a", 100.2F)); assertEquals(new BasicBSONObject("a", 100.1D), new BasicBSONObject("a", 100.1D)); assertEquals(new BasicBSONObject("a", 100.1F), new BasicBSONObject("a", 100.1F)); assertEquals(new BasicBSONObject("a", 100L), new BasicBSONObject("a", 100L)); } private class TestDate { final int year; final int month; final int date; final int hour; final int minute; final int second; public TestDate(int year , int month , int date , int hour , int minute , int second) { this.year = year; this.month = month; this.date = date; this.hour = hour; this.minute = minute; this.second = second; } public TestDate(int year , int month , int date) { this( year , month , date , 0 , 0 , 0 ); } @Override public boolean equals( Object other ){ if ( this == other ) return true; if ( !( other instanceof TestDate ) ) return false; TestDate otherDt = (TestDate) other; return ( otherDt.year == this.year && otherDt.month == this.month && otherDt.date == this.date && otherDt.hour == this.hour && otherDt.minute == this.minute && otherDt.second == this.second ); } @Override public String toString(){ return year + "-" + month + "-" + date + " " + hour + ":" + minute + ":" + second; } } private class TestDateTransformer implements Transformer { @SuppressWarnings( "deprecation" ) public Object transform( Object o ){ if ( o instanceof TestDate ) { TestDate td = (TestDate) o; return new java.util.Date( td.year , td.month , td.date , td.hour , td.minute , td.second ); } else if ( o instanceof java.util.Date ) { Date d = (Date) o; return new TestDate( d.getYear() , d.getMonth() , d.getDate() , d.getHours() , d.getMinutes() , d.getSeconds() ); } else return o; } } void _roundTrip( BSONObject o ){ assertEquals( o , BSON.decode( BSON.encode( o ) ) ); } @Test public void testRandomRoundTrips(){ _roundTrip( new BasicBSONObject( "a" , "" ) ); _roundTrip( new BasicBSONObject( "a" , "a" ) ); _roundTrip( new BasicBSONObject( "a" , "b" ) ); } List _data = new ArrayList(); }