org.lenskit.data.packed.BinaryRatingDAOTest.java Source code

Java tutorial

Introduction

Here is the source code for org.lenskit.data.packed.BinaryRatingDAOTest.java

Source

/*
 * LensKit, an open source recommender systems toolkit.
 * Copyright 2010-2014 LensKit Contributors.  See CONTRIBUTORS.md.
 * Work on LensKit has been funded by the National Science Foundation under
 * grants IIS 05-34939, 08-08692, 08-12148, and 10-17697.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 51
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */
package org.lenskit.data.packed;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.SerializationUtils;
import org.lenskit.util.io.ObjectStreams;
import org.lenskit.data.dao.SortOrder;
import org.lenskit.data.events.Event;
import org.lenskit.data.ratings.Rating;
import org.lenskit.data.history.UserHistory;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.List;

import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;

/**
 * @author <a href="http://www.grouplens.org">GroupLens Research</a>
 */
public class BinaryRatingDAOTest {
    @Rule
    public TemporaryFolder folder = new TemporaryFolder();

    List<Rating> ratings;

    @Before
    public void createRatingList() {
        ImmutableList.Builder<Rating> bld = ImmutableList.builder();
        bld.add(Rating.create(42, 105, 3.5, 100L)).add(Rating.create(42, 120, 2.5, 110L))
                .add(Rating.create(39, 120, 4.5, 120L));
        ratings = bld.build();
    }

    @Test
    public void testEmptyDAO() throws IOException {
        File file = folder.newFile("ratings.bin");
        BinaryRatingPacker packer = BinaryRatingPacker.open(file);
        packer.close();

        BinaryRatingDAO dao = BinaryRatingDAO.open(file);
        assertThat(ObjectStreams.makeList(dao.streamEvents()), hasSize(0));
        assertThat(dao.getUserIds(), hasSize(0));
        assertThat(dao.getItemIds(), hasSize(0));
    }

    @Test
    public void testSimpleDAO() throws IOException {
        File file = folder.newFile("ratings.bin");
        BinaryRatingPacker packer = BinaryRatingPacker.open(file);
        try {
            packer.writeRatings(ratings);
        } finally {
            packer.close();
        }

        BinaryRatingDAO dao = BinaryRatingDAO.open(file);
        verifySimpleDAO(dao);
    }

    @Test
    public void testTimestampedDAO() throws IOException {
        File file = folder.newFile("ratings.bin");
        BinaryRatingPacker packer = BinaryRatingPacker.open(file, BinaryFormatFlag.TIMESTAMPS);
        try {
            packer.writeRatings(ratings);
        } finally {
            packer.close();
        }

        BinaryRatingDAO dao = BinaryRatingDAO.open(file);
        assertThat(ObjectStreams.makeList(dao.streamEvents(Rating.class)), equalTo(ratings));
    }

    @Test
    public void testOutOfOrderDAO() throws IOException {
        List<Rating> reordered = new ArrayList<>();
        for (int i = 0; i < ratings.size(); i++) {
            reordered.add(ratings.get((i + 1) % ratings.size()));
        }

        File file = folder.newFile("ratings.bin");
        BinaryRatingPacker packer = BinaryRatingPacker.open(file, BinaryFormatFlag.TIMESTAMPS);
        try {
            packer.writeRatings(reordered);
        } finally {
            packer.close();
        }

        BinaryRatingDAO dao = BinaryRatingDAO.open(file);
        assertThat(ObjectStreams.makeList(dao.streamEvents(Rating.class)), equalTo(ratings));
        assertThat(dao.getEventsForUser(42), hasSize(2));
        assertThat(dao.getEventsForUser(42, Rating.class), contains(ratings.get(0), ratings.get(1)));
        assertThat(dao.getEventsForUser(39), hasSize(1));
        assertThat(dao.getEventsForUser(39, Rating.class), contains(ratings.get(2)));
    }

