/* Copyright 2013 Jonatan Jönsson
*
* 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 se.softhouse.common.testlib;
import static java.util.Locale.CANADA;
import static org.fest.assertions.Assertions.assertThat;
import static org.fest.assertions.Fail.fail;
import static se.softhouse.common.testlib.Constants.EXPECTED_TEST_TIME_FOR_THIS_SUITE;
import static se.softhouse.common.testlib.Locales.SWEDISH;
import static se.softhouse.common.testlib.Locales.TURKISH;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.Locale;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.Test;
import org.junit.runner.RunWith;
import com.google.code.tempusfugit.concurrency.ConcurrentTestRunner;
import com.google.common.testing.NullPointerTester;
import com.google.common.testing.NullPointerTester.Visibility;
import com.google.common.util.concurrent.Atomics;
@RunWith(ConcurrentTestRunner.class)
public class LocalesTest
{
@Test
public void testThatResetDefaultLocaleResetsToTheOneBeforeSetDefaultWasCalled() throws Exception
{
Locale before = Locales.setDefault(Locales.SWEDISH);
Locale after = Locales.resetDefaultLocale();
assertThat(after).isEqualTo(before);
}
@Test
public void testThatInterruptedExceptionIsThrownForTimeoutsWhenWaitingForThreadToBeDoneWithLocale() throws Throwable
{
final String ownerThread = Thread.currentThread().getName();
final Semaphore greenSignal = new Semaphore(1);
final AtomicReference<Throwable> failure = Atomics.newReference();
Thread thread = new Thread(){
@Override
public void run()
{
try
{
greenSignal.release();
Locales.setDefault(TURKISH);
fail("Should timeout as other thread isn't finished with using the default locale");
}
catch(InterruptedException expectedException)
{
String currentThreadDescription = Thread.currentThread().getName();
String startOfMessage = currentThreadDescription + " waited on";
String endOfMessage = "[Locked by thread " + ownerThread + "] to finish using " + CANADA + " but got interrupted";
assertThat(expectedException.getMessage()).startsWith(startOfMessage).endsWith(endOfMessage);
// Verify that this thread can't reset the locale
try
{
Locales.resetDefaultLocale();
fail("Current thread: " + Thread.currentThread() + " should not own lock and therefore be forbidden to release it");
}
catch(IllegalStateException expected)
{
startOfMessage = "Current thread: " + currentThreadDescription + " may not unlock: ";
endOfMessage = "[Locked by thread " + ownerThread + "]";
assertThat(expected.getMessage()).startsWith(startOfMessage).endsWith(endOfMessage);
}
assertThat(Locale.getDefault()).isEqualTo(CANADA);
}
}
};
thread.setUncaughtExceptionHandler(new UncaughtExceptionHandler(){
@Override
public void uncaughtException(Thread t, Throwable e)
{
failure.set(e);
}
});
Locales.setDefault(SWEDISH);
// This thread should be allowed to set the locale several times during its "period"
Locales.setDefault(CANADA);
thread.start();
greenSignal.acquireUninterruptibly();
thread.interrupt();
thread.join(EXPECTED_TEST_TIME_FOR_THIS_SUITE);
if(failure.get() != null)
throw failure.get();
Locales.resetDefaultLocale();
}
@Test
public void testThatNullContractsAreFollowed() throws Exception
{
new NullPointerTester().testStaticMethods(Locales.class, Visibility.PACKAGE);
}
}