Skip to content

Commit

Permalink
Grafana etc. init set up + refactors
Browse files Browse the repository at this point in the history
  • Loading branch information
sdikyarts committed May 25, 2024
1 parent b0d5d5e commit 2fe028f
Show file tree
Hide file tree
Showing 10 changed files with 230 additions and 11 deletions.
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ on:
push:
branches:
- main
- staging

jobs:
build:
Expand Down
75 changes: 75 additions & 0 deletions .github/workflows/sonarcloud.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
name: SonarCloud

on:
push:
branches:
- staging
- main
pull_request:
types: [opened, synchronize, reopened]

jobs:
build:
name: Build, analyze, and test
runs-on: ubuntu-latest

services:
postgres:
image: postgres:latest
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready -U postgres"
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: subscription-admin

steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
distribution: "temurin"
java-version: "21"
cache: "gradle"
- name: Cache SonarCloud packages
uses: actions/cache@v3
with:
path: ~/.sonar/cache
key: ${{ runner.os }}-sonar
restore-keys: ${{ runner.os }}-sonar
- name: Cache Gradle packages
uses: actions/cache@v3
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
restore-keys: ${{ runner.os }}-gradle
- name: Wait for PostgreSQL
run: |
for i in {1..30}; do
if pg_isready -h localhost -p 5432 -U postgres; then
echo "PostgreSQL is up and running"
break
fi
echo "Waiting for PostgreSQL..."
sleep 1
done
if ! pg_isready -h localhost -p 5432 -U postgres; then
echo "PostgreSQL failed to start" && exit 1
fi
- name: Build and analyze
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SPRING_DATASOURCE_URL: jdbc:postgresql://localhost:5432/subscription-admin
SPRING_DATASOURCE_USERNAME: postgres
SPRING_DATASOURCE_PASSWORD: postgres
run: |
chmod +x ./gradlew
./gradlew build jacocoTestReport sonarqube --info
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
HELP.md
.env
.gradle
build/
!gradle/wrapper/gradle-wrapper.jar
Expand Down
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ dependencies {
testImplementation("org.junit.jupiter:junit-jupiter-engine:$junitJupiterVersion")
runtimeOnly("io.micrometer:micrometer-registry-prometheus:1.12.5")
implementation("org.springframework.boot:spring-boot-starter-actuator:3.2.5")
implementation("me.paulschwarz:spring-dotenv:4.0.0")
}

tasks.register<Test>("unitTest") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ public AdminController(AdminService adminService) {
this.adminService = adminService;
}

@GetMapping("")
public ResponseEntity<String> home() {
return ResponseEntity.ok("Snackscription - Admin Subscription Management API");
}

@PostMapping("/create")
public CompletableFuture<ResponseEntity<AdminSubscription>> create(@RequestBody AdminDTO adminDTO) {
return adminService.create(adminDTO).thenApply(ResponseEntity::ok)
Expand Down Expand Up @@ -50,7 +55,12 @@ public CompletableFuture<ResponseEntity<AdminSubscription>> update(@RequestBody
return CompletableFuture.completedFuture(ResponseEntity.badRequest().build());
}

return adminService.update(adminDTO).thenApply(ResponseEntity::ok)
CompletableFuture<AdminSubscription> updatedSubscription = adminService.update(adminDTO);
if(updatedSubscription == null) {
return CompletableFuture.completedFuture(ResponseEntity.notFound().build());
}

return updatedSubscription.thenApply(ResponseEntity::ok)
.exceptionally(ex -> ResponseEntity.notFound().build());
}

