Package org.eurekastreams.server.action.execution.feed

Source Code of org.eurekastreams.server.action.execution.feed.RefreshFeedExecutionTest

/*
* Copyright (c) 2010 Lockheed Martin Corporation
*
* 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.eurekastreams.server.action.execution.feed;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.eurekastreams.commons.actions.context.ActionContext;
import org.eurekastreams.server.action.request.feed.RefreshFeedRequest;
import org.eurekastreams.server.domain.DomainGroup;
import org.eurekastreams.server.domain.EntityType;
import org.eurekastreams.server.domain.Person;
import org.eurekastreams.server.domain.gadgetspec.GadgetMetaDataDTO;
import org.eurekastreams.server.domain.stream.Activity;
import org.eurekastreams.server.domain.stream.BaseObjectType;
import org.eurekastreams.server.domain.stream.plugins.Feed;
import org.eurekastreams.server.domain.stream.plugins.FeedSubscriber;
import org.eurekastreams.server.domain.stream.plugins.PluginDefinition;
import org.eurekastreams.server.persistence.mappers.FindByIdMapper;
import org.eurekastreams.server.persistence.mappers.InsertMapper;
import org.eurekastreams.server.persistence.mappers.UpdateMapper;
import org.eurekastreams.server.persistence.mappers.cache.CacheKeys;
import org.eurekastreams.server.persistence.mappers.cache.MemcachedCache;
import org.eurekastreams.server.persistence.mappers.requests.FindByIdRequest;
import org.eurekastreams.server.persistence.mappers.requests.PersistenceRequest;
import org.eurekastreams.server.service.actions.strategies.activity.plugins.FeedObjectActivityBuilder;
import org.eurekastreams.server.service.actions.strategies.activity.plugins.ObjectBuilderForSpecificUrl;
import org.eurekastreams.server.service.actions.strategies.activity.plugins.rome.ActivityStreamsModule;
import org.eurekastreams.server.service.actions.strategies.activity.plugins.rome.ActivityStreamsModuleImpl;
import org.eurekastreams.server.service.actions.strategies.activity.plugins.rome.FeedFactory;
import org.eurekastreams.server.service.opensocial.gadgets.spec.GadgetMetaDataFetcher;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.jmock.lib.legacy.ClassImposteriser;
import org.junit.Before;
import org.junit.Test;

import com.sun.syndication.feed.module.SyModule;
import com.sun.syndication.feed.synd.SyndEntryImpl;
import com.sun.syndication.feed.synd.SyndFeed;

/**
* Test for the RefreshFeedAction.
*
*/
public class RefreshFeedExecutionTest
{
    /**
     * Context for building mock objects.
     */
    private final Mockery context = new JUnit4Mockery()
    {
        {
            setImposteriser(ClassImposteriser.INSTANCE);
        }
    };

    /** Test data. */
    private static final String FEED_URL = "http://www.flickr.com/rss/feed";

    /**
     * Minutes in an hour.
     */
    private static final long MININHOUR = 60L;

    /**
     * Minutes in a day.
     */
    private static final long MININDAY = 1440L;

    /**
     * Minutes in a week.
     */
    private static final long MININWEEK = 10080L;

    /**
     * Minutes in a month.
     */
    private static final long MININMONTH = 44640L;

    /**
     * Minutes in a year.
     */
    private static final long MININYEAR = 525600L;

    /**
     * Standard feed mappers.
     */
    private final HashMap<BaseObjectType, FeedObjectActivityBuilder> standardFeedMappers
    // break
    = new HashMap<BaseObjectType, FeedObjectActivityBuilder>();

    /**
     * Mappers for specific websites.
     */
    private final List<ObjectBuilderForSpecificUrl> specificUrlMappers = new LinkedList<ObjectBuilderForSpecificUrl>();

    /**
     * Bulk insert activity into the DB.
     */
    private final InsertMapper<Activity> activityDBInserter = context.mock(InsertMapper.class);

    /**
     * The cache.
     */
    private final MemcachedCache cache = context.mock(MemcachedCache.class);

