/*
* The MIT License
*
* Copyright 2015 Tim Boudreau.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.mastfrog.acteur.mongo.async;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.inject.AbstractModule;
import com.google.inject.name.Named;
import com.mastfrog.acteur.mongo.async.ByteBufCodecTest.M;
import com.mastfrog.giulius.mongodb.async.GiuliusMongoAsyncModule;
import com.mastfrog.giulius.mongodb.async.MongoHarness;
import com.mastfrog.giulius.tests.GuiceRunner;
import com.mastfrog.giulius.tests.TestWith;
import com.mastfrog.util.Exceptions;
import com.mastfrog.util.Streams;
import com.mongodb.async.SingleResultCallback;
import com.mongodb.async.client.MongoCollection;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.ByteBufInputStream;
import java.io.IOException;
import static java.util.Arrays.asList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.apache.commons.codec.binary.Base64;
import org.bson.Document;
import org.bson.codecs.BsonValueCodecProvider;
import org.bson.codecs.DocumentCodecProvider;
import org.bson.codecs.ValueCodecProvider;
import static org.bson.codecs.configuration.CodecRegistries.fromProviders;
import org.bson.codecs.configuration.CodecRegistry;
import org.bson.types.ObjectId;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.bson.codecs.configuration.CodecRegistries.fromProviders;
/**
*
* @author Tim Boudreau
*/
@RunWith(GuiceRunner.class)
@TestWith({M.class, MongoHarness.Module.class})
public class ByteBufCodecTest {
private static final CodecRegistry DEFAULT_CODEC_REGISTRY
= fromProviders(asList(new ValueCodecProvider(),
new DocumentCodecProvider(),
new BsonValueCodecProvider()));
@Test
public void test(@Named("stuff") MongoCollection<Document> stuff) throws InterruptedException, IOException {
byte[] bytes = new byte[120];
for (int i = 0; i < bytes.length; i++) {
bytes[i] = (byte) (120 - i);
}
List<Object> list = new LinkedList<>();
list.add(1);
list.add(2);
list.add(2);
list.add("hello");
list.add(new Document("in", "list"));
Document document = new Document("hello", "world")
.append("boolValue", true)
.append("list", list)
.append("intValue", 32)
.append("dbl", 32.000235D)
.append("subdoc", new Document("other", "stuff"))
.append("longValue", Long.valueOf(Integer.MAX_VALUE + 1L))
.append("_id", new ObjectId())
.append("bytes", bytes);
CB<Void> cb = new CB<Void>();
stuff.insertOne(document, cb);
cb.get();
Thread.sleep(200);
MongoCollection<ByteBuf> bbc = stuff.withDocumentClass(ByteBuf.class);
CB<ByteBuf> bb = new CB<ByteBuf>();
bbc.find(new Document("_id", document.get("_id")))
.batchSize(1)
.projection(new Document("hello", 1)
.append("boolValue", 1)
.append("intValue", 1)
.append("longValue", 1)
.append("dbl", 1)
.append("list", 1)
.append("subdoc", 1)
.append("bytes", 1)
.append("_id", 1))
.first(bb);
ByteBuf buf = bb.get();
assertNotNull(buf);
String content = Streams.readString(new ByteBufInputStream(buf));
System.out.println("CONTENT: " + content);
buf.resetReaderIndex();
Map m = new ObjectMapper().readValue(content, Map.class);
for (Map.Entry<String, Object> e : document.entrySet()) {
Object other = m.get(e.getKey());
assertNotNull(e.getKey() + " is null", other);
Object value = e.getValue();
assertNotNull(value);
switch (e.getKey()) {
case "_id":
assertTrue(value instanceof ObjectId);
assertTrue(other instanceof String);
value = value.toString();
break;
case "bytes":
assertTrue(other.getClass().getName(), other instanceof String);
other = Base64.decodeBase64((String) other);
continue;
}
if (value instanceof byte[]) {
assertTrue(other instanceof byte[]);
assertTrue(value instanceof byte[]);
assertArrayEquals((byte[]) value, (byte[]) other);
} else {
assertEquals(other, value);
}
}
}
static class M extends AbstractModule {
@Override
protected void configure() {
GiuliusMongoAsyncModule m = new GiuliusMongoAsyncModule().withCodec(ByteBufCodec.class)
.bindCollection("stuff");
bind(ByteBufAllocator.class).toInstance(ByteBufAllocator.DEFAULT);
install(m);
}
}
static class CB<T> implements SingleResultCallback<T> {
private T result;
private volatile boolean done;
private Throwable thrown;
public T get() throws InterruptedException {
synchronized (this) {
do {
T res = result;
if (res != null) {
return res;
}
if (thrown != null) {
Exceptions.chuck(thrown);
}
wait(500L);
} while (!done);
}
return result;
}
@Override
public synchronized void onResult(T t, Throwable thrwbl) {
System.out.println("ONRES " + t);
result = t;
if (thrwbl != null) {
thrwbl.printStackTrace();
}
done = true;
thrown = thrwbl;
notifyAll();
}
}
}