/* * Copyright (C) 2007 Google Inc. * * 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 com.google.common.base; import static com.google.testing.util.SerializableTester.reserialize; import com.google.common.annotations.GwtCompatible; import com.google.common.annotations.GwtIncompatible; import com.google.common.collect.Lists; import com.google.testing.util.NullPointerTester; import junit.framework.TestCase; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; /** * Tests com.google.common.base.Suppliers. * * @author Laurence Gonsalves * @author Harry Heymann */ @GwtCompatible(emulated = true) public class SuppliersTest extends TestCase { public void testCompose() { Supplier fiveSupplier = new Supplier() { public Integer get() { return 5; } }; Function intValueFunction = new Function() { public Integer apply(Number x) { return x.intValue(); } }; Supplier squareSupplier = Suppliers.compose(intValueFunction, fiveSupplier); assertEquals(Integer.valueOf(5), squareSupplier.get()); } public void testComposeWithLists() { Supplier> listSupplier = new Supplier>() { public ArrayList get() { return Lists.newArrayList(0); } }; Function, List> addElementFunction = new Function, List>() { public List apply(List list) { ArrayList result = Lists.newArrayList(list); result.add(1); return result; } }; Supplier> addSupplier = Suppliers.compose(addElementFunction, listSupplier); List result = addSupplier.get(); assertEquals(Integer.valueOf(0), result.get(0)); assertEquals(Integer.valueOf(1), result.get(1)); } static class CountingSupplier implements Supplier, Serializable { transient int calls = 0; public Integer get() { calls++; return calls * 10; } } public void testMemoize() { CountingSupplier countingSupplier = new CountingSupplier(); Supplier memoizedSupplier = Suppliers.memoize(countingSupplier); checkMemoize(countingSupplier, memoizedSupplier); } @GwtIncompatible("SerializableTester") public void testMemoizeSerialized() { CountingSupplier countingSupplier = new CountingSupplier(); Supplier memoizedSupplier = Suppliers.memoize(countingSupplier); checkMemoize(countingSupplier, memoizedSupplier); // Calls to the original memoized supplier shouldn't affect its copy. memoizedSupplier.get(); Supplier copy = reserialize(memoizedSupplier); memoizedSupplier.get(); CountingSupplier countingCopy = (CountingSupplier) ((Suppliers.MemoizingSupplier) copy).delegate; checkMemoize(countingCopy, copy); } private void checkMemoize( CountingSupplier countingSupplier, Supplier memoizedSupplier) { // the underlying supplier hasn't executed yet assertEquals(0, countingSupplier.calls); assertEquals(10, (int) memoizedSupplier.get()); // now it has assertEquals(1, countingSupplier.calls); assertEquals(10, (int) memoizedSupplier.get()); // it still should only have executed once due to memoization assertEquals(1, countingSupplier.calls); } public void testMemoizeExceptionThrown() { Supplier exceptingSupplier = new Supplier() { public Integer get() { throw new NullPointerException(); } }; Supplier memoizedSupplier = Suppliers.memoize(exceptingSupplier); // call get() twice to make sure that memoization doesn't interfere // with throwing the exception for (int i = 0; i < 2; i++) { try { memoizedSupplier.get(); fail("failed to throw NullPointerException"); } catch (NullPointerException e) { // this is what should happen } } } @GwtIncompatible("Thread.sleep") public void testMemoizeWithExpiration() throws InterruptedException { CountingSupplier countingSupplier = new CountingSupplier(); Supplier memoizedSupplier = Suppliers.memoizeWithExpiration( countingSupplier, 75, TimeUnit.MILLISECONDS); checkExpiration(countingSupplier, memoizedSupplier); } @GwtIncompatible("Thread.sleep, SerializationTester") public void testMemoizeWithExpirationSerialized() throws InterruptedException { CountingSupplier countingSupplier = new CountingSupplier(); Supplier memoizedSupplier = Suppliers.memoizeWithExpiration( countingSupplier, 75, TimeUnit.MILLISECONDS); // Calls to the original memoized supplier shouldn't affect its copy. memoizedSupplier.get(); Supplier copy = reserialize(memoizedSupplier); memoizedSupplier.get(); CountingSupplier countingCopy = (CountingSupplier) ((Suppliers.ExpiringMemoizingSupplier) copy).delegate; checkExpiration(countingCopy, copy); } @GwtIncompatible("Thread.sleep") private void checkExpiration( CountingSupplier countingSupplier, Supplier memoizedSupplier) throws InterruptedException { // the underlying supplier hasn't executed yet assertEquals(0, countingSupplier.calls); assertEquals(10, (int) memoizedSupplier.get()); // now it has assertEquals(1, countingSupplier.calls); assertEquals(10, (int) memoizedSupplier.get()); // it still should only have executed once due to memoization assertEquals(1, countingSupplier.calls); Thread.sleep(150); assertEquals(20, (int) memoizedSupplier.get()); // old value expired assertEquals(2, countingSupplier.calls); assertEquals(20, (int) memoizedSupplier.get()); // it still should only have executed twice due to memoization assertEquals(2, countingSupplier.calls); } public void testOfInstanceSuppliesSameInstance() { Object toBeSupplied = new Object(); Supplier objectSupplier = Suppliers.ofInstance(toBeSupplied); assertSame(toBeSupplied,objectSupplier.get()); assertSame(toBeSupplied,objectSupplier.get()); // idempotent } public void testOfInstanceSuppliesNull() { Supplier nullSupplier = Suppliers.ofInstance(null); assertNull(nullSupplier.get()); } @GwtIncompatible("Thread") public void testThreadSafe() throws InterruptedException { final Supplier nonThreadSafe = new Supplier() { int counter = 0; public Integer get() { int nextValue = counter + 1; Thread.yield(); counter = nextValue; return counter; } }; final int numThreads = 10; final int iterations = 1000; Thread[] threads = new Thread[numThreads]; for (int i = 0; i < numThreads; i++) { threads[i] = new Thread() { @Override public void run() { for (int j = 0; j < iterations; j++) { Suppliers.synchronizedSupplier(nonThreadSafe).get(); } } }; } for (Thread t : threads) { t.start(); } for (Thread t : threads) { t.join(); } assertEquals(new Integer(numThreads * iterations + 1), nonThreadSafe.get()); } @GwtIncompatible("SerializationTester") public void testSerialization() { assertEquals( Integer.valueOf(5), reserialize(Suppliers.ofInstance(5)).get()); assertEquals(Integer.valueOf(5), reserialize(Suppliers.compose( Functions.identity(), Suppliers.ofInstance(5))).get()); assertEquals(Integer.valueOf(5), reserialize(Suppliers.memoize(Suppliers.ofInstance(5))).get()); assertEquals(Integer.valueOf(5), reserialize(Suppliers.memoizeWithExpiration( Suppliers.ofInstance(5), 30, TimeUnit.MINUTES)).get()); assertEquals(Integer.valueOf(5), reserialize( Suppliers.synchronizedSupplier(Suppliers.ofInstance(5))).get()); } @GwtIncompatible("NullPointerTest") public void testNullPointers() throws Exception { NullPointerTester tester = new NullPointerTester(); tester.testAllPublicStaticMethods(Suppliers.class); } }