package com.github.liblevenshtein.collection.dictionary;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import com.google.common.base.Joiner;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import static org.assertj.core.api.Assertions.assertThat;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import com.github.liblevenshtein.collection.dictionary.factory.DawgFactory;
import static com.github.liblevenshtein.assertion.SetAssertions.assertThat;
@Slf4j
public class DawgTest {
private List<String> terms;
private DawgFactory dawgFactory;
private Dawg emptyDawg;
private Dawg fullDawg;
@BeforeClass
public void setUp() throws IOException {
try (final BufferedReader reader = new BufferedReader(
new InputStreamReader(
getClass().getResourceAsStream("/wordsEn.txt"),
StandardCharsets.UTF_8))) {
final List<String> termsList = new ArrayList<>();
String term;
while ((term = reader.readLine()) != null) {
termsList.add(term);
}
Collections.sort(termsList);
this.terms = termsList;
this.dawgFactory = new DawgFactory();
this.emptyDawg = dawgFactory.build(new ArrayList<>(0));
this.fullDawg = dawgFactory.build(termsList);
}
}
@DataProvider(name = "terms")
public Iterator<Object[]> terms() {
return new TermIterator(terms.iterator());
}
@Test(dataProvider = "terms")
public void emptyDawgAcceptsNothing(final String term) {
assertThat(emptyDawg).doesNotContain(term);
}
@Test(dataProvider = "terms")
public void dawgAcceptsAllItsTerms(final String term) {
assertThat(fullDawg).contains(term);
}
@Test
public void dawgAcceptsNoTermsItDoesNotContain() {
assertThat(fullDawg).doesNotContain("", "foobar", "C+");
}
@Test
public void dawgSizeIsSameAsTerms() {
assertThat(emptyDawg)
.isEmpty()
.hasSize(0);
assertThat(fullDawg)
.isNotEmpty()
.hasSize(terms.size());
}
@Test
public void dawgAcceptsEmptyStringIfInTerms() {
final List<String> termsList = new ArrayList<>(1);
termsList.add("");
final Dawg dawg = dawgFactory.build(termsList);
assertThat(dawg).contains("");
}
@Test
public void dawgShouldIterateOverAllTerms() {
final Set<String> termsList = new HashSet<>(this.terms);
for (final String term : fullDawg) {
try {
assertThat(termsList).contains(term);
}
catch (final AssertionError exception) {
throw new AssertionError("Expected terms to contain: \"" + term + "\"", exception);
}
termsList.remove(term);
}
if (!termsList.isEmpty()) {
final String message =
String.format("Expected all terms to be iterated over, but missed [%s]",
Joiner.on(", ").join(termsList));
throw new AssertionError(message);
}
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void insertingTermsOutOfOrderShouldThrowAnException() {
final List<String> termsList = new ArrayList<>(3);
termsList.add("a");
termsList.add("c");
termsList.add("b");
dawgFactory.build(termsList, true);
}
@Test
public void equivalentDawgsShouldBeEqual() {
final Dawg other = dawgFactory.build(new ArrayList<>(terms));
assertThat(fullDawg).isEqualTo(other);
}
@RequiredArgsConstructor
private static class TermIterator implements Iterator<Object[]> {
private final Iterator<String> terms;
private Object[] params = null;
private Object[] buffer = new Object[1];
@Override
public boolean hasNext() {
advance();
return null != params;
}
@Override
public Object[] next() {
advance();
final Object[] paramsLocal = this.params;
this.params = null;
return paramsLocal;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
public void advance() {
if (null == params && terms.hasNext()) {
buffer[0] = terms.next();
params = buffer;
}
}
}
}