diff --git a/pom.xml b/pom.xml
index d5e071f..d7d5242 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,96 +1,181 @@
-
-
- 4.0.0
-
- org.springframework.boot
- spring-boot-starter-parent
- 3.0.6
-
-
- com.medeiros
- SPRINGProject
- 0.0.1-SNAPSHOT
- SPRINGProject
- Demo project for Spring Boot
-
- 20
-
- 6.0.3
-
-
-
- org.springframework.boot
- spring-boot-starter-data-jpa
-
-
- org.springframework.boot
- spring-boot-starter-web
-
-
-
- org.springframework.boot
- spring-boot-devtools
- runtime
- true
-
-
- com.mysql
- mysql-connector-j
- runtime
-
-
- org.springframework.boot
- spring-boot-starter-test
- test
-
-
-
- org.springframework.boot
- spring-boot-starter-thymeleaf
- 3.0.6
-
-
-
- org.springframework.boot
- spring-boot-starter-security
-
-
-
- io.jsonwebtoken
- jjwt-api
- 0.11.5
-
-
-
-
-
-
- org.springframework.security
- spring-security-core
- 6.0.3
-
-
-
-
-
-
- io.jsonwebtoken
- jjwt-impl
- 0.11.5
- runtime
-
-
-
-
-
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
-
-
-
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.0.6
+
+
+
+ com.medeiros
+ SPRINGProject
+ 0.0.1-SNAPSHOT
+ SPRINGProject
+ Demo project for Spring Boot
+
+ 20
+
+ 6.0.3
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ runtime
+ true
+
+
+ com.mysql
+ mysql-connector-j
+ runtime
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.springframework.boot
+ spring-boot-starter-thymeleaf
+ 3.0.6
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+
+ io.jsonwebtoken
+ jjwt-api
+ 0.11.5
+
+
+
+ org.springframework.security
+ spring-security-core
+ 6.0.3
+
+
+
+
+ io.jsonwebtoken
+ jjwt-impl
+ 0.11.5
+ runtime
+
+
+ org.mockito
+ mockito-junit-jupiter
+ 2.23.4
+ test
+
+
+
+ io.spring.javaformat
+ spring-javaformat-formatter
+ 0.0.40
+
+
+
+ io.jsonwebtoken
+ jjwt-jackson
+ 0.11.5
+ runtime
+
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ 5.9.2
+ test
+
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ 5.9.2
+ test
+
+
+
+ org.mockito
+ mockito-core
+ 5.2.0
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ org.jacoco
+ jacoco-maven-plugin
+ 0.8.11
+
+
+
+ prepare-agent
+
+
+
+ report
+ test
+
+ report
+
+
+ coverageReport
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.2.5
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-report-plugin
+ 3.2.5
+
+ testReport
+
+
+
+
+ org.apache.maven.plugins
+ maven-site-plugin
+ 2.1
+
+ testReport
+
+
+
+
+ io.spring.javaformat
+ spring-javaformat-maven-plugin
+ 0.0.40
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/java/com/medeiros/SPRINGProject/Controllers/UserAccountControllerUpdateUserByIdTest.java b/src/test/java/com/medeiros/SPRINGProject/Controllers/UserAccountControllerUpdateUserByIdTest.java
new file mode 100644
index 0000000..e8e010c
--- /dev/null
+++ b/src/test/java/com/medeiros/SPRINGProject/Controllers/UserAccountControllerUpdateUserByIdTest.java
@@ -0,0 +1,246 @@
+
+// ********RoostGPT********
+/*
+Test generated by RoostGPT for test java-music using AI Type Claude AI and AI Model claude-3-7-sonnet-20250219
+
+ROOST_METHOD_HASH=updateUserById_45a90e9627
+ROOST_METHOD_SIG_HASH=updateUserById_9cf5a84c94
+
+[
+ {
+ "vulnerability": "CWE-798: Use of Hard-coded Credentials",
+ "issue": "The method accepts a password as a plain text parameter and stores it directly in the database without any encryption or hashing, exposing sensitive authentication data.",
+ "solution": "Implement password hashing using a strong algorithm like BCrypt before storing passwords. Use Spring Security's PasswordEncoder: `@Autowired private PasswordEncoder passwordEncoder;` and then `userExist.setPassword(passwordEncoder.encode(password));`"
+ },
+ {
+ "vulnerability": "CWE-20: Improper Input Validation",
+ "issue": "The method directly parses the ID string to integer without proper validation, which could lead to NumberFormatException if non-numeric input is provided.",
+ "solution": "Add try-catch block for parsing or use validation annotations: `try { int intID = Integer.parseInt(id); } catch (NumberFormatException e) { return \"Invalid ID format\"; }`"
+ },
+ {
+ "vulnerability": "CWE-352: Cross-Site Request Forgery (CSRF)",
+ "issue": "The method appears to be modifying data but doesn't implement CSRF protection, making it vulnerable to CSRF attacks.",
+ "solution": "Enable CSRF protection in Spring Security configuration and use @CrossOrigin with specific origins: `@CrossOrigin(origins = \"https://trusted-domain.com\", allowCredentials = \"true\")`"
+ },
+ {
+ "vulnerability": "CWE-284: Improper Access Control",
+ "issue": "The method doesn't verify if the requester has permission to update the user, allowing anyone to modify any user's data if they know the ID.",
+ "solution": "Implement authentication and authorization checks: `@PreAuthorize(\"hasRole('ADMIN') or #id == authentication.principal.id\")` and use Spring Security to enforce these permissions."
+ },
+ {
+ "vulnerability": "CWE-233: Improper Handling of Parameters",
+ "issue": "The method accepts all parameters as required without validation for null, empty values, or proper format (e.g., email validation).",
+ "solution": "Add input validation: `if (email == null || !email.matches(\"^[\\\\w-\\\\.]+@([\\\\w-]+\\\\.)+[\\\\w-]{2,4}$\")) { return \"Invalid email format\"; }`"
+ },
+ {
+ "vulnerability": "CWE-209: Information Exposure Through Error Messages",
+ "issue": "The method returns simple string messages that might expose internal information about the existence of users in the system.",
+ "solution": "Use standardized response objects with appropriate HTTP status codes: `return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ErrorResponse(\"User not found\"));`"
+ },
+ {
+ "vulnerability": "CWE-732: Incorrect Permission Assignment for Critical Resource",
+ "issue": "The method is likely public but missing proper annotations to define its HTTP method and security constraints.",
+ "solution": "Add proper annotations: `@PutMapping(\"/users\") @PreAuthorize(\"isAuthenticated()\") public ResponseEntity> updateUserById(...)`"
+ }
+]
+,1bc64f0c-859b-4a7a-827b-0292c9789534Scenario 1: Successfully Update Existing User
+
+Details:
+ TestName: successfullyUpdateExistingUser
+ Description: Verify that the method correctly updates an existing user's credentials and returns a success message.
+
+Execution:
+ Arrange:
+ - Mock UserAccRepository to return a valid User_Credentials object when findById is called with a valid ID
+ - Create a User_Credentials object with initial values
+ - Prepare new values for email, password, and username
+
+ Act:
+ - Call updateUserById with valid ID and new credential values
+
+ Assert:
+ - Verify that the returned message is "Usuário Salvo"
+ - Verify that UserAccRepository.save was called with the updated User_Credentials object
+ - Verify that the User_Credentials object was updated with the new values
+
+Validation:
+ This test confirms that the method correctly updates user credentials when a valid user ID is provided. It ensures that the repository's save method is called with the updated user object and that the appropriate success message is returned.
+
+*/
+
+// ********RoostGPT********
+
+package com.medeiros.SPRINGProject.Controllers;
+
+import com.medeiros.SPRINGProject.Models.*;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.*;
+import org.junit.jupiter.api.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import java.time.LocalDateTime;
+import java.util.Objects;
+import java.util.Optional;
+
+@ExtendWith(MockitoExtension.class)
+public class UserAccountControllerUpdateUserByIdTest {
+
+ @Mock
+ private UserAccRepository UserAccRepo;
+
+ @Mock
+ private UserInfoRepository UserInfoRepo;
+
+ @Mock
+ private LogRepository Log;
+
+ @InjectMocks
+ private UserAccountController userAccountController;
+
+ private User_Credentials testUser;
+
+ @BeforeEach
+ void setUp() {
+ testUser = new User_Credentials();
+ testUser.setId(1);
+ testUser.setEmail("old@example.com");
+ testUser.setPassword("oldPassword");
+ testUser.setUsername("oldUsername");
+ }
+
+ @Test
+ @Tag("valid")
+ void successfullyUpdateExistingUser() {
+ // Arrange
+ String id = "1";
+ String newEmail = "new@example.com";
+ String newPassword = "newPassword";
+ String newUsername = "newUsername";
+
+ when(UserAccRepo.findById(1)).thenReturn(testUser);
+
+ // Act
+ String result = userAccountController.updateUserById(id, newEmail, newPassword, newUsername);
+
+ // Assert
+ assertEquals("Usuário Salvo", result);
+ assertEquals(newEmail, testUser.getEmail());
+ assertEquals(newPassword, testUser.getPassword());
+ assertEquals(newUsername, testUser.getUsername());
+ verify(UserAccRepo).save(testUser);
+ }
+
+ @Test
+ @Tag("invalid")
+ void userNotFoundReturnsErrorMessage() {
+ // Arrange
+ String id = "999";
+ String email = "test@example.com";
+ String password = "password";
+ String username = "username";
+
+ when(UserAccRepo.findById(999)).thenReturn(null);
+
+ // Act
+ String result = userAccountController.updateUserById(id, email, password, username);
+
+ // Assert
+ assertEquals("User não encontrado", result);
+ verify(UserAccRepo, never()).save(any());
+ }
+
+ @Test
+ @Tag("invalid")
+ void invalidIdFormatThrowsException() {
+ // Arrange
+ String id = "invalid";
+ String email = "test@example.com";
+ String password = "password";
+ String username = "username";
+
+ // Act & Assert
+ try {
+ userAccountController.updateUserById(id, email, password, username);
+ }
+ catch (NumberFormatException e) {
+ // Expected exception
+ verify(UserAccRepo, never()).findById(anyInt());
+ verify(UserAccRepo, never()).save(any());
+ }
+ }
+
+ @Test
+ @Tag("boundary")
+ void updateUserWithEmptyFields() {
+ // Arrange
+ String id = "1";
+ String emptyEmail = "";
+ String emptyPassword = "";
+ String emptyUsername = "";
+
+ when(UserAccRepo.findById(1)).thenReturn(testUser);
+
+ // Act
+ String result = userAccountController.updateUserById(id, emptyEmail, emptyPassword, emptyUsername);
+
+ // Assert
+ assertEquals("Usuário Salvo", result);
+ assertEquals(emptyEmail, testUser.getEmail());
+ assertEquals(emptyPassword, testUser.getPassword());
+ assertEquals(emptyUsername, testUser.getUsername());
+ verify(UserAccRepo).save(testUser);
+ }
+
+ @Test
+ @Tag("boundary")
+ void updateUserWithMaxIntegerId() {
+ // Arrange
+ String id = String.valueOf(Integer.MAX_VALUE);
+ String email = "test@example.com";
+ String password = "password";
+ String username = "username";
+
+ User_Credentials maxIdUser = new User_Credentials();
+ maxIdUser.setId(Integer.MAX_VALUE);
+
+ when(UserAccRepo.findById(Integer.MAX_VALUE)).thenReturn(maxIdUser);
+
+ // Act
+ String result = userAccountController.updateUserById(id, email, password, username);
+
+ // Assert
+ assertEquals("Usuário Salvo", result);
+ verify(UserAccRepo).save(any(User_Credentials.class));
+ }
+
+ @Test
+ @Tag("integration")
+ void updateUserIntegrationTest() {
+ // Arrange
+ String id = "1";
+ String newEmail = "integration@example.com";
+ String newPassword = "integrationPassword";
+ String newUsername = "integrationUser";
+
+ when(UserAccRepo.findById(1)).thenReturn(testUser);
+
+ // Act
+ String result = userAccountController.updateUserById(id, newEmail, newPassword, newUsername);
+
+ // Assert
+ assertEquals("Usuário Salvo", result);
+ assertEquals(newEmail, testUser.getEmail());
+ assertEquals(newPassword, testUser.getPassword());
+ assertEquals(newUsername, testUser.getUsername());
+ verify(UserAccRepo).save(testUser);
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/java/com/medeiros/SPRINGProject/algorithm/AlgorithmBlenderAlgorithmCalcTest.java b/src/test/java/com/medeiros/SPRINGProject/algorithm/AlgorithmBlenderAlgorithmCalcTest.java
new file mode 100644
index 0000000..0734bf0
--- /dev/null
+++ b/src/test/java/com/medeiros/SPRINGProject/algorithm/AlgorithmBlenderAlgorithmCalcTest.java
@@ -0,0 +1,264 @@
+
+// ********RoostGPT********
+/*
+Test generated by RoostGPT for test java-music using AI Type Claude AI and AI Model claude-3-7-sonnet-20250219
+
+ROOST_METHOD_HASH=algorithmCalc_e489e5c1fc
+ROOST_METHOD_SIG_HASH=algorithmCalc_009085eae1
+
+[
+ {
+ "vulnerability": "CWE-470: Use of Externally-Controlled Input to Select Classes or Code ('Unsafe Reflection')",
+ "issue": "The 'AD' class is used without proper import or definition, which could lead to runtime errors or potential security issues if it's dynamically loaded or accessed through reflection.",
+ "solution": "Properly import the AD class or define it within the scope. Ensure all class references are properly defined and avoid using reflection to load classes based on external input."
+ },
+ {
+ "vulnerability": "CWE-798: Use of Hard-coded Credentials",
+ "issue": "While not explicitly shown in the code, the algorithm calculation might be using hard-coded values or credentials in the AD class methods.",
+ "solution": "Ensure no credentials or sensitive configuration values are hard-coded. Use proper configuration management and secure credential storage."
+ },
+ {
+ "vulnerability": "CWE-400: Uncontrolled Resource Consumption",
+ "issue": "The code iterates through 'listMusics' without any bounds checking, which could lead to resource exhaustion if the collection is very large.",
+ "solution": "Implement pagination or limit the size of data being processed at once. Consider using stream processing for large datasets."
+ },
+ {
+ "vulnerability": "CWE-209: Information Exposure Through Error Messages",
+ "issue": "No exception handling is implemented, which might lead to detailed stack traces being exposed if an error occurs.",
+ "solution": "Implement proper exception handling with appropriate logging that doesn't expose sensitive information to end users."
+ },
+ {
+ "vulnerability": "CWE-502: Deserialization of Untrusted Data",
+ "issue": "If MusicModel objects come from deserialized data (not shown in the code), there could be risks associated with untrusted input.",
+ "solution": "Validate all input data before processing. If deserializing objects, use secure deserialization practices or consider alternatives like JSON with explicit parsing."
+ },
+ {
+ "vulnerability": "CWE-664: Improper Control of a Resource Through its Lifetime",
+ "issue": "The method creates a HashMap but doesn't specify an initial capacity, which could lead to multiple rehashing operations if the dataset is large.",
+ "solution": "Initialize the HashMap with an appropriate capacity if the size of listMusics is known or can be estimated."
+ }
+]
+,cf13c61b-5f96-499c-8202-8e2ccfafecf8Scenario 1: Calculate Points for a Single Music Item
+
+Details:
+ TestName: calculatePointsForSingleMusic
+ Description: Verify that the algorithmCalc method correctly calculates and stores rhythm points for a single music item based on its likes and comments.
+
+Execution:
+ Arrange:
+ - Create a mock MusicModel with a known number of likes, comments, and music name
+ - Set up the expected behavior for AD.rithmPointsByLike() and AD.rithmPointsByComents() methods
+ - Create a list containing only this single music item
+
+ Act:
+ - Call the algorithmCalc method with the created list
+
+ Assert:
+ - Verify that the returned HashMap contains exactly one entry
+ - Verify that the key matches the music name
+ - Verify that the value matches the expected sum of like points and comment points
+
+Validation:
+ This test confirms that the basic calculation logic works correctly for a single item. It ensures that the method properly retrieves likes and comments from the music model, calculates points using the algorithm data methods, and stores the result with the correct music name as the key.
+
+*/
+
+// ********RoostGPT********
+
+package com.medeiros.SPRINGProject.algorithm;
+
+import com.medeiros.SPRINGProject.Models.MusicModel;
+import com.medeiros.SPRINGProject.utils.hashMapFunctions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+import org.junit.jupiter.api.*;
+
+@ExtendWith(MockitoExtension.class)
+public class AlgorithmBlenderAlgorithmCalcTest {
+
+ private algorithmBlender algorithmBlender;
+
+ @Mock
+ private algorithmData mockAD;
+
+ @Mock
+ private MusicModel mockMusic;
+
+ @BeforeEach
+ void setUp() {
+ algorithmBlender = new algorithmBlender();
+ // Using reflection to set the mocked algorithmData
+ try {
+ java.lang.reflect.Field field = algorithmBlender.getClass().getDeclaredField("AD");
+ field.setAccessible(true);
+ field.set(algorithmBlender, mockAD);
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Test
+ @Tag("valid")
+ void calculatePointsForSingleMusic() {
+ // Arrange
+ when(mockMusic.getNumberOfLikes()).thenReturn(10);
+ when(mockMusic.getNumberOfComents()).thenReturn(5);
+ when(mockMusic.getMusicName()).thenReturn("Test Song");
+
+ when(mockAD.rithmPointsByLike(10)).thenReturn(100);
+ when(mockAD.rithmPointsByComents(5)).thenReturn(75);
+
+ List musicList = new ArrayList<>();
+ musicList.add(mockMusic);
+
+ // Act
+ Map result = algorithmBlender.algorithmCalc(musicList);
+
+ // Assert
+ assertEquals(1, result.size());
+ assertTrue(result.containsKey("Test Song"));
+ assertEquals(175, result.get("Test Song"));
+
+ verify(mockMusic).getNumberOfLikes();
+ verify(mockMusic).getNumberOfComents();
+ verify(mockMusic).getMusicName();
+ verify(mockAD).rithmPointsByLike(10);
+ verify(mockAD).rithmPointsByComents(5);
+ }
+
+ @Test
+ @Tag("valid")
+ void calculatePointsForMultipleMusics() {
+ // Arrange
+ MusicModel music1 = mock(MusicModel.class);
+ MusicModel music2 = mock(MusicModel.class);
+
+ when(music1.getNumberOfLikes()).thenReturn(10);
+ when(music1.getNumberOfComents()).thenReturn(5);
+ when(music1.getMusicName()).thenReturn("Song 1");
+
+ when(music2.getNumberOfLikes()).thenReturn(20);
+ when(music2.getNumberOfComents()).thenReturn(10);
+ when(music2.getMusicName()).thenReturn("Song 2");
+
+ when(mockAD.rithmPointsByLike(10)).thenReturn(100);
+ when(mockAD.rithmPointsByComents(5)).thenReturn(75);
+ when(mockAD.rithmPointsByLike(20)).thenReturn(200);
+ when(mockAD.rithmPointsByComents(10)).thenReturn(150);
+
+ List musicList = new ArrayList<>();
+ musicList.add(music1);
+ musicList.add(music2);
+
+ // Act
+ Map result = algorithmBlender.algorithmCalc(musicList);
+
+ // Assert
+ assertEquals(2, result.size());
+ assertEquals(175, result.get("Song 1"));
+ assertEquals(350, result.get("Song 2"));
+ }
+
+ @Test
+ @Tag("boundary")
+ void calculatePointsForEmptyList() {
+ // Arrange
+ List emptyList = new ArrayList<>();
+
+ // Act
+ Map result = algorithmBlender.algorithmCalc(emptyList);
+
+ // Assert
+ assertNotNull(result);
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ @Tag("boundary")
+ void calculatePointsForZeroLikesAndComments() {
+ // Arrange
+ when(mockMusic.getNumberOfLikes()).thenReturn(0);
+ when(mockMusic.getNumberOfComents()).thenReturn(0);
+ when(mockMusic.getMusicName()).thenReturn("Zero Engagement Song");
+
+ when(mockAD.rithmPointsByLike(0)).thenReturn(0);
+ when(mockAD.rithmPointsByComents(0)).thenReturn(0);
+
+ List musicList = new ArrayList<>();
+ musicList.add(mockMusic);
+
+ // Act
+ Map result = algorithmBlender.algorithmCalc(musicList);
+
+ // Assert
+ assertEquals(1, result.size());
+ assertEquals(0, result.get("Zero Engagement Song"));
+ }
+
+ @Test
+ @Tag("valid")
+ void calculatePointsForDuplicateMusicNames() {
+ // Arrange
+ MusicModel music1 = mock(MusicModel.class);
+ MusicModel music2 = mock(MusicModel.class);
+
+ when(music1.getNumberOfLikes()).thenReturn(10);
+ when(music1.getNumberOfComents()).thenReturn(5);
+ when(music1.getMusicName()).thenReturn("Same Song Name");
+
+ when(music2.getNumberOfLikes()).thenReturn(20);
+ when(music2.getNumberOfComents()).thenReturn(10);
+ when(music2.getMusicName()).thenReturn("Same Song Name");
+
+ when(mockAD.rithmPointsByLike(10)).thenReturn(100);
+ when(mockAD.rithmPointsByComents(5)).thenReturn(75);
+ when(mockAD.rithmPointsByLike(20)).thenReturn(200);
+ when(mockAD.rithmPointsByComents(10)).thenReturn(150);
+
+ List musicList = new ArrayList<>();
+ musicList.add(music1);
+ musicList.add(music2);
+
+ // Act
+ Map result = algorithmBlender.algorithmCalc(musicList);
+
+ // Assert
+ assertEquals(1, result.size());
+ assertEquals(350, result.get("Same Song Name"));
+ }
+
+ @Test
+ @Tag("boundary")
+ void calculatePointsForNegativeLikesAndComments() {
+ // Arrange
+ when(mockMusic.getNumberOfLikes()).thenReturn(-5);
+ when(mockMusic.getNumberOfComents()).thenReturn(-3);
+ when(mockMusic.getMusicName()).thenReturn("Negative Engagement Song");
+
+ when(mockAD.rithmPointsByLike(-5)).thenReturn(-50);
+ when(mockAD.rithmPointsByComents(-3)).thenReturn(-45);
+
+ List musicList = new ArrayList<>();
+ musicList.add(mockMusic);
+
+ // Act
+ Map result = algorithmBlender.algorithmCalc(musicList);
+
+ // Assert
+ assertEquals(1, result.size());
+ assertEquals(-95, result.get("Negative Engagement Song"));
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/java/com/medeiros/SPRINGProject/utils/HashMapFunctionsOrdenarHashMapPorValorTest.java b/src/test/java/com/medeiros/SPRINGProject/utils/HashMapFunctionsOrdenarHashMapPorValorTest.java
new file mode 100644
index 0000000..0ac8393
--- /dev/null
+++ b/src/test/java/com/medeiros/SPRINGProject/utils/HashMapFunctionsOrdenarHashMapPorValorTest.java
@@ -0,0 +1,187 @@
+
+// ********RoostGPT********
+/*
+Test generated by RoostGPT for test java-music using AI Type Claude AI and AI Model claude-3-7-sonnet-20250219
+
+ROOST_METHOD_HASH=ordenarHashMapPorValor_29e282f5b3
+ROOST_METHOD_SIG_HASH=ordenarHashMapPorValor_afd4884fe1
+
+[
+ {
+ "vulnerability": "method declaration error",
+ "issue": "The method is declared as static directly in the class body without being inside a class method. This will cause a compilation error and the code won't execute.",
+ "solution": "Move the static method inside a class or make it a non-static method of the class."
+ },
+ {
+ "vulnerability": "unchecked type safety",
+ "issue": "The code uses raw types for LinkedList constructor which can lead to type safety issues at runtime.",
+ "solution": "Use the diamond operator to ensure proper generic type inference: new LinkedList<>(hashMap.entrySet());"
+ },
+ {
+ "vulnerability": "inefficient collection usage",
+ "issue": "Creating a LinkedList just for sorting operations is less efficient than using ArrayList which provides better random access performance.",
+ "solution": "Use ArrayList instead: List> list = new ArrayList<>(hashMap.entrySet());"
+ },
+ {
+ "vulnerability": "null pointer dereference",
+ "issue": "The code doesn't check if the input hashMap is null before operating on it, which could lead to NullPointerException.",
+ "solution": "Add null check at the beginning of the method: if (hashMap == null) return new LinkedHashMap<>();"
+ },
+ {
+ "vulnerability": "potential autoboxing overhead",
+ "issue": "The compareTo method causes autoboxing/unboxing which can impact performance with large datasets.",
+ "solution": "Use primitive comparison: return Integer.compare(o2.getValue(), o1.getValue());"
+ }
+]
+,382d8766-c84a-4f1b-922b-2bd045a02f57Scenario 1: Sort HashMap with Multiple Entries in Descending Order
+
+Details:
+ TestName: sortHashMapWithMultipleEntriesInDescendingOrder
+ Description: Verify that the method correctly sorts a HashMap with multiple entries in descending order based on their integer values.
+
+Execution:
+ Arrange: Create a HashMap with multiple key-value pairs with different integer values.
+ Act: Call the ordenarHashMapPorValor method with the created HashMap.
+ Assert: Verify that the returned HashMap has entries sorted in descending order by their values.
+
+Validation:
+ The test confirms that the method properly sorts HashMap entries by their integer values in descending order. This is the core functionality of the method and ensures that higher values appear first in the sorted result.
+
+*/
+
+// ********RoostGPT********
+
+package com.medeiros.SPRINGProject.utils;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import static org.junit.jupiter.api.Assertions.*;
+import org.junit.jupiter.api.*;
+import java.util.*;
+
+class HashMapFunctionsOrdenarHashMapPorValorTest {
+
+ @Test
+ @DisplayName("Sort HashMap with Multiple Entries in Descending Order")
+ @Tag("valid")
+ void sortHashMapWithMultipleEntriesInDescendingOrder() {
+ // Arrange
+ HashMap unsortedMap = new HashMap<>();
+ unsortedMap.put("apple", 50);
+ unsortedMap.put("banana", 30);
+ unsortedMap.put("cherry", 70);
+ unsortedMap.put("date", 10);
+ unsortedMap.put("elderberry", 90);
+ // Act
+ HashMap sortedMap = hashMapFunctions.ordenarHashMapPorValor(unsortedMap);
+ // Assert
+ int previousValue = Integer.MAX_VALUE;
+ for (Map.Entry entry : sortedMap.entrySet()) {
+ assertTrue(entry.getValue() <= previousValue, "Values should be in descending order");
+ previousValue = entry.getValue();
+ }
+ // Additional verification - check first and last entries
+ assertEquals(90, sortedMap.values().toArray()[0], "First value should be 90");
+ assertEquals(10, sortedMap.values().toArray()[sortedMap.size() - 1], "Last value should be 10");
+ }
+
+ @Test
+ @DisplayName("Sort Empty HashMap")
+ @Tag("boundary")
+ void sortEmptyHashMap() {
+ // Arrange
+ HashMap emptyMap = new HashMap<>();
+ // Act
+ HashMap result = hashMapFunctions.ordenarHashMapPorValor(emptyMap);
+ // Assert
+ assertTrue(result.isEmpty(), "Result should be empty");
+ assertNotNull(result, "Result should not be null");
+ }
+
+ @Test
+ @DisplayName("Sort HashMap with Single Entry")
+ @Tag("boundary")
+ void sortHashMapWithSingleEntry() {
+ // Arrange
+ HashMap singleEntryMap = new HashMap<>();
+ singleEntryMap.put("key1", 100);
+ // Act
+ HashMap result = hashMapFunctions.ordenarHashMapPorValor(singleEntryMap);
+ // Assert
+ assertEquals(1, result.size(), "Result should have one entry");
+ assertEquals(100, result.get("key1"), "Value should be preserved");
+ }
+
+ @Test
+ @DisplayName("Sort HashMap with Duplicate Values")
+ @Tag("valid")
+ void sortHashMapWithDuplicateValues() {
+ // Arrange
+ HashMap mapWithDuplicates = new HashMap<>();
+ mapWithDuplicates.put("item1", 50);
+ mapWithDuplicates.put("item2", 30);
+ mapWithDuplicates.put("item3", 50);
+ mapWithDuplicates.put("item4", 30);
+ mapWithDuplicates.put("item5", 10);
+ // Act
+ HashMap result = hashMapFunctions.ordenarHashMapPorValor(mapWithDuplicates);
+ // Assert
+ int previousValue = Integer.MAX_VALUE;
+ for (Integer value : result.values()) {
+ assertTrue(value <= previousValue, "Values should be in descending order");
+ previousValue = value;
+ }
+
+ assertEquals(5, result.size(), "Result should maintain all entries");
+ }
+
+ @Test
+ @DisplayName("Sort HashMap with Negative Values")
+ @Tag("valid")
+ void sortHashMapWithNegativeValues() {
+ // Arrange
+ HashMap mapWithNegatives = new HashMap<>();
+ mapWithNegatives.put("a", -10);
+ mapWithNegatives.put("b", 20);
+ mapWithNegatives.put("c", -30);
+ mapWithNegatives.put("d", 0);
+ mapWithNegatives.put("e", 5);
+ // Act
+ HashMap result = hashMapFunctions.ordenarHashMapPorValor(mapWithNegatives);
+ // Assert
+ int previousValue = Integer.MAX_VALUE;
+ for (Integer value : result.values()) {
+ assertTrue(value <= previousValue, "Values should be in descending order");
+ previousValue = value;
+ }
+
+ // Check first and last values
+ assertEquals(20, result.values().toArray()[0], "First value should be 20");
+ assertEquals(-30, result.values().toArray()[result.size() - 1], "Last value should be -30");
+ }
+
+ @Test
+ @DisplayName("Verify Result is LinkedHashMap for Order Preservation")
+ @Tag("valid")
+ void verifyResultIsLinkedHashMapForOrderPreservation() {
+ // Arrange
+ HashMap map = new HashMap<>();
+ map.put("one", 1);
+ map.put("two", 2);
+ map.put("three", 3);
+ // Act
+ HashMap result = hashMapFunctions.ordenarHashMapPorValor(map);
+ // Assert
+ assertTrue(result instanceof LinkedHashMap, "Result should be a LinkedHashMap to preserve order");
+
+ // Verify order is maintained by iterating
+ Integer[] expectedValues = { 3, 2, 1 };
+ Integer[] actualValues = result.values().toArray(new Integer[0]);
+ assertArrayEquals(expectedValues, actualValues, "Values should be in descending order");
+ }
+
+}
\ No newline at end of file