Expand All @@ -61,7 +71,11 @@ public CompletableFuture<ResponseEntity<String>> delete(@PathVariable String sub
} catch (IllegalArgumentException e) {
return CompletableFuture.completedFuture(ResponseEntity.badRequest().build());
}
return adminService.delete(subscriptionId).thenApply(deleted -> ResponseEntity.ok("DELETE SUCCESS"))
.exceptionally(ex -> ResponseEntity.notFound().build());
try {
return adminService.delete(subscriptionId).thenApply(deleted -> ResponseEntity.ok("DELETE SUCCESS"))
.exceptionally(ex -> ResponseEntity.notFound().build());
} catch (IllegalArgumentException e) {
return CompletableFuture.completedFuture(ResponseEntity.notFound().build());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ public class AdminServiceImpl implements AdminService{
@Override
@Async
public CompletableFuture<AdminSubscription> create(AdminDTO adminDTO) {
if (adminDTO == null || adminDTO.getSubscriptionId() == null) {
throw new IllegalArgumentException("AdminDTO cannot be null and must have a valid subscriptionId");
}
AdminSubscription adminSubscription = DTOMapper.convertDTOtoModel(adminDTO);
return CompletableFuture.completedFuture(adminRepository.create(adminSubscription));
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/application.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
spring.application.name=subscription-admin
spring.profiles.active=${PRODUCTION:dev}
spring.profiles.active=${PRODUCTION:prod}
management.endpoints.web.exposure.include=*
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package snackscription.subscriptionadmin.config;

import org.junit.jupiter.api.Test;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;


class AsyncConfigTest {

@Test
void testAsyncExecutor() {

AsyncConfiguration asyncConfiguration = new AsyncConfiguration();

AsyncTaskExecutor executor = asyncConfiguration.getAsyncExecutor();

assertNotNull(executor);

assertEquals(5, ((ThreadPoolTaskExecutor) executor).getCorePoolSize());
assertEquals(10, ((ThreadPoolTaskExecutor) executor).getMaxPoolSize());
assertEquals(100, ((ThreadPoolTaskExecutor) executor).getQueueCapacity());
assertEquals("Async-Executor-", ((ThreadPoolTaskExecutor) executor).getThreadNamePrefix());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@

import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.UUID;
import java.util.concurrent.*;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
Expand Down Expand Up @@ -49,6 +49,13 @@ void setUp(){
adminSubscription.setSubscriptionStatus("PENDING");
}

@Test
void testHome(){
ResponseEntity<String> response = adminController.home();
assertNotNull(response);
assertEquals(ResponseEntity.ok("Snackscription - Admin Subscription Management API"), response);
}

@Test
void testCreate(){
when(adminService.create(adminDTO)).thenReturn(CompletableFuture.completedFuture(adminSubscription));
Expand Down Expand Up @@ -100,4 +107,51 @@ void testDelete(){
assertNotNull(response);
assertEquals(ResponseEntity.ok("DELETE SUCCESS"), response.join());
}

@Test
void testUpdateInvalidSubscriptionId(){
AdminDTO adminDTO = new AdminDTO();

CompletableFuture<ResponseEntity<AdminSubscription>> expectedResponse = CompletableFuture.completedFuture(ResponseEntity.badRequest().build());
CompletableFuture<ResponseEntity<AdminSubscription>> response = adminController.update(adminDTO);

assertTrue(response.isDone());
assertEquals(expectedResponse.join(), response.join());
}

@Test
void testUpdateNonexistentSubscription(){
AdminDTO adminDTO = new AdminDTO();
adminDTO.setSubscriptionId(UUID.randomUUID().toString());
CompletableFuture<ResponseEntity<AdminSubscription>> expectedResponse = CompletableFuture.completedFuture(ResponseEntity.notFound().build());

when(adminService.findById(adminDTO.getSubscriptionId())).thenReturn(CompletableFuture.completedFuture(null));

CompletableFuture<ResponseEntity<AdminSubscription>> response = adminController.update(adminDTO);

assertTrue(response.isDone());
assertEquals(expectedResponse.join(), response.join());
}

@Test
void testDeleteInvalidSubscriptionId(){
CompletableFuture<ResponseEntity<String>> expectedResponse = CompletableFuture.completedFuture(ResponseEntity.badRequest().build());
CompletableFuture<ResponseEntity<String>> response = adminController.delete("invalid-id");

assertTrue(response.isDone());
assertEquals(expectedResponse.join(), response.join());
}

@Test
void testDeleteNonexistentSubscription(){
String validUUID = UUID.randomUUID().toString();
CompletableFuture<ResponseEntity<String>> expectedResponse = CompletableFuture.completedFuture(ResponseEntity.notFound().build());

when(adminService.delete(validUUID)).thenThrow(new IllegalArgumentException("Subscription not found"));

CompletableFuture<ResponseEntity<String>> response = adminController.delete(validUUID);

assertTrue(response.isDone());
assertEquals(expectedResponse.join(), response.join());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.ResponseEntity;
import snackscription.subscriptionadmin.controller.AdminController;
import snackscription.subscriptionadmin.dto.AdminDTO;
import snackscription.subscriptionadmin.factory.AdminSubscriptionFactory;
import snackscription.subscriptionadmin.model.AdminSubscription;
Expand All @@ -28,14 +26,13 @@ public class AdminServiceImplTest {
private AdminRepository adminRepository;

@Mock
private AdminSubscriptionFactory adminSubscriptionFactory;
private AdminDTO adminDTO;

@InjectMocks
private AdminServiceImpl adminService;
private AdminController adminController;

@Mock
private AdminSubscription adminSubscription;
private AdminDTO adminDTO;

@BeforeEach
void setUp() {
Expand Down Expand Up @@ -117,4 +114,50 @@ void testDelete() {
assertTrue(result.isDone());
assertNull(result.join());
}

@Test
void findByIdNullOrEmpty() {
assertThrows(IllegalArgumentException.class, () -> {
adminService.findById(null).join();
adminService.findById("").join();
});
}

@Test
void updateNull() {
assertThrows(IllegalArgumentException.class, () -> adminService.update(null).join());
}

@Test
void updateNonExistent() {
assertThrows(IllegalArgumentException.class, () -> {
when(adminRepository.findById(adminDTO.getSubscriptionId())).thenReturn(Optional.empty());
adminService.update(adminDTO).join();
});
}

@Test
void deleteNullOrEmpty() {
assertThrows(IllegalArgumentException.class, () -> {
adminService.delete(null).join();
adminService.delete("").join();
});
}

@Test
void deleteNonExistent() {
assertThrows(IllegalArgumentException.class, () -> {
String id = "non-existent-id";
when(adminRepository.findById(id)).thenReturn(Optional.empty());
adminService.delete(id).join();
});
}

@Test
void createInvalid() {
assertThrows(IllegalArgumentException.class, () -> {
AdminDTO invalidDTO = new AdminDTO();
adminService.create(invalidDTO).join();
});
}
}

0 comments on commit 2fe028f

Please sign in to comment.