diff --git a/.gitignore b/.gitignore index 65cc287..13675ca 100644 --- a/.gitignore +++ b/.gitignore @@ -24,4 +24,6 @@ nbdist/ .nb-gradle/ application.properties -test_repository/ \ No newline at end of file +test_repository/ +/pom.xml.releaseBackup +/release.properties diff --git a/README.md b/README.md index f2a3045..acba8b1 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,12 @@ is repository for Vagrant's Virtual Machine boxes, which can manage box versions By default, http server will start on port *8083*. +#### Build status (travis-ci) + +devel [![Build Status](https://travis-ci.org/sparkoo/boxitory.svg?branch=devel)](https://travis-ci.org/sparkoo/boxitory) + +master: [![Build Status](https://travis-ci.org/sparkoo/boxitory.svg?branch=master)](https://travis-ci.org/sparkoo/boxitory) + ## How it works *Boxitory* currently implements just filesystem box provider. That requires strict folder structure. @@ -72,11 +78,26 @@ $ curl http://localhost:8083/f26 * do define for example protocol or server, where boxes are placed * e.g.: `sftp://my_box_server:` * **default value**: *empty* - + * `box.sort_desc` + * boolean value `true|false` + * when default or `false`, boxes are sorted by version in ascending order + * when `true`, boxes are sorted by version in descending order + * default value: `false` + * `box.checksum` + * string value: `disabled|md5|sha1|sha256` + * default value: `disabled` + * when default or `disabled` boxes output json not contains properties `checksumType` and `checksum` + * when `md5|sha1|sha256` boxes output json contains properties `checksumType` and `checksum` with coresponding values +### Advanced Options + * `box.checksum_buffer_size` + * Box file is loaded to this buffer to calculate box checksums + * default value: `1024` + +### How to configuration Configuration can be provided by `application.properties` file on classpath ``` # application.properties box.home=/tmp/test_repository box.prefix=sftp://my_box_server: ``` -or as command line arguments `java -jar -Dbox.home=/tmp/test_repository target/boxsitory-${version}.jar` \ No newline at end of file +or as command line arguments `java -jar -Dbox.home=/tmp/test_repository target/boxsitory-${version}.jar` diff --git a/application.properties_template b/application.properties_template index 77495fb..21b68a0 100644 --- a/application.properties_template +++ b/application.properties_template @@ -1,3 +1,5 @@ box.home=/custom/test/repository/path box.host_prefix=sftp://localhost: -server.port=8083 \ No newline at end of file +server.port=8083 +box.checksum=disabled +box.sort_desc=false diff --git a/pom.xml b/pom.xml index a8cb36c..3af461b 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ cz.sparko.boxitory boxitory - 1.1.0 + 1.2.0 jar boxitory @@ -34,7 +34,7 @@ https://github.com/sparkoo/boxitory scm:git:git://github.com/sparkoo/boxitory.git scm:git:git@github.com:sparkoo/boxitory.git - v1.1.0 + v1.2.0 @@ -48,6 +48,10 @@ org.springframework.boot spring-boot-starter-web + + org.springframework.boot + spring-boot-starter-thymeleaf + org.springframework.boot spring-boot-configuration-processor diff --git a/src/main/java/cz/sparko/boxitory/App.java b/src/main/java/cz/sparko/boxitory/App.java index db754e8..db4acec 100644 --- a/src/main/java/cz/sparko/boxitory/App.java +++ b/src/main/java/cz/sparko/boxitory/App.java @@ -1,13 +1,17 @@ package cz.sparko.boxitory; import cz.sparko.boxitory.conf.AppProperties; +import cz.sparko.boxitory.factory.HashServiceFactory; import cz.sparko.boxitory.service.BoxRepository; import cz.sparko.boxitory.service.FilesystemBoxRepository; +import cz.sparko.boxitory.service.HashService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; +import java.security.NoSuchAlgorithmException; + @SpringBootApplication public class App { @@ -17,7 +21,8 @@ public static void main(String[] args) { @Bean @Autowired - public BoxRepository boxRepository(AppProperties appProperties) { - return new FilesystemBoxRepository(appProperties); + public BoxRepository boxRepository(AppProperties appProperties) throws NoSuchAlgorithmException { + HashService hashService = HashServiceFactory.createHashService(appProperties); + return new FilesystemBoxRepository(appProperties, hashService); } } diff --git a/src/main/java/cz/sparko/boxitory/conf/AppProperties.java b/src/main/java/cz/sparko/boxitory/conf/AppProperties.java index f027979..5e0f01d 100644 --- a/src/main/java/cz/sparko/boxitory/conf/AppProperties.java +++ b/src/main/java/cz/sparko/boxitory/conf/AppProperties.java @@ -8,7 +8,9 @@ public class AppProperties { private String home = "."; private String host_prefix = ""; + private String checksum = "disabled"; private boolean sort_desc = false; + private int checksum_buffer_size = 1024; public String getHome() { return home; @@ -22,6 +24,14 @@ public boolean isSort_desc() { return sort_desc; } + public String getChecksum() { + return checksum; + } + + public int getChecksum_buffer_size() { + return checksum_buffer_size; + } + public void setSort_desc(boolean sort_desc) { this.sort_desc = sort_desc; } @@ -33,4 +43,12 @@ public void setHome(String home) { public void setHost_prefix(String host_prefix) { this.host_prefix = host_prefix; } + + public void setChecksum(String checksum) { + this.checksum = checksum; + } + + public void setChecksum_buffer_size(int checksum_buffer_size) { + this.checksum_buffer_size = checksum_buffer_size; + } } diff --git a/src/main/java/cz/sparko/boxitory/controller/BoxController.java b/src/main/java/cz/sparko/boxitory/controller/BoxController.java index e0144bc..977a939 100644 --- a/src/main/java/cz/sparko/boxitory/controller/BoxController.java +++ b/src/main/java/cz/sparko/boxitory/controller/BoxController.java @@ -4,10 +4,11 @@ import cz.sparko.boxitory.domain.Box; import cz.sparko.boxitory.service.BoxRepository; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; -@RestController -@RequestMapping(value = "/", method = RequestMethod.GET) +@Controller public class BoxController { private BoxRepository boxRepository; @@ -16,10 +17,16 @@ public BoxController(BoxRepository boxRepository) { this.boxRepository = boxRepository; } - @RequestMapping("{boxName}") + @RequestMapping(value = "/{boxName}", method = RequestMethod.GET) @ResponseBody - public Box getBoxes(@PathVariable String boxName) { + public Box box(@PathVariable String boxName) { return boxRepository.getBox(boxName) - .orElseThrow(() -> new NotFoundException("[" + boxName + "] does not exist")); + .orElseThrow(() -> new NotFoundException("box [" + boxName + "] does not exist")); + } + + @RequestMapping(value = "/", method = RequestMethod.GET) + public String index(Model model) { + model.addAttribute("boxes", boxRepository.getBoxes()); + return "index"; } } diff --git a/src/main/java/cz/sparko/boxitory/domain/Box.java b/src/main/java/cz/sparko/boxitory/domain/Box.java index d4c686f..75a670b 100644 --- a/src/main/java/cz/sparko/boxitory/domain/Box.java +++ b/src/main/java/cz/sparko/boxitory/domain/Box.java @@ -3,6 +3,9 @@ import java.util.List; import java.util.Objects; +/** + * Full description of Vagrant's box as needed in http API. + */ public class Box { private final String name; private final String description; diff --git a/src/main/java/cz/sparko/boxitory/domain/BoxProvider.java b/src/main/java/cz/sparko/boxitory/domain/BoxProvider.java index 7a96517..1901716 100644 --- a/src/main/java/cz/sparko/boxitory/domain/BoxProvider.java +++ b/src/main/java/cz/sparko/boxitory/domain/BoxProvider.java @@ -1,14 +1,21 @@ package cz.sparko.boxitory.domain; +import com.fasterxml.jackson.annotation.JsonInclude; + import java.util.Objects; +@JsonInclude(JsonInclude.Include.NON_NULL) public class BoxProvider { private final String url; private final String name; + private final String checksumType; + private final String checksum; - public BoxProvider(String url, String name) { + public BoxProvider(String url, String name, String checksumType, String checksum) { this.url = url; this.name = name; + this.checksumType = checksumType; + this.checksum = checksum; } @Override @@ -16,6 +23,8 @@ public String toString() { return "BoxProvider{" + "url='" + url + '\'' + ", name='" + name + '\'' + + ", checksumType='" + checksumType + '\'' + + ", checksum='" + checksum + '\'' + '}'; } @@ -25,12 +34,14 @@ public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) { return false; } BoxProvider that = (BoxProvider) o; return Objects.equals(url, that.url) && - Objects.equals(name, that.name); + Objects.equals(name, that.name) && + Objects.equals(checksumType, that.checksumType) && + Objects.equals(checksum, that.checksum); } @Override public int hashCode() { - return Objects.hash(url, name); + return Objects.hash(url, name, checksumType, checksum); } public String getUrl() { @@ -40,4 +51,8 @@ public String getUrl() { public String getName() { return name; } + + public String getChecksumType() { return checksumType; } + + public String getChecksum() { return checksum; } } diff --git a/src/main/java/cz/sparko/boxitory/factory/HashServiceFactory.java b/src/main/java/cz/sparko/boxitory/factory/HashServiceFactory.java new file mode 100644 index 0000000..a1e7e84 --- /dev/null +++ b/src/main/java/cz/sparko/boxitory/factory/HashServiceFactory.java @@ -0,0 +1,31 @@ +package cz.sparko.boxitory.factory; + +import cz.sparko.boxitory.conf.AppProperties; +import cz.sparko.boxitory.service.FilesystemDigestHashService; +import cz.sparko.boxitory.service.NoopHashService; +import cz.sparko.boxitory.service.HashService; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +public class HashServiceFactory { + + public static HashService createHashService(AppProperties appProperties) throws NoSuchAlgorithmException { + String algorithm = appProperties.getChecksum().toUpperCase(); + + switch (algorithm) { + case "MD5": + return new FilesystemDigestHashService(MessageDigest.getInstance(algorithm), appProperties); + case "SHA1": + return new FilesystemDigestHashService(MessageDigest.getInstance("SHA-1"), appProperties); + case "SHA256": + return new FilesystemDigestHashService(MessageDigest.getInstance("SHA-256"), appProperties); + case "DISABLED": + return new NoopHashService(); + default: + throw new IllegalArgumentException( + "Configured checksum type (box.checksum=" + algorithm + ") is not supported" + ); + } + } +} diff --git a/src/main/java/cz/sparko/boxitory/service/BoxRepository.java b/src/main/java/cz/sparko/boxitory/service/BoxRepository.java index 6b6e061..4171661 100644 --- a/src/main/java/cz/sparko/boxitory/service/BoxRepository.java +++ b/src/main/java/cz/sparko/boxitory/service/BoxRepository.java @@ -2,6 +2,7 @@ import cz.sparko.boxitory.domain.Box; +import java.util.List; import java.util.Optional; public interface BoxRepository { @@ -12,4 +13,12 @@ public interface BoxRepository { * @return {@link Box} when found, {@link Optional#empty()} when not found */ Optional getBox(String boxName); + + /** + * Returns {@link List} of names of available {@link Box}es. Call {@link BoxRepository#getBox(String)} with any of + * returned name should get valid result. + * + * @return names of available {@link Box}es + */ + List getBoxes(); } diff --git a/src/main/java/cz/sparko/boxitory/service/FilesystemBoxRepository.java b/src/main/java/cz/sparko/boxitory/service/FilesystemBoxRepository.java index 3132f92..95d1b67 100644 --- a/src/main/java/cz/sparko/boxitory/service/FilesystemBoxRepository.java +++ b/src/main/java/cz/sparko/boxitory/service/FilesystemBoxRepository.java @@ -8,28 +8,40 @@ import org.slf4j.LoggerFactory; import java.io.File; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static java.lang.Integer.compare; -import static java.lang.Integer.parseInt; -import static java.util.Comparator.comparingInt; public class FilesystemBoxRepository implements BoxRepository { private static final Logger LOG = LoggerFactory.getLogger(FilesystemBoxRepository.class); private final String hostPrefix; private final File boxHome; + private final HashService hashService; private final boolean sortDesc; - public FilesystemBoxRepository(AppProperties appProperties) { + public FilesystemBoxRepository(AppProperties appProperties, HashService hashService) { this.boxHome = new File(appProperties.getHome()); this.hostPrefix = appProperties.getHost_prefix(); this.sortDesc = appProperties.isSort_desc(); + this.hashService = hashService; LOG.info("setting BOX_HOME as [{}] and HOST_PREFIX as [{}]", boxHome.getAbsolutePath(), hostPrefix); } + @Override + public List getBoxes() { + return Arrays.stream(boxHome.listFiles(File::isDirectory)) + .filter(this::containsValidBoxFile) + .map(File::getName) + .sorted() + .collect(Collectors.toList()); + } + @Override public Optional getBox(String boxName) { Map> groupedBoxFiles = new HashMap<>(); @@ -71,8 +83,9 @@ private Map> groupBoxFilesByVersion(File boxDir) { private boolean validateFilename(File boxFile) { String filename = boxFile.getName(); - List parsedFilename = Arrays.asList(filename.split("_")); - if (parsedFilename.size() != 3) { + File parentDir = boxFile.getParentFile(); + + if (!filename.matches(parentDir.getName() + "_(\\d+)_(\\w+)\\.box")) { LOG.warn("box file [{}] has wrong name. must be in format ${name}_${version}_${provider}.box", filename); return false; } @@ -109,10 +122,21 @@ private BoxVersion createBoxVersion(String version, List fileList) { private BoxProvider createBoxProviderFromFile(File file) { String filename = file.getName(); List parsedFilename = Arrays.asList(filename.split("_")); + String provider = parsedFilename.get(2); if (provider.endsWith(".box")) { provider = provider.substring(0, provider.length() - 4); } - return new BoxProvider(hostPrefix + file.getAbsolutePath(), provider); + return new BoxProvider( + hostPrefix + file.getAbsolutePath(), + provider, + hashService.getHashType(), + hashService.getChecksum(file.getAbsolutePath()) + ); + } + + private boolean containsValidBoxFile(File file) { + File[] files = file.listFiles(this::validateFilename); + return files.length > 0; } } diff --git a/src/main/java/cz/sparko/boxitory/service/FilesystemDigestHashService.java b/src/main/java/cz/sparko/boxitory/service/FilesystemDigestHashService.java new file mode 100644 index 0000000..ebcfb04 --- /dev/null +++ b/src/main/java/cz/sparko/boxitory/service/FilesystemDigestHashService.java @@ -0,0 +1,75 @@ +package cz.sparko.boxitory.service; + +import cz.sparko.boxitory.conf.AppProperties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.xml.bind.DatatypeConverter; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.security.MessageDigest; +import java.util.Objects; + +public class FilesystemDigestHashService implements HashService { + + private static final Logger LOG = LoggerFactory.getLogger(FilesystemDigestHashService.class); + private MessageDigest messageDigest; + private int streamBufferLength; + + public FilesystemDigestHashService(MessageDigest messageDigest, AppProperties appProperties) { + this.messageDigest = messageDigest; + streamBufferLength = appProperties.getChecksum_buffer_size(); + } + + @Override + public String getHashType() { + return messageDigest.getAlgorithm().replaceAll("-", "").toLowerCase(); + } + + @Override + public String getChecksum(String string) { + try (InputStream boxDataStream = Files.newInputStream(new File(string).toPath())) { + LOG.trace("buffering box data (buffer size [{}]b) ...", streamBufferLength); + final byte[] buffer = new byte[streamBufferLength]; + int read = boxDataStream.read(buffer, 0, streamBufferLength); + + while (read > -1) { + messageDigest.update(buffer, 0, read); + read = boxDataStream.read(buffer, 0, streamBufferLength); + } + } catch (IOException e) { + LOG.error("Error during processing file [{}], message: [{}]", string, e.getMessage()); + throw new RuntimeException( + "Error while getting checksum for file " + string + " reason: " + e.getMessage(), e + ); + } + + return getHash(messageDigest.digest()); + } + + private String getHash(byte[] diggestBytes) { + return DatatypeConverter.printHexBinary(diggestBytes).toLowerCase(); + } + + @Override + public String toString() { + return "FilesystemDigestHashService{" + + "messageDigest=" + messageDigest + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) { return true; } + if (o == null || getClass() != o.getClass()) { return false; } + FilesystemDigestHashService that = (FilesystemDigestHashService) o; + return messageDigest.getAlgorithm().equals(that.messageDigest.getAlgorithm()); + } + + @Override + public int hashCode() { + return Objects.hash(messageDigest); + } +} diff --git a/src/main/java/cz/sparko/boxitory/service/HashService.java b/src/main/java/cz/sparko/boxitory/service/HashService.java new file mode 100644 index 0000000..75482a1 --- /dev/null +++ b/src/main/java/cz/sparko/boxitory/service/HashService.java @@ -0,0 +1,7 @@ +package cz.sparko.boxitory.service; + + +public interface HashService { + String getHashType(); + String getChecksum(String string); +} diff --git a/src/main/java/cz/sparko/boxitory/service/NoopHashService.java b/src/main/java/cz/sparko/boxitory/service/NoopHashService.java new file mode 100644 index 0000000..f3aeaa5 --- /dev/null +++ b/src/main/java/cz/sparko/boxitory/service/NoopHashService.java @@ -0,0 +1,20 @@ +package cz.sparko.boxitory.service; + + +public class NoopHashService implements HashService { + + @Override + public String getHashType() { + return null; + } + + @Override + public String getChecksum(String string) { + return null; + } + + @Override + public boolean equals(Object obj) { + return obj.getClass().getName().equals(NoopHashService.class.getName()); + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 9146c65..21818de 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,4 +1,5 @@ box.home=. box.host_prefix= +box.checksum=disabled server.port=8083 box.sort_desc=false \ No newline at end of file diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml new file mode 100644 index 0000000..b9cbec6 --- /dev/null +++ b/src/main/resources/logback.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html new file mode 100644 index 0000000..f951981 --- /dev/null +++ b/src/main/resources/templates/index.html @@ -0,0 +1,12 @@ + + + + + + +

Available boxes

+
    +
  • +
+ + \ No newline at end of file diff --git a/src/test/java/cz/sparko/boxitory/service/FilesystemBoxRepositoryTest.java b/src/test/java/cz/sparko/boxitory/service/FilesystemBoxRepositoryTest.java index 0380a4a..4198b99 100644 --- a/src/test/java/cz/sparko/boxitory/service/FilesystemBoxRepositoryTest.java +++ b/src/test/java/cz/sparko/boxitory/service/FilesystemBoxRepositoryTest.java @@ -19,6 +19,8 @@ import java.util.Optional; import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; @SpringBootTest public class FilesystemBoxRepositoryTest { @@ -82,23 +84,28 @@ public Object[][] boxes() { {"f25", Optional.of(new Box("f25", "f25", Arrays.asList( new BoxVersion("1", Collections.singletonList( - new BoxProvider(composePath("f25", "1", "virtualbox"), "virtualbox") + new BoxProvider(composePath("f25", "1", "virtualbox"), + "virtualbox", null, null) )), new BoxVersion("2", Collections.singletonList( - new BoxProvider(composePath("f25", "2", "virtualbox"), "virtualbox") + new BoxProvider(composePath("f25", "2", "virtualbox"), + "virtualbox", null, null) )) ))) }, {"f26", Optional.of(new Box("f26", "f26", Arrays.asList( new BoxVersion("1", Collections.singletonList( - new BoxProvider(composePath("f26", "1", "virtualbox"), "virtualbox") + new BoxProvider(composePath("f26", "1", "virtualbox"), + "virtualbox", null, null) )), new BoxVersion("2", Collections.singletonList( - new BoxProvider(composePath("f26", "2", "virtualbox"), "virtualbox") + new BoxProvider(composePath("f26", "2", "virtualbox"), + "virtualbox", null, null) )), new BoxVersion("3", Collections.singletonList( - new BoxProvider(composePath("f26", "3", "virtualbox"), "virtualbox") + new BoxProvider(composePath("f26", "3", "virtualbox"), + "virtualbox", null, null) )) ))) }, @@ -106,11 +113,14 @@ public Object[][] boxes() { {"f28", Optional.of(new Box("f28", "f28", Arrays.asList( new BoxVersion("1", Arrays.asList( - new BoxProvider(composePath("f28", "1", "virtualbox"), "virtualbox"), - new BoxProvider(composePath("f28", "1", "vmware"), "vmware") + new BoxProvider(composePath("f28", "1", "virtualbox"), + "virtualbox", null, null), + new BoxProvider(composePath("f28", "1", "vmware"), + "vmware", null, null) )), new BoxVersion("2", Collections.singletonList( - new BoxProvider(composePath("f28", "2", "virtualbox"), "virtualbox") + new BoxProvider(composePath("f28", "2", "virtualbox"), + "virtualbox", null, null) )) ))) }, @@ -121,7 +131,7 @@ public Object[][] boxes() { @Test(dataProvider = "boxes") public void givenRepository_whenGetBox_thenGetWhenFound(String boxName, Optional expectedResult) { - BoxRepository boxRepository = new FilesystemBoxRepository(testAppProperties); + BoxRepository boxRepository = new FilesystemBoxRepository(testAppProperties, new NoopHashService()); Optional providedBox = boxRepository.getBox(boxName); @@ -134,7 +144,7 @@ public void givenRepository_whenGetBox_thenGetWhenFound(String boxName, Optional public void givenSortAscending_whenGetBox_thenVersionsSortedAsc() { testAppProperties.setSort_desc(false); - BoxRepository boxRepository = new FilesystemBoxRepository(testAppProperties); + BoxRepository boxRepository = new FilesystemBoxRepository(testAppProperties, new NoopHashService()); List versions = boxRepository.getBox("f29").get().getVersions(); assertEquals(versions.get(0).getVersion(), "1"); @@ -146,7 +156,7 @@ public void givenSortAscending_whenGetBox_thenVersionsSortedAsc() { public void givenSortDescending_whenGetBox_thenVersionsSortedDesc() { testAppProperties.setSort_desc(true); - BoxRepository boxRepository = new FilesystemBoxRepository(testAppProperties); + BoxRepository boxRepository = new FilesystemBoxRepository(testAppProperties, new NoopHashService()); List versions = boxRepository.getBox("f29").get().getVersions(); assertEquals(versions.get(0).getVersion(), "3"); @@ -154,6 +164,15 @@ public void givenSortDescending_whenGetBox_thenVersionsSortedDesc() { assertEquals(versions.get(2).getVersion(), "1"); } + @Test + public void givenValidRepositoryWithBoxes_whenIndex_thenGetValidBoxes() { + BoxRepository boxRepository = new FilesystemBoxRepository(testAppProperties, new NoopHashService()); + + List boxes = boxRepository.getBoxes(); + assertTrue(boxes.containsAll(Arrays.asList("f25", "f26", "f28", "f29"))); + assertFalse(boxes.containsAll(Arrays.asList("f27"))); + } + private String composePath(String boxName, String version, String provider) { return String.format("%s%s/%s/%s_%s_%s.box", TEST_BOX_PREFIX, testHomeDir.getAbsolutePath(), boxName, boxName, version, provider); diff --git a/src/test/java/cz/sparko/boxitory/service/FilesystemDigestHashServiceTest.java b/src/test/java/cz/sparko/boxitory/service/FilesystemDigestHashServiceTest.java new file mode 100644 index 0000000..c4c274d --- /dev/null +++ b/src/test/java/cz/sparko/boxitory/service/FilesystemDigestHashServiceTest.java @@ -0,0 +1,85 @@ +package cz.sparko.boxitory.service; + +import cz.sparko.boxitory.conf.AppProperties; +import org.apache.commons.io.FileUtils; +import org.springframework.boot.test.context.SpringBootTest; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +import static org.testng.Assert.assertEquals; + +@SpringBootTest +public class FilesystemDigestHashServiceTest { + + private final String TEST_HOME = "test_repository"; + private File testHomeDir; + + @BeforeClass + public void setUp() throws IOException { + testHomeDir = new File(TEST_HOME); + + createTestFolderStructure(); + } + + private void createTestFolderStructure() throws IOException { + testHomeDir.mkdir(); + File f25 = new File(testHomeDir.getAbsolutePath() + "/f25"); + File f26 = new File(testHomeDir.getAbsolutePath() + "/f26"); + File f27 = new File(testHomeDir.getAbsolutePath() + "/f27"); + + f25.mkdir(); + f26.mkdir(); + f27.mkdir(); + + File f25box1 = new File(f25.getAbsolutePath() + "/f25_1_virtualbox.box"); + f25box1.createNewFile(); + FileWriter fileWriter = new FileWriter(f25box1); + fileWriter.write("123456789\n987654321\nabcdefghi"); + fileWriter.close(); + } + + @AfterClass + public void tearDown() throws IOException { + FileUtils.deleteDirectory(testHomeDir); + } + + @DataProvider + public Object[][] filesAndHashes() { + return new Object[][]{ + { + "MD5", + new File(testHomeDir.getAbsolutePath() + "/f25/f25_1_virtualbox.box"), + "86462c346f1358ddbf4f137fb5da43cf" + }, + { + "SHA-1", + new File(testHomeDir.getAbsolutePath() + "/f25/f25_1_virtualbox.box"), + "6efeafd3d3304cf5d7fd37db2a7ddbaac09f425d" + }, + { + "SHA-256", + new File(testHomeDir.getAbsolutePath() + "/f25/f25_1_virtualbox.box"), + "ae4fe7f29f683d3901d4c620ef2e3c7ed17ebb6813158efd6a16f81b71a0aa43" + } + }; + } + + @Test(dataProvider = "filesAndHashes") + public void givenHashService_whenGetChecksum_thenChecksumsAreEquals(String algorithm, File file, String + expectedChecksum) throws NoSuchAlgorithmException { + HashService hashService = new FilesystemDigestHashService(MessageDigest.getInstance(algorithm), new AppProperties()); + + String checksum = hashService.getChecksum(file.getAbsolutePath()); + + assertEquals(checksum, expectedChecksum); + } + +} diff --git a/src/test/java/cz/sparko/boxitory/service/HashServiceFactoryTest.java b/src/test/java/cz/sparko/boxitory/service/HashServiceFactoryTest.java new file mode 100644 index 0000000..aa0bd20 --- /dev/null +++ b/src/test/java/cz/sparko/boxitory/service/HashServiceFactoryTest.java @@ -0,0 +1,43 @@ +package cz.sparko.boxitory.service; + +import cz.sparko.boxitory.conf.AppProperties; +import cz.sparko.boxitory.factory.HashServiceFactory; +import org.springframework.boot.test.context.SpringBootTest; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + + +import static org.testng.Assert.assertEquals; + +@SpringBootTest +public class HashServiceFactoryTest { + + @DataProvider + public Object[][] hashServiceTypes() throws NoSuchAlgorithmException { + return new Object[][]{ + {"md5", new FilesystemDigestHashService(MessageDigest.getInstance("MD5"), new AppProperties())}, + {"sha1", new FilesystemDigestHashService(MessageDigest.getInstance("SHA-1"), new AppProperties())}, + {"sha256", new FilesystemDigestHashService(MessageDigest.getInstance("SHA-256"), new AppProperties())}, + {"disabled", new NoopHashService()} + }; + } + + @Test(dataProvider = "hashServiceTypes") + public void givenFactory_whenCreateHashService_thenGetExpectedInstance(String type, HashService expectedService) throws NoSuchAlgorithmException { + AppProperties appProperties = new AppProperties(); + appProperties.setChecksum(type); + HashService hashService = HashServiceFactory.createHashService(appProperties); + + assertEquals(hashService, expectedService); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void givenFactory_whenCreateUnsupportedHashService_thenExceptionIsThrown() throws NoSuchAlgorithmException { + AppProperties appProperties = new AppProperties(); + appProperties.setChecksum("foo"); + HashServiceFactory.createHashService(appProperties); + } +}