    /**
     * System under test.
     */
    private RefreshFeedExecution sut;

    /**
     * Context for tests.
     */
    private final ActionContext ac = context.mock(ActionContext.class);

    /**
     * Feed factory mock.
     */
    private final FeedFactory feedFetcherFactory = context.mock(FeedFactory.class);
    /**
     * Flickr mapper mock.
     */
    private final ObjectBuilderForSpecificUrl flickrMapper = context.mock(ObjectBuilderForSpecificUrl.class, "flickr");
    /**
     * Youtube mapper mock.
     */
    private final ObjectBuilderForSpecificUrl youTubeMapper = context
            .mock(ObjectBuilderForSpecificUrl.class, "youtube");
    /**
     * Notemapper mock.
     */
    private final FeedObjectActivityBuilder noteMapper = context.mock(FeedObjectActivityBuilder.class, "note");
    /**
     * Bookmark mapper mock.
     */
    private final FeedObjectActivityBuilder bookmarkMapper = context.mock(FeedObjectActivityBuilder.class, "bookmark");

    /**
     * Find by id person mapper.
     */
    private final FindByIdMapper<Person> personMapper = context.mock(FindByIdMapper.class);

    /**
     * Find by id group mapper.
     */
    private final FindByIdMapper<DomainGroup> groupMapper = context.mock(FindByIdMapper.class, "gm");

    /**
     * Find by id feed mapper.
     */
    private final FindByIdMapper<Feed> feedMapper = context.mock(FindByIdMapper.class, "fm");

    /**
     * Person owner.
     */
    private final Person personOwner = context.mock(Person.class);
    /**
     * Group owner.
     */
    private final DomainGroup groupOwner = context.mock(DomainGroup.class);

    /**
     * Group owner.
     */
    private final UpdateMapper<Feed> updateMapper = context.mock(UpdateMapper.class);

    /**
     * Gadget metadata fetcher.
     */
    private final GadgetMetaDataFetcher fetcher = context.mock(GadgetMetaDataFetcher.class);

    /**
     * Unordered feeds.
     */
    private List<String> unorderedFeeds = new ArrayList<String>();

    /** Fixture: feed. */
    private final Feed feed = context.mock(Feed.class);

    /** Fixture: stream plugin. */
    private final PluginDefinition plugin = context.mock(PluginDefinition.class);

    /** Fixture: atom feed. */
    private final SyndFeed atomFeed1 = context.mock(SyndFeed.class, "atomFeed1");

    /** Fixture: atom feed. */
    private final SyndFeed atomFeed2 = context.mock(SyndFeed.class, "atomFeed2");

