Skip to content

Commit

Permalink
Development: Fix exercise deletion with existing Iris messages (#9875)
Browse files Browse the repository at this point in the history
  • Loading branch information
kaancayli authored Dec 3, 2024
1 parent 36adbf6 commit 05646bf
Show file tree
Hide file tree
Showing 3 changed files with 158 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8"?>

<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
<changeSet id="20241125000900" author="kaancayli">
<preConditions onFail="MARK_RAN">
<!-- Check if the foreign keys exists before modifying -->
<foreignKeyConstraintExists foreignKeyName="fk_iris_message_session_id"/>
<foreignKeyConstraintExists foreignKeyName="fk_iris_message_content_message_id"/>
<foreignKeyConstraintExists foreignKeyName="fk_text_id_to_content_id"/>
<foreignKeyConstraintExists foreignKeyName="fk_json_id_to_content_id"/>
</preConditions>

<!-- Drop the existing foreign keys -->
<dropForeignKeyConstraint
baseTableName="iris_message"
constraintName="fk_iris_message_session_id"/>

<dropForeignKeyConstraint
baseTableName="iris_message_content"
constraintName="fk_iris_message_content_message_id"/>

<dropForeignKeyConstraint
baseTableName="iris_json_message_content"
constraintName="fk_json_id_to_content_id"/>

<dropForeignKeyConstraint
baseTableName="iris_text_message_content"
constraintName="fk_text_id_to_content_id"/>

<!-- Add the foreign keys back with ON DELETE CASCADE -->
<addForeignKeyConstraint
baseTableName="iris_message"
baseColumnNames="session_id"
referencedTableName="iris_session"
referencedColumnNames="id"
constraintName="fk_iris_message_session_id"
onDelete="CASCADE"/>

<addForeignKeyConstraint
baseTableName="iris_message_content"
baseColumnNames="message_id"
constraintName="fk_iris_message_content_message_id"
referencedTableName="iris_message"
referencedColumnNames="id"
onDelete="CASCADE"/>

<addForeignKeyConstraint
baseColumnNames="id"
baseTableName="iris_text_message_content"
constraintName="fk_text_id_to_content_id"
referencedColumnNames="id"
referencedTableName="iris_message_content"
onDelete="CASCADE"/>

<addForeignKeyConstraint
baseColumnNames="id"
baseTableName="iris_json_message_content"
constraintName="fk_json_id_to_content_id"
referencedColumnNames="id"
referencedTableName="iris_message_content"
onDelete="CASCADE"/>

</changeSet>
</databaseChangeLog>
1 change: 1 addition & 0 deletions src/main/resources/config/liquibase/master.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
<include file="classpath:config/liquibase/changelog/20241101121000_changelog.xml" relativeToChangelogFile="false"/>
<include file="classpath:config/liquibase/changelog/20241105150000_changelog.xml" relativeToChangelogFile="false"/>
<include file="classpath:config/liquibase/changelog/20241112123600_changelog.xml" relativeToChangelogFile="false"/>
<include file="classpath:config/liquibase/changelog/20241125000900_changelog.xml" relativeToChangelogFile="false"/>

<!-- NOTE: please use the format "YYYYMMDDhhmmss_changelog.xml", i.e. year month day hour minutes seconds and not something else! -->
<!-- we should also stay in a chronological order! -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,30 @@
import static org.assertj.core.api.Assertions.assertThat;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ThreadLocalRandom;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.test.context.support.WithMockUser;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import de.tum.cit.aet.artemis.core.domain.Course;
import de.tum.cit.aet.artemis.iris.domain.message.IrisJsonMessageContent;
import de.tum.cit.aet.artemis.iris.domain.message.IrisMessage;
import de.tum.cit.aet.artemis.iris.domain.message.IrisMessageContent;
import de.tum.cit.aet.artemis.iris.domain.message.IrisMessageSender;
import de.tum.cit.aet.artemis.iris.domain.message.IrisTextMessageContent;
import de.tum.cit.aet.artemis.iris.domain.session.IrisExerciseChatSession;
import de.tum.cit.aet.artemis.iris.domain.session.IrisSession;
import de.tum.cit.aet.artemis.iris.dto.IrisStatusDTO;
import de.tum.cit.aet.artemis.iris.repository.IrisExerciseChatSessionRepository;
import de.tum.cit.aet.artemis.iris.repository.IrisMessageRepository;
import de.tum.cit.aet.artemis.iris.service.IrisMessageService;
import de.tum.cit.aet.artemis.programming.domain.ProgrammingExercise;

class IrisExerciseChatSessionIntegrationTest extends AbstractIrisIntegrationTest {
Expand All @@ -24,6 +36,12 @@ class IrisExerciseChatSessionIntegrationTest extends AbstractIrisIntegrationTest
@Autowired
private IrisExerciseChatSessionRepository irisExerciseChatSessionRepository;

@Autowired
private IrisMessageService irisMessageService;

@Autowired
private IrisMessageRepository irisMessageRepository;

private ProgrammingExercise exercise;

@BeforeEach
Expand All @@ -37,6 +55,41 @@ void initTestCase() {
activateIrisFor(exercise);
}

private IrisExerciseChatSession createSessionForUser(String userLogin) {
var user = userUtilService.getUserByLogin(TEST_PREFIX + userLogin);
return irisExerciseChatSessionRepository.save(new IrisExerciseChatSession(exercise, user));
}

private IrisMessage createDefaultMockTextMessage(IrisSession irisSession) {
var messageToSend = irisSession.newMessage();
messageToSend.addContent(createMockTextContent(), createMockTextContent(), createMockTextContent());
return messageToSend;
}

private IrisMessageContent createMockTextContent() {
String[] adjectives = { "happy", "sad", "angry", "funny", "silly", "crazy", "beautiful", "smart" };
String[] nouns = { "dog", "cat", "house", "car", "book", "computer", "phone", "shoe" };

var rdm = ThreadLocalRandom.current();
String randomAdjective = adjectives[rdm.nextInt(adjectives.length)];
String randomNoun = nouns[rdm.nextInt(nouns.length)];

var text = "The " + randomAdjective + " " + randomNoun + " jumped over the lazy dog.";
return new IrisTextMessageContent(text);
}

private IrisMessage createDefaultMockJsonMessage(IrisSession irisSession) {
var messageToSend = irisSession.newMessage();
messageToSend.addContent(createMockJsonContent(), createMockJsonContent(), createMockJsonContent());
return messageToSend;
}

private IrisJsonMessageContent createMockJsonContent() {
var jsonMap = Map.of("key1", "value1", "key2", "value2", "key3", "value3");
JsonNode jsonNode = new ObjectMapper().valueToTree(jsonMap);
return new IrisJsonMessageContent(jsonNode);
}

@Test
@WithMockUser(username = TEST_PREFIX + "student1", roles = "USER")
void createSession() throws Exception {
Expand Down Expand Up @@ -101,6 +154,44 @@ void testDeleteExerciseWithIrisSession() throws Exception {
assertThat(irisExerciseChatSessionRepository.findById(irisSession.getId())).isEmpty();
}

@Test
@WithMockUser(username = TEST_PREFIX + "instructor1", roles = "INSTRUCTOR")
void testDeleteExerciseWithIrisMessagesWithTextMessageContent() throws Exception {
var irisSession = createSessionForUser("instructor1");

// Create and some messages to the session
irisMessageService.saveMessage(createDefaultMockTextMessage(irisSession), irisSession, IrisMessageSender.USER);
irisMessageService.saveMessage(createDefaultMockTextMessage(irisSession), irisSession, IrisMessageSender.LLM);
irisMessageService.saveMessage(createDefaultMockTextMessage(irisSession), irisSession, IrisMessageSender.USER);
irisMessageService.saveMessage(createDefaultMockTextMessage(irisSession), irisSession, IrisMessageSender.LLM);

assertThat(irisExerciseChatSessionRepository.findByIdElseThrow(irisSession.getId())).isNotNull();
// Set the URL request parameters to prevent an internal server error which is irrelevant for this test
var url = "/api/programming-exercises/" + exercise.getId() + "?deleteStudentReposBuildPlans=false&deleteBaseReposBuildPlans=false";
request.delete(url, HttpStatus.OK);
assertThat(irisExerciseChatSessionRepository.findById(irisSession.getId())).isEmpty();
assertThat(irisMessageRepository.findAllBySessionId(irisSession.getId())).isEmpty();
}

@Test
@WithMockUser(username = TEST_PREFIX + "instructor1", roles = "INSTRUCTOR")
void testDeleteExerciseWithIrisMessagesWithJsonMessageContent() throws Exception {
var irisSession = createSessionForUser("instructor1");

// Create and some messages to the session
irisMessageService.saveMessage(createDefaultMockJsonMessage(irisSession), irisSession, IrisMessageSender.USER);
irisMessageService.saveMessage(createDefaultMockJsonMessage(irisSession), irisSession, IrisMessageSender.LLM);
irisMessageService.saveMessage(createDefaultMockJsonMessage(irisSession), irisSession, IrisMessageSender.USER);
irisMessageService.saveMessage(createDefaultMockJsonMessage(irisSession), irisSession, IrisMessageSender.LLM);

assertThat(irisExerciseChatSessionRepository.findByIdElseThrow(irisSession.getId())).isNotNull();
// Set the URL request parameters to prevent an internal server error which is irrelevant for this test
var url = "/api/programming-exercises/" + exercise.getId() + "?deleteStudentReposBuildPlans=false&deleteBaseReposBuildPlans=false";
request.delete(url, HttpStatus.OK);
assertThat(irisExerciseChatSessionRepository.findById(irisSession.getId())).isEmpty();
assertThat(irisMessageRepository.findAllBySessionId(irisSession.getId())).isEmpty();
}

private static String exerciseChatUrl(long sessionId) {
return "/api/iris/exercise-chat/" + sessionId + "/sessions";
}
Expand Down

0 comments on commit 05646bf

Please sign in to comment.