package org.zalando.catwatch.backend.web;
import org.hamcrest.Matchers;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.zalando.catwatch.backend.model.Language;
import org.zalando.catwatch.backend.model.Project;
import org.zalando.catwatch.backend.repo.ProjectRepository;
import org.zalando.catwatch.backend.repo.builder.BuilderUtil;
import org.zalando.catwatch.backend.repo.builder.ProjectBuilder;
import org.zalando.catwatch.backend.util.TestUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
public class LanguagesControllerIT extends AbstractCatwatchIT {
private final String LANG_CS = "C#", LANG_JAVA = "Java", LANG_CPP = "C++", LANG_CSS = "CSS", //
LANG_HTML = "HTML5", LANG_JS = "JavaScript", LANG_PSCL = "Pascal", LANG_GO = "Go", LANG_SCALA = "Scala",
LANG_PY = "Python", LANG_GRV = "Groovy", LANG_VB = "VB";
private final String ORG1 = "organization1", ORG2 = "organization2";
@Autowired
ProjectRepository repository;
@Test
public void testGetLanguages() {
// given
this.repository.deleteAll();
fillRepositoryRandom(6, ORG2);
List<String> languageNames = fillRepositoryRandom(40, ORG1);
List<Language> sortedLanguages = generateLanguageList(languageNames);
// when
String url = TestUtils.createAbsoluteLanguagesUrl(this.base.toString(), ORG1, null, null, null);
ResponseEntity<Language[]> response = template.getForEntity(url, Language[].class);
Language[] langResponse = response.getBody();
// then
Assert.assertThat(langResponse.length, Matchers.equalTo(5));
checkLanguages(langResponse, sortedLanguages, 0);
}
@Test
public void testGetLanguagesWithOffsetAndLimit() {
// given
this.repository.deleteAll();
fillRepositoryRandom(6, ORG2);
List<String> languageNames = fillRepository(ORG1);
List<Language> languageList = generateLanguageList(languageNames);
int limit = 6;
int offset = 0;
// when
String url = TestUtils.createAbsoluteLanguagesUrl(this.base.toString(), ORG1, limit, offset, null);
ResponseEntity<Language[]> response = template.getForEntity(url, Language[].class);
Language[] langResponse = response.getBody();
Assert.assertThat(langResponse.length, Matchers.equalTo(limit));
checkLanguages(langResponse, languageList, offset);
offset += limit;
limit = 3;
// when
url = TestUtils.createAbsoluteLanguagesUrl(this.base.toString(), ORG1, limit, offset, null);
response = template.getForEntity(url, Language[].class);
langResponse = response.getBody();
checkLanguages(langResponse, languageList, offset);
}
@SuppressWarnings("unused")
@Test
public void testGetLanguagesWithQueryFilter() {
// given
this.repository.deleteAll();
fillRepositoryRandom(6, ORG2);
List<String> languageNames = fillRepository(ORG1);
// when
String url = TestUtils.createAbsoluteLanguagesUrl(this.base.toString(), ORG1, null, null, LANG_CPP);
ResponseEntity<Language[]> response = template.getForEntity(url, Language[].class);
Language[] langResponse = response.getBody();
//FIXME Assert.assertThat(langResponse.length, Matchers.equalTo(Collections.frequency(languageNames, LANG_CPP)));
}
private List<String> fillRepositoryRandom(final int nrOfProjects, String organization) {
List<String> languages = new ArrayList<>();
Date now = new Date();
for (int i = 0; i < nrOfProjects; i++) {
Project p = new ProjectBuilder(repository, new Date(), 0L, null, null, 0, 0, 0, 0, 0, 0)
.primaryLanguage(BuilderUtil.randomLanguage()).organizationName(organization).snapshotDate(now)
.name("p" + i).save();
languages.add(p.getPrimaryLanguage());
}
Assert.assertEquals(nrOfProjects,
repository.findProjects(organization, Optional.empty(), Optional.empty()).size());
return languages;
}
private List<String> fillRepository(String organization) {
List<String> langs = Arrays.asList(
LANG_JAVA, LANG_JAVA, LANG_JAVA, LANG_JAVA, LANG_JAVA, LANG_JAVA, LANG_JAVA,
LANG_HTML, LANG_HTML, LANG_HTML, LANG_HTML, LANG_HTML,
LANG_SCALA, LANG_SCALA, LANG_SCALA, LANG_SCALA,
LANG_CPP, LANG_CPP, LANG_CPP,
LANG_CSS, LANG_CSS, LANG_CSS, LANG_CSS, LANG_CSS,
LANG_JS, LANG_JS, LANG_JS, LANG_JS, LANG_JS, LANG_JS, LANG_JS,
LANG_GO,
LANG_VB, LANG_VB,
LANG_CS, LANG_CS,
LANG_GRV,
LANG_PY, LANG_PY, LANG_PY,
LANG_PSCL
);
Collections.shuffle(langs);
List<String> result = new ArrayList<>();
Date now = new Date();
for (int i = 0; i < langs.size(); i++) {
Project p = new ProjectBuilder(repository, new Date(), 0L, null, null, 0, 0, 0, 0, 0, 0)
.primaryLanguage(BuilderUtil.randomLanguage()).organizationName(organization).snapshotDate(now)
.name("p" + i).description("Test project "+i).gitHubProjectId(1234456).score((int) (Math.random() * 100))
.languages(Arrays.asList(BuilderUtil.randomLanguage(), BuilderUtil.randomLanguage(), BuilderUtil.randomLanguage()))
.lastPushed(null).save();
result.add(p.getPrimaryLanguage());
}
Assert.assertEquals(langs.size(),
repository.findProjects(organization, Optional.empty(), Optional.empty()).size());
return result;
}
private class LanguageComparator implements Comparator<Language> {
Collection<String> stringCollection;
public LanguageComparator(final Collection<String> languageNames) {
this.stringCollection = languageNames;
}
@Override
public int compare(final Language o1, final Language o2) {
int f1 = Collections.frequency(stringCollection, o1.getName());
int f2 = Collections.frequency(stringCollection, o2.getName());
if (f1 >= f2) {
return -1;
}
return 1;
}
}
private List<Language> generateLanguageList(List<String> languageNames) {
List<Language> languages;
Map<String, Integer> languageCount = new HashMap<>();
Iterator<String> iter = languageNames.iterator();
String langName;
while (iter.hasNext()) {
langName = iter.next();
if (!languageCount.keySet().contains(langName)) {
languageCount.put(langName, 1);
} else {
int old = languageCount.get(langName);
languageCount.put(langName, ++old);
}
}
languages = new ArrayList<>();
for (String name : languageCount.keySet()) {
Language lang = new Language(name);
lang.setProjectsCount(languageCount.get(name));
lang.setPercentage((int) Math.round((double) lang.getProjectsCount() / languageNames.size() * 100));
languages.add(lang);
}
Collections.sort(languages, new LanguageComparator(languageNames));
return languages;
}
private void checkLanguages(Language[] actualLangs, List<Language> expectedLangs, int offset) {
int tmpProjectCount = Integer.MAX_VALUE, tmpPercentage = Integer.MAX_VALUE;
Language actual, expected;
for (int i = 0; i < actualLangs.length; i++) {
actual = actualLangs[i];
expected = expectedLangs.get(offset + i);
Assert.assertThat(actual.getPercentage(), Matchers.lessThanOrEqualTo(tmpPercentage));
Assert.assertThat(actual.getProjectsCount(), Matchers.lessThanOrEqualTo(tmpProjectCount));
Assert.assertThat(actual.getPercentage(), Matchers.equalTo(expected.getPercentage()));
Assert.assertThat(actual.getProjectsCount(), Matchers.equalTo(expected.getProjectsCount()));
Assert.assertThat(actual.toString(), Matchers.stringContainsInOrder(Arrays.asList("name: ", "projectsCount: ", "percentage: ")));
tmpPercentage = actual.getPercentage();
tmpProjectCount = actual.getProjectsCount();
}
}
}