    @Test
    public void testUpgradedDAO() throws IOException {
        List<Rating> all = Lists.newArrayList(ratings);
        all.add(Rating.create(39L, Integer.MAX_VALUE + 100L, Math.PI, 23049L));

        File file = folder.newFile("ratings.bin");
        BinaryRatingPacker packer = BinaryRatingPacker.open(file, BinaryFormatFlag.TIMESTAMPS);
        try {
            packer.writeRatings(all);
        } finally {
            packer.close();
        }

        BinaryRatingDAO dao = BinaryRatingDAO.open(file);
        assertThat(ObjectStreams.makeList(dao.streamEvents(Rating.class)), equalTo(all));
        assertThat(dao.getEventsForUser(42), hasSize(2));
        assertThat(dao.getEventsForUser(42, Rating.class), contains(ratings.get(0), ratings.get(1)));
        assertThat(dao.getEventsForUser(39), hasSize(2));
        assertThat(dao.getEventsForUser(39, Rating.class), contains(ratings.get(2), all.get(3)));
    }

    @Test
    public void testSerializedDAO() throws IOException {
        File file = folder.newFile("ratings.bin");
        BinaryRatingPacker packer = BinaryRatingPacker.open(file);
        try {
            packer.writeRatings(ratings);
        } finally {
            packer.close();
        }

        BinaryRatingDAO dao = BinaryRatingDAO.open(file);
        BinaryRatingDAO clone = SerializationUtils.clone(dao);
        verifySimpleDAO(clone);
    }

    @Test
    public void testBufferDAO() throws IOException {
        File file = folder.newFile("ratings.bin");
        BinaryRatingPacker packer = BinaryRatingPacker.open(file);
        try {
            packer.writeRatings(ratings);
        } finally {
            packer.close();
        }

        ByteBuffer buffer;
        try (FileInputStream istr = new FileInputStream(file)) {
            FileChannel chan = istr.getChannel();
            buffer = chan.map(FileChannel.MapMode.READ_ONLY, 0, chan.size());
        }

        BinaryRatingDAO dao = BinaryRatingDAO.fromBuffer(buffer);
        verifySimpleDAO(dao);
    }

    private void verifySimpleDAO(BinaryRatingDAO dao) {
        assertThat(ObjectStreams.makeList(dao.streamEvents()), hasSize(3));
        assertThat(dao.getUserIds(), containsInAnyOrder(42L, 39L));
        assertThat(dao.getItemIds(), containsInAnyOrder(105L, 120L));
        assertThat(dao.getUsersForItem(105), containsInAnyOrder(42L));
        assertThat(dao.getUsersForItem(120), containsInAnyOrder(42L, 39L));
        assertThat(dao.getEventsForUser(39, Rating.class), contains(Rating.create(39, 120, 4.5)));
        assertThat(dao.getEventsForUser(42, Rating.class),
                containsInAnyOrder(Rating.create(42, 120, 2.5), Rating.create(42, 105, 3.5)));
        assertThat(dao.getEventsForItem(105, Rating.class), contains(Rating.create(42, 105, 3.5)));
        assertThat(dao.getEventsForItem(120, Rating.class),
                containsInAnyOrder(Rating.create(39, 120, 4.5), Rating.create(42, 120, 2.5)));
        assertThat(dao.getEventsForItem(42), nullValue());
        assertThat(dao.getEventsForUser(105), nullValue());

        List<UserHistory<Event>> histories = ObjectStreams.makeList(dao.streamEventsByUser());
        assertThat(histories, hasSize(2));
        assertThat(histories.get(0).getUserId(), equalTo(39L));
        assertThat(histories.get(0), equalTo(dao.getEventsForUser(39)));
        assertThat(histories.get(1).getUserId(), equalTo(42L));
        assertThat(histories.get(1), equalTo(dao.getEventsForUser(42)));

        List<Rating> events = ObjectStreams.makeList(dao.streamEvents(Rating.class, SortOrder.USER));
        assertThat(events, hasSize(3));
        assertThat(events.get(0).getUserId(), equalTo(39L));

        events = ObjectStreams.makeList(dao.streamEvents(Rating.class, SortOrder.ITEM));
        assertThat(events, hasSize(3));
        assertThat(events.get(0).getUserId(), equalTo(42L));
        assertThat(events.get(0).getItemId(), equalTo(105L));
    }
}