org.fastmongo.odm.dbobject.mapping.core.DbObjectToDomainConverterTest.java Source code

Java tutorial

Introduction

Here is the source code for org.fastmongo.odm.dbobject.mapping.core.DbObjectToDomainConverterTest.java

Source

/*
 * Copyright (c) 2014 Alexander Gulko <kirhog at gmail dot com>.
 *
 * 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.fastmongo.odm.dbobject.mapping.core;

import com.mongodb.DBObject;
import org.fastmongo.odm.document.support.LazyCollectionProxy;
import org.fastmongo.odm.document.support.LazyProxy;
import org.fastmongo.odm.model.TestDomainObjectsFixtures;
import org.fastmongo.odm.model.TestObjectUtils;
import org.fastmongo.odm.model.user.Attribute;
import org.fastmongo.odm.model.user.Group;
import org.fastmongo.odm.model.user.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.testng.Assert;
import org.testng.annotations.Test;

import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;

import static org.fastmongo.odm.dbobject.mapping.core.ConverterHelper.getValue;
import static org.fastmongo.odm.model.FixtureUtils.nextId;

/**
 * @author Alexander Gulko
 */
@ContextConfiguration("classpath:common-converter-test-context.xml")
public class DbObjectToDomainConverterTest extends AbstractTestNGSpringContextTests {
    @Autowired
    private DomainToDbObjectConverter toDbConverter;
    @Autowired
    private DbObjectToDomainConverter fromDbConverter;
    @Autowired
    private TestMongoTemplate mongoTemplate;

    @Test
    public void testFromDbObject() {
        Group expected = createGroup();

        DBObject db = toDbConverter.toDbObject(expected);
        Assert.assertNotNull(db);

        Group actual = fromDbConverter.fromDbObject(db, Group.class);
        Assert.assertTrue(TestObjectUtils.equals(actual, expected));
    }

    @Test
    public void testCyclicDependencies() {
        DBObject db = toDbConverter.toDbObject(createGroup());
        Assert.assertNotNull(db);

        Group topGroup = fromDbConverter.fromDbObject(db, Group.class);

        User user = topGroup.getUsers().iterator().next();
        Assert.assertTrue(user.getGroup() instanceof LazyProxy);
        Assert.assertTrue(user.getGroup() instanceof Group); // asm proxy

        String id = user.getGroup().getId(); // load id through loader
        Assert.assertEquals(id, db.get("id"));
        // still proxy
        Assert.assertTrue(user.getGroup() instanceof LazyProxy);
        Assert.assertTrue(user.getGroup() instanceof Group);

        //noinspection ResultOfMethodCallIgnored
        user.getGroup().toString(); // touch lazy and replace proxy
        Assert.assertFalse(user.getGroup() instanceof LazyProxy);
        Assert.assertTrue(user.getGroup() instanceof Group);

        Group sameGroup = user.getGroup();
        Assert.assertTrue(TestObjectUtils.equals(topGroup, sameGroup));
    }

    @Test
    public void testEscapeAndUnescape() {
        String keyWithPoint = "key.with.point";
        User user = new User();
        user.setAttribute(keyWithPoint, new Attribute());

        DBObject db = toDbConverter.toDbObject(user);
        DBObject attributes = getValue(db, "attributeMap");
        Assert.assertEquals(attributes.keySet().size(), 1);

        String escapedKey = attributes.keySet().iterator().next();
        Assert.assertFalse(escapedKey.contains("."));
        Assert.assertEquals(escapedKey, ConverterHelper.escape(keyWithPoint));

        User actualUser = fromDbConverter.fromDbObject(db, User.class);
        Assert.assertEquals(actualUser.getAttributeMap().size(), 1);
        String unescapedKey = actualUser.getAttributeMap().keySet().iterator().next();
        Assert.assertTrue(unescapedKey.contains("."));
        Assert.assertEquals(unescapedKey, ConverterHelper.unescape(escapedKey));
        Assert.assertEquals(unescapedKey, keyWithPoint);
    }

    @Test
    public void testGarbageCollectedRootObjects() {
        DBObject db;
        {
            Group root = TestDomainObjectsFixtures.createGroup(5, 10);
            db = toDbConverter.toDbObject(root);
        }

        Group root = fromDbConverter.fromDbObject(db, Group.class);
        Reference<Group> ref = new WeakReference<>(root);
        List<User> list = root.getUsers();

        Assert.assertNotNull(ref.get());

        //noinspection UnusedAssignment
        root = null;

        Runtime.getRuntime().gc();

        int limit = 10;
        int wait = 0;
        while (ref.get() != null && wait++ < limit) {
            if (ref.get() == null) {
                break;
            }

            LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(100)); // wait a bit
        }

        Assert.assertNull(ref.get());

        // touch proxy, it should not throw NPE as before
        Assert.assertTrue(!list.isEmpty());
    }

    @Test
    public void test_collectionLoader() {
        Group group = new Group(nextId() + "");
        group.setUsers(new ArrayList<User>());
        group.getUsers().add(new User(nextId()));
        group.getUsers().add(new User(nextId()));
        group.getUsers().add(new User(nextId()));
        mongoTemplate.saveGroup(group);

        DBObject db = mongoTemplate.findById(Group.class, group.getId());
        Group actual = fromDbConverter.fromDbObject(db, Group.class);

        Assert.assertTrue(actual.getUsers() instanceof LazyCollectionProxy);

        Assert.assertFalse(actual.getUsers().isEmpty());
        Assert.assertTrue(actual.getUsers() instanceof LazyCollectionProxy); // still proxy

        Assert.assertEquals(actual.getUsers().size(), group.getUsers().size());
        Assert.assertTrue(actual.getUsers() instanceof LazyCollectionProxy); // still proxy

        actual.getUsers().iterator();
        Assert.assertFalse(actual.getUsers() instanceof LazyCollectionProxy); // not a proxy
    }

    private Group createGroup() {
        Group group = TestDomainObjectsFixtures.createGroup(2, 3);
        mongoTemplate.saveGroup(group);

        return group;
    }
}