diff --git a/.gitignore b/.gitignore
index 9f11b75..c44bb5a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,5 @@
.idea/
+build
+.gradle
+gradle/
+out/
\ No newline at end of file
diff --git a/.gradle/7.5.1/checksums/checksums.lock b/.gradle/7.5.1/checksums/checksums.lock
deleted file mode 100644
index a03e8ed..0000000
Binary files a/.gradle/7.5.1/checksums/checksums.lock and /dev/null differ
diff --git a/.gradle/7.5.1/checksums/md5-checksums.bin b/.gradle/7.5.1/checksums/md5-checksums.bin
deleted file mode 100644
index a9dfcd7..0000000
Binary files a/.gradle/7.5.1/checksums/md5-checksums.bin and /dev/null differ
diff --git a/.gradle/7.5.1/checksums/sha1-checksums.bin b/.gradle/7.5.1/checksums/sha1-checksums.bin
deleted file mode 100644
index 1fa5fcd..0000000
Binary files a/.gradle/7.5.1/checksums/sha1-checksums.bin and /dev/null differ
diff --git a/.gradle/7.5.1/dependencies-accessors/dependencies-accessors.lock b/.gradle/7.5.1/dependencies-accessors/dependencies-accessors.lock
deleted file mode 100644
index 09280f7..0000000
Binary files a/.gradle/7.5.1/dependencies-accessors/dependencies-accessors.lock and /dev/null differ
diff --git a/.gradle/7.5.1/dependencies-accessors/gc.properties b/.gradle/7.5.1/dependencies-accessors/gc.properties
deleted file mode 100644
index e69de29..0000000
diff --git a/.gradle/7.5.1/executionHistory/executionHistory.bin b/.gradle/7.5.1/executionHistory/executionHistory.bin
deleted file mode 100644
index 955abc9..0000000
Binary files a/.gradle/7.5.1/executionHistory/executionHistory.bin and /dev/null differ
diff --git a/.gradle/7.5.1/executionHistory/executionHistory.lock b/.gradle/7.5.1/executionHistory/executionHistory.lock
deleted file mode 100644
index 9323e89..0000000
Binary files a/.gradle/7.5.1/executionHistory/executionHistory.lock and /dev/null differ
diff --git a/.gradle/7.5.1/fileChanges/last-build.bin b/.gradle/7.5.1/fileChanges/last-build.bin
deleted file mode 100644
index f76dd23..0000000
Binary files a/.gradle/7.5.1/fileChanges/last-build.bin and /dev/null differ
diff --git a/.gradle/7.5.1/fileHashes/fileHashes.bin b/.gradle/7.5.1/fileHashes/fileHashes.bin
deleted file mode 100644
index e958afe..0000000
Binary files a/.gradle/7.5.1/fileHashes/fileHashes.bin and /dev/null differ
diff --git a/.gradle/7.5.1/fileHashes/fileHashes.lock b/.gradle/7.5.1/fileHashes/fileHashes.lock
deleted file mode 100644
index 8ca5f3d..0000000
Binary files a/.gradle/7.5.1/fileHashes/fileHashes.lock and /dev/null differ
diff --git a/.gradle/7.5.1/fileHashes/resourceHashesCache.bin b/.gradle/7.5.1/fileHashes/resourceHashesCache.bin
deleted file mode 100644
index 73577d1..0000000
Binary files a/.gradle/7.5.1/fileHashes/resourceHashesCache.bin and /dev/null differ
diff --git a/.gradle/7.5.1/gc.properties b/.gradle/7.5.1/gc.properties
deleted file mode 100644
index e69de29..0000000
diff --git a/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/.gradle/buildOutputCleanup/buildOutputCleanup.lock
deleted file mode 100644
index 555ade8..0000000
Binary files a/.gradle/buildOutputCleanup/buildOutputCleanup.lock and /dev/null differ
diff --git a/.gradle/buildOutputCleanup/cache.properties b/.gradle/buildOutputCleanup/cache.properties
deleted file mode 100644
index 79c6d9f..0000000
--- a/.gradle/buildOutputCleanup/cache.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-#Thu Apr 11 12:53:51 GMT+04:00 2024
-gradle.version=7.5.1
diff --git a/.gradle/buildOutputCleanup/outputFiles.bin b/.gradle/buildOutputCleanup/outputFiles.bin
deleted file mode 100644
index 580bcee..0000000
Binary files a/.gradle/buildOutputCleanup/outputFiles.bin and /dev/null differ
diff --git a/.gradle/file-system.probe b/.gradle/file-system.probe
deleted file mode 100644
index 6368ebf..0000000
Binary files a/.gradle/file-system.probe and /dev/null differ
diff --git a/.gradle/vcs-1/gc.properties b/.gradle/vcs-1/gc.properties
deleted file mode 100644
index e69de29..0000000
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..63f01a6
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,7 @@
+FROM dockerhub.timeweb.cloud/library/openjdk:17-jdk-alpine
+
+ARG JAR_FILE=build/libs/LinkShortener-0.0.1-SNAPSHOT.jar
+
+COPY ./build/libs/LinkShortener-0.0.1-SNAPSHOT.jar app.jar
+
+ENTRYPOINT ["java", "-jar", "/app.jar"]
diff --git a/build.gradle b/build.gradle
index 3cae2d7..420c2bb 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,17 +1,35 @@
plugins {
id 'java'
+ id 'org.springframework.boot' version '3.3.0'
+ id 'io.spring.dependency-management' version '1.1.5'
}
-group 'org.example'
-version '1.0-SNAPSHOT'
+
+
+group = 'org.example'
+version = '0.0.1-SNAPSHOT'
+
+java {
+ sourceCompatibility = '17'
+}
repositories {
mavenCentral()
}
dependencies {
- testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
- testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
+ testImplementation platform('org.junit:junit-bom:5.9.1')
+ testImplementation 'org.junit.jupiter:junit-jupiter'
+ testImplementation(group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: '3.2.4')
+ testImplementation group: 'com.h2database', name: 'h2', version: '2.2.224'
+
+ implementation(group: 'org.springframework.boot', name: 'spring-boot-starter', version: '3.2.4')
+ implementation(group: 'org.springframework.boot', name: 'spring-boot-starter-jetty', version: '3.2.4')
+ implementation(group: 'org.springframework.boot', name: 'spring-boot-starter-web-services', version: '3.2.4')
+ implementation 'org.springframework.boot:spring-boot-starter-data-jdbc:3.3.0'
+ implementation 'org.springframework.boot:spring-boot-starter-data-jpa:3.3.0'
+ implementation group: 'com.github.jsqlparser', name: 'jsqlparser', version: '4.9'
+ runtimeOnly 'org.postgresql:postgresql:42.7.2'
}
test {
diff --git a/build/classes/java/main/org/example/Main.class b/build/classes/java/main/org/example/Main.class
deleted file mode 100644
index fb64510..0000000
Binary files a/build/classes/java/main/org/example/Main.class and /dev/null differ
diff --git a/build/classes/java/main/org/example/database/Database.class b/build/classes/java/main/org/example/database/Database.class
deleted file mode 100644
index 46c1bbf..0000000
Binary files a/build/classes/java/main/org/example/database/Database.class and /dev/null differ
diff --git a/build/classes/java/main/org/example/exception/UnknownShortLinkException.class b/build/classes/java/main/org/example/exception/UnknownShortLinkException.class
deleted file mode 100644
index 5a091dd..0000000
Binary files a/build/classes/java/main/org/example/exception/UnknownShortLinkException.class and /dev/null differ
diff --git a/build/classes/java/main/org/example/service/MainService.class b/build/classes/java/main/org/example/service/MainService.class
deleted file mode 100644
index 8fd3685..0000000
Binary files a/build/classes/java/main/org/example/service/MainService.class and /dev/null differ
diff --git a/build/classes/java/main/org/example/service/MainServiceImpl.class b/build/classes/java/main/org/example/service/MainServiceImpl.class
deleted file mode 100644
index 89d029b..0000000
Binary files a/build/classes/java/main/org/example/service/MainServiceImpl.class and /dev/null differ
diff --git a/build/classes/java/test/org/example/service/MainServiceTest.class b/build/classes/java/test/org/example/service/MainServiceTest.class
deleted file mode 100644
index 0d03df1..0000000
Binary files a/build/classes/java/test/org/example/service/MainServiceTest.class and /dev/null differ
diff --git a/build/reports/tests/test/classes/org.example.service.MainServiceTest.html b/build/reports/tests/test/classes/org.example.service.MainServiceTest.html
deleted file mode 100644
index b338007..0000000
--- a/build/reports/tests/test/classes/org.example.service.MainServiceTest.html
+++ /dev/null
@@ -1,111 +0,0 @@
-
-
-
-
-
-Test results - MainServiceTest
-
-
-
-
-
-
-
MainServiceTest
-
-
-
-
-
-
-
-
-|
-
- |
-
-
- |
-
-
- |
-
-
- |
-
-
-
- |
-
-
- |
-
-
-
-
-
-
-
Tests
-
-
-
-| Test |
-Duration |
-Result |
-
-
-
-| testException() |
-0.039s |
-passed |
-
-
-| testGetLongLink() |
-0.005s |
-passed |
-
-
-| testGetShortLink() |
-0.019s |
-passed |
-
-
-| testUniqueness() |
-3.557s |
-passed |
-
-
-
-
-
-
-
-
diff --git a/build/reports/tests/test/css/base-style.css b/build/reports/tests/test/css/base-style.css
deleted file mode 100644
index 4afa73e..0000000
--- a/build/reports/tests/test/css/base-style.css
+++ /dev/null
@@ -1,179 +0,0 @@
-
-body {
- margin: 0;
- padding: 0;
- font-family: sans-serif;
- font-size: 12pt;
-}
-
-body, a, a:visited {
- color: #303030;
-}
-
-#content {
- padding-left: 50px;
- padding-right: 50px;
- padding-top: 30px;
- padding-bottom: 30px;
-}
-
-#content h1 {
- font-size: 160%;
- margin-bottom: 10px;
-}
-
-#footer {
- margin-top: 100px;
- font-size: 80%;
- white-space: nowrap;
-}
-
-#footer, #footer a {
- color: #a0a0a0;
-}
-
-#line-wrapping-toggle {
- vertical-align: middle;
-}
-
-#label-for-line-wrapping-toggle {
- vertical-align: middle;
-}
-
-ul {
- margin-left: 0;
-}
-
-h1, h2, h3 {
- white-space: nowrap;
-}
-
-h2 {
- font-size: 120%;
-}
-
-ul.tabLinks {
- padding-left: 0;
- padding-top: 10px;
- padding-bottom: 10px;
- overflow: auto;
- min-width: 800px;
- width: auto !important;
- width: 800px;
-}
-
-ul.tabLinks li {
- float: left;
- height: 100%;
- list-style: none;
- padding-left: 10px;
- padding-right: 10px;
- padding-top: 5px;
- padding-bottom: 5px;
- margin-bottom: 0;
- -moz-border-radius: 7px;
- border-radius: 7px;
- margin-right: 25px;
- border: solid 1px #d4d4d4;
- background-color: #f0f0f0;
-}
-
-ul.tabLinks li:hover {
- background-color: #fafafa;
-}
-
-ul.tabLinks li.selected {
- background-color: #c5f0f5;
- border-color: #c5f0f5;
-}
-
-ul.tabLinks a {
- font-size: 120%;
- display: block;
- outline: none;
- text-decoration: none;
- margin: 0;
- padding: 0;
-}
-
-ul.tabLinks li h2 {
- margin: 0;
- padding: 0;
-}
-
-div.tab {
-}
-
-div.selected {
- display: block;
-}
-
-div.deselected {
- display: none;
-}
-
-div.tab table {
- min-width: 350px;
- width: auto !important;
- width: 350px;
- border-collapse: collapse;
-}
-
-div.tab th, div.tab table {
- border-bottom: solid #d0d0d0 1px;
-}
-
-div.tab th {
- text-align: left;
- white-space: nowrap;
- padding-left: 6em;
-}
-
-div.tab th:first-child {
- padding-left: 0;
-}
-
-div.tab td {
- white-space: nowrap;
- padding-left: 6em;
- padding-top: 5px;
- padding-bottom: 5px;
-}
-
-div.tab td:first-child {
- padding-left: 0;
-}
-
-div.tab td.numeric, div.tab th.numeric {
- text-align: right;
-}
-
-span.code {
- display: inline-block;
- margin-top: 0em;
- margin-bottom: 1em;
-}
-
-span.code pre {
- font-size: 11pt;
- padding-top: 10px;
- padding-bottom: 10px;
- padding-left: 10px;
- padding-right: 10px;
- margin: 0;
- background-color: #f7f7f7;
- border: solid 1px #d0d0d0;
- min-width: 700px;
- width: auto !important;
- width: 700px;
-}
-
-span.wrapped pre {
- word-wrap: break-word;
- white-space: pre-wrap;
- word-break: break-all;
-}
-
-label.hidden {
- display: none;
-}
\ No newline at end of file
diff --git a/build/reports/tests/test/css/style.css b/build/reports/tests/test/css/style.css
deleted file mode 100644
index 3dc4913..0000000
--- a/build/reports/tests/test/css/style.css
+++ /dev/null
@@ -1,84 +0,0 @@
-
-#summary {
- margin-top: 30px;
- margin-bottom: 40px;
-}
-
-#summary table {
- border-collapse: collapse;
-}
-
-#summary td {
- vertical-align: top;
-}
-
-.breadcrumbs, .breadcrumbs a {
- color: #606060;
-}
-
-.infoBox {
- width: 110px;
- padding-top: 15px;
- padding-bottom: 15px;
- text-align: center;
-}
-
-.infoBox p {
- margin: 0;
-}
-
-.counter, .percent {
- font-size: 120%;
- font-weight: bold;
- margin-bottom: 8px;
-}
-
-#duration {
- width: 125px;
-}
-
-#successRate, .summaryGroup {
- border: solid 2px #d0d0d0;
- -moz-border-radius: 10px;
- border-radius: 10px;
-}
-
-#successRate {
- width: 140px;
- margin-left: 35px;
-}
-
-#successRate .percent {
- font-size: 180%;
-}
-
-.success, .success a {
- color: #008000;
-}
-
-div.success, #successRate.success {
- background-color: #bbd9bb;
- border-color: #008000;
-}
-
-.failures, .failures a {
- color: #b60808;
-}
-
-.skipped, .skipped a {
- color: #c09853;
-}
-
-div.failures, #successRate.failures {
- background-color: #ecdada;
- border-color: #b60808;
-}
-
-ul.linkList {
- padding-left: 0;
-}
-
-ul.linkList li {
- list-style: none;
- margin-bottom: 5px;
-}
diff --git a/build/reports/tests/test/index.html b/build/reports/tests/test/index.html
deleted file mode 100644
index a2a465e..0000000
--- a/build/reports/tests/test/index.html
+++ /dev/null
@@ -1,133 +0,0 @@
-
-
-
-
-
-Test results - Test Summary
-
-
-
-
-
-
-
Test Summary
-
-
-
-
-
-
-
-|
-
- |
-
-
- |
-
-
- |
-
-
- |
-
-
-
- |
-
-
- |
-
-
-
-
-
-
-
Packages
-
-
-
-| Package |
-Tests |
-Failures |
-Ignored |
-Duration |
-Success rate |
-
-
-
-
-|
-org.example.service
- |
-4 |
-0 |
-0 |
-3.620s |
-100% |
-
-
-
-
-
-
-
-
-
-
diff --git a/build/reports/tests/test/js/report.js b/build/reports/tests/test/js/report.js
deleted file mode 100644
index 83bab4a..0000000
--- a/build/reports/tests/test/js/report.js
+++ /dev/null
@@ -1,194 +0,0 @@
-(function (window, document) {
- "use strict";
-
- var tabs = {};
-
- function changeElementClass(element, classValue) {
- if (element.getAttribute("className")) {
- element.setAttribute("className", classValue);
- } else {
- element.setAttribute("class", classValue);
- }
- }
-
- function getClassAttribute(element) {
- if (element.getAttribute("className")) {
- return element.getAttribute("className");
- } else {
- return element.getAttribute("class");
- }
- }
-
- function addClass(element, classValue) {
- changeElementClass(element, getClassAttribute(element) + " " + classValue);
- }
-
- function removeClass(element, classValue) {
- changeElementClass(element, getClassAttribute(element).replace(classValue, ""));
- }
-
- function initTabs() {
- var container = document.getElementById("tabs");
-
- tabs.tabs = findTabs(container);
- tabs.titles = findTitles(tabs.tabs);
- tabs.headers = findHeaders(container);
- tabs.select = select;
- tabs.deselectAll = deselectAll;
- tabs.select(0);
-
- return true;
- }
-
- function getCheckBox() {
- return document.getElementById("line-wrapping-toggle");
- }
-
- function getLabelForCheckBox() {
- return document.getElementById("label-for-line-wrapping-toggle");
- }
-
- function findCodeBlocks() {
- var spans = document.getElementById("tabs").getElementsByTagName("span");
- var codeBlocks = [];
- for (var i = 0; i < spans.length; ++i) {
- if (spans[i].className.indexOf("code") >= 0) {
- codeBlocks.push(spans[i]);
- }
- }
- return codeBlocks;
- }
-
- function forAllCodeBlocks(operation) {
- var codeBlocks = findCodeBlocks();
-
- for (var i = 0; i < codeBlocks.length; ++i) {
- operation(codeBlocks[i], "wrapped");
- }
- }
-
- function toggleLineWrapping() {
- var checkBox = getCheckBox();
-
- if (checkBox.checked) {
- forAllCodeBlocks(addClass);
- } else {
- forAllCodeBlocks(removeClass);
- }
- }
-
- function initControls() {
- if (findCodeBlocks().length > 0) {
- var checkBox = getCheckBox();
- var label = getLabelForCheckBox();
-
- checkBox.onclick = toggleLineWrapping;
- checkBox.checked = false;
-
- removeClass(label, "hidden");
- }
- }
-
- function switchTab() {
- var id = this.id.substr(1);
-
- for (var i = 0; i < tabs.tabs.length; i++) {
- if (tabs.tabs[i].id === id) {
- tabs.select(i);
- break;
- }
- }
-
- return false;
- }
-
- function select(i) {
- this.deselectAll();
-
- changeElementClass(this.tabs[i], "tab selected");
- changeElementClass(this.headers[i], "selected");
-
- while (this.headers[i].firstChild) {
- this.headers[i].removeChild(this.headers[i].firstChild);
- }
-
- var h2 = document.createElement("H2");
-
- h2.appendChild(document.createTextNode(this.titles[i]));
- this.headers[i].appendChild(h2);
- }
-
- function deselectAll() {
- for (var i = 0; i < this.tabs.length; i++) {
- changeElementClass(this.tabs[i], "tab deselected");
- changeElementClass(this.headers[i], "deselected");
-
- while (this.headers[i].firstChild) {
- this.headers[i].removeChild(this.headers[i].firstChild);
- }
-
- var a = document.createElement("A");
-
- a.setAttribute("id", "ltab" + i);
- a.setAttribute("href", "#tab" + i);
- a.onclick = switchTab;
- a.appendChild(document.createTextNode(this.titles[i]));
-
- this.headers[i].appendChild(a);
- }
- }
-
- function findTabs(container) {
- return findChildElements(container, "DIV", "tab");
- }
-
- function findHeaders(container) {
- var owner = findChildElements(container, "UL", "tabLinks");
- return findChildElements(owner[0], "LI", null);
- }
-
- function findTitles(tabs) {
- var titles = [];
-
- for (var i = 0; i < tabs.length; i++) {
- var tab = tabs[i];
- var header = findChildElements(tab, "H2", null)[0];
-
- header.parentNode.removeChild(header);
-
- if (header.innerText) {
- titles.push(header.innerText);
- } else {
- titles.push(header.textContent);
- }
- }
-
- return titles;
- }
-
- function findChildElements(container, name, targetClass) {
- var elements = [];
- var children = container.childNodes;
-
- for (var i = 0; i < children.length; i++) {
- var child = children.item(i);
-
- if (child.nodeType === 1 && child.nodeName === name) {
- if (targetClass && child.className.indexOf(targetClass) < 0) {
- continue;
- }
-
- elements.push(child);
- }
- }
-
- return elements;
- }
-
- // Entry point.
-
- window.onload = function() {
- initTabs();
- initControls();
- };
-} (window, window.document));
\ No newline at end of file
diff --git a/build/reports/tests/test/packages/org.example.service.html b/build/reports/tests/test/packages/org.example.service.html
deleted file mode 100644
index f22e014..0000000
--- a/build/reports/tests/test/packages/org.example.service.html
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
-
-Test results - Package org.example.service
-
-
-
-
-
-
-
Package org.example.service
-
-
all > org.example.service
-
-
-
-
-
-
-
-|
-
- |
-
-
- |
-
-
- |
-
-
- |
-
-
-
- |
-
-
- |
-
-
-
-
-
-
-
Classes
-
-
-
-| Class |
-Tests |
-Failures |
-Ignored |
-Duration |
-Success rate |
-
-
-
-|
-MainServiceTest
- |
-4 |
-0 |
-0 |
-3.620s |
-100% |
-
-
-
-
-
-
-
-
diff --git a/build/test-results/test/TEST-org.example.service.MainServiceTest.xml b/build/test-results/test/TEST-org.example.service.MainServiceTest.xml
deleted file mode 100644
index 79b5ccf..0000000
--- a/build/test-results/test/TEST-org.example.service.MainServiceTest.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
diff --git a/build/test-results/test/binary/output.bin b/build/test-results/test/binary/output.bin
deleted file mode 100644
index e69de29..0000000
diff --git a/build/test-results/test/binary/output.bin.idx b/build/test-results/test/binary/output.bin.idx
deleted file mode 100644
index f76dd23..0000000
Binary files a/build/test-results/test/binary/output.bin.idx and /dev/null differ
diff --git a/build/test-results/test/binary/results.bin b/build/test-results/test/binary/results.bin
deleted file mode 100644
index 7f5e71f..0000000
Binary files a/build/test-results/test/binary/results.bin and /dev/null differ
diff --git a/build/tmp/compileJava/previous-compilation-data.bin b/build/tmp/compileJava/previous-compilation-data.bin
deleted file mode 100644
index 0826bd6..0000000
Binary files a/build/tmp/compileJava/previous-compilation-data.bin and /dev/null differ
diff --git a/build/tmp/compileTestJava/previous-compilation-data.bin b/build/tmp/compileTestJava/previous-compilation-data.bin
deleted file mode 100644
index 19a83b1..0000000
Binary files a/build/tmp/compileTestJava/previous-compilation-data.bin and /dev/null differ
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..c36b192
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,22 @@
+services:
+ app:
+ image: 'docker-spring-boot-postgres:latest'
+ build:
+ context: .
+ container_name: app
+ depends_on:
+ - db
+ environment:
+ - SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/postgres
+ - SPRING_DATASOURCE_USERNAME=postgres
+ - SPRING_DATASOURCE_PASSWORD=123
+ - SPRING_JPA_HIBERNATE_DDL_AUTO=update
+ ports:
+ - 8080:8080
+
+ db:
+ image: 'postgres:16'
+ container_name: db
+ environment:
+ - POSTGRES_USER=postgres
+ - POSTGRES_PASSWORD=123
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
deleted file mode 100644
index 249e583..0000000
Binary files a/gradle/wrapper/gradle-wrapper.jar and /dev/null differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
deleted file mode 100644
index ae04661..0000000
--- a/gradle/wrapper/gradle-wrapper.properties
+++ /dev/null
@@ -1,5 +0,0 @@
-distributionBase=GRADLE_USER_HOME
-distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
-zipStoreBase=GRADLE_USER_HOME
-zipStorePath=wrapper/dists
diff --git a/out/production/LinkShortener/main/java/org/example/Main.class b/out/production/LinkShortener/main/java/org/example/Main.class
deleted file mode 100644
index 460ab32..0000000
Binary files a/out/production/LinkShortener/main/java/org/example/Main.class and /dev/null differ
diff --git a/out/production/LinkShortener/main/java/org/example/database/Database.class b/out/production/LinkShortener/main/java/org/example/database/Database.class
deleted file mode 100644
index effe396..0000000
Binary files a/out/production/LinkShortener/main/java/org/example/database/Database.class and /dev/null differ
diff --git a/out/production/LinkShortener/main/java/org/example/exception/UnknownShortLinkException.class b/out/production/LinkShortener/main/java/org/example/exception/UnknownShortLinkException.class
deleted file mode 100644
index d6f6951..0000000
Binary files a/out/production/LinkShortener/main/java/org/example/exception/UnknownShortLinkException.class and /dev/null differ
diff --git a/out/production/LinkShortener/main/java/org/example/service/MainService.class b/out/production/LinkShortener/main/java/org/example/service/MainService.class
deleted file mode 100644
index 297da95..0000000
Binary files a/out/production/LinkShortener/main/java/org/example/service/MainService.class and /dev/null differ
diff --git a/out/production/LinkShortener/main/java/org/example/service/MainServiceImpl.class b/out/production/LinkShortener/main/java/org/example/service/MainServiceImpl.class
deleted file mode 100644
index 973f7cd..0000000
Binary files a/out/production/LinkShortener/main/java/org/example/service/MainServiceImpl.class and /dev/null differ
diff --git a/src/main/java/org/example/LinkShortenerApplication.java b/src/main/java/org/example/LinkShortenerApplication.java
new file mode 100644
index 0000000..6a3628a
--- /dev/null
+++ b/src/main/java/org/example/LinkShortenerApplication.java
@@ -0,0 +1,11 @@
+package org.example;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class LinkShortenerApplication {
+ public static void main(String... args) {
+ SpringApplication.run(LinkShortenerApplication.class);
+ }
+}
diff --git a/src/main/java/org/example/Main.java b/src/main/java/org/example/Main.java
deleted file mode 100644
index 689f5c0..0000000
--- a/src/main/java/org/example/Main.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package org.example;
-
-
-
-import org.example.exception.UnknownShortLinkException;
-import org.example.service.MainService;
-import org.example.service.MainServiceImpl;
-
-import java.util.Scanner;
-
-import static org.example.service.MainServiceImpl.shortLinksDomain;
-
-public class Main {
- public static Scanner sc = new Scanner(System.in);
- public static MainService service = new MainServiceImpl();
- public static void main(String[] args) {
- while (true) {
- printMenu();
-
- String chosenService = sc.nextLine();
-
- if (chosenService.equals("1")) {
- System.out.println("Введите длинную ссылку");
- String longLink = null;
- while (longLink == null) {
- longLink = readAndValidateLongLink();
- }
- String shortLink = service.getShortLink(longLink);
- System.out.println("Короткая ссылка: " + shortLink);
-
- } else if (chosenService.equals("2")) {
- System.out.println("Введите короткую ссылку:");
- String shortLink = null;
- while (shortLink == null) {
- shortLink = readAndValidateShortLink();
- }
- try {
- String longLink = service.getLongLink(shortLink);
- System.out.println("Длинная ссылка: " + longLink);
- } catch(UnknownShortLinkException ex) {
- System.out.println("Данной короткой ссылке не соответствует никакая длинная");
- }
- } else if (chosenService.equals("3")) {
- return;
- } else {
- System.out.println("Выберите валидный вариант");
- }
- }
- }
-
- private static String readAndValidateLongLink() {
- String link = sc.nextLine();
-
- if (link == null || link.isBlank()) {
- System.out.println("Некорректная ссылка, введите ещё раз");
- return null;
- }
-
- return link;
- }
-
- private static String readAndValidateShortLink() {
- String link = sc.nextLine();
- int len = shortLinksDomain.length();
-
- if (link == null || link.length() < len || !shortLinksDomain.equals(link.substring(0, len))) {
- System.out.println("Короткая ссылка должна начинаться с \"" + shortLinksDomain + "\". Введите ссылку ещё раз");
- return null;
- }
-
- return link;
- }
-
-
- private static void printMenu() {
- System.out.println("""
- Выберите действие:
- 1. Укоротить ссылку
- 2. Восстановить длинную ссылку по короткой
- 3. Выйти
- """);
- }
-
-
-}
\ No newline at end of file
diff --git a/src/main/java/org/example/advice/MyControllerAdvice.java b/src/main/java/org/example/advice/MyControllerAdvice.java
new file mode 100644
index 0000000..a6cfa2f
--- /dev/null
+++ b/src/main/java/org/example/advice/MyControllerAdvice.java
@@ -0,0 +1,34 @@
+package org.example.advice;
+
+import org.example.exception.BadRepositoryFunctionCallException;
+import org.example.exception.IncorrectLongLinkException;
+import org.example.exception.UnknownShortLinkException;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+
+import java.sql.SQLException;
+
+@ControllerAdvice
+public class MyControllerAdvice {
+ @ExceptionHandler(IncorrectLongLinkException.class)
+ public ResponseEntity handleIncorrectLongLink(IncorrectLongLinkException e) {
+ return new ResponseEntity("Incorrect long link", HttpStatus.BAD_REQUEST);
+ }
+
+ @ExceptionHandler(UnknownShortLinkException.class)
+ public ResponseEntity handleUnknownShortLink(UnknownShortLinkException e) {
+ return new ResponseEntity("There is no corresponding long link", HttpStatus.BAD_REQUEST);
+ }
+
+ @ExceptionHandler(BadRepositoryFunctionCallException.class)
+ public ResponseEntity handleBadCall(BadRepositoryFunctionCallException e) {
+ return new ResponseEntity(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+
+ @ExceptionHandler(SQLException.class)
+ public ResponseEntity handleSQLException(SQLException e) {
+ return new ResponseEntity("Internal Server Error", HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+}
diff --git a/src/main/java/org/example/controller/MainController.java b/src/main/java/org/example/controller/MainController.java
new file mode 100644
index 0000000..1181f1a
--- /dev/null
+++ b/src/main/java/org/example/controller/MainController.java
@@ -0,0 +1,38 @@
+package org.example.controller;
+
+import org.example.dao.repository.LinksRepository;
+import org.example.exception.BadRepositoryFunctionCallException;
+import org.example.exception.IncorrectLongLinkException;
+import org.example.exception.UnknownShortLinkException;
+import org.example.service.LinkService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import static org.example.service.LinkServiceImpl.shortLinksDomain;
+
+@RestController
+@RequestMapping("/url")
+public class MainController {
+ private final LinkService linkService;
+ public MainController(LinkService linkService) {
+ this.linkService = linkService;
+ }
+ @PostMapping(value = "/create")
+ public String createShortLink(@RequestBody String longLink)
+ throws IncorrectLongLinkException, BadRepositoryFunctionCallException {
+ if(longLink == null || longLink.isBlank())
+ throw new IncorrectLongLinkException();
+
+ return linkService.getShortLink(longLink);
+ }
+
+ @Autowired
+ private LinksRepository linksRepository;
+
+
+ @GetMapping("/{shortCode}")
+ public String getLongLink(@PathVariable("shortCode") String shortCode)
+ throws UnknownShortLinkException {
+ return linkService.getLongLink(shortLinksDomain + shortCode);
+ }
+}
diff --git a/src/main/java/org/example/dao/entity/LinksEntity.java b/src/main/java/org/example/dao/entity/LinksEntity.java
new file mode 100644
index 0000000..4a7ece2
--- /dev/null
+++ b/src/main/java/org/example/dao/entity/LinksEntity.java
@@ -0,0 +1,35 @@
+package org.example.dao.entity;
+
+import jakarta.persistence.*;
+
+@Entity(name = "links")
+@Table(indexes = @Index(columnList = "LONG_LINK, SHORT_CODE"))
+public class LinksEntity {
+ @Id
+ @Column(length = 5)
+ private String shortCode;
+ @Column(length = 1000)
+ private String longLink;
+
+ public LinksEntity() {}
+ public LinksEntity(String shortCode, String longLink) {
+ this.shortCode = shortCode;
+ this.longLink = longLink;
+ }
+
+ public String getShortCode() {
+ return shortCode;
+ }
+
+ public void setShortCode(String shortCode) {
+ this.shortCode = shortCode;
+ }
+
+ public String getLongLink() {
+ return longLink;
+ }
+
+ public void setLongLink(String longLink) {
+ this.longLink = longLink;
+ }
+}
diff --git a/src/main/java/org/example/dao/repository/LinksRepository.java b/src/main/java/org/example/dao/repository/LinksRepository.java
new file mode 100644
index 0000000..0cebd84
--- /dev/null
+++ b/src/main/java/org/example/dao/repository/LinksRepository.java
@@ -0,0 +1,19 @@
+package org.example.dao.repository;
+
+import org.example.dao.entity.LinksEntity;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface LinksRepository extends JpaRepository {
+ @Query(nativeQuery = true,
+ value = "SELECT LONG_LINK FROM links WHERE SHORT_CODE = :shortCode")
+ List findLongLinksByShortCode(@Param("shortCode") String shortCode);
+ @Query(nativeQuery = true,
+ value = "SELECT SHORT_CODE FROM links WHERE LONG_LINK = :longLink")
+ List findShortCodesByLongLink(@Param("longLink") String longLink);
+}
diff --git a/src/main/java/org/example/database/Database.java b/src/main/java/org/example/database/Database.java
deleted file mode 100644
index 07f4921..0000000
--- a/src/main/java/org/example/database/Database.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package org.example.database;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class Database {
- private static final Database instance = new Database();
- private Database() {}
- public static Database getInstance() {
- return instance;
- }
-
- private final Map shortCodes = new HashMap<>(); // key = long link, value = short code (without domain)
- private final Map longLinks = new HashMap<>(); // key = short code, value = long link
-
- public String getShortCode(String longLink) {
- return shortCodes.get(longLink);
- }
-
- public String getLongLink(String shortCode) {
- return longLinks.get(shortCode);
- }
-
- public boolean containsLongLink(String longLink) {
- return shortCodes.containsKey(longLink);
- }
-
- public boolean containsShortCode(String shortCode) {
- return longLinks.containsKey(shortCode);
- }
-
- public void addPairOfLinks(String longLink, String shortCode) {
- longLinks.put(shortCode, longLink);
- shortCodes.put(longLink, shortCode);
- }
-}
diff --git a/src/main/java/org/example/exception/BadRepositoryFunctionCallException.java b/src/main/java/org/example/exception/BadRepositoryFunctionCallException.java
new file mode 100644
index 0000000..b6fe15d
--- /dev/null
+++ b/src/main/java/org/example/exception/BadRepositoryFunctionCallException.java
@@ -0,0 +1,7 @@
+package org.example.exception;
+
+public class BadRepositoryFunctionCallException extends RuntimeException {
+ public BadRepositoryFunctionCallException() {}
+
+ public BadRepositoryFunctionCallException(String message) {super(message);}
+}
diff --git a/src/main/java/org/example/exception/IncorrectLongLinkException.java b/src/main/java/org/example/exception/IncorrectLongLinkException.java
new file mode 100644
index 0000000..5e1b4a9
--- /dev/null
+++ b/src/main/java/org/example/exception/IncorrectLongLinkException.java
@@ -0,0 +1,12 @@
+package org.example.exception;
+
+public class IncorrectLongLinkException extends RuntimeException {
+
+ public IncorrectLongLinkException() {
+ }
+
+ public IncorrectLongLinkException(String message) {
+ super(message);
+ }
+
+}
diff --git a/src/main/java/org/example/exception/UnknownShortLinkException.java b/src/main/java/org/example/exception/UnknownShortLinkException.java
index 094959f..bc85ac2 100644
--- a/src/main/java/org/example/exception/UnknownShortLinkException.java
+++ b/src/main/java/org/example/exception/UnknownShortLinkException.java
@@ -9,4 +9,4 @@ public UnknownShortLinkException(String message) {
super(message);
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/org/example/service/DBService.java b/src/main/java/org/example/service/DBService.java
new file mode 100644
index 0000000..46d2963
--- /dev/null
+++ b/src/main/java/org/example/service/DBService.java
@@ -0,0 +1,9 @@
+package org.example.service;
+
+public interface DBService {
+ String getShortCodeFromDB(String longLink);
+ String getLongLinkFromDB(String shortCode);
+ boolean containsShortCode(String shortCode);
+ boolean containsLongLink(String longLink);
+ void addPairOfLinks(String longLink, String shortCode);
+}
diff --git a/src/main/java/org/example/service/DBServiceImpl.java b/src/main/java/org/example/service/DBServiceImpl.java
new file mode 100644
index 0000000..68249b0
--- /dev/null
+++ b/src/main/java/org/example/service/DBServiceImpl.java
@@ -0,0 +1,56 @@
+package org.example.service;
+
+import org.example.dao.entity.LinksEntity;
+import org.example.dao.repository.LinksRepository;
+import org.example.exception.BadRepositoryFunctionCallException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class DBServiceImpl implements DBService {
+ @Autowired
+ private final LinksRepository linksRepository;
+
+ public DBServiceImpl(LinksRepository linksRepository) { this.linksRepository = linksRepository; }
+
+ @Override
+ public String getShortCodeFromDB(String longLink) {
+ List shortCodes = linksRepository.findShortCodesByLongLink(longLink);
+
+ if (!shortCodes.isEmpty()) {
+ return shortCodes.get(0);
+ }
+
+ throw new BadRepositoryFunctionCallException("Error: long link is not found");
+ }
+
+ @Override
+ public String getLongLinkFromDB(String shortCode) {
+ List longLinks = linksRepository.findLongLinksByShortCode(shortCode);
+
+ if(!longLinks.isEmpty()) {
+ return longLinks.get(0);
+ }
+
+ throw new BadRepositoryFunctionCallException("Error: short code is not found");
+ }
+
+ @Override
+ public boolean containsShortCode(String shortCode) {
+ List longLinks = linksRepository.findLongLinksByShortCode(shortCode);
+ return !longLinks.isEmpty();
+ }
+
+ @Override
+ public boolean containsLongLink(String longLink) {
+ List shortCodes = linksRepository.findShortCodesByLongLink(longLink);
+ return !shortCodes.isEmpty();
+ }
+
+ @Override
+ public void addPairOfLinks(String longLink, String shortCode) {
+ linksRepository.save(new LinksEntity(shortCode, longLink));
+ }
+}
diff --git a/src/main/java/org/example/service/MainService.java b/src/main/java/org/example/service/LinkService.java
similarity index 86%
rename from src/main/java/org/example/service/MainService.java
rename to src/main/java/org/example/service/LinkService.java
index 2a006ab..7a6651e 100644
--- a/src/main/java/org/example/service/MainService.java
+++ b/src/main/java/org/example/service/LinkService.java
@@ -2,7 +2,7 @@
import org.example.exception.UnknownShortLinkException;
-public interface MainService {
+public interface LinkService {
String getShortLink(String longLink);
String getLongLink(String shortLink) throws UnknownShortLinkException;
}
diff --git a/src/main/java/org/example/service/MainServiceImpl.java b/src/main/java/org/example/service/LinkServiceImpl.java
similarity index 63%
rename from src/main/java/org/example/service/MainServiceImpl.java
rename to src/main/java/org/example/service/LinkServiceImpl.java
index c348207..3fb5387 100644
--- a/src/main/java/org/example/service/MainServiceImpl.java
+++ b/src/main/java/org/example/service/LinkServiceImpl.java
@@ -1,13 +1,19 @@
package org.example.service;
-import org.example.database.Database;
import org.example.exception.UnknownShortLinkException;
+import org.springframework.stereotype.Service;
import java.util.Random;
-public class MainServiceImpl implements MainService {
+@Service
+public class LinkServiceImpl implements LinkService {
public static final int shortLinkLength = 5;
- public static final String shortLinksDomain = "localhost:8080/";
+ public static final String shortLinksDomain = "localhost:8080/url/";
+ private final DBService dbService;
+
+ public LinkServiceImpl(DBService dbService) {
+ this.dbService = dbService;
+ }
char getSymbol(int code) {
if(code < 26)
@@ -18,20 +24,20 @@ else if(code < 52)
}
@Override
public String getShortLink(String longLink) {
- if(Database.getInstance().containsLongLink(longLink))
- return shortLinksDomain + Database.getInstance().getShortCode(longLink);
+ if(dbService.containsLongLink(longLink))
+ return shortLinksDomain + dbService.getShortCodeFromDB(longLink);
String shortLink = null;
Random random = new Random();
- while(shortLink == null || Database.getInstance().containsShortCode(shortLink)) {
+ while(shortLink == null || dbService.containsShortCode(shortLink)) {
shortLink = "";
for(int i = 0; i < shortLinkLength; i++)
shortLink += getSymbol(random.nextInt(62));
}
- Database.getInstance().addPairOfLinks(longLink, shortLink);
+ dbService.addPairOfLinks(longLink, shortLink);
return shortLinksDomain + shortLink;
}
@@ -39,8 +45,8 @@ public String getShortLink(String longLink) {
@Override
public String getLongLink(String shortLink) throws UnknownShortLinkException {
shortLink = shortLink.substring(shortLinksDomain.length(), shortLink.length());
- if(!Database.getInstance().containsShortCode(shortLink))
+ if(!dbService.containsShortCode(shortLink))
throw new UnknownShortLinkException("Короткая ссылка не найдена");
- else return Database.getInstance().getLongLink(shortLink);
+ else return dbService.getLongLinkFromDB(shortLink);
}
}
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
new file mode 100644
index 0000000..dee1170
--- /dev/null
+++ b/src/main/resources/application.yml
@@ -0,0 +1,9 @@
+spring:
+ jpa:
+ hibernate:
+ ddl-auto: update
+ datasource:
+ username: postgres
+ password: 123
+ driverClassName: org.postgresql.Driver
+ url: jdbc:postgresql://localhost:5432/postgres
\ No newline at end of file
diff --git a/src/test/java/org/example/controller/MainControllerTest.java b/src/test/java/org/example/controller/MainControllerTest.java
new file mode 100644
index 0000000..c58bb43
--- /dev/null
+++ b/src/test/java/org/example/controller/MainControllerTest.java
@@ -0,0 +1,103 @@
+package org.example.controller;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
+import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.MvcResult;
+
+import java.util.HashMap;
+import java.util.Random;
+
+import static org.example.service.LinkServiceImpl.shortLinkLength;
+import static org.example.service.LinkServiceImpl.shortLinksDomain;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+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.result.MockMvcResultMatchers.status;
+
+@SpringBootTest
+@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.ANY)
+@AutoConfigureMockMvc
+public class MainControllerTest {
+ @Autowired
+ private MockMvc mockMvc;
+ private Random random = new Random();
+
+ @Test
+ void testGetShortLink() throws Exception {
+ String longLink = "";
+
+ for(int i = 0; i < 10; i++)
+ longLink += (char)random.nextInt('a', 'z' + 1);
+
+ MvcResult mvcResult = mockMvc.perform(post("/url/create").content(longLink))
+ .andExpect(status().isOk()).andReturn();
+
+ String shortLink = mvcResult.getResponse().getContentAsString();
+
+ mvcResult = mockMvc.perform(post("/url/create").content(longLink))
+ .andExpect(status().isOk()).andReturn();
+
+ String shortLink2 = mvcResult.getResponse().getContentAsString();
+
+ assert(shortLink.length() == shortLinksDomain.length() + shortLinkLength);
+ assertEquals(shortLink.substring(0, shortLinksDomain.length()), shortLinksDomain);
+ assertEquals(shortLink, shortLink2);
+ }
+
+ @Test
+ void testGetLongLink() throws Exception {
+ String longLink = "";
+
+ for(int i = 0; i < 10; i++)
+ longLink += (char)random.nextInt('a', 'z' + 1);
+
+ MvcResult mvcResult = mockMvc.perform(post("/url/create").content(longLink))
+ .andExpect(status().isOk()).andReturn();
+
+ String shortLink = mvcResult.getResponse().getContentAsString();
+
+ mvcResult = mockMvc.perform(get("/url" + shortLink.substring(shortLinksDomain.length() - 1, shortLink.length())))
+ .andExpect(status().isOk()).andReturn();
+
+ String longLink2 = mvcResult.getResponse().getContentAsString();
+ assertEquals(longLink, longLink2);
+ }
+
+ @Test
+ void testUniqueness() throws Exception {
+ int N = 100000;
+ HashMap map = new HashMap<>();
+
+ for(int i = 0; i < N; i++)
+ {
+ String longLink = "";
+
+ for(int j = 0; j < 3; j++)
+ longLink += (char)random.nextInt('a', 'z' + 1);
+
+ longLink += Integer.toString(i);
+
+ MvcResult mvcResult = mockMvc.perform(post("/url/create").content(longLink))
+ .andExpect(status().isOk()).andReturn();
+
+ String shortLink = mvcResult.getResponse().getContentAsString();
+ map.put(shortLink, i);
+ }
+
+ assertEquals(map.size(), N);
+ }
+
+ @Test
+ void testLinkNotFound() throws Exception {
+
+ MvcResult mvcResult = mockMvc.perform(get("/url/a"))
+ .andExpect(status().isBadRequest()).andReturn();
+
+ String longLink = mvcResult.getResponse().getContentAsString();
+ assertEquals(longLink, "There is no corresponding long link");
+ }
+}
diff --git a/src/test/java/org/example/service/MainServiceTest.java b/src/test/java/org/example/service/MainServiceTest.java
deleted file mode 100644
index f442a1a..0000000
--- a/src/test/java/org/example/service/MainServiceTest.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package org.example.service;
-
-import org.example.exception.UnknownShortLinkException;
-import org.junit.jupiter.api.Test;
-
-import java.util.HashMap;
-
-import static org.example.service.MainServiceImpl.shortLinkLength;
-import static org.example.service.MainServiceImpl.shortLinksDomain;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-public class MainServiceTest {
- private final MainService service = new MainServiceImpl();
-
- @Test
- void testGetShortLink() throws Exception {
- //given:
- String longLink = "www.example.com";
- //when:
- String shortLink = service.getShortLink(longLink);
- String shortLink2 = service.getShortLink(longLink);
- //then:
- assert(shortLink.length() == shortLinksDomain.length() + shortLinkLength);
- assertEquals(shortLink.substring(0, shortLinksDomain.length()), shortLinksDomain);
- assertEquals(shortLink, shortLink2);
- }
-
- @Test
- void testGetLongLink() throws Exception {
- //given:
- String longLink = "www.example.com";
- //when:
- String shortLink = service.getShortLink(longLink);
- String longLink2 = service.getLongLink(shortLink);
- //then:
- assertEquals(longLink, longLink2);
- }
-
- @Test
- void testUniqueness() throws Exception {
- //given:
- int N = 1000000;
- HashMap map = new HashMap<>();
- //when:
- for(int i = 0; i < N; i++)
- {
- String shortLink = service.getShortLink(Integer.toString(i));
- map.put(shortLink, i);
- }
- //then:
- assertEquals(map.size(), N);
- }
-
- @Test
- void testException() throws Exception {
- //given:
- String shortLink = shortLinksDomain;
- //when:
- boolean exceptionThrown = false;
- try {
- String longLink = service.getLongLink(shortLink);
- } catch (UnknownShortLinkException e) {
- exceptionThrown = true;
- }
-
- assert(exceptionThrown);
- }
-}