/*
* Copyright (C) 2008-2017, Juick
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
package com.juick.tests;
import ch.vorburger.exec.ManagedProcessException;
import ch.vorburger.mariadb4j.DB;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.juick.Message;
import com.juick.Tag;
import com.juick.User;
import com.juick.server.helpers.TagStats;
import com.juick.server.protocol.JuickProtocol;
import com.juick.server.protocol.ProtocolListener;
import com.juick.service.MessagesService;
import com.juick.service.SubscriptionService;
import com.juick.service.TagService;
import com.juick.service.UserService;
import com.juick.service.search.SearchService;
import com.juick.www.WebApp;
import com.mitchellbosecke.pebble.PebbleEngine;
import com.mitchellbosecke.pebble.loader.StringLoader;
import com.mitchellbosecke.pebble.template.PebbleTemplate;
import org.apache.commons.dbcp2.BasicDataSource;
import org.apache.commons.lang3.StringUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.TransactionManagementConfigurer;
import ru.sape.Sape;
import javax.inject.Inject;
import java.lang.reflect.InvocationTargetException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
/**
* Created by vt on 14.01.2016.
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class ApiTests {
@Configuration
@ComponentScan(basePackages = {"com.juick.service", "com.juick.server.protocol"})
static class Config implements TransactionManagementConfigurer {
@Bean
public BasicDataSource dataSource() {
try {
DB db = DB.newEmbeddedDB(33306);
db.start();
db.createDB("juick");
db.source("schema.sql");
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:33306/juick?autoReconnect=true&user=root");
dataSource.setValidationQuery("select 1");
return dataSource;
} catch (ManagedProcessException e) {
return null;
}
}
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
@Override
public PlatformTransactionManager annotationDrivenTransactionManager() {
return transactionManager();
}
@Bean
@DependsOn("dataSource")
public JdbcTemplate jdbcTemplate() {
return new JdbcTemplate(dataSource());
}
@Bean
public SearchService emptySearchService() {
return new SearchService() {
@Override
public void setMaxResult(int maxResult) {
}
@Override
public List searchInAllMessages(String searchString, int messageIdBefore) {
return Collections.emptyList();
}
@Override
public List searchByStringAndUser(String searchString, int userId, int messageIdBefore) {
return Collections.emptyList();
}
};
}
@Bean
public JuickProtocol juickProtocol() {
return new JuickProtocol("http://localhost:8080/");
}
@Bean
public Sape sape() {
return Mockito.mock(Sape.class);
}
@Bean
public WebApp webApp() {
return Mockito.mock(WebApp.class);
}
}
@Inject
UserService userService;
@Inject
MessagesService messagesService;
@Inject
TagService tagService;
@Inject
SubscriptionService subscriptionService;
@Inject
JdbcTemplate jdbcTemplate;
@Inject
JuickProtocol juickProtocol;
@Mock
ProtocolListener listener;
@Before
public void setup() {
userService.createUser("ugnich", "secret");
userService.createUser("juick", "secret");
MockitoAnnotations.initMocks(this);
}
@Test
public void messageTests() {
int user_id = userService.createUser("mmmme", "secret");
User user = userService.getUserByUID(user_id).orElse(new User());
assertEquals("it should be me", "mmmme", user.getName());
int mid = messagesService.createMessage(user_id, "yo", null, new ArrayList<>());
Message msg = messagesService.getMessage(mid);
assertEquals("yo", msg.getText());
Calendar calendar = Calendar.getInstance();
calendar.setTime(msg.getDate());
assertEquals(2017, calendar.get(Calendar.YEAR));
User me = msg.getUser();
assertEquals("mmmme", me.getName());
assertEquals("mmmme", messagesService.getMessageAuthor(mid).getName());
int tagID = tagService.createTag("weather");
Tag tag = tagService.getTag(tagID);
List tagList = new ArrayList<>();
tagList.add(tag);
int mid2 = messagesService.createMessage(user_id, "yo2", null, tagList);
Message msg2 = messagesService.getMessage(mid2);
assertEquals(1, msg2.getTags().size());
assertEquals("we already have ugnich", -1, userService.createUser("ugnich", "x"));
int ugnich_id = userService.createUser("hugnich", "x");
User ugnich = userService.getUserByUID(ugnich_id).orElse(new User());
int rid = messagesService.createReply(msg2.getMid(), 0, ugnich.getUid(), "bla-bla", null);
assertEquals(1, rid);
Message msg3 = messagesService.getMessage(mid2);
assertEquals(1, msg3.getReplies());
assertEquals("weather", msg3.getTags().get(0).getName());
assertEquals(ugnich.getUid(), userService.checkPassword(ugnich.getName(), "x"));
assertEquals(-1, userService.checkPassword(ugnich.getName(), "xy"));
subscriptionService.subscribeMessage(msg.getMid(), ugnich.getUid());
assertEquals(1, subscriptionService.getUsersSubscribedToComments(msg.getMid(), user.getUid()).size());
messagesService.deleteMessage(user_id, mid);
messagesService.deleteMessage(user_id, mid2);
String htmlTagName = ">_<";
Tag htmlTag = tagService.getTag(htmlTagName, true);
TagStats htmlTagStats = new TagStats();
htmlTagStats.setTag(htmlTag);
String dbTagName = jdbcTemplate.queryForObject("select name from tags where name=?", String.class, htmlTagName);
assertEquals("db tags should not be escaped", dbTagName, htmlTag.getName());
int mid4 = messagesService.createMessage(user_id, "yoyoyo", null, null);
Message msg4 = messagesService.getMessage(mid4);
assertEquals("tags string should be empty", StringUtils.EMPTY, msg4.getTagsString());
messagesService.deleteMessage(user_id, mid4);
}
@Test
public void protocolTests() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, ParseException, JsonProcessingException {
juickProtocol.setListener(listener);
assertEquals("juick user should have uid 2", 2, userService.getUIDbyName("juick"));
int uid = userService.createUser("me", "secret");
User user = userService.getUserByUID(uid).orElse(new User());
String expectedMessage = "New message posted";
assertEquals("should be message", true,
juickProtocol.getReply(user, "*yo yoyo").startsWith(expectedMessage));
int mid = messagesService.getUserBlog(user.getUid(), -1, 0).stream().reduce((first, second) -> second).get();
assertEquals("text should match", "yoyo",
messagesService.getMessage(mid).getText());
assertEquals("tag should match", "yo",
tagService.getMessageTags(mid).get(0).getTag().getName());
assertNotEquals("should not be error", "Error", juickProtocol.getReply(user, "#" + mid));
assertEquals("should be PONG", "PONG", juickProtocol.getReply(user, "ping"));
int readerUid = userService.createUser("dummyReader", "dummySecret");
User readerUser = userService.getUserByUID(readerUid).orElse(new User());
assertEquals("should be subscribed", "Subscribed",
juickProtocol.getReply(readerUser, "S #" + mid));
assertEquals("number of subscribed users should match", 1,
subscriptionService.getUsersSubscribedToComments(mid, uid).size());
assertEquals("should be subscribed", "Subscribed",
juickProtocol.getReply(readerUser, "S @" + user.getName()));
List friends = userService.getUserFriends(readerUid);
assertEquals("number of friend users should match", 2,
friends.size());
assertEquals("number of reader users should match", 1,
userService.getUserReaders(uid).size());
String expectedReply = "Reply posted.\n#" + mid + "/1 "
+ juickProtocol.getBaseUri() + mid + "#1";
String expectedSecondReply = "Reply posted.\n#" + mid + "/2 "
+ juickProtocol.getBaseUri() + mid + "#2";
assertEquals("should be reply", expectedReply,
juickProtocol.getReply(user, "#" + mid + " yoyo"));
assertEquals("should be second reply", expectedSecondReply,
juickProtocol.getReply(user, "#" + mid + "/1 yoyo"));
Message reply = messagesService.getReplies(mid).stream().filter(m -> m.getRid() == 2).findFirst()
.orElse(new Message());
assertEquals("should be reply to first comment", 1, reply.getReplyto());
assertNotEquals("tags should NOT be updated", "Tags are updated",
juickProtocol.getReply(readerUser, "#" + mid + " *yo *there"));
assertEquals("tags should be updated", "Tags are updated",
juickProtocol.getReply(user, "#" + mid + " *there"));
assertEquals("number of tags should match", 2,
tagService.getMessageTags(mid).size());
assertEquals("should be blacklisted", "Tag added to your blacklist",
juickProtocol.getReply(readerUser, "BL *there"));
assertEquals("number of subscribed users should match", 0,
subscriptionService.getSubscribedUsers(uid, mid).size());
assertEquals("tags should be updated", "Tags are updated",
juickProtocol.getReply(user, "#" + mid + " *there"));
assertEquals("number of tags should match", 1,
tagService.getMessageTags(mid).size());
int taggerUid = userService.createUser("dummyTagger", "dummySecret");
User taggerUser = userService.getUserByUID(taggerUid).orElse(new User());
assertEquals("should be subscribed", "Subscribed",
juickProtocol.getReply(taggerUser, "S *yo"));
assertEquals("number of subscribed users should match", 2,
subscriptionService.getSubscribedUsers(uid, mid).size());
assertEquals("should be unsubscribed", "Unsubscribed from yo",
juickProtocol.getReply(taggerUser, "U *yo"));
assertEquals("number of subscribed users should match", 1,
subscriptionService.getSubscribedUsers(uid, mid).size());
assertEquals("number of readers should match", 1,
userService.getUserReaders(uid).size());
String readerFeed = juickProtocol.getReply(readerUser, "#");
assertEquals("description should match", true, readerFeed.startsWith("Your feed"));
assertEquals("should be unsubscribed", "Unsubscribed from @" + user.getName(),
juickProtocol.getReply(readerUser, "U @" + user.getName()));
assertEquals("number of readers should match", 0,
userService.getUserReaders(uid).size());
assertEquals("number of friends should match", 1,
userService.getUserFriends(uid).size());
assertEquals("should be unsubscribed", "Unsubscribed from #" + mid,
juickProtocol.getReply(readerUser, "u #" + mid));
assertEquals("number of subscribed users should match", 0,
subscriptionService.getUsersSubscribedToComments(mid, uid).size());
assertNotEquals("should NOT be deleted", String.format("Message %s deleted", mid),
juickProtocol.getReply(readerUser, "D #" + mid));
assertEquals("should be deleted", String.format("Message %s deleted", mid),
juickProtocol.getReply(user, "D #" + mid));
assertEquals("should not have messages", 0, messagesService.getAll(user.getUid(), 0).size());
}
}