    /**
     * Prep the system under test for the test suite.
     *
     * @throws Exception
     *             exception.
     */
    @Before
    public void setUp() throws Exception
    {
        final List<GadgetMetaDataDTO> metaDataList = new ArrayList<GadgetMetaDataDTO>();
        metaDataList.add(new GadgetMetaDataDTO(null));

        FeedSubscriber sub1 = new FeedSubscriber();
        sub1.setEntityId(1L);
        sub1.setEntityType(EntityType.PERSON);
        sub1.setRequestor(new Person("user1", "", "", "", ""));
        FeedSubscriber sub2 = new FeedSubscriber();
        sub2.setEntityId(2L);
        sub2.setEntityType(EntityType.GROUP);
        sub2.setRequestor(new Person("user2", "", "", "", ""));
        final List<FeedSubscriber> feedSubs = new ArrayList<FeedSubscriber>();
        feedSubs.add(sub1);
        feedSubs.add(sub2);

        specificUrlMappers.add(youTubeMapper);
        specificUrlMappers.add(flickrMapper);

        standardFeedMappers.put(BaseObjectType.NOTE, noteMapper);
        standardFeedMappers.put(BaseObjectType.BOOKMARK, bookmarkMapper);

        sut = new RefreshFeedExecution(standardFeedMappers, specificUrlMappers, activityDBInserter, cache,
                feedFetcherFactory, personMapper, groupMapper, feedMapper, fetcher, updateMapper, unorderedFeeds);
        context.checking(new Expectations()
        {
            {
                allowing(ac).getParams();
                will(returnValue(new RefreshFeedRequest(5L)));

                // ---- feed ----
                allowing(feed).getUrl();
                will(returnValue(FEED_URL));

                allowing(feed).getLastSeenGUID();
                will(returnValue(""));

                allowing(feed).getLastPostDate();
                will(returnValue(new Date(2)));

                allowing(feed).getPlugin();
                will(returnValue(plugin));

                allowing(feed).getFeedSubscribers();
                will(returnValue(feedSubs));

                allowing(feed).getTitle();
                will(returnValue("This is a feed"));

                // allowing(feed).getId();
                // will(returnValue(5L));

                // ---- plugin ----
                allowing(plugin).getUrl();

                allowing(plugin).getId();
                will(returnValue(1L));

                allowing(plugin).getObjectType();
                will(returnValue(BaseObjectType.BOOKMARK));

                oneOf(youTubeMapper).match(with(any(String.class)));
                will(returnValue(false));

                allowing(updateMapper).execute(with(any(PersistenceRequest.class)));

                allowing(cache).get(CacheKeys.BUFFERED_ACTIVITIES);
                will(returnValue(1L));

                allowing(fetcher).getGadgetsMetaData(with(any(Map.class)));
                will(returnValue(metaDataList));

                allowing(activityDBInserter).execute(with(any(PersistenceRequest.class)));
                allowing(cache).addToTopOfList(with(any(String.class)), with(any(ArrayList.class)));

                allowing(personMapper).execute(with(any(FindByIdRequest.class)));
                will(returnValue(personOwner));

                allowing(groupMapper).execute(with(any(FindByIdRequest.class)));
                will(returnValue(groupOwner));

                allowing(feedMapper).execute(with(any(FindByIdRequest.class)));
                will(returnValue(feed));

                // ---- updates always made ----
                oneOf(feed).setLastPostDate(with(any(Date.class)));
                oneOf(feed).setLastUpdated(with(any(Long.class)));
                oneOf(feed).setPending(false);
                oneOf(feed).setLastSeenGUID(with(any(String.class)));
                oneOf(feed).setIsFeedBroken(with(any(Boolean.class)));
            }
        });

    }

    /**
     * Setup expectations for fetching anonymously.
     *
     * @throws Exception
     *             Shouldn't.
     */
    private void setupFetchAnonymous() throws Exception
    {
        context.checking(new Expectations()
        {
            {
                allowing(feedFetcherFactory).getSyndicatedFeed(with(equal(FEED_URL)), with(any(List.class)));
                will(returnValue(Collections.singletonMap(null, atomFeed1)));
            }
        });
    }

    /**
     * Setup expectations for fetching on a per-user basis.
     *
     * @throws Exception
     *             Shouldn't.
     */
    private void setupFetchByUser() throws Exception
    {
        final Map<String, SyndFeed> feeds = new TreeMap<String, SyndFeed>(); // use TreeMap to force order
        feeds.put("user1", atomFeed1);
        feeds.put("user2", atomFeed2);

        context.checking(new Expectations()
        {
            {
                allowing(feedFetcherFactory).getSyndicatedFeed(with(equal(FEED_URL)), with(any(List.class)));
                will(returnValue(feeds));
            }
        });
    }

    /**
     * Creates expectations for no SyMod.
     */
    private void setupNoSyMod()
    {
        context.checking(new Expectations()
        {
            {
                allowing(atomFeed1).getModule(SyModule.URI);
                will(returnValue(null));

                allowing(atomFeed2).getModule(SyModule.URI);
                will(returnValue(null));

                oneOf(feed).setUpdateFrequency(null);
            }
        });
    }

