/* * Copyright 2015 MovingBlocks * * 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.terasology.assets; import com.google.common.collect.ImmutableSet; import org.junit.Test; import org.terasology.assets.test.Return; import org.terasology.assets.test.VirtualModuleEnvironment; import org.terasology.assets.test.stubs.text.Text; import org.terasology.assets.test.stubs.text.TextData; import org.terasology.assets.test.stubs.text.TextFactory; import org.terasology.naming.Name; import java.io.IOException; import java.util.Optional; import java.util.Set; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; /** * @author Immortius */ public class AssetTypeTest extends VirtualModuleEnvironment { public static final String TEXT_VALUE = "Value"; public static final String TEXT_VALUE_2 = "Value_2"; public static final ResourceUrn URN = new ResourceUrn("test", "example"); private AssetType<Text, TextData> assetType = new AssetType<>(Text.class, new TextFactory()); public AssetTypeTest() throws Exception { } @Test public void construction() { assertEquals(Text.class, assetType.getAssetClass()); assertTrue(assetType.getProducers().isEmpty()); } @Test public void loadData() { TextData data = new TextData(TEXT_VALUE); assertFalse(assetType.isLoaded(URN)); Text createdText = assetType.loadAsset(URN, data); assertEquals(TEXT_VALUE, createdText.getValue()); assertTrue(assetType.isLoaded(URN)); } @Test public void retrieveLoadedDataByUrn() { TextData data = new TextData(TEXT_VALUE); Text loadedText = assetType.loadAsset(URN, data); Optional<? extends Text> retrievedText = assetType.getAsset(URN); assertEquals(loadedText, retrievedText.get()); } @Test public void loadingAssetWithSameUrnReloadsExistingAsset() { TextData initialData = new TextData(TEXT_VALUE); Text initialText = assetType.loadAsset(URN, initialData); TextData newData = new TextData(TEXT_VALUE_2); Text newText = assetType.loadAsset(URN, newData); assertSame(initialText, newText); assertEquals(newData.getValue(), initialText.getValue()); } @Test public void disposingAsset() { TextData data = new TextData(TEXT_VALUE); Text asset = assetType.loadAsset(URN, data); asset.dispose(); assertTrue(asset.isDisposed()); assertFalse(assetType.getAsset(URN).isPresent()); } @Test public void addProducer() { AssetDataProducer producer = mock(AssetDataProducer.class); assetType.addProducer(producer); assertEquals(1, assetType.getProducers().size()); assertTrue(assetType.getProducers().contains(producer)); } @Test public void removeProducer() { AssetDataProducer producer = mock(AssetDataProducer.class); assetType.addProducer(producer); assetType.removeProducer(producer); assertTrue(assetType.getProducers().isEmpty()); } @Test public void clearProducers() { AssetDataProducer producer = mock(AssetDataProducer.class); assetType.addProducer(producer); assetType.clearProducers(); assertTrue(assetType.getProducers().isEmpty()); } @Test public void resolveFullUrnReturnsUrn() { Set<ResourceUrn> results = assetType.resolve(URN.toString()); assertEquals(1, results.size()); assertTrue(results.contains(URN)); } @Test public void resolvePartialReturnsNothingWithNoPossibilities() { Set<ResourceUrn> results = assetType.resolve(URN.getResourceName().toString()); assertTrue(results.isEmpty()); } @Test public void resolvePartialReturnsPossibilitiesFromProducers() { AssetDataProducer producer = mock(AssetDataProducer.class); assetType.addProducer(producer); when(producer.getModulesProviding(URN.getResourceName())).thenReturn(ImmutableSet.of(URN.getModuleName())); Set<ResourceUrn> results = assetType.resolve(URN.getResourceName().toString()); assertEquals(1, results.size()); assertTrue(results.contains(URN)); } @Test public void resolvePartialWithContextCallsResolutionStrategy() { AssetDataProducer producer = mock(AssetDataProducer.class); assetType.addProducer(producer); ResolutionStrategy strategy = mock(ResolutionStrategy.class); when(strategy.resolve(ImmutableSet.of(URN.getModuleName()), URN.getModuleName())).thenReturn(ImmutableSet.of(URN.getModuleName())); assetType.setResolutionStrategy(strategy); when(producer.getModulesProviding(URN.getResourceName())).thenReturn(ImmutableSet.of(URN.getModuleName())); Set<ResourceUrn> results = assetType.resolve(URN.getResourceName().toString(), URN.getModuleName()); assertEquals(1, results.size()); assertTrue(results.contains(URN)); verify(strategy).resolve(ImmutableSet.of(URN.getModuleName()), URN.getModuleName()); } @Test public void getUnknownAsset() { assertFalse(assetType.getAsset(URN).isPresent()); } @Test public void getAssetLoadsFromProducers() throws Exception { AssetDataProducer producer = mock(AssetDataProducer.class); assetType.addProducer(producer); when(producer.redirect(URN)).thenReturn(URN); when(producer.getAssetData(URN)).thenReturn(Optional.of(new TextData(TEXT_VALUE))); Optional<? extends Text> asset = assetType.getAsset(URN); assertTrue(asset.isPresent()); assertEquals(URN, asset.get().getUrn()); assertEquals(TEXT_VALUE, asset.get().getValue()); assertTrue(assetType.isLoaded(URN)); } @Test public void getAssetWhenProducerFails() throws Exception { AssetDataProducer producer = mock(AssetDataProducer.class); assetType.addProducer(producer); when(producer.redirect(any(ResourceUrn.class))).thenAnswer(Return.firstArgument()); when(producer.getAssetData(URN)).thenThrow(new IOException()); assertFalse(assetType.getAsset(URN).isPresent()); assertFalse(assetType.isLoaded(URN)); } @Test public void followRedirectsGettingAssets() throws Exception { AssetDataProducer producer = mock(AssetDataProducer.class); ResourceUrn realUrn = new ResourceUrn("engine:real"); when(producer.redirect(any(ResourceUrn.class))).thenAnswer(Return.firstArgument()); when(producer.redirect(URN)).thenReturn(realUrn); when(producer.getAssetData(realUrn)).thenReturn(Optional.of(new TextData(TEXT_VALUE_2))); assetType.addProducer(producer); Optional<Text> asset = assetType.getAsset(URN); assertTrue(asset.isPresent()); assertEquals(realUrn, asset.get().getUrn()); assertEquals(TEXT_VALUE_2, asset.get().getValue()); } @Test public void redirectsChainForMultipleProducers() throws Exception { ResourceUrn realUrn = new ResourceUrn("engine:real"); ResourceUrn realUrn2 = new ResourceUrn("engine:real2"); AssetDataProducer producer = mock(AssetDataProducer.class); when(producer.getAssetData(any(ResourceUrn.class))).thenReturn(Optional.empty()); when(producer.redirect(any(ResourceUrn.class))).thenAnswer(Return.firstArgument()); when(producer.redirect(URN)).thenReturn(realUrn); AssetDataProducer producer2 = mock(AssetDataProducer.class); when(producer2.getAssetData(any(ResourceUrn.class))).thenReturn(Optional.empty()); when(producer2.getAssetData(realUrn2)).thenReturn(Optional.of(new TextData(TEXT_VALUE_2))); when(producer2.redirect(any(ResourceUrn.class))).thenAnswer(Return.firstArgument()); when(producer2.redirect(realUrn)).thenReturn(realUrn2); assetType.addProducer(producer); assetType.addProducer(producer2); Optional<Text> asset = assetType.getAsset(URN); assertTrue(asset.isPresent()); assertEquals(realUrn2, asset.get().getUrn()); assertEquals(TEXT_VALUE_2, asset.get().getValue()); } @Test public void redirectsChainForMultipleProducersAnyOrder() throws Exception { ResourceUrn realUrn = new ResourceUrn("engine:real"); ResourceUrn realUrn2 = new ResourceUrn("engine:real2"); AssetDataProducer producer = mock(AssetDataProducer.class); when(producer.getAssetData(any(ResourceUrn.class))).thenReturn(Optional.empty()); when(producer.redirect(any(ResourceUrn.class))).thenAnswer(Return.firstArgument()); when(producer.redirect(URN)).thenReturn(realUrn); AssetDataProducer producer2 = mock(AssetDataProducer.class); when(producer2.redirect(any(ResourceUrn.class))).thenAnswer(Return.firstArgument()); when(producer2.redirect(realUrn)).thenReturn(realUrn2); when(producer2.getAssetData(realUrn2)).thenReturn(Optional.of(new TextData(TEXT_VALUE_2))); assetType.addProducer(producer2); assetType.addProducer(producer); Optional<Text> asset = assetType.getAsset(URN); assertTrue(asset.isPresent()); assertEquals(realUrn2, asset.get().getUrn()); assertEquals(TEXT_VALUE_2, asset.get().getValue()); } @Test public void disposeAssetsOnDisposeAll() throws Exception { TextData data = new TextData(TEXT_VALUE); Text createdText = assetType.loadAsset(URN, data); assetType.disposeAll(); assertTrue(createdText.isDisposed()); assertFalse(assetType.getAsset(URN).isPresent()); } @Test public void disposeUnavailableAssetsOnRefresh() throws Exception { AssetDataProducer producer = mock(AssetDataProducer.class); assetType.addProducer(producer); when(producer.redirect(URN)).thenReturn(URN); when(producer.getAssetData(any(ResourceUrn.class))).thenReturn(Optional.empty()); when(producer.getAssetData(URN)).thenReturn(Optional.of(new TextData(TEXT_VALUE))); Optional<Text> asset = assetType.getAsset(URN); assertTrue(asset.isPresent()); assertFalse(asset.get().isDisposed()); when(producer.getAssetData(URN)).thenReturn(Optional.empty()); assetType.refresh(); assertTrue(asset.get().isDisposed()); } @Test public void reloadAvailableAssetsOnRefresh() throws Exception { AssetDataProducer producer = mock(AssetDataProducer.class); assetType.addProducer(producer); when(producer.redirect(URN)).thenReturn(URN); when(producer.getAssetData(URN)).thenReturn(Optional.of(new TextData(TEXT_VALUE))); Optional<Text> asset = assetType.getAsset(URN); assertTrue(asset.isPresent()); assertEquals(TEXT_VALUE, asset.get().getValue()); when(producer.getAssetData(URN)).thenReturn(Optional.of(new TextData(TEXT_VALUE_2))); assetType.refresh(); assertEquals(TEXT_VALUE_2, asset.get().getValue()); assertFalse(asset.get().isDisposed()); } @Test public void disposeAssetOnRefreshIfRedirectExists() throws Exception { AssetDataProducer producer = mock(AssetDataProducer.class); assetType.addProducer(producer); when(producer.redirect(any(ResourceUrn.class))).thenAnswer(Return.firstArgument()); when(producer.redirect(URN)).thenReturn(URN); when(producer.getAssetData(URN)).thenReturn(Optional.of(new TextData(TEXT_VALUE))); Optional<Text> asset = assetType.getAsset(URN); when(producer.redirect(URN)).thenReturn(new ResourceUrn(URN.getModuleName(), new Name("redirect"))); assetType.refresh(); assertTrue(asset.get().isDisposed()); } @Test public void loadAssetInstance() throws Exception { AssetDataProducer producer = mock(AssetDataProducer.class); assetType.addProducer(producer); when(producer.redirect(any(ResourceUrn.class))).thenAnswer(Return.firstArgument()); TextData data = new TextData(TEXT_VALUE); when(producer.getAssetData(URN)).thenReturn(Optional.of(data)); Text text = assetType.getAsset(URN).get(); Optional<Text> result = assetType.getAsset(URN.getInstanceUrn()); assertTrue(result.isPresent()); assertNotSame(text, result.get()); assertTrue(result.get().getUrn().isInstance()); assertEquals(URN, result.get().getUrn().getParentUrn()); } @Test public void resolvePartialInstanceUrn() throws Exception { AssetDataProducer producer = mock(AssetDataProducer.class); assetType.addProducer(producer); when(producer.getModulesProviding(URN.getResourceName())).thenReturn(ImmutableSet.of(URN.getModuleName())); Set<ResourceUrn> results = assetType.resolve(URN.getResourceName().toString() + ResourceUrn.INSTANCE_INDICATOR); assertEquals(1, results.size()); assertTrue(results.contains(URN.getInstanceUrn())); } @Test public void resolvePartialFragmentUrn() throws Exception { AssetDataProducer producer = mock(AssetDataProducer.class); assetType.addProducer(producer); when(producer.getModulesProviding(URN.getResourceName())).thenReturn(ImmutableSet.of(URN.getModuleName())); Set<ResourceUrn> results = assetType.resolve(URN.getResourceName().toString() + ResourceUrn.FRAGMENT_SEPARATOR + "something"); assertEquals(1, results.size()); assertTrue(results.contains(new ResourceUrn(URN.getModuleName(), URN.getResourceName(), new Name("something")))); } @Test public void getLoaded() throws Exception { TextData data = new TextData(TEXT_VALUE); assertTrue(assetType.getLoadedAssetUrns().isEmpty()); assetType.loadAsset(URN, data); assertEquals(ImmutableSet.of(URN), assetType.getLoadedAssetUrns()); } @Test public void getAvailableIncludesLoaded() { TextData data = new TextData(TEXT_VALUE); assertTrue(assetType.getAvailableAssetUrns().isEmpty()); assetType.loadAsset(URN, data); assertEquals(ImmutableSet.of(URN), assetType.getAvailableAssetUrns()); } @Test public void getAvailableIncludesFromProducer() { AssetDataProducer producer = mock(AssetDataProducer.class); when(producer.getAvailableAssetUrns()).thenReturn(ImmutableSet.of(URN)); assetType.addProducer(producer); assertEquals(ImmutableSet.of(URN), assetType.getAvailableAssetUrns()); } @Test public void instancesDisposedWhenTypeClosed() { TextData data = new TextData(TEXT_VALUE); Text loadedText = assetType.loadAsset(URN, data); Optional<Text> newText = loadedText.createInstance(); assertTrue(newText.isPresent()); assetType.close(); assertTrue(assetType.isClosed()); assertTrue(newText.get().isDisposed()); } }