Tworze zadanie na platforme z roznymi zagadkami programistycznymi (kiedys reklamowalem ten serwis w dziale OT). Wymyslilem sobie, zeby uzytkownicy zaimplementowali bezpiecznego watkowo singletona z leniwa ewaluacja.
Przykladowo zle zaimplementowany przez uzytkownika singleton moze wygladac tak:
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();}
return instance;
}
A moj test jednostkowy weryfikujacy rozwiazanie tak:
public void testUnique() throws ExecutionException, InterruptedException {
final ExecutorService pool = Executors.newFixedThreadPool(2);
final Future<Singleton> value1 = pool.submit(() -> Singleton.getInstance());
final Future<Singleton> value2 = pool.submit(() -> Singleton.getInstance());
assertEquals(value1.get(), value2.get());
}
Oczywiscie aby test sie wywalil musi byc powtorzony wiele razy. Idea nie jest najlepsza bo mimo wszystko test jest niedeterministyczny, ale lepszego pomyslu nie mam. Problemem jest jednak odpalenie go n razy. Uzycie junitowego @RunWith(Parameterized.class) nie zda egzaminu, poniewaz kazde odpalenie testu powinno byc w osobnej VM. Inaczej w przypadku gdy pierwsza proba przejdzie pomyslnie, reszta nie ma szans sie wywalic. Normalnie moglbym sobie poradzic przy pomocy parametru fork z ant-junit tudziez innych bibliotek wspomagajacych junita, ale na platformie mam tylko JUnit 4.11.
Jednym pomyslem ktory mam jest zaimplementowanie metody reset wykorzystujac refleksje wykonywanej po @After, ktora bedzie ustawiac pole przechowujaca instancje singletona na nulla. Problem w tym, ze niektorzy uzytkownicy moga miec rozne szalone pomysly na zaimplementowanie testowanego singletona i niekoniecznie taka zmienna w ich kodzie byc musi.