Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • arsnova/arsnova-backend
  • pcvl72/arsnova-backend
  • tksl38/arsnova-backend
3 results
Show changes
Showing
with 1214 additions and 1374 deletions
/*
* This file is part of ARSnova Backend.
* Copyright (C) 2012-2019 The ARSnova Team and Contributors
*
* ARSnova Backend is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ARSnova Backend 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.thm.arsnova.config;
import static org.junit.Assert.assertNull;
import java.util.Collections;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import java.util.Arrays;
import de.thm.arsnova.config.properties.SecurityProperties;
import de.thm.arsnova.connector.client.ConnectorClient;
import java.util.List;
import static org.junit.Assert.assertEquals;
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = {
AppConfig.class,
TestAppConfig.class,
TestPersistanceConfig.class,
TestSecurityConfig.class,
WebSocketConfig.class})
@ActiveProfiles("test")
public class AppConfigTest extends AbstractJUnit4SpringContextTests {
@Autowired
private SecurityProperties securityProperties;
@Autowired(required = false)
private ConnectorClient connectorClient;
private List<String> adminAccounts;
@Test
public void testShouldNotLoadConnectorClientByDefault() {
assertNull(connectorClient);
}
@Test
public void testShouldUseAdminAccountFromTestPropertiesFile() {
final List<String> expected = Collections.singletonList("TestAdmin");
final List<String> actual = securityProperties.getAdminAccounts();
assertEquals("Configuration did not load correct property file", expected, actual);
}
}
package de.thm.arsnova.config;
import static org.junit.Assert.assertNull;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import de.thm.arsnova.connector.client.ConnectorClient;
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = {
"file:src/main/webapp/WEB-INF/spring/arsnova-servlet.xml",
"file:src/main/webapp/WEB-INF/spring/spring-main.xml",
"file:src/test/resources/test-config.xml",
"file:src/test/resources/test-socketioconfig.xml"
})
@ActiveProfiles("test")
public class ExtraConfigTest {
@Autowired(required = false)
private ConnectorClient connectorClient;
@Test
public void testShouldNotLoadConnectorClientByDefault() {
assertNull(connectorClient);
}
}
/*
* This file is part of ARSnova Backend.
* Copyright (C) 2012-2019 The ARSnova Team and Contributors
*
* ARSnova Backend is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ARSnova Backend 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.thm.arsnova.config;
import de.thm.arsnova.config.properties.SystemProperties;
import de.thm.arsnova.config.properties.AuthenticationProviderProperties;
import de.thm.arsnova.config.properties.SecurityProperties;
import de.thm.arsnova.controller.JsonViewControllerAdviceTest;
import de.thm.arsnova.service.EntityService;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.CustomScopeConfigurer;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.AdviceMode;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Profile;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.aspectj.EnableSpringConfigured;
import org.springframework.context.support.SimpleThreadScope;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mock.web.MockServletContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
import org.springframework.validation.Validator;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import de.thm.arsnova.persistence.UserRepository;
import de.thm.arsnova.service.StubUserService;
import de.thm.arsnova.websocket.ArsnovaSocketioServer;
import de.thm.arsnova.websocket.ArsnovaSocketioServerImpl;
@ComponentScan({
"de.thm.arsnova.aop",
"de.thm.arsnova.cache",
"de.thm.arsnova.controller",
"de.thm.arsnova.dao",
"de.thm.arsnova.events",
"de.thm.arsnova.security",
"de.thm.arsnova.services",
"de.thm.arsnova.web"})
@Configuration
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
@EnableCaching(mode = AdviceMode.ASPECTJ)
@EnableSpringConfigured
@EnableWebMvc
@PropertySource(
value = "classpath:config/test.yml",
encoding = "UTF-8",
factory = YamlPropertySourceFactory.class
)
@Profile("test")
public class TestAppConfig {
private static int testPortOffset = 0;
@Autowired
private SystemProperties systemProperties;
@Bean
public MockServletContext servletContext() {
return new MockServletContext();
}
@Bean
public static CustomScopeConfigurer customScopeConfigurer() {
final CustomScopeConfigurer configurer = new CustomScopeConfigurer();
configurer.addScope("session", new SimpleThreadScope());
return configurer;
}
@Bean(name = "socketServer", initMethod = "startServer", destroyMethod = "stopServer")
public ArsnovaSocketioServer socketTestServer() {
final int testSocketPort = 1234 + testPortOffset++ % 10;
final ArsnovaSocketioServerImpl socketServer = new ArsnovaSocketioServerImpl();
socketServer.setHostIp(systemProperties.getSocketio().getBindAddress());
socketServer.setPortNumber(systemProperties.getSocketio().getPort() + testSocketPort);
return socketServer;
}
@Bean
@Primary
public StubUserService stubUserService(
final UserRepository repository,
final SystemProperties systemProperties,
final SecurityProperties securityProperties,
final AuthenticationProviderProperties authenticationProviderProperties,
final JavaMailSender mailSender,
@Qualifier("defaultJsonMessageConverter")
final MappingJackson2HttpMessageConverter jackson2HttpMessageConverter,
final Validator validator) {
return new StubUserService(repository, systemProperties, securityProperties, authenticationProviderProperties,
mailSender, jackson2HttpMessageConverter, validator);
}
@Bean
public EntityService<JsonViewControllerAdviceTest.DummyEntity> dummyEntityService() {
return Mockito.mock(EntityService.class);
}
}
/*
* This file is part of ARSnova Backend.
* Copyright (C) 2012-2019 The ARSnova Team and Contributors
*
* ARSnova Backend is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ARSnova Backend 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.thm.arsnova.config;
import org.mockito.Mockito;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import de.thm.arsnova.persistence.AnswerRepository;
import de.thm.arsnova.persistence.AttachmentRepository;
import de.thm.arsnova.persistence.CommentRepository;
import de.thm.arsnova.persistence.ContentGroupRepository;
import de.thm.arsnova.persistence.ContentRepository;
import de.thm.arsnova.persistence.LogEntryRepository;
import de.thm.arsnova.persistence.MotdRepository;
import de.thm.arsnova.persistence.RoomRepository;
import de.thm.arsnova.persistence.SessionStatisticsRepository;
import de.thm.arsnova.persistence.StatisticsRepository;
import de.thm.arsnova.persistence.UserRepository;
@Profile("test")
@Configuration
public class TestPersistanceConfig {
@Bean
public LogEntryRepository logEntryRepository() {
return Mockito.mock(LogEntryRepository.class);
}
@Bean
public UserRepository userRepository() {
return Mockito.mock(UserRepository.class);
}
@Bean
public RoomRepository sessionRepository() {
return Mockito.mock(RoomRepository.class);
}
@Bean
public CommentRepository commentRepository() {
return Mockito.mock(CommentRepository.class);
}
@Bean
public ContentRepository contentRepository() {
return Mockito.mock(ContentRepository.class);
}
@Bean
public ContentGroupRepository contentGroupRepository() {
return Mockito.mock(ContentGroupRepository.class);
}
@Bean
public AnswerRepository answerRepository() {
return Mockito.mock(AnswerRepository.class);
}
@Bean
public AttachmentRepository attachmentRepository() {
return Mockito.mock(AttachmentRepository.class);
}
@Bean
public MotdRepository motdRepository() {
return Mockito.mock(MotdRepository.class);
}
@Bean
public StatisticsRepository statisticsRepository() {
return Mockito.mock(StatisticsRepository.class);
}
@Bean
public SessionStatisticsRepository sessionStatisticsRepository() {
return Mockito.mock(SessionStatisticsRepository.class);
}
}
/*
* This file is part of ARSnova Backend.
* Copyright (C) 2012-2019 The ARSnova Team and Contributors
*
* ARSnova Backend is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ARSnova Backend 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.thm.arsnova.config; package de.thm.arsnova.config;
import javax.servlet.ServletContext;
import org.jasig.cas.client.validation.Cas20ProxyTicketValidator; import org.jasig.cas.client.validation.Cas20ProxyTicketValidator;
import org.scribe.up.provider.impl.FacebookProvider; import org.pac4j.oauth.client.FacebookClient;
import org.scribe.up.provider.impl.Google2Provider; import org.pac4j.oauth.client.TwitterClient;
import org.scribe.up.provider.impl.TwitterProvider; import org.pac4j.oidc.client.GoogleOidcClient;
import org.springframework.context.annotation.AdviceMode;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile; import org.springframework.context.annotation.Profile;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.cas.ServiceProperties; import org.springframework.security.cas.ServiceProperties;
import org.springframework.security.cas.authentication.CasAuthenticationProvider; import org.springframework.security.cas.authentication.CasAuthenticationProvider;
import org.springframework.security.cas.web.CasAuthenticationEntryPoint; import org.springframework.security.cas.web.CasAuthenticationEntryPoint;
import org.springframework.security.cas.web.CasAuthenticationFilter; import org.springframework.security.cas.web.CasAuthenticationFilter;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.session.SessionRegistry; import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl; import org.springframework.security.core.session.SessionRegistryImpl;
import com.github.leleuj.ss.oauth.client.authentication.OAuthAuthenticationProvider; import de.thm.arsnova.config.properties.SystemProperties;
import com.github.leleuj.ss.oauth.client.web.OAuthAuthenticationEntryPoint; import de.thm.arsnova.config.properties.AuthenticationProviderProperties;
import com.github.leleuj.ss.oauth.client.web.OAuthAuthenticationFilter; import de.thm.arsnova.security.CasUserDetailsService;
import de.thm.arsnova.CasUserDetailsService;
@Configuration @Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true) @EnableGlobalMethodSecurity(mode = AdviceMode.ASPECTJ, prePostEnabled = true)
@EnableWebSecurity @EnableWebSecurity
@Profile("test") @Profile("test")
public class TestSecurityConfig extends SecurityConfig { public class TestSecurityConfig extends SecurityConfig {
@Override public TestSecurityConfig(
protected void configure(HttpSecurity http) {}; final SystemProperties systemProperties,
final AuthenticationProviderProperties authenticationProviderProperties,
@Override final ServletContext servletContext) {
protected void configure(AuthenticationManagerBuilder auth) throws Exception { super(systemProperties, authenticationProviderProperties, servletContext);
auth.inMemoryAuthentication()
.withUser("ptsr00")
.password("secret")
.authorities("ROLE_USER")
;
} }
@Bean
@Override @Override
public AuthenticationManager authenticationManagerBean() throws Exception { protected void configure(final HttpSecurity http) {}
return super.authenticationManager();
}
@Override @Override
@Bean @Bean
...@@ -88,52 +96,17 @@ public class TestSecurityConfig extends SecurityConfig { ...@@ -88,52 +96,17 @@ public class TestSecurityConfig extends SecurityConfig {
} }
@Override @Override
public FacebookProvider facebookProvider() { public FacebookClient facebookClient() {
return null;
}
@Override
public OAuthAuthenticationFilter facebookFilter() {
return null;
}
@Override
public OAuthAuthenticationProvider facebookAuthProvider() {
return null;
}
@Override
public OAuthAuthenticationEntryPoint facebookEntryPoint() {
return null;
}
@Override
public Google2Provider googleProvider() {
return null;
}
@Override
public OAuthAuthenticationFilter googleFilter() {
return null;
}
@Override
public OAuthAuthenticationProvider googleAuthProvider() {
return null;
}
@Override
public TwitterProvider twitterProvider() {
return null; return null;
} }
@Override @Override
public OAuthAuthenticationFilter twitterFilter() { public GoogleOidcClient googleClient() {
return null; return null;
} }
@Override @Override
public OAuthAuthenticationProvider twitterAuthProvider() { public TwitterClient twitterClient() {
return null; return null;
} }
} }
/*
* This file is part of ARSnova Backend.
* Copyright (C) 2012-2019 The ARSnova Team and Contributors
*
* ARSnova Backend is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ARSnova Backend 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.thm.arsnova.controller; package de.thm.arsnova.controller;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.junit.After; import org.junit.After;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import de.thm.arsnova.services.StubUserService; import de.thm.arsnova.config.AppConfig;
import de.thm.arsnova.config.TestAppConfig;
import de.thm.arsnova.config.TestPersistanceConfig;
import de.thm.arsnova.config.TestSecurityConfig;
import de.thm.arsnova.config.WebSocketConfig;
import de.thm.arsnova.service.StubUserService;
public abstract class AbstractControllerTest { @RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = {
AppConfig.class,
TestAppConfig.class,
TestPersistanceConfig.class,
TestSecurityConfig.class,
WebSocketConfig.class})
@ActiveProfiles("test")
public abstract class AbstractControllerTest extends AbstractJUnit4SpringContextTests {
@Autowired protected StubUserService userService; @Autowired protected StubUserService userService;
...@@ -20,7 +57,7 @@ public abstract class AbstractControllerTest { ...@@ -20,7 +57,7 @@ public abstract class AbstractControllerTest {
} }
protected void setAuthenticated(final boolean isAuthenticated, final String username) { protected void setAuthenticated(final boolean isAuthenticated, final String username) {
final List<GrantedAuthority> ga = new ArrayList<GrantedAuthority>(); final List<GrantedAuthority> ga = new ArrayList<>();
if (isAuthenticated) { if (isAuthenticated) {
final UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, "secret", ga); final UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, "secret", ga);
SecurityContextHolder.getContext().setAuthentication(token); SecurityContextHolder.getContext().setAuthentication(token);
...@@ -31,9 +68,9 @@ public abstract class AbstractControllerTest { ...@@ -31,9 +68,9 @@ public abstract class AbstractControllerTest {
} }
@After @After
public final void cleanup() { public void cleanup() {
SecurityContextHolder.clearContext(); SecurityContextHolder.clearContext();
userService.setUserAuthenticated(false); userService.setUserAuthenticated(false);
} }
} }
\ No newline at end of file
package de.thm.arsnova.controller;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import de.thm.arsnova.services.StubUserService;
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = {
"file:src/main/webapp/WEB-INF/spring/arsnova-servlet.xml",
"file:src/main/webapp/WEB-INF/spring/spring-main.xml",
"file:src/test/resources/test-config.xml",
"file:src/test/resources/test-socketioconfig.xml"
})
@ActiveProfiles("test")
public class FeedbackControllerTest {
@Autowired
private StubUserService userService;
private MockMvc mockMvc;
@Autowired
private WebApplicationContext webApplicationContext;
@Before
public void setup() {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
@Test
public void testShouldNotGetFeedbackForUnknownSession() throws Exception {
userService.setUserAuthenticated(true);
mockMvc.perform(get("/session/00000000/feedback").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isNotFound());
}
@Test
public void testShouldNotGetAverageFeedbackContentForSessionWithoutFeedback() throws Exception {
userService.setUserAuthenticated(true);
mockMvc.perform(get("/session/12345678/averagefeedback").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isNoContent());
}
@Test
public void testShouldNotGetCorrectFeedbackCountForSessionWithoutFeedback() throws Exception {
userService.setUserAuthenticated(true);
mockMvc.perform(get("/session/12345678/feedbackcount").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().string("0"));
}
@Test
public void testShouldReturnFeedback() throws Exception {
userService.setUserAuthenticated(true);
mockMvc.perform(get("/session/87654321/feedback").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.values").isArray());
}
@Test
public void testShouldReturnXDeprecatedApiHeaderForFeedback() throws Exception {
userService.setUserAuthenticated(true);
mockMvc.perform(get("/session/87654321/feedback").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(header().string(AbstractController.X_DEPRECATED_API, "1"));
}
}
/*
* This file is part of ARSnova Backend.
* Copyright (C) 2012-2019 The ARSnova Team and Contributors
*
* ARSnova Backend is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ARSnova Backend 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.thm.arsnova.controller;
import com.fasterxml.jackson.annotation.JsonView;
import de.thm.arsnova.config.AppConfig;
import de.thm.arsnova.config.TestAppConfig;
import de.thm.arsnova.config.TestPersistanceConfig;
import de.thm.arsnova.config.TestSecurityConfig;
import de.thm.arsnova.config.WebSocketConfig;
import de.thm.arsnova.model.Entity;
import de.thm.arsnova.model.serialization.View;
import de.thm.arsnova.service.EntityService;
import de.thm.arsnova.test.context.support.WithMockUser;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.WebApplicationContext;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
/**
* This class tests {@link JsonViewControllerAdvice} which should be applied to
* controllers which extend {@link AbstractEntityController}. It tests that the
* correct {@link JsonView} is applied for serialization based on the
* <code>view</code> query parameter and that unauthorized view requests are
* rejected.
*
* @author Daniel Gerhardt
*/
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = {
AppConfig.class,
TestAppConfig.class,
TestPersistanceConfig.class,
TestSecurityConfig.class,
WebSocketConfig.class})
@ActiveProfiles("test")
public class JsonViewControllerAdviceTest {
private static final Logger logger = LoggerFactory.getLogger(JsonViewControllerAdviceTest.class);
@Autowired
private WebApplicationContext webApplicationContext;
private MockMvc mockMvc;
@InjectMocks
private DummyEntityController dummyEntityController;
@Autowired
private EntityService<DummyEntity> dummyEntityService;
@Before
public void setup() {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
when(dummyEntityService.get("1")).thenReturn(new DummyEntity());
}
@Test
@WithMockUser("TestUser")
public void testShouldNotSerializeAdminViewForRegularUser() throws Exception {
logger.info("Auth: {}", SecurityContextHolder.getContext().getAuthentication());
mockMvc.perform(get("/dummy/1?view=admin").accept(MediaType.APPLICATION_JSON))
.andDo(h -> logger.info(h.getResponse().getContentAsString()))
.andExpect(status().isForbidden());
}
@Test
@WithMockUser("TestAdmin")
public void testShouldSerializeAdminViewForAdmin() throws Exception {
logger.info("Auth: {}", SecurityContextHolder.getContext().getAuthentication());
mockMvc.perform(get("/dummy/1?view=admin").accept(MediaType.APPLICATION_JSON))
.andDo(h -> logger.info(h.getResponse().getContentAsString()))
.andExpect(status().isOk());
}
@Test
@WithMockUser("TestAdmin")
public void testShouldSerializeOwnerViewForAdmin() throws Exception {
logger.info("Auth: {}", SecurityContextHolder.getContext().getAuthentication());
mockMvc.perform(get("/dummy/1?view=owner").accept(MediaType.APPLICATION_JSON))
.andDo(h -> logger.info(h.getResponse().getContentAsString()))
.andExpect(status().isOk());
}
@Test
@WithMockUser("TestAdmin")
public void testAdminViewShouldContainAdminProperties() throws Exception {
logger.info("Auth: {}", SecurityContextHolder.getContext().getAuthentication());
mockMvc.perform(get("/dummy/1?view=admin").accept(MediaType.APPLICATION_JSON))
.andDo(h -> logger.info(h.getResponse().getContentAsString()))
.andExpect(jsonPath("$.adminReadableString").exists())
.andExpect(jsonPath("$.ownerReadableString").exists())
.andExpect(jsonPath("$.publicReadableString").exists());
}
@Test
@WithMockUser("TestAdmin")
public void testOwnerViewShouldContainOwnerProperties() throws Exception {
logger.info("Auth: {}", SecurityContextHolder.getContext().getAuthentication());
mockMvc.perform(get("/dummy/1?view=owner").accept(MediaType.APPLICATION_JSON))
.andDo(h -> logger.info(h.getResponse().getContentAsString()))
.andExpect(jsonPath("$.adminReadableString").doesNotExist())
.andExpect(jsonPath("$.ownerReadableString").exists())
.andExpect(jsonPath("$.publicReadableString").exists());
}
@Test
@WithMockUser("TestAdmin")
public void testDefaultViewShouldContainPublicProperties() throws Exception {
logger.info("Auth: {}", SecurityContextHolder.getContext().getAuthentication());
mockMvc.perform(get("/dummy/1").accept(MediaType.APPLICATION_JSON))
.andDo(h -> logger.info(h.getResponse().getContentAsString()))
.andExpect(jsonPath("$.adminReadableString").doesNotExist())
.andExpect(jsonPath("$.ownerReadableString").doesNotExist())
.andExpect(jsonPath("$.publicReadableString").exists());
}
@RestController
@RequestMapping(DummyEntityController.REQUEST_MAPPING)
static class DummyEntityController extends AbstractEntityController<DummyEntity> {
private static final String REQUEST_MAPPING = "/dummy";
protected DummyEntityController(final EntityService<DummyEntity> entityService) {
super(entityService);
}
@Override
protected String getMapping() {
return REQUEST_MAPPING;
}
}
public static class DummyEntity extends Entity {
@JsonView(View.Public.class) public String publicReadableString = "public";
@JsonView(View.Owner.class) public String ownerReadableString = "owner";
@JsonView(View.Admin.class) public String adminReadableString = "admin";
}
}
package de.thm.arsnova.controller;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import java.util.ArrayList;
import java.util.List;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import de.thm.arsnova.services.StubUserService;
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = {
"file:src/main/webapp/WEB-INF/spring/arsnova-servlet.xml",
"file:src/main/webapp/WEB-INF/spring/spring-main.xml",
"file:src/test/resources/test-config.xml",
"file:src/test/resources/test-socketioconfig.xml"
})
@ActiveProfiles("test")
public class LecturerQuestionControllerTest {
@Autowired
private StubUserService userService;
@Autowired
private LecturerQuestionController questionController;
private MockMvc mockMvc;
@Autowired
private WebApplicationContext webApplicationContext;
private void setAuthenticated(final boolean isAuthenticated, final String username) {
if (isAuthenticated) {
final List<GrantedAuthority> ga = new ArrayList<GrantedAuthority>();
final UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, "secret", ga);
SecurityContextHolder.getContext().setAuthentication(token);
userService.setUserAuthenticated(isAuthenticated, username);
} else {
userService.setUserAuthenticated(isAuthenticated);
}
}
@Before
public final void startup() {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
SecurityContextHolder.clearContext();
}
@After
public final void cleanup() {
SecurityContextHolder.clearContext();
userService.setUserAuthenticated(false);
}
@Test
public void testShouldNotGetLecturerQuestionsIfUnauthorized() throws Exception {
setAuthenticated(false, "nobody");
mockMvc.perform(
get("/lecturerquestion/")
.param("sessionkey", "12345678").param("lecturequestionsonly", "true")
.accept(MediaType.APPLICATION_JSON)
).andExpect(status().isUnauthorized()
);
}
@Test
public void testShouldNotGetPreparationQuestionsIfUnauthorized() throws Exception {
setAuthenticated(false, "nobody");
mockMvc.perform(
get("/lecturerquestion/")
.param("sessionkey", "12345678").param("preparationquestionsonly", "true")
.accept(MediaType.APPLICATION_JSON)
).andExpect(status().isUnauthorized()
);
}
@Test
public void testShouldReturnQuestionCount() throws Exception {
setAuthenticated(true, "somebody");
mockMvc.perform(
get("/lecturerquestion/count")
.param("sessionkey", "12345678").param("lecturequestionsonly", "true")
.accept(MediaType.APPLICATION_JSON)
).andExpect(status().isOk())
.andExpect(content().string("0")
);
}
@Test
public void testShouldReturnXDeprecatedApiHeaderForQuestionCount() throws Exception {
setAuthenticated(true, "somebody");
mockMvc.perform(
get("/lecturerquestion/count")
.param("sessionkey", "12345678").param("lecturequestionsonly", "true")
.accept(MediaType.APPLICATION_JSON)
).andExpect(status().isOk())
.andExpect(header().string(AbstractController.X_DEPRECATED_API, "1")
);
}
}
package de.thm.arsnova.controller;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import java.util.ArrayList;
import java.util.List;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import de.thm.arsnova.services.StubUserService;
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = {
"file:src/main/webapp/WEB-INF/spring/arsnova-servlet.xml",
"file:src/main/webapp/WEB-INF/spring/spring-main.xml",
"file:src/test/resources/test-config.xml",
"file:src/test/resources/test-socketioconfig.xml"
})
@ActiveProfiles("test")
public class SessionControllerTest {
@Autowired
private StubUserService userService;
@Autowired
private SessionController sessionController;
private MockMvc mockMvc;
@Autowired
private WebApplicationContext webApplicationContext;
private void setAuthenticated(final boolean isAuthenticated, final String username) {
if (isAuthenticated) {
final List<GrantedAuthority> ga = new ArrayList<GrantedAuthority>();
final UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, "secret", ga);
SecurityContextHolder.getContext().setAuthentication(token);
userService.setUserAuthenticated(isAuthenticated, username);
} else {
userService.setUserAuthenticated(isAuthenticated);
}
}
@Before
public final void startup() {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
SecurityContextHolder.clearContext();
}
@After
public final void cleanup() {
SecurityContextHolder.clearContext();
userService.setUserAuthenticated(false);
}
@Test
public void testShouldNotGetUnknownSession() throws Exception {
setAuthenticated(true, "ptsr00");
mockMvc.perform(get("/session/00000000").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isNotFound());
}
@Test
public void testShouldNotGetUnknownSessionIfUnauthorized() throws Exception {
setAuthenticated(false, "ptsr00");
mockMvc.perform(get("/session/00000000").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isUnauthorized());
}
@Test
public void testShouldCreateSessionIfUnauthorized() throws Exception {
setAuthenticated(false, "ptsr00");
mockMvc.perform(
post("/session/")
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.content("{\"keyword\":12345678}")
)
.andExpect(status().isUnauthorized());
}
@Test
public void testShouldNotReturnMySessionsIfUnauthorized() throws Exception {
setAuthenticated(false, "ptsr00");
mockMvc.perform(get("/session/").param("ownedonly", "true").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isUnauthorized());
}
@Test
public void testShouldNotReturnMyVisitedSessionsIfUnauthorized() throws Exception {
setAuthenticated(false, "ptsr00");
mockMvc.perform(get("/session/").param("visitedonly", "true").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isUnauthorized());
}
@Test
public void testShouldShowUnimplementedIfNoFlagIsSet() throws Exception {
setAuthenticated(false, "ptsr00");
mockMvc.perform(get("/session/").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isNotImplemented());
}
@Test
public void testShouldReturnActiveUserCount() throws Exception {
setAuthenticated(false, "ptsr00");
mockMvc.perform(get("/session/12345678/activeusercount").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
.andExpect(content().string("0"));
}
@Test
public void testShouldReturnXDeprecatedApiHeaderForActiveUserCount() throws Exception {
setAuthenticated(false, "ptsr00");
mockMvc.perform(get("/session/12345678/activeusercount").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(header().string(AbstractController.X_DEPRECATED_API, "1"));
}
@Test
public void testShouldEndInForbidden() throws Exception {
setAuthenticated(true, "ptsr00");
mockMvc.perform(
put("/session/12345678")
.content("{\"keyword\":\"12345678\", \"name\":\"Testsession\"}, \"shortName\":\"TS\", \"creator\":\"ptsr00\", \"active\":true")
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk());
setAuthenticated(true, "other");
mockMvc.perform(delete("/session/12345678")).andExpect(status().isForbidden());
}
}
package de.thm.arsnova.controller;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = {
"file:src/main/webapp/WEB-INF/spring/arsnova-servlet.xml",
"file:src/main/webapp/WEB-INF/spring/spring-main.xml",
"file:src/test/resources/test-config.xml",
"file:src/test/resources/test-socketioconfig.xml"
})
@ActiveProfiles("test")
public class StatisticsControllerTest {
@Autowired
private StatisticsController statisticsController;
private MockMvc mockMvc;
@Autowired
private WebApplicationContext webApplicationContext;
@Before
public void setup() {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
@Test
public final void testShouldGetCurrentOnlineUsers() throws Exception {
mockMvc.perform(get("/statistics/activeusercount").accept(MediaType.TEXT_PLAIN))
.andExpect(status().isOk())
.andExpect(content().contentType("text/plain"));
}
@Test
public final void testShouldSendXDeprecatedApiForGetCurrentOnlineUsers() throws Exception {
mockMvc.perform(get("/statistics/activeusercount").accept(MediaType.TEXT_PLAIN))
.andExpect(status().isOk())
.andExpect(content().contentType("text/plain"))
.andExpect(header().string(AbstractController.X_DEPRECATED_API,"1"));
}
@Test
public final void testShouldGetSessionCount() throws Exception {
mockMvc.perform(get("/statistics/sessioncount").accept(MediaType.TEXT_PLAIN))
.andExpect(status().isOk())
.andExpect(content().contentType("text/plain"))
.andExpect(content().string("3"));
}
@Test
public final void testShouldSendXDeprecatedApiForGetSessionCount() throws Exception {
mockMvc.perform(get("/statistics/sessioncount").accept(MediaType.TEXT_PLAIN))
.andExpect(status().isOk())
.andExpect(content().contentType("text/plain"))
.andExpect(header().string(AbstractController.X_DEPRECATED_API,"1"));
}
@Test
public final void testShouldGetStatistics() throws Exception {
mockMvc.perform(get("/statistics").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.answers").value(0))
.andExpect(jsonPath("$.questions").value(0))
.andExpect(jsonPath("$.openSessions").value(3))
.andExpect(jsonPath("$.closedSessions").value(0))
.andExpect(jsonPath("$.activeUsers").exists());
}
@Test
public final void testShouldGetCacheControlHeaderForStatistics() throws Exception {
mockMvc.perform(get("/statistics").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(header().string("cache-control", "public, max-age=60"));
}
}
/* /*
* Copyright (C) 2012 THM webMedia * This file is part of ARSnova Backend.
* Copyright (C) 2012-2019 The ARSnova Team and Contributors
* *
* This file is part of ARSnova. * ARSnova Backend is free software: you can redistribute it and/or modify
*
* ARSnova is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* ARSnova is distributed in the hope that it will be useful, * ARSnova Backend is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
...@@ -16,43 +15,32 @@ ...@@ -16,43 +15,32 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package de.thm.arsnova.controller;
package de.thm.arsnova.controller.v2;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotSame;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.Before; import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.WebApplicationContext;
import de.thm.arsnova.services.StubUserService; import de.thm.arsnova.controller.AbstractControllerTest;
import de.thm.arsnova.service.StubUserService;
@RunWith(SpringJUnit4ClassRunner.class) public class AuthenticationControllerTest extends AbstractControllerTest {
@WebAppConfiguration
@ContextConfiguration(locations = {
"file:src/main/webapp/WEB-INF/spring/arsnova-servlet.xml",
"file:src/main/webapp/WEB-INF/spring/spring-main.xml",
"file:src/test/resources/test-config.xml",
"file:src/test/resources/test-socketioconfig.xml"
})
@ActiveProfiles("test")
public class LoginControllerTest {
@Autowired @Autowired
private StubUserService userService; private StubUserService userService;
...@@ -68,42 +56,43 @@ public class LoginControllerTest { ...@@ -68,42 +56,43 @@ public class LoginControllerTest {
} }
@Test @Test
@Ignore("Mockup needed for DB/Auth")
public void testGuestLogin() throws Exception { public void testGuestLogin() throws Exception {
mockMvc.perform( mockMvc.perform(
get("/doLogin") get("/v2/auth/doLogin")
.param("type", "guest") .param("type", "guest")
).andExpect(status().isOk()); ).andExpect(status().isOk());
} }
@Test @Test
@Ignore("Mockup needed for UserService")
public void testReuseGuestLogin() throws Exception { public void testReuseGuestLogin() throws Exception {
mockMvc.perform( mockMvc.perform(
get("/doLogin") get("/v2/auth/doLogin")
.param("type", "guest").param("user","Guest1234567890") .param("type", "guest")
).andExpect(status().isOk());
final Authentication auth1 = SecurityContextHolder.getContext().getAuthentication();
cleanup();
mockMvc.perform(
get("/v2/auth/doLogin")
.param("type", "guest").param("user", auth1.getName())
).andExpect(status().isOk()); ).andExpect(status().isOk());
final Authentication auth = SecurityContextHolder.getContext() final Authentication auth2 = SecurityContextHolder.getContext().getAuthentication();
.getAuthentication(); assertEquals(auth2.getClass(), UsernamePasswordAuthenticationToken.class);
assertEquals(auth.getClass(), UsernamePasswordAuthenticationToken.class); assertNotSame(auth1, auth2);
assertEquals("Guest1234567890", auth.getName()); assertEquals(auth1, auth2);
} }
@Test @Test
@Ignore("Causes 'ServletException: Circular view path' for an unknown reason.")
public void testUser() throws Exception { public void testUser() throws Exception {
userService.setUserAuthenticated(true); userService.setUserAuthenticated(true);
mockMvc.perform(get("/whoami").accept(MediaType.APPLICATION_JSON)) mockMvc.perform(get("/v2/auth/whoami").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.username").value("ptsr00")) .andExpect(jsonPath("$.username").value("ptsr00"))
.andExpect(jsonPath("$.type").value("ldap")); .andExpect(jsonPath("$.type").value("ldap"));
} }
@Test
public void testLogoutWithoutRedirect() throws Exception {
mockMvc.perform(get("/logout"))
.andExpect(status().isMovedTemporarily())
.andExpect(redirectedUrl("/"));
}
} }
package de.thm.arsnova.controller; /*
* This file is part of ARSnova Backend.
* Copyright (C) 2012-2019 The ARSnova Team and Contributors
*
* ARSnova Backend is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ARSnova Backend 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.thm.arsnova.controller.v2;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import java.util.ArrayList;
import java.util.List;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks; import org.mockito.InjectMocks;
import org.mockito.Mock; import org.mockito.Mock;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.WebApplicationContext;
import de.thm.arsnova.connector.client.ConnectorClient; import de.thm.arsnova.connector.client.ConnectorClient;
import de.thm.arsnova.services.StubUserService; import de.thm.arsnova.controller.AbstractControllerTest;
import de.thm.arsnova.service.StubUserService;
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = {
"file:src/main/webapp/WEB-INF/spring/arsnova-servlet.xml",
"file:src/main/webapp/WEB-INF/spring/spring-main.xml",
"file:src/test/resources/test-config.xml",
"file:src/test/resources/test-socketioconfig.xml"
})
@ActiveProfiles("test") public class CourseControllerTest extends AbstractControllerTest {
public class CourseControllerTest {
private MockMvc mockMvc; private MockMvc mockMvc;
...@@ -53,35 +51,24 @@ public class CourseControllerTest { ...@@ -53,35 +51,24 @@ public class CourseControllerTest {
@Mock @Mock
private ConnectorClient connectorClient; private ConnectorClient connectorClient;
private void setAuthenticated(final boolean isAuthenticated, final String username) {
if (isAuthenticated) {
final List<GrantedAuthority> ga = new ArrayList<GrantedAuthority>();
final UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, "secret", ga);
SecurityContextHolder.getContext().setAuthentication(token);
userService.setUserAuthenticated(isAuthenticated, username);
} else {
userService.setUserAuthenticated(isAuthenticated);
}
}
@Before @Before
public void setup() { public void setup() {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
} }
@Test @Test
public final void testShouldIndicateNotImplementedIfInactiveClient() throws Exception { public void testShouldIndicateNotImplementedIfInactiveClient() throws Exception {
setAuthenticated(true, "ptsr00"); setAuthenticated(true, "ptsr00");
mockMvc.perform(get("/mycourses").accept(MediaType.TEXT_PLAIN)) mockMvc.perform(get("/v2/mycourses").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isNotImplemented()); .andExpect(status().isNotImplemented());
} }
@Test @Test
public final void testShouldNotReturnCurrentUsersCoursesIfUnauthorized() throws Exception { public void testShouldNotReturnCurrentUsersCoursesIfUnauthorized() throws Exception {
setAuthenticated(false, "nobody"); setAuthenticated(false, "nobody");
mockMvc.perform(get("/mycourses").accept(MediaType.TEXT_PLAIN)) mockMvc.perform(get("/v2/mycourses").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isUnauthorized()); .andExpect(status().isUnauthorized());
} }
} }
/*
* Copyright (C) 2012 THM webMedia
*
* This file is part of ARSnova.
*
* ARSnova is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ARSnova 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.thm.arsnova.dao;
import static org.junit.Assert.*;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Arrays;
import org.junit.Test;
import de.thm.arsnova.dao.NovaView.StaleMode;
public class NovaViewTest {
@Test
public void setKeyShouldAcceptSingleArgument() {
final NovaView v = new NovaView(null);
v.setKey("foo");
assertEncodedEquals("key", "\"foo\"", v.getQueryString());
}
@Test
public void setKeyShouldAcceptMultipleArgument() {
final NovaView v = new NovaView(null);
v.setKey("foo", "bar", "baz");
assertEncodedEquals("key", "[\"foo\",\"bar\",\"baz\"]", v.getQueryString());
}
@Test
public void setStartKeyShouldAcceptSingleArgument() {
final NovaView v = new NovaView(null);
v.setStartKey("foo");
assertEncodedEquals("startkey", "\"foo\"", v.getQueryString());
}
@Test
public void setStartKeyShouldAcceptSingleArgumentArray() {
final NovaView v = new NovaView(null);
v.setStartKeyArray("foo");
assertEncodedEquals("startkey", "[\"foo\"]", v.getQueryString());
}
@Test
public void setEndKeyShouldAcceptSingleArgumentArray() {
final NovaView v = new NovaView(null);
v.setEndKeyArray("foo");
assertEncodedEquals("endkey", "[\"foo\"]", v.getQueryString());
}
@Test
public void setEndKeyShouldAcceptSingleArgument() {
final NovaView v = new NovaView(null);
v.setEndKey("foo");
assertEncodedEquals("endkey", "\"foo\"", v.getQueryString());
}
@Test
public void setStartKeyShouldAcceptMultipleArgument() {
final NovaView v = new NovaView(null);
v.setStartKey("foo", "bar", "baz");
assertEncodedEquals("startkey", "[\"foo\",\"bar\",\"baz\"]", v.getQueryString());
}
@Test
public void setEndKeyShouldAcceptMultipleArgument() {
final NovaView v = new NovaView(null);
v.setEndKey("foo", "bar", "baz");
assertEncodedEquals("endkey", "[\"foo\",\"bar\",\"baz\"]", v.getQueryString());
}
@Test
public void keysShouldSupportEmptyObject() {
final NovaView v = new NovaView(null);
v.setKey("foo", "bar", "{}");
assertEncodedEquals("key", "[\"foo\",\"bar\",{}]", v.getQueryString());
}
@Test
public void arrayKeysShouldNotEnquoteNumbers() {
final NovaView v = new NovaView(null);
v.setKey("foo", "bar", "2");
assertEncodedEquals("key", "[\"foo\",\"bar\",2]", v.getQueryString());
}
@Test
public void singleArrayKeysShouldNotEnquoteNumbers() {
final NovaView v1 = new NovaView(null);
final NovaView v2 = new NovaView(null);
v1.setStartKeyArray("2");
v2.setEndKeyArray("2");
assertEncodedEquals("startkey", "[2]", v1.getQueryString());
assertEncodedEquals("endkey", "[2]", v2.getQueryString());
}
@Test
public void shouldSupportAddingKeysParameter() {
String[] stringKeys = new String[] { "foo", "bar" };
String[] numberKeys = new String[] { "123", "456" };
String[] mixedKeys = new String[] { "foo", "123" };
String[] arrayKeys = new String[] { "[\"foo\",123]", "[456,\"bar\"]" };
String[] emptyKeys = new String[0];
final NovaView v1 = new NovaView(null);
final NovaView v2 = new NovaView(null);
final NovaView v3 = new NovaView(null);
final NovaView v4 = new NovaView(null);
final NovaView v5 = new NovaView(null);
v1.setKeys(Arrays.asList(stringKeys));
v2.setKeys(Arrays.asList(numberKeys));
v3.setKeys(Arrays.asList(mixedKeys));
v4.setKeys(Arrays.asList(arrayKeys));
v5.setKeys(Arrays.asList(emptyKeys));
assertEncodedEquals("keys", "[\"foo\",\"bar\"]", v1.getQueryString());
assertEncodedEquals("keys", "[123,456]", v2.getQueryString());
assertEncodedEquals("keys", "[\"foo\",123]", v3.getQueryString());
assertEncodedEquals("keys", "[[\"foo\",123],[456,\"bar\"]]", v4.getQueryString());
assertEncodedEquals("keys", "[]", v5.getQueryString());
}
@Test
public void shouldSupportStaleViews() {
final NovaView v1 = new NovaView(null);
final NovaView v2 = new NovaView(null);
final NovaView v3 = new NovaView(null);
final NovaView v4 = new NovaView(null);
v1.setStale(StaleMode.NONE);
v2.setStale(StaleMode.OK);
v3.setStale(StaleMode.UPDATE_AFTER);
assertNull(v1.getQueryString());
assertEncodedEquals("stale", "ok", v2.getQueryString());
assertEncodedEquals("stale", "update_after", v3.getQueryString());
assertNull(v4.getQueryString());
}
private void assertEncodedEquals(final String key, final String expected, final String actual) {
try {
assertEquals(key + "=" + URLEncoder.encode(expected, "UTF-8"), actual);
} catch (final UnsupportedEncodingException e) {
fail(e.getLocalizedMessage());
}
}
}
/*
* Copyright (C) 2012 THM webMedia
*
* This file is part of ARSnova.
*
* ARSnova is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ARSnova 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.thm.arsnova.dao;
import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import de.thm.arsnova.connector.model.Course;
import de.thm.arsnova.entities.Answer;
import de.thm.arsnova.entities.DbUser;
import de.thm.arsnova.entities.Feedback;
import de.thm.arsnova.entities.InterposedQuestion;
import de.thm.arsnova.entities.InterposedReadingCount;
import de.thm.arsnova.entities.LoggedIn;
import de.thm.arsnova.entities.Question;
import de.thm.arsnova.entities.Session;
import de.thm.arsnova.entities.SessionInfo;
import de.thm.arsnova.entities.User;
import de.thm.arsnova.exceptions.ForbiddenException;
import de.thm.arsnova.exceptions.NoContentException;
import de.thm.arsnova.exceptions.NotFoundException;
public class StubDatabaseDao implements IDatabaseDao {
private static Map<String, Session> stubSessions = new ConcurrentHashMap<String, Session>();
private static Map<String, Feedback> stubFeedbacks = new ConcurrentHashMap<String, Feedback>();
private static Map<String, List<Question>> stubQuestions = new ConcurrentHashMap<String, List<Question>>();
private static Map<String, User> stubUsers = new ConcurrentHashMap<String, User>();
public InterposedQuestion interposedQuestion;
public StubDatabaseDao() {
fillWithDummySessions();
fillWithDummyFeedbacks();
fillWithDummyQuestions();
}
public void cleanupTestData() {
stubSessions.clear();
stubFeedbacks.clear();
stubQuestions.clear();
stubUsers.clear();
fillWithDummySessions();
fillWithDummyFeedbacks();
fillWithDummyQuestions();
}
private void fillWithDummySessions() {
Session session = new Session();
session.setActive(true);
session.setCreator("ptsr00");
session.setKeyword("12345678");
session.setName("TestSession1");
session.setShortName("TS1");
stubSessions.put("12345678", session);
session = new Session();
session.setActive(true);
session.setCreator("ptsr00");
session.setKeyword("87654321");
session.setName("TestSession2");
session.setShortName("TS2");
stubSessions.put("87654321", session);
session = new Session();
session.setActive(true);
session.setCreator("ptsr00");
session.setKeyword("18273645");
session.setName("TestSession2");
session.setShortName("TS3");
stubSessions.put("18273645", session);
}
private void fillWithDummyFeedbacks() {
stubFeedbacks.put("12345678", new Feedback(0, 0, 0, 0));
stubFeedbacks.put("87654321", new Feedback(2, 3, 5, 7));
stubFeedbacks.put("18273645", new Feedback(2, 3, 5, 11));
}
private void fillWithDummyQuestions() {
List<Question> questions = new ArrayList<Question>();
questions.add(new Question());
stubQuestions.put("12345678", questions);
}
@Override
public Session getSession(String keyword) {
// Magic keyword for forbidden session
if (keyword.equals("99999999"))
throw new ForbiddenException();
Session session = stubSessions.get(keyword);
if (session == null)
throw new NotFoundException();
return session;
}
@Override
public Session saveSession(User user, Session session) {
stubSessions.put(session.getKeyword(), session);
return session;
}
@Override
public int countSessions() {
return stubSessions.size();
}
@Override
public int countOpenSessions() {
int result = 0;
for (Session session : stubSessions.values()) {
if (session.isActive()) result++;
}
return result;
}
@Override
public int countClosedSessions() {
int result = 0;
for (Session session : stubSessions.values()) {
if (! session.isActive()) result++;
}
return result;
}
@Override
public boolean sessionKeyAvailable(String keyword) {
return (stubSessions.get(keyword) == null);
}
@Override
public Session getSessionFromKeyword(String keyword) {
return stubSessions.get(keyword);
}
@Override
public Question saveQuestion(Session session, Question question) {
List<Question> questions = stubQuestions.get(session.get_id());
questions.add(question);
stubQuestions.put(session.get_id(), questions);
return question;
}
@Override
public Question getQuestion(String id) {
// Simply ... no such question ;-)
return null;
}
@Override
public List<Question> getSkillQuestions(User user, Session session) {
if (session == null)
throw new NotFoundException();
List<Question> questions = stubQuestions.get(session);
if (questions == null)
throw new NoContentException();
return questions;
}
@Override
public int getSkillQuestionCount(Session session) {
return stubQuestions.get(session.getKeyword()).size();
}
@Override
public List<Session> getMySessions(User user) {
// TODO Auto-generated method stub
return null;
}
@Override
public List<Session> getPublicPoolSessions() {
// TODO Auto-generated method stub
return null;
}
@Override
public List<SessionInfo> getPublicPoolSessionsInfo() {
// TODO Auto-generated method stub
return null;
}
@Override
public List<Session> getMyPublicPoolSessions(User user) {
// TODO Auto-generated method stub
return null;
}
@Override
public List<SessionInfo> getMyPublicPoolSessionsInfo(final User user) {
// TODO Auto-generated method stub
return null;
}
@Override
public LoggedIn registerAsOnlineUser(User u, Session s) {
stubUsers.put(s.getKeyword(), u);
return new LoggedIn();
}
@Override
public void updateSessionOwnerActivity(Session session) {
// TODO Auto-generated method stub
}
@Override
public Answer getMyAnswer(User user, String questionId, int piRound) {
// TODO Auto-generated method stub
return null;
}
@Override
public List<Answer> getAnswers(String questionId, int piRound) {
// TODO Auto-generated method stub
return null;
}
@Override
public int getAnswerCount(Question question, int piRound) {
// TODO Auto-generated method stub
return 0;
}
@Override
public List<Answer> getFreetextAnswers(String questionId) {
// TODO Auto-generated method stub
return null;
}
@Override
public List<Answer> getMyAnswers(User user, String sessionKey) {
return new ArrayList<Answer>();
}
@Override
public int getTotalAnswerCount(String sessionKey) {
// TODO Auto-generated method stub
return 0;
}
@Override
public int getInterposedCount(String sessionKey) {
// TODO Auto-generated method stub
return 0;
}
@Override
public List<InterposedQuestion> getInterposedQuestions(Session session) {
// TODO Auto-generated method stub
return null;
}
@Override
public int countAnswers() {
// TODO Auto-generated method stub
return 0;
}
@Override
public int countQuestions() {
// TODO Auto-generated method stub
return 0;
}
@Override
public InterposedQuestion saveQuestion(Session session, InterposedQuestion question, User user) {
// TODO Auto-generated method stub
return null;
}
@Override
public InterposedQuestion getInterposedQuestion(String questionId) {
return this.interposedQuestion;
}
@Override
public void markInterposedQuestionAsRead(InterposedQuestion question) {
this.interposedQuestion.setRead(true);
}
@Override
public List<Session> getMyVisitedSessions(User user) {
// TODO Auto-generated method stub
return null;
}
@Override
public InterposedReadingCount getInterposedReadingCount(Session session) {
// TODO Auto-generated method stub
return null;
}
@Override
public List<String> getQuestionIds(Session session, User user) {
// TODO Auto-generated method stub
return null;
}
@Override
public List<String> getUnAnsweredQuestionIds(Session session, User user) {
// TODO Auto-generated method stub
return null;
}
@Override
public Question updateQuestion(Question question) {
// TODO Auto-generated method stub
return null;
}
@Override
public void deleteQuestionWithAnswers(Question question) {
// TODO Auto-generated method stub
}
@Override
public void deleteAnswers(Question question) {
// TODO Auto-generated method stub
}
@Override
public Answer saveAnswer(Answer answer, User user) {
// TODO Auto-generated method stub
return null;
}
@Override
public Answer updateAnswer(Answer answer) {
// TODO Auto-generated method stub
return null;
}
@Override
public Session getSessionFromId(String sessionId) {
// TODO Auto-generated method stub
return null;
}
@Override
public void deleteAnswer(String answerId) {
// TODO Auto-generated method stub
}
@Override
public void deleteInterposedQuestion(InterposedQuestion question) {
// TODO Auto-generated method stub
}
@Override
public List<Session> getCourseSessions(List<Course> courses) {
return null;
}
@Override
public Session lockSession(Session session, Boolean lock) {
// TODO Auto-generated method stub
return null;
}
@Override
public Session updateSession(Session session) {
// TODO Auto-generated method stub
return null;
}
@Override
public void deleteSession(Session session) {
// TODO Auto-generated method stub
}
@Override
public void deleteAllQuestionsWithAnswers(Session session) {
// TODO Auto-generated method stub
}
@Override
public List<Question> getLectureQuestions(User user, Session session) {
// TODO Auto-generated method stub
return null;
}
@Override
public List<Question> getFlashcards(User user, Session session) {
// TODO Auto-generated method stub
return null;
}
@Override
public List<Question> getPreparationQuestions(User user, Session session) {
// TODO Auto-generated method stub
return null;
}
@Override
public int getLectureQuestionCount(Session session) {
// TODO Auto-generated method stub
return 0;
}
@Override
public int getFlashcardCount(Session session) {
// TODO Auto-generated method stub
return 0;
}
@Override
public int getPreparationQuestionCount(Session session) {
// TODO Auto-generated method stub
return 0;
}
@Override
public int countLectureQuestionAnswers(Session session) {
// TODO Auto-generated method stub
return 0;
}
@Override
public int countPreparationQuestionAnswers(Session session) {
// TODO Auto-generated method stub
return 0;
}
@Override
public void deleteAllLectureQuestionsWithAnswers(Session session) {
// TODO Auto-generated method stub
}
@Override
public void deleteAllFlashcardsWithAnswers(Session session) {
// TODO Auto-generated method stub
}
@Override
public void deleteAllPreparationQuestionsWithAnswers(Session session) {
// TODO Auto-generated method stub
}
@Override
public List<String> getUnAnsweredLectureQuestionIds(Session session, User user) {
// TODO Auto-generated method stub
return null;
}
@Override
public List<String> getUnAnsweredPreparationQuestionIds(Session session, User user) {
// TODO Auto-generated method stub
return null;
}
@Override
public void deleteAllInterposedQuestions(Session session) {
// TODO Auto-generated method stub
}
@Override
public void publishQuestions(Session session, boolean publish, List<Question> questions) {
// TODO Auto-generated method stub
}
@Override
public void publishAllQuestions(Session session, boolean publish) {
// TODO Auto-generated method stub
}
@Override
public void deleteAllQuestionsAnswers(Session session) {
// TODO Auto-generated method stub
}
@Override
public DbUser createOrUpdateUser(DbUser user) {
// TODO Auto-generated method stub
return null;
}
@Override
public DbUser getUser(String username) {
// TODO Auto-generated method stub
return null;
}
@Override
public int getLearningProgress(Session session) {
// TODO Auto-generated method stub
return 0;
}
@Override
public SimpleEntry<Integer, Integer> getMyLearningProgress(Session session, User user) {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean deleteUser(DbUser dbUser) {
// TODO Auto-generated method stub
return false;
}
@Override
public List<InterposedQuestion> getInterposedQuestions(Session session, User user) {
// TODO Auto-generated method stub
return null;
}
@Override
public void deleteAllInterposedQuestions(Session session, User user) {
// TODO Auto-generated method stub
}
@Override
public InterposedReadingCount getInterposedReadingCount(Session session, User user) {
// TODO Auto-generated method stub
return null;
}
@Override
public List<SessionInfo> getMySessionsInfo(User user) {
// TODO Auto-generated method stub
return null;
}
@Override
public List<SessionInfo> getMyVisitedSessionsInfo(User currentUser) {
// TODO Auto-generated method stub
return null;
}
@Override
public void deleteAllPreparationAnswers(Session session) {
// TODO Auto-generated method stub
}
@Override
public void deleteAllLectureAnswers(Session session) {
// TODO Auto-generated method stub
}
@Override
public int getAbstentionAnswerCount(String questionId) {
// TODO Auto-generated method stub
return 0;
}
}
/*
* This file is part of ARSnova Backend.
* Copyright (C) 2012-2019 The ARSnova Team and Contributors
*
* ARSnova Backend is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ARSnova Backend 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.thm.arsnova.event;
import static org.junit.Assert.assertEquals;
import static org.mockito.AdditionalAnswers.returnsFirstArg;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.when;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.EventListener;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.validation.Validator;
import de.thm.arsnova.config.AppConfig;
import de.thm.arsnova.config.TestAppConfig;
import de.thm.arsnova.config.TestPersistanceConfig;
import de.thm.arsnova.config.TestSecurityConfig;
import de.thm.arsnova.config.WebSocketConfig;
import de.thm.arsnova.model.Content;
import de.thm.arsnova.model.Room;
import de.thm.arsnova.persistence.ContentRepository;
import de.thm.arsnova.persistence.RoomRepository;
import de.thm.arsnova.service.DefaultEntityServiceImpl;
import de.thm.arsnova.test.context.support.WithMockUser;
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = {
AppConfig.class,
TestAppConfig.class,
TestPersistanceConfig.class,
TestSecurityConfig.class,
WebSocketConfig.class})
@ActiveProfiles("test")
public class StateEventDispatcherTest {
private static final String SOME_TEXT = "SomeText";
public static final String SETTINGS_PROPERTY_NAME = "settings";
public static final String STATE_PROPERTY_NAME = "state";
private static final String QUESTIONS_ENABLED_PROPERTY_NAME = "questionsEnabled";
private static final String VISIBLE_PROPERTY_NAME = "visible";
private static final String TEST_USER_ID = "TestUser";
private static final String TEST_ROOM_ID = "TestRoom";
@Autowired
private EventListenerConfig eventListenerConfig;
@Autowired
@Qualifier("defaultJsonMessageConverter")
private MappingJackson2HttpMessageConverter jackson2HttpMessageConverter;
@Autowired
private Validator validator;
@Autowired
private ApplicationEventPublisher eventPublisher;
@Autowired
private RoomRepository roomRepository;
@Autowired
private ContentRepository contentRepository;
@Before
public void prepare() {
eventListenerConfig.resetEvents();
}
@Test
@WithMockUser(TEST_USER_ID)
public void testDispatchRoomSettingsStateEvent() throws IOException {
final ObjectMapper objectMapper = jackson2HttpMessageConverter.getObjectMapper();
final DefaultEntityServiceImpl<Room> entityService = new DefaultEntityServiceImpl<>(
Room.class, roomRepository, objectMapper, validator);
entityService.setApplicationEventPublisher(eventPublisher);
when(roomRepository.save(any(Room.class))).then(returnsFirstArg());
final Room room = new Room();
prefillRoomFields(room);
room.setOwnerId(TEST_USER_ID);
entityService.patch(room, Collections.singletonMap(QUESTIONS_ENABLED_PROPERTY_NAME, false), Room::getSettings);
assertEquals(1, eventListenerConfig.getRoomSettingsStateChangeEvents().size());
assertEquals(SETTINGS_PROPERTY_NAME, eventListenerConfig.getRoomSettingsStateChangeEvents().get(0).getStateName());
}
@Test
@WithMockUser(TEST_USER_ID)
public void testDispatchContentStateEvent() throws IOException {
final ObjectMapper objectMapper = jackson2HttpMessageConverter.getObjectMapper();
final DefaultEntityServiceImpl<Content> entityService = new DefaultEntityServiceImpl<>(
Content.class, contentRepository, objectMapper, validator);
entityService.setApplicationEventPublisher(eventPublisher);
final Room room = new Room();
prefillRoomFields(room);
room.setId(TEST_ROOM_ID);
room.setOwnerId(TEST_USER_ID);
when(contentRepository.save(any(Content.class))).then(returnsFirstArg());
when(roomRepository.findOne(eq(room.getId()))).thenReturn(room);
final Content content = new Content();
prefillContentFields(content);
content.setRoomId(room.getId());
entityService.patch(content, Collections.singletonMap(VISIBLE_PROPERTY_NAME, false), Content::getState);
assertEquals(1, eventListenerConfig.getContentStateChangeEvents().size());
assertEquals(STATE_PROPERTY_NAME, eventListenerConfig.getContentStateChangeEvents().get(0).getStateName());
}
private void prefillRoomFields(final Room room) {
room.setName(SOME_TEXT);
room.setAbbreviation(SOME_TEXT);
room.setShortId("12345678");
}
private void prefillContentFields(final Content content) {
content.setSubject(SOME_TEXT);
content.setBody(SOME_TEXT);
content.setFormat(Content.Format.CHOICE);
}
@Configuration
public static class EventListenerConfig {
private List<StateChangeEvent<Room, Room.Settings>> roomSettingsStateChangeEvents = new ArrayList<>();
private List<StateChangeEvent<Content, Content.State>> contentStateChangeEvents = new ArrayList<>();
@EventListener(condition = "#event.stateName == '" + SETTINGS_PROPERTY_NAME + "'")
public void handleRoomSettingsStateChangeEvent(final StateChangeEvent<Room, Room.Settings> event) {
roomSettingsStateChangeEvents.add(event);
}
@EventListener(condition = "#event.stateName == '" + STATE_PROPERTY_NAME + "'")
public void handleContentStateChangeEvent(final StateChangeEvent<Content, Content.State> event) {
contentStateChangeEvents.add(event);
}
public List<StateChangeEvent<Room, Room.Settings>> getRoomSettingsStateChangeEvents() {
return roomSettingsStateChangeEvents;
}
public List<StateChangeEvent<Content, Content.State>> getContentStateChangeEvents() {
return contentStateChangeEvents;
}
public void resetEvents() {
roomSettingsStateChangeEvents.clear();
contentStateChangeEvents.clear();
}
}
}
/*
* This file is part of ARSnova Backend.
* Copyright (C) 2012-2019 The ARSnova Team and Contributors
*
* ARSnova Backend is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ARSnova Backend 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.thm.arsnova.model;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import org.junit.Test;
import de.thm.arsnova.model.migration.v2.Answer;
import de.thm.arsnova.model.migration.v2.AnswerOption;
import de.thm.arsnova.model.migration.v2.Content;
public class ContentTest {
@SuppressWarnings("serial")
@Test
public void shouldComputeBasedOnCorrectAnswerWithExactMatch() {
final AnswerOption p1 = new AnswerOption();
p1.setText("Yes");
p1.setCorrect(true);
p1.setValue(10);
final AnswerOption p2 = new AnswerOption();
p2.setText("No");
p2.setCorrect(false);
p2.setValue(-10);
final Content q = new Content();
q.setQuestionType("yesno");
q.setPossibleAnswers(new ArrayList<AnswerOption>() {{
add(p1);
add(p2);
}});
final Answer answer1 = new Answer();
answer1.setAnswerText("Yes");
final Answer answer2 = new Answer();
answer2.setAnswerText("No");
assertEquals(10, q.calculateValue(answer1));
assertEquals(-10, q.calculateValue(answer2));
}
@SuppressWarnings("serial")
@Test
public void shouldEqualAbstentionToZeroValue() {
final AnswerOption p1 = new AnswerOption();
p1.setText("Yes");
p1.setCorrect(true);
p1.setValue(10);
final AnswerOption p2 = new AnswerOption();
p2.setText("No");
p2.setCorrect(false);
p2.setValue(-10);
final Content q = new Content();
q.setAbstention(true);
q.setPossibleAnswers(new ArrayList<AnswerOption>() {{
add(p1);
add(p2);
}});
final Answer answer = new Answer();
answer.setAbstention(true);
assertEquals(0, q.calculateValue(answer));
}
@SuppressWarnings("serial")
@Test
public void shouldCalculateMultipleChoiceAnswers() {
final AnswerOption p1 = new AnswerOption();
p1.setText("Yes");
p1.setCorrect(true);
p1.setValue(10);
final AnswerOption p2 = new AnswerOption();
p2.setText("No");
p2.setCorrect(false);
p2.setValue(-10);
final AnswerOption p3 = new AnswerOption();
p3.setText("Maybe");
p3.setCorrect(true);
p3.setValue(10);
final Content q = new Content();
q.setQuestionType("mc");
q.setPossibleAnswers(new ArrayList<AnswerOption>() {{
add(p1);
add(p2);
add(p3);
}});
final Answer answer1 = createAnswerWithText("0,0,0");
final Answer answer2 = createAnswerWithText("0,0,1");
final Answer answer3 = createAnswerWithText("0,1,0");
final Answer answer4 = createAnswerWithText("0,1,1");
final Answer answer5 = createAnswerWithText("1,0,0");
final Answer answer6 = createAnswerWithText("1,0,1");
final Answer answer7 = createAnswerWithText("1,1,0");
final Answer answer8 = createAnswerWithText("1,1,1");
assertEquals(0, q.calculateValue(answer1));
assertEquals(10, q.calculateValue(answer2));
assertEquals(-10, q.calculateValue(answer3));
assertEquals(0, q.calculateValue(answer4));
assertEquals(10, q.calculateValue(answer5));
assertEquals(20, q.calculateValue(answer6));
assertEquals(0, q.calculateValue(answer7));
assertEquals(10, q.calculateValue(answer8));
}
@SuppressWarnings("serial")
@Test
public void shouldCalculatePictureQuestionAnswers() {
final AnswerOption p1 = new AnswerOption();
p1.setText("0;0");
p1.setCorrect(true);
p1.setValue(10);
final AnswerOption p2 = new AnswerOption();
p2.setText("0;1");
p2.setCorrect(false);
p2.setValue(-10);
final AnswerOption p3 = new AnswerOption();
p3.setText("1;0");
p3.setCorrect(true);
p3.setValue(10);
final AnswerOption p4 = new AnswerOption();
p4.setText("1;1");
p4.setCorrect(true);
p4.setValue(10);
final Content q = new Content();
q.setQuestionType("grid");
q.setPossibleAnswers(new ArrayList<AnswerOption>() {{
add(p1);
add(p2);
add(p3);
add(p4);
}});
final Answer answer1 = createAnswerWithText("0;0");
final Answer answer2 = createAnswerWithText("0;1,1;1");
final Answer answer3 = createAnswerWithText("0;0,1;0,1;1");
assertEquals(10, q.calculateValue(answer1));
assertEquals(0, q.calculateValue(answer2));
assertEquals(30, q.calculateValue(answer3));
}
private static Answer createAnswerWithText(final String text) {
final Answer answer = new Answer();
answer.setAnswerText(text);
return answer;
}
}
/*
* This file is part of ARSnova Backend.
* Copyright (C) 2012-2019 The ARSnova Team and Contributors
*
* ARSnova Backend is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ARSnova Backend 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.thm.arsnova.model;
import static org.hamcrest.Matchers.endsWith;
import static org.hamcrest.Matchers.startsWith;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertThat;
import java.util.Date;
import org.junit.Test;
import org.springframework.core.style.ToStringCreator;
/**
* Tests {@link Entity}'s overrides for {@link Object#hashCode()}, {@link Object#equals(Object)}, and
* {@link Object#toString()}.
*
* @author Daniel Gerhardt
*/
public class EntityTest {
class SomeEntity extends Entity {
private String testA;
public SomeEntity(final String id, final String rev, final Date creationTimestamp, final Date updateTimestamp, final String testA) {
this.id = id;
this.rev = rev;
this.creationTimestamp = creationTimestamp;
this.updateTimestamp = updateTimestamp;
this.testA = testA;
}
@Override
public int hashCode() {
return hashCode(super.hashCode(), testA);
}
@Override
public ToStringCreator buildToString() {
return super.buildToString().append("testA", testA);
}
}
class AnotherEntity extends SomeEntity {
private String testB;
public AnotherEntity(
final String id, final String rev, final Date creationTimestamp, final Date updateTimestamp, final String testA, final String testB) {
super(id, rev, creationTimestamp, updateTimestamp, testA);
this.testB = testB;
}
@Override
public int hashCode() {
return hashCode(super.hashCode(), testB);
}
@Override
public ToStringCreator buildToString() {
return super.buildToString().append("testB", testB);
}
}
@Test
public void testHashCode() {
final SomeEntity entity1 = new SomeEntity("id", "rev", new Date(0), new Date(0), "test");
final SomeEntity entity2 = new SomeEntity("id", "rev", new Date(0), new Date(0), "test");
final SomeEntity entity3 = new SomeEntity("wrongId", "rev", new Date(0), new Date(0), "test");
assertEquals(entity1.hashCode(), entity2.hashCode());
assertNotEquals(entity1.hashCode(), entity3.hashCode());
final AnotherEntity entity4 = new AnotherEntity("id", "rev", new Date(0), new Date(0), "someTest", "anotherTest");
final AnotherEntity entity5 = new AnotherEntity("id", "rev", new Date(0), new Date(0), "someTest", "anotherTest");
final AnotherEntity entity6 = new AnotherEntity("id", "rev", new Date(0), new Date(0), "someTest", "wrong");
assertEquals(entity4.hashCode(), entity5.hashCode());
assertNotEquals(entity4.hashCode(), entity6.hashCode());
}
@Test
public void testEquals() {
final SomeEntity entity1 = new SomeEntity("id", "rev", new Date(0), new Date(0), "test");
final SomeEntity entity2 = new SomeEntity("id", "rev", new Date(0), new Date(0), "test");
final SomeEntity entity3 = new SomeEntity("wrongId", "rev", new Date(0), new Date(0), "test");
assertEquals(entity1, entity2);
assertNotEquals(entity1, entity3);
}
@Test
public void testToString() {
final SomeEntity entity1 = new SomeEntity("id", "rev", new Date(0), new Date(0), "test");
assertThat(entity1.toString(), startsWith("[EntityTest.SomeEntity"));
assertThat(entity1.toString(), endsWith("testA = 'test']"));
final AnotherEntity entity2 = new AnotherEntity("id", "rev", new Date(0), new Date(0), "someTest", "anotherTest");
assertThat(entity2.toString(), startsWith("[EntityTest.AnotherEntity"));
assertThat(entity2.toString(), endsWith("testA = 'someTest', testB = 'anotherTest']"));
}
}
/* /*
* Copyright (C) 2012 THM webMedia * This file is part of ARSnova Backend.
* Copyright (C) 2012-2019 The ARSnova Team and Contributors
* *
* This file is part of ARSnova. * ARSnova Backend is free software: you can redistribute it and/or modify
*
* ARSnova is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* ARSnova is distributed in the hope that it will be useful, * ARSnova Backend is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
...@@ -16,27 +15,30 @@ ...@@ -16,27 +15,30 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package de.thm.arsnova.entities;
package de.thm.arsnova.model;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import java.util.Optional;
import org.junit.Test; import org.junit.Test;
public class FeedbackTest { public class FeedbackTest {
@Test @Test
public void differentObjectsShouldNotBeEqual() { public void differentObjectsShouldNotBeEqual() {
Feedback f = new Feedback(0, 0, 0, 0); final Feedback f = new Feedback(0, 0, 0, 0);
String x = ""; final String x = "";
assertFalse(f.equals(x)); assertFalse(f.equals(x));
} }
@Test @Test
public void differentlySizedFeedbacksShouldNotBeEqual() { public void differentlySizedFeedbacksShouldNotBeEqual() {
Feedback f1 = new Feedback(0, 0, 0, 0); final Feedback f1 = new Feedback(0, 0, 0, 0);
Feedback f2 = new Feedback(0, 0, 0, 0); final Feedback f2 = new Feedback(0, 0, 0, 0);
f2.getValues().add(0); f2.getValues().add(0);
assertFalse(f1.equals(f2)); assertFalse(f1.equals(f2));
...@@ -44,14 +46,14 @@ public class FeedbackTest { ...@@ -44,14 +46,14 @@ public class FeedbackTest {
@Test @Test
public void nullShouldNotBeEqual() { public void nullShouldNotBeEqual() {
Feedback f = new Feedback(0, 0, 0, 0); final Feedback f = new Feedback(0, 0, 0, 0);
assertFalse(f.equals(null)); assertFalse(f.equals(null));
} }
@Test @Test
public void sameContentsShouldBeEqual() { public void sameContentsShouldBeEqual() {
Feedback f1 = new Feedback(1, 2, 3, 4); final Feedback f1 = new Feedback(1, 2, 3, 4);
Feedback f2 = new Feedback(1, 2, 3, 4); final Feedback f2 = new Feedback(1, 2, 3, 4);
assertTrue(f1.equals(f2)); assertTrue(f1.equals(f2));
assertTrue(f2.equals(f1)); assertTrue(f2.equals(f1));
...@@ -59,10 +61,40 @@ public class FeedbackTest { ...@@ -59,10 +61,40 @@ public class FeedbackTest {
@Test @Test
public void differentContentsShouldNotBeEqual() { public void differentContentsShouldNotBeEqual() {
Feedback f1 = new Feedback(1, 2, 3, 4); final Feedback f1 = new Feedback(1, 2, 3, 4);
Feedback f2 = new Feedback(4, 3, 2, 1); final Feedback f2 = new Feedback(4, 3, 2, 1);
assertFalse(f1.equals(f2)); assertFalse(f1.equals(f2));
assertFalse(f2.equals(f1)); assertFalse(f2.equals(f1));
} }
@Test
public void shouldCalculateAverageValue() {
final Feedback f = new Feedback(1, 0, 0, 1);
final double expected = 1.5;
final double actual = f.getAverage().get();
assertEquals(expected, actual, 0.01);
}
@Test
public void averageCalculationShouldAvoidDivisionByZero() {
final Feedback f = new Feedback(0, 0, 0, 0);
final Optional<Double> actual = f.getAverage();
assertFalse(actual.isPresent());
}
@Test
public void shouldCountVotes() {
final Feedback f = new Feedback(2, 4, 8, 16);
final int expected = 30;
final int actual = f.getCount();
assertEquals(expected, actual);
}
} }
/* /*
* This file is part of ARSnova Backend. * This file is part of ARSnova Backend.
* Copyright (C) 2012-2015 The ARSnova Team * Copyright (C) 2012-2019 The ARSnova Team and Contributors
* *
* ARSnova Backend is free software: you can redistribute it and/or modify * ARSnova Backend is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -15,29 +15,25 @@ ...@@ -15,29 +15,25 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package de.thm.arsnova.events;
import de.thm.arsnova.entities.InterposedQuestion; package de.thm.arsnova.model;
import de.thm.arsnova.entities.Session;
public class DeleteInterposedQuestionEvent extends NovaEvent { import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import org.springframework.security.core.GrantedAuthority;
private static final long serialVersionUID = 1L; import de.thm.arsnova.model.migration.v2.ClientAuthentication;
private final Session session;
private final InterposedQuestion question;
public DeleteInterposedQuestionEvent(Object source, Session session, InterposedQuestion question) {
super(source);
this.session = session;
this.question = question;
}
@Override
public void accept(NovaEventVisitor visitor) {
// TODO Auto-generated method stub
public class TestClient extends ClientAuthentication {
private static final long serialVersionUID = 1L;
private final Set<GrantedAuthority> grantedAuthorities;
public TestClient(final String username) {
super();
grantedAuthorities = new HashSet<>();
setId(UUID.randomUUID().toString());
setUsername(username);
setAuthProvider(UserProfile.AuthProvider.ARSNOVA);
} }
} }