/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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.apache.mahout.cf.taste.impl.model; import java.util.Iterator; import org.apache.mahout.cf.taste.common.NoSuchUserException; import org.apache.mahout.cf.taste.common.TasteException; import org.apache.mahout.cf.taste.model.PreferenceArray; import org.apache.mahout.cf.taste.impl.common.FastByIDMap; import org.apache.mahout.common.MahoutTestCase; import org.junit.Test; public final class PlusAnonymousConcurrentUserDataModelTest extends MahoutTestCase { /** * Prepares a testable object without delegate data */ private static PlusAnonymousConcurrentUserDataModel getTestableWithoutDelegateData(int maxConcurrentUsers) { FastByIDMap<PreferenceArray> delegatePreferences = new FastByIDMap<PreferenceArray>(); return new PlusAnonymousConcurrentUserDataModel(new GenericDataModel(delegatePreferences), maxConcurrentUsers); } /** * Prepares a testable object with delegate data */ private static PlusAnonymousConcurrentUserDataModel getTestableWithDelegateData( int maxConcurrentUsers, FastByIDMap<PreferenceArray> delegatePreferences) { return new PlusAnonymousConcurrentUserDataModel(new GenericDataModel(delegatePreferences), maxConcurrentUsers); } /** * Test taking the first available user */ @Test public void testTakeFirstAvailableUser() { PlusAnonymousConcurrentUserDataModel instance = getTestableWithoutDelegateData(10); Long expResult = PlusAnonymousUserDataModel.TEMP_USER_ID; Long result = instance.takeAvailableUser(); assertEquals(expResult, result); } /** * Test taking the next available user */ @Test public void testTakeNextAvailableUser() { PlusAnonymousConcurrentUserDataModel instance = getTestableWithoutDelegateData(10); // Skip first user instance.takeAvailableUser(); Long result = instance.takeAvailableUser(); Long expResult = PlusAnonymousUserDataModel.TEMP_USER_ID + 1; assertEquals(expResult, result); } /** * Test taking an unavailable user */ @Test public void testTakeUnavailableUser() { PlusAnonymousConcurrentUserDataModel instance = getTestableWithoutDelegateData(1); // Take the only available user instance.takeAvailableUser(); // There are no more users available assertNull(instance.takeAvailableUser()); } /** * Test releasing a valid previously taken user */ @Test public void testReleaseValidUser() { PlusAnonymousConcurrentUserDataModel instance = getTestableWithoutDelegateData(10); Long takenUserID = instance.takeAvailableUser(); assertTrue(instance.releaseUser(takenUserID)); } /** * Test releasing an invalid user */ @Test public void testReleaseInvalidUser() { PlusAnonymousConcurrentUserDataModel instance = getTestableWithoutDelegateData(10); assertFalse(instance.releaseUser(Long.MAX_VALUE)); } /** * Test releasing a user which had been released earlier */ @Test public void testReleasePreviouslyReleasedUser() { PlusAnonymousConcurrentUserDataModel instance = getTestableWithoutDelegateData(10); Long takenUserID = instance.takeAvailableUser(); assertTrue(instance.releaseUser(takenUserID)); assertFalse(instance.releaseUser(takenUserID)); } /** * Test setting anonymous user preferences */ @Test public void testSetAndGetTempPreferences() throws TasteException { PlusAnonymousConcurrentUserDataModel instance = getTestableWithoutDelegateData(10); Long anonymousUserID = instance.takeAvailableUser(); PreferenceArray tempPrefs = new GenericUserPreferenceArray(1); tempPrefs.setUserID(0, anonymousUserID); tempPrefs.setItemID(0, 1); instance.setTempPrefs(tempPrefs, anonymousUserID); assertEquals(tempPrefs, instance.getPreferencesFromUser(anonymousUserID)); instance.releaseUser(anonymousUserID); } /** * Test setting and getting preferences from several concurrent anonymous users */ @Test public void testSetMultipleTempPreferences() throws TasteException { PlusAnonymousConcurrentUserDataModel instance = getTestableWithoutDelegateData(10); Long anonymousUserID1 = instance.takeAvailableUser(); Long anonymousUserID2 = instance.takeAvailableUser(); PreferenceArray tempPrefs1 = new GenericUserPreferenceArray(1); tempPrefs1.setUserID(0, anonymousUserID1); tempPrefs1.setItemID(0, 1); PreferenceArray tempPrefs2 = new GenericUserPreferenceArray(2); tempPrefs2.setUserID(0, anonymousUserID2); tempPrefs2.setItemID(0, 2); tempPrefs2.setUserID(1, anonymousUserID2); tempPrefs2.setItemID(1, 3); instance.setTempPrefs(tempPrefs1, anonymousUserID1); instance.setTempPrefs(tempPrefs2, anonymousUserID2); assertEquals(tempPrefs1, instance.getPreferencesFromUser(anonymousUserID1)); assertEquals(tempPrefs2, instance.getPreferencesFromUser(anonymousUserID2)); } /** * Test counting the number of delegate users */ @Test public void testGetNumUsersWithDelegateUsersOnly() throws TasteException { PreferenceArray prefs = new GenericUserPreferenceArray(1); long sampleUserID = 1; prefs.setUserID(0, sampleUserID); long sampleItemID = 11; prefs.setItemID(0, sampleItemID); FastByIDMap<PreferenceArray> delegatePreferences = new FastByIDMap<PreferenceArray>(); delegatePreferences.put(sampleUserID, prefs); PlusAnonymousConcurrentUserDataModel instance = getTestableWithDelegateData(10, delegatePreferences); assertEquals(1, instance.getNumUsers()); } /** * Test counting the number of anonymous users */ @Test public void testGetNumAnonymousUsers() throws TasteException { PlusAnonymousConcurrentUserDataModel instance = getTestableWithoutDelegateData(10); Long anonymousUserID1 = instance.takeAvailableUser(); PreferenceArray tempPrefs1 = new GenericUserPreferenceArray(1); tempPrefs1.setUserID(0, anonymousUserID1); tempPrefs1.setItemID(0, 1); instance.setTempPrefs(tempPrefs1, anonymousUserID1); // Anonymous users should not be included into the universe. assertEquals(0, instance.getNumUsers()); } /** * Test retrieve a single preference value of an anonymous user */ @Test public void testGetPreferenceValue() throws TasteException { PlusAnonymousConcurrentUserDataModel instance = getTestableWithoutDelegateData(10); Long anonymousUserID = instance.takeAvailableUser(); PreferenceArray tempPrefs = new GenericUserPreferenceArray(1); tempPrefs.setUserID(0, anonymousUserID); long sampleItemID = 1; tempPrefs.setItemID(0, sampleItemID); tempPrefs.setValue(0, Float.MAX_VALUE); instance.setTempPrefs(tempPrefs, anonymousUserID); assertEquals(Float.MAX_VALUE, instance.getPreferenceValue(anonymousUserID, sampleItemID), EPSILON); } /** * Test retrieve preferences for existing non-anonymous user */ @Test public void testGetPreferencesForNonAnonymousUser() throws TasteException { PreferenceArray prefs = new GenericUserPreferenceArray(1); long sampleUserID = 1; prefs.setUserID(0, sampleUserID); long sampleItemID = 11; prefs.setItemID(0, sampleItemID); FastByIDMap<PreferenceArray> delegatePreferences = new FastByIDMap<PreferenceArray>(); delegatePreferences.put(sampleUserID, prefs); PlusAnonymousConcurrentUserDataModel instance = getTestableWithDelegateData(10, delegatePreferences); assertEquals(prefs, instance.getPreferencesFromUser(sampleUserID)); } /** * Test retrieve preferences for non-anonymous and non-existing user */ @Test(expected=NoSuchUserException.class) public void testGetPreferencesForNonExistingUser() throws TasteException { PlusAnonymousConcurrentUserDataModel instance = getTestableWithoutDelegateData(10); // Exception is expected since such user does not exist instance.getPreferencesFromUser(1); } /** * Test retrieving the user IDs and verifying that anonymous ones are not included */ @Test public void testGetUserIDs() throws TasteException { PreferenceArray prefs = new GenericUserPreferenceArray(1); long sampleUserID = 1; prefs.setUserID(0, sampleUserID); long sampleItemID = 11; prefs.setItemID(0, sampleItemID); FastByIDMap<PreferenceArray> delegatePreferences = new FastByIDMap<PreferenceArray>(); delegatePreferences.put(sampleUserID, prefs); PlusAnonymousConcurrentUserDataModel instance = getTestableWithDelegateData(10, delegatePreferences); Long anonymousUserID = instance.takeAvailableUser(); PreferenceArray tempPrefs = new GenericUserPreferenceArray(1); tempPrefs.setUserID(0, anonymousUserID); tempPrefs.setItemID(0, 22); instance.setTempPrefs(tempPrefs, anonymousUserID); Iterator<Long> userIDs = instance.getUserIDs(); assertSame(sampleUserID, userIDs.next()); assertFalse(userIDs.hasNext()); } /** * Test getting preferences for an item. * * @throws TasteException */ @Test public void testGetPreferencesForItem() throws TasteException { PreferenceArray prefs = new GenericUserPreferenceArray(2); long sampleUserID = 4; prefs.setUserID(0, sampleUserID); long sampleItemID = 11; prefs.setItemID(0, sampleItemID); prefs.setUserID(1, sampleUserID); long sampleItemID2 = 22; prefs.setItemID(1, sampleItemID2); FastByIDMap<PreferenceArray> delegatePreferences = new FastByIDMap<PreferenceArray>(); delegatePreferences.put(sampleUserID, prefs); PlusAnonymousConcurrentUserDataModel instance = getTestableWithDelegateData(10, delegatePreferences); Long anonymousUserID = instance.takeAvailableUser(); PreferenceArray tempPrefs = new GenericUserPreferenceArray(2); tempPrefs.setUserID(0, anonymousUserID); tempPrefs.setItemID(0, sampleItemID); tempPrefs.setUserID(1, anonymousUserID); long sampleItemID3 = 33; tempPrefs.setItemID(1, sampleItemID3); instance.setTempPrefs(tempPrefs, anonymousUserID); assertEquals(sampleUserID, instance.getPreferencesForItem(sampleItemID).get(0).getUserID()); assertEquals(2, instance.getPreferencesForItem(sampleItemID).length()); assertEquals(1, instance.getPreferencesForItem(sampleItemID2).length()); assertEquals(1, instance.getPreferencesForItem(sampleItemID3).length()); assertEquals(2, instance.getNumUsersWithPreferenceFor(sampleItemID)); assertEquals(1, instance.getNumUsersWithPreferenceFor(sampleItemID, sampleItemID2)); assertEquals(1, instance.getNumUsersWithPreferenceFor(sampleItemID, sampleItemID3)); } }