package org.odroid.server.controllers; import static java.util.Arrays.asList; import static org.apache.commons.io.FileUtils.deleteDirectory; import static org.apache.commons.io.FileUtils.readFileToByteArray; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.odroid.server.entities.ApplicationDataType.MAP_PRICE; import java.io.File; import java.io.IOException; import java.util.List; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.odroid.server.entities.Application; import org.odroid.server.exception.ApplicationNotFoundException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.mock.web.MockMultipartFile; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.web.multipart.MultipartFile; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "/root-context-test.xml", "/servlet-context-test.xml" }) public class ApplicationControllerTest { private Logger l = LoggerFactory.getLogger(getClass()); @Autowired private SessionFactory sf; @Autowired private ApplicationController ac; @Value("${os.filestore}") private String APP_FILESTORE; public static final String HASH_PATTERN = "[0-9a-z]+"; public static final String INVALID_HASH = "invalid hash ~!#$@"; @Rule public ExpectedException exception = ExpectedException.none(); @Before public void before() { clearDB(); } private void clearDB() { Session s = null; try { s = sf.openSession(); Transaction t = s.beginTransaction(); Query q = s.createQuery("delete from Application"); int itemsDeleted = q.executeUpdate(); l.info("Deleted applications: {}", itemsDeleted); t.commit(); } finally { if (s != null) { s.close(); } } } @Test public void testCreateApplication() { Application a = application(); l.debug("Application before create: {}", a); a = ac.create(a); l.debug("Application after create: {}", a); assertNotNull(a); assertNotNull(a.getHash()); assertTrue(a.getHash().matches(HASH_PATTERN)); assertNotNull(a.getId()); assertTrue(a.getActive()); } @Test public void testGetApplicationForHash() { Application newApp = application(); newApp = ac.create(newApp); String hash = newApp.getHash(); assertNotNull(hash); assertTrue(hash.matches(HASH_PATTERN)); Application appForHash = ac.applicationForHash(hash); assertEquals(newApp, appForHash); l.debug("All applications: {}", ac.applications()); } @Test public void testGetApplications() { Application a1 = application(); Application a2 = application(); a1 = ac.create(a1); a2 = ac.create(a2); List<Application> apps = ac.applications(); l.debug("All applications: {}", apps); assertFalse(apps.isEmpty()); assertEquals(2, apps.size()); assertTrue(apps.containsAll(asList(a1, a2))); } @Test public void testLockAndUnlockApplication() { Application a = application(); a = ac.create(a); assertTrue(a.getActive()); a = ac.lock(a.getHash()); assertFalse(a.getActive()); a = ac.unlock(a.getHash()); assertTrue(a.getActive()); } @Test public void testAddData() throws IOException { Application a = application(); a = ac.create(a); String response = ac.addData(a.getHash(), MAP_PRICE, mockMapPriceFile(MAP_PRICE.name().toLowerCase(), mockMapPriceContent())); assertArrayEquals(mockMapPriceContent(), response.getBytes()); File appDir = new File(APP_FILESTORE, a.getHash()); assertTrue(appDir.exists()); assertTrue(appDir.isDirectory()); assertTrue(appDir.list().length > 0); File mapPriceFile = new File(appDir, MAP_PRICE.name().toLowerCase()); assertTrue(mapPriceFile.exists()); assertTrue(mapPriceFile.isFile()); assertArrayEquals(mockMapPriceContent(), readFileToByteArray(mapPriceFile)); response = ac.addData(a.getHash(), MAP_PRICE, mockMapPriceFile(MAP_PRICE.name().toLowerCase(), mockMapPriceContent2())); assertArrayEquals(mockMapPriceContent2(), response.getBytes()); assertTrue(appDir.exists()); assertTrue(appDir.isDirectory()); assertTrue(appDir.list().length > 0); mapPriceFile = new File(appDir, MAP_PRICE.name().toLowerCase()); assertTrue(mapPriceFile.exists()); assertTrue(mapPriceFile.isFile()); assertArrayEquals(mockMapPriceContent2(), readFileToByteArray(mapPriceFile)); deleteDirectory(appDir); assertFalse(appDir.exists()); } private MultipartFile mockMapPriceFile(String name, byte[] content) { return new MockMultipartFile(name, content); } private byte[] mockMapPriceContent() { StringBuilder sb = new StringBuilder(); sb.append("123456788=2.45\n"); sb.append("123456789=1.47\n"); return sb.toString().getBytes(); } private byte[] mockMapPriceContent2() { StringBuilder sb = new StringBuilder(); sb.append("123456786=0.45\n"); sb.append("123456787=11.475\n"); return sb.toString().getBytes(); } @Test public void testCreateApplicationEmptyName() { exception.expect(IllegalArgumentException.class); exception.expectMessage("Name must be set"); Application a = new Application(); a = ac.create(a); } @Test public void testCreateApplicationHashNoEmpty() { exception.expect(IllegalArgumentException.class); exception.expectMessage("Hash mustn't be set"); Application a = new Application(); a.setName("app name"); a.setHash("app hash"); a = ac.create(a); } @Test public void testGetApplicationForInvalidHash() { exception.expect(ApplicationNotFoundException.class); exception.expectMessage("No application found for hash: " + INVALID_HASH); Application a = ac.applicationForHash(INVALID_HASH); assertNull(a); } @Test public void testLockApplicationForInvalidHash() { exception.expect(ApplicationNotFoundException.class); exception.expectMessage("No application found for hash: " + INVALID_HASH); ac.lock(INVALID_HASH); } @Test public void testUnlockApplicationForInvalidHash() { exception.expect(ApplicationNotFoundException.class); exception.expectMessage("No application found for hash: " + INVALID_HASH); ac.unlock(INVALID_HASH); } @Test public void testAddDataInvalidHash() throws IOException { exception.expect(ApplicationNotFoundException.class); exception.expectMessage("No application found for hash: " + INVALID_HASH); ac.addData(INVALID_HASH, MAP_PRICE, new MockMultipartFile("name", "".getBytes())); } private Application application() { Application a = new Application(); a.setName("App Name " + System.currentTimeMillis()); a.setActive(true); return a; } }