    /**
     * Core behavior for update frequency tests.
     *
     * @param period
     *            Time unit of update period.
     * @param frequency
     *            Frequency of update.
     * @param expected
     *            Expected value to be set in the feed.
     * @throws Exception
     *             Shouldn't.
     */
    private void coreUpdateFrequencyTest(final String period, final int frequency, final Long expected)
            throws Exception
    {
        final SyModule syMod = context.mock(SyModule.class);

        setupFetchByUser();
        context.checking(new Expectations()
        {
            {
                allowing(flickrMapper).match(FEED_URL);
                will(returnValue(false));

                allowing(atomFeed1).getModule(SyModule.URI);
                will(returnValue(syMod));

                never(atomFeed2).getModule(with(any(String.class)));

                allowing(syMod).getUpdateFrequency();
                will(returnValue(frequency));

                allowing(syMod).getUpdatePeriod();
                will(returnValue(period));

                allowing(atomFeed1).getEntries();
                will(returnValue(Collections.EMPTY_LIST));

                allowing(atomFeed2).getEntries();
                will(returnValue(Collections.EMPTY_LIST));

                oneOf(feed).setUpdateFrequency(expected);
            }
        });

        sut.execute(ac);

        context.assertIsSatisfied();
    }

    /**
     * Tests SyMod-specified update frequency.
     *
     * @throws Exception
     *             Shouldn't.
     */
    @Test
    public void testSymodDefault() throws Exception
    {
        coreUpdateFrequencyTest("Undefined Value", 1, MININHOUR);
    }

    /**
     * Tests SyMod-specified update frequency.
     *
     * @throws Exception
     *             Shouldn't.
     */
    @Test
    public void testSymodHourly() throws Exception
    {
        coreUpdateFrequencyTest(SyModule.HOURLY, 1, MININHOUR);
    }

    /**
     * Tests SyMod-specified update frequency.
     *
     * @throws Exception
     *             Shouldn't.
     */
    @Test
    public void testSymodDaily() throws Exception
    {
        coreUpdateFrequencyTest(SyModule.DAILY, 1, MININDAY);
    }

    /**
     * Tests SyMod-specified update frequency.
     *
     * @throws Exception
     *             Shouldn't.
     */
    @Test
    public void testSymodWeekly() throws Exception
    {
        coreUpdateFrequencyTest(SyModule.WEEKLY, 1, MININWEEK);
    }

    /**
     * Tests SyMod-specified update frequency.
     *
     * @throws Exception
     *             Shouldn't.
     */
    @Test
    public void testSymodMonthly() throws Exception
    {
        coreUpdateFrequencyTest(SyModule.MONTHLY, 1, MININMONTH);
    }

    /**
     * Tests SyMod-specified update frequency.
     *
     * @throws Exception
     *             Shouldn't.
     */
    @Test
    public void testSymodYearly() throws Exception
    {
        coreUpdateFrequencyTest(SyModule.YEARLY, 1, MININYEAR);
    }

    /**
     * Test with no mapper and a specific URL mapper for the feed and 1 entry.
     *
     * @throws Exception
     *             exception feed throws.
     */
    @Test
    public void withSpecificMapper() throws Exception
    {
        final FeedObjectActivityBuilder flickrObjectMapper = context.mock(FeedObjectActivityBuilder.class);
        final SyndEntryImpl entry1 = context.mock(SyndEntryImpl.class, "e1");
        final List<SyndEntryImpl> entryList = Collections.singletonList(entry1);

        setupNoSyMod();
        setupFetchAnonymous();
        context.checking(new Expectations()
        {
            {
                oneOf(flickrMapper).match(FEED_URL);
                will(returnValue(true));

                oneOf(flickrMapper).getBuilder();
                will(returnValue(flickrObjectMapper));

                allowing(entry1).getPublishedDate();
                will(returnValue(new Date(3)));

                allowing(entry1).getUpdatedDate();
                will(returnValue(new Date(3)));

                allowing(entry1).getUri();
                will(returnValue("uri"));

                oneOf(flickrObjectMapper).build(with(equal(feed)), with(equal(entry1)), with(any(Activity.class)));
               
                allowing(personOwner).isAccountLocked();
                will(returnValue(false));
               
                allowing(personOwner).getAccountId();
                allowing(personOwner).getId();
                allowing(personOwner).getStreamScope();
                allowing(groupOwner).getStreamScope();
                allowing(groupOwner).isPublicGroup();
                allowing(groupOwner).getShortName();
                will(returnValue(false));

                allowing(atomFeed1).getEntries();
                will(returnValue(entryList));

            }
        });

        sut.execute(ac);

        context.assertIsSatisfied();
    }

    /**
     * Test with 1 old entry, 1 activitystreams entry, 1 unsupported activitystreams object, and 1 standard note object.
     *
     * @throws Exception
     *             exception feed throws.
     */
    @Test
    public void withOneActivityStreamsAndOneEntryError() throws Exception
    {
        final ActivityStreamsModuleImpl activityModule = context.mock(ActivityStreamsModuleImpl.class);
        // Feed is too old.
        final SyndEntryImpl entry1 = context.mock(SyndEntryImpl.class, "e1");
        // This feed should error out.
        final SyndEntryImpl entry2 = context.mock(SyndEntryImpl.class, "e2");
        // This feed is an activitystreams that has no object support
        final SyndEntryImpl entry3 = context.mock(SyndEntryImpl.class, "e3");
        // This is a standard entry with a known object
        final SyndEntryImpl entry4 = context.mock(SyndEntryImpl.class, "e4");

        final List<SyndEntryImpl> entryList = new LinkedList<SyndEntryImpl>();
        entryList.add(entry1);
        entryList.add(entry2);
        entryList.add(entry3);
        entryList.add(entry4);

        setupNoSyMod();
        setupFetchAnonymous();
        context.checking(new Expectations()
        {
            {
              allowing(personOwner).isAccountLocked();
                will(returnValue(false));
               
                allowing(personOwner).getAccountId();
                allowing(personOwner).getId();
                allowing(personOwner).getStreamScope();
                allowing(groupOwner).getStreamScope();
                allowing(groupOwner).isPublicGroup();
                allowing(groupOwner).getShortName();
                will(returnValue(false));

                oneOf(flickrMapper).match(FEED_URL);
                will(returnValue(false));

                // ENTRY 1
                allowing(entry1).getPublishedDate();
                will(returnValue(new Date()));
                allowing(entry1).getUpdatedDate();

                allowing(entry1).getUri();
                will(returnValue(""));

                oneOf(entry1).getModule(ActivityStreamsModule.URI);
                will(returnValue(null));

                // ENTRY 2
                allowing(entry2).getPublishedDate();
                will(returnValue(new Date()));

                allowing(entry2).getUpdatedDate();
                will(throwException(new Exception()));

                allowing(entry2).getUri();
                will(returnValue("uri"));

                // ENTRY 3
                allowing(entry3).getPublishedDate();
                will(returnValue(new Date()));

                allowing(entry3).getUpdatedDate();
                will(returnValue(new Date()));

                allowing(entry3).getUri();
                will(returnValue("uri"));

                oneOf(entry3).getModule(ActivityStreamsModule.URI);
                will(returnValue(activityModule));

                oneOf(activityModule).getObjectType();
                will(returnValue("PHOTO"));

                oneOf(activityModule).getAtomEntry();
                will(returnValue(entry3));

                oneOf(noteMapper).build(with(equal(feed)), with(equal(entry3)), with(any(Activity.class)));

                // ENTRY 4
                allowing(entry4).getPublishedDate();
                will(returnValue(new Date()));

                allowing(entry4).getUpdatedDate();
                will(returnValue(new Date()));

                allowing(entry4).getUri();
                will(returnValue("uri"));

                oneOf(entry4).getModule(ActivityStreamsModule.URI);
                will(returnValue(null));

                allowing(atomFeed1).getEntries();
                will(returnValue(entryList));

                oneOf(bookmarkMapper).build(with(equal(feed)), with(equal(entry4)), with(any(Activity.class)));
                oneOf(bookmarkMapper).build(with(equal(feed)), with(equal(entry1)), with(any(Activity.class)));
            }
        });

        sut.execute(ac);

        context.assertIsSatisfied();
    }
}
TOP

Related Classes of org.eurekastreams.server.action.execution.feed.RefreshFeedExecutionTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.