Skip to content
Open
Show file tree
Hide file tree
Changes from 97 commits
Commits
Show all changes
133 commits
Select commit Hold shift + click to select a range
c06832d
converted athena endpoints to return filemaps
ekayandan Sep 4, 2025
2e196a4
Merge branch 'develop' into chore/convert-athena-endpoints-to-filemap
ekayandan Sep 4, 2025
9d00023
Merge remote-tracking branch 'origin' into chore/convert-athena-endpo…
ekayandan Sep 5, 2025
73c8a7d
Merge branch 'chore/convert-athena-endpoints-to-filemap' of github.co…
ekayandan Sep 5, 2025
707637e
improvements on performance and tests
ekayandan Sep 5, 2025
0356671
Merge branch 'develop' into chore/convert-athena-endpoints-to-filemap
ekayandan Sep 5, 2025
6a0d3f2
added missing docstring
ekayandan Sep 5, 2025
0767f61
Merge branch 'chore/convert-athena-endpoints-to-filemap' of github.co…
ekayandan Sep 5, 2025
f5f5a87
Merge branch 'develop' into chore/convert-athena-endpoints-to-filemap
ekayandan Sep 6, 2025
d2dc5f1
Merge branch 'develop' into chore/convert-athena-endpoints-to-filemap
ekayandan Sep 6, 2025
e218bd7
Merge branch 'develop' into chore/convert-athena-endpoints-to-filemap
ekayandan Sep 6, 2025
b5beb91
review comments
ekayandan Sep 8, 2025
51c8cca
Adapt tests and lint
ekayandan Sep 8, 2025
42dfaa4
Merge branch 'develop' into chore/convert-athena-endpoints-to-filemap
ekayandan Sep 10, 2025
0eecf38
Merge branch 'develop' into chore/convert-athena-endpoints-to-filemap
ekayandan Sep 15, 2025
1da53b5
Enhancement: Add feedback suggestion module validation in Athena serv…
ekayandan Sep 15, 2025
3eb6dde
Merge branch 'develop' into chore/convert-athena-endpoints-to-filemap
ekayandan Sep 15, 2025
f12077f
Merge remote-tracking branch 'origin' into chore/convert-athena-endpo…
ekayandan Sep 15, 2025
6fa9b85
Merge branch 'chore/convert-athena-endpoints-to-filemap' of github.co…
ekayandan Sep 15, 2025
e437a1d
removed one of the last 2 GitRepositoryExportService mocks
ekayandan Sep 16, 2025
3c0d266
Merge branch 'chore/convert-athena-endpoints-to-filemap' into chore/p…
ekayandan Sep 17, 2025
4f00aeb
Merge remote-tracking branch 'origin' into chore/programming-exercise…
ekayandan Sep 17, 2025
28483ea
fixed other tests failing
ekayandan Sep 17, 2025
7945c00
Merge branch 'develop' into chore/programming-exercises/improve-expor…
ekayandan Sep 17, 2025
c1b326f
Merge branch 'develop' into chore/convert-athena-endpoints-to-filemap
ekayandan Sep 25, 2025
c366f1e
Merge branch 'develop' into chore/convert-athena-endpoints-to-filemap
ekayandan Sep 29, 2025
7e33edc
review comments
ekayandan Sep 29, 2025
1de24ff
fixed server test
ekayandan Sep 29, 2025
d5ba771
Merge branch 'chore/convert-athena-endpoints-to-filemap' of github.co…
ekayandan Sep 29, 2025
4127676
converted var to type
ekayandan Sep 30, 2025
ae9ee78
Merge branch 'develop' into chore/convert-athena-endpoints-to-filemap
ekayandan Sep 30, 2025
457508b
fixed tests & applied some of the comments
ekayandan Oct 1, 2025
9bbfc4b
Merge branch 'chore/convert-athena-endpoints-to-filemap' of github.co…
ekayandan Oct 1, 2025
2e13784
remaining review comments
ekayandan Oct 1, 2025
ded36b3
changed naming to avoid confusions
ekayandan Oct 1, 2025
99efbf8
Update src/main/webapp/i18n/de/error.json
ekayandan Oct 3, 2025
52b19d2
Merge branch 'develop' into chore/convert-athena-endpoints-to-filemap
ekayandan Oct 3, 2025
f3f0c35
Merge branch 'develop' into chore/convert-athena-endpoints-to-filemap
ekayandan Oct 4, 2025
2911656
Merge remote-tracking branch 'origin/develop' into chore/convert-athe…
ekayandan Oct 20, 2025
8c0ee2c
Merge branch 'chore/convert-athena-endpoints-to-filemap' of github.co…
ekayandan Oct 20, 2025
87ffab9
added even more client tests
ekayandan Oct 21, 2025
23b7eee
fixed test compile
ekayandan Oct 21, 2025
323374c
Merge remote-tracking branch 'origin/develop' into chore/convert-athe…
ekayandan Oct 21, 2025
efa540c
added server tests for athena
ekayandan Oct 21, 2025
e1c9444
fixed failing test
ekayandan Oct 22, 2025
dbc0913
Merge branch 'develop' into chore/convert-athena-endpoints-to-filemap
ekayandan Oct 22, 2025
df17fae
Merge remote-tracking branch 'origin/develop' into chore/convert-athe…
ekayandan Oct 23, 2025
8d31d0b
Added extra guardrails and test cases
ekayandan Oct 23, 2025
742197c
added missing javadoc
ekayandan Oct 23, 2025
ceb168d
Merge branch 'develop' into chore/convert-athena-endpoints-to-filemap
ekayandan Oct 23, 2025
6e4f64e
Merge branch 'develop' into chore/convert-athena-endpoints-to-filemap
maximiliansoelch Oct 29, 2025
7cf6802
Merge branch 'develop' into chore/convert-athena-endpoints-to-filemap
ekayandan Oct 30, 2025
c0e91e5
Merge branch 'develop' into chore/convert-athena-endpoints-to-filemap
ekayandan Oct 31, 2025
83638d2
pr comments + fixed error keys
ekayandan Oct 31, 2025
4fd765f
Merge branch 'chore/convert-athena-endpoints-to-filemap' of github.co…
ekayandan Oct 31, 2025
4e4f5d2
Merge branch 'develop' into chore/convert-athena-endpoints-to-filemap
ekayandan Oct 31, 2025
464345f
Adapted tests for correct error keys
ekayandan Nov 1, 2025
33e85e6
Merge branch 'chore/convert-athena-endpoints-to-filemap' of github.co…
ekayandan Nov 1, 2025
c02029f
Merge branch 'develop' into chore/programming-exercises/improve-expor…
ekayandan Nov 1, 2025
6ba1957
resolved merge conflicts
ekayandan Nov 3, 2025
9cb68e7
resolved merge conflicts
ekayandan Nov 3, 2025
0d7ffe7
Merge branch 'develop' into chore/convert-athena-endpoints-to-filemap
ekayandan Nov 4, 2025
82c3228
Merge branch 'develop' into chore/convert-athena-endpoints-to-filemap
ekayandan Nov 4, 2025
5a78006
Merge branch 'chore/convert-athena-endpoints-to-filemap' into chore/p…
ekayandan Nov 4, 2025
e176532
resolved merge conflicts
ekayandan Nov 4, 2025
cfee00a
added missing positive case
ekayandan Nov 5, 2025
0d81396
Created central export test util class and adapted suites using actua…
ekayandan Nov 6, 2025
a020143
converted ProgrammingExerciseGitIntegrationTest
ekayandan Nov 6, 2025
a495d44
converted some more
ekayandan Nov 8, 2025
4efbb43
conversion progressing
ekayandan Nov 8, 2025
c89b3e0
Merge develop
ekayandan Nov 8, 2025
e6db107
Converted auxiliary repo
ekayandan Nov 8, 2025
fa37d23
cleaned up code
ekayandan Nov 8, 2025
14486ea
Converted remaining from exerciseIntegration
ekayandan Nov 9, 2025
ace53f5
Merge remote-tracking branch 'origin/develop' into chore/programming-…
ekayandan Nov 9, 2025
95b7bd5
Fixed failing tests after merge develop
ekayandan Nov 9, 2025
4ccc8bf
Clean Auxiliary Tests
ekayandan Nov 9, 2025
2d3f429
cleaned ProgrammingExerciseIntegrationTestService
ekayandan Nov 9, 2025
2e00db0
removed gitservice mocks
ekayandan Nov 9, 2025
34f9707
Cleaned first(easier, but bigger) half of gitservice mock residues
ekayandan Nov 10, 2025
e5d9630
removing residues continued
ekayandan Nov 10, 2025
685b843
removed more mocks
ekayandan Nov 10, 2025
b2d3473
2 more batches to go
ekayandan Nov 11, 2025
431c075
Removed all mock related code. All passing
ekayandan Nov 11, 2025
c40ec2e
removed some more optional ones
ekayandan Nov 11, 2025
4ddeadd
fix some failing tests after merge
ekayandan Nov 12, 2025
ae24c88
Merge branch 'develop' into chore/programming-exercises/improve-expor…
ekayandan Nov 12, 2025
5753e41
Adapted RepositoryExportTestUtil
ekayandan Nov 13, 2025
3505f6f
Last mocks removed. Remaining are necessary
ekayandan Nov 13, 2025
120e9a9
centralize functionality
ekayandan Nov 13, 2025
db58d3c
move conversions and expansion of util class
ekayandan Nov 14, 2025
848138f
Merge branch 'chore/programming-exercises/improve-export-tests' of gi…
ekayandan Nov 14, 2025
1cc5e86
linte
ekayandan Nov 14, 2025
40ce916
removed last mocks
ekayandan Nov 15, 2025
906ed8e
introducing centralized auto cleaner
ekayandan Nov 16, 2025
47e8641
converted all classes to use repository tracker
ekayandan Nov 16, 2025
970f7bc
Merge branch 'develop' into chore/programming-exercises/improve-expor…
ekayandan Nov 16, 2025
1336f73
update disable reason
ekayandan Nov 16, 2025
7310288
small comments
ekayandan Nov 16, 2025
e91a7bf
reverted temporary main repo changes
ekayandan Nov 16, 2025
d5931de
Merge branch 'develop' into chore/programming-exercises/improve-expor…
MaximilianAnzinger Nov 26, 2025
90ead74
fix spy bean
MaximilianAnzinger Dec 1, 2025
97a1923
Merge branch 'develop' into chore/programming-exercises/improve-expor…
MaximilianAnzinger Dec 1, 2025
3367410
reset mocks
MaximilianAnzinger Dec 1, 2025
dad3d8d
Fix export tests by dynamically assigning available ports
MarcosOlivaKaczmarek Dec 2, 2025
f7c7591
Enhance integration tests by injecting local server port for URI cons…
MarcosOlivaKaczmarek Dec 2, 2025
568834a
Fix Tests again
MarcosOlivaKaczmarek Dec 2, 2025
34810fb
Fix LocalVCIntegration test
MarcosOlivaKaczmarek Dec 2, 2025
c694745
Fix topic listeners
MarcosOlivaKaczmarek Dec 2, 2025
0baabaf
Merge remote-tracking branch 'origin/chore/programming-exercises/impr…
MarcosOlivaKaczmarek Dec 2, 2025
b2bacf2
Fix testExportSubmissionAnonymization
MarcosOlivaKaczmarek Dec 2, 2025
c1251fe
Fix remaining tests
MarcosOlivaKaczmarek Dec 2, 2025
7e706e0
Refix listener
MarcosOlivaKaczmarek Dec 2, 2025
b5d4b34
Fix early repo closing in PEIJLVCTest
MarcosOlivaKaczmarek Dec 2, 2025
78321a8
Revert previous commit
MarcosOlivaKaczmarek Dec 2, 2025
214f036
Fix last test
MarcosOlivaKaczmarek Dec 2, 2025
83d828a
Cleanup repos
MarcosOlivaKaczmarek Dec 3, 2025
71cdb43
Merge branch 'develop' into chore/programming-exercises/improve-expor…
MarcosOlivaKaczmarek Dec 3, 2025
71bd5fe
Adress CodeRabbit Comments
MarcosOlivaKaczmarek Dec 3, 2025
40afc55
Merge branch 'develop' into chore/programming-exercises/improve-expor…
MarcosOlivaKaczmarek Dec 5, 2025
41b9861
Cleanup repos
MarcosOlivaKaczmarek Dec 3, 2025
438c76d
Merge remote-tracking branch 'origin/chore/programming-exercises/impr…
MarcosOlivaKaczmarek Dec 8, 2025
d876f85
Merge branch 'develop' into chore/programming-exercises/improve-expor…
MarcosOlivaKaczmarek Dec 8, 2025
63bf31b
Fix flaky tests
MarcosOlivaKaczmarek Dec 8, 2025
5daa873
Cleanup After Tests
MarcosOlivaKaczmarek Dec 8, 2025
226fcc2
Cleanup before test execution
MarcosOlivaKaczmarek Dec 8, 2025
9b52091
Remove excesive cleanup
MarcosOlivaKaczmarek Dec 8, 2025
681892b
Fix Plagiarism tests
MarcosOlivaKaczmarek Dec 8, 2025
d629803
Make cleanup happen in the right order
MarcosOlivaKaczmarek Dec 8, 2025
c064081
Avoid duplicate repo creation
MarcosOlivaKaczmarek Dec 8, 2025
1a33499
Revert "Avoid duplicate repo creation"
MarcosOlivaKaczmarek Dec 8, 2025
aa2f571
"Revert last commit
MarcosOlivaKaczmarek Dec 8, 2025
f6ba134
Validate participation exists in plagiarism check test
MarcosOlivaKaczmarek Dec 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -263,17 +263,14 @@ private void validateAthenaEnabled(long exerciseId) {
}

/**
* GET public/programming-exercises/:exerciseId/submissions/:submissionId/repository : Get the repository as a zip file download
* GET public/programming-exercises/:exerciseId/submissions/:submissionId/repository : Deprecated, forwards to internal endpoint
*
* @param exerciseId the id of the exercise the submission belongs to
* @param submissionId the id of the submission to get the repository for
* @param auth the auth header value to check
* @param request the HTTP request
* @param response the HTTP response
* @throws ServletException if the forward fails
* @deprecated Use {@code api/athena/internal/programming-exercises/{exerciseId}/submissions/{submissionId}/repository} instead
* @param request the HTTP servlet request used for forwarding
* @param response the HTTP servlet response used for forwarding
*/
@Deprecated
@GetMapping("public/programming-exercises/{exerciseId}/submissions/{submissionId}/repository")
@EnforceNothing // We check the Athena secret and validation here
@ManualConfig
Expand All @@ -285,27 +282,7 @@ public void getRepository(@PathVariable long exerciseId, @PathVariable long subm
request.getRequestDispatcher("/api/athena/internal/programming-exercises/" + exerciseId + "/submissions/" + submissionId + "/repository").forward(request, response);
}

/**
* GET public/programming-exercises/:exerciseId/repository/template : Get the template repository as a zip file download
*
* @param exerciseId the id of the exercise
* @param auth the auth header value to check
* @param request the HTTP request
* @param response the HTTP response
* @throws ServletException if the forward fails
* @deprecated Use {@code api/athena/internal/programming-exercises/{exerciseId}/repository/template} instead
*/
@Deprecated
@GetMapping("public/programming-exercises/{exerciseId}/repository/template")
@EnforceNothing // We check the Athena secret and validation here
@ManualConfig
public void getTemplateRepository(@PathVariable long exerciseId, @RequestHeader(HttpHeaders.AUTHORIZATION) String auth, HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
log.debug("REST call to deprecated endpoint, forwarding to internal endpoint for exercise {}", exerciseId);
checkAthenaSecret(auth);
validateAthenaEnabled(exerciseId);
request.getRequestDispatcher("/api/athena/internal/programming-exercises/" + exerciseId + "/repository/template").forward(request, response);
}
// Removed legacy generic instructor repository endpoint in favor of specific endpoints below

/**
* GET public/programming-exercises/:exerciseId/repository/solution : Get the solution repository as a zip file download
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1239,6 +1239,10 @@ public Map<File, FileType> listFilesAndFolders(Repository repo, boolean omitBina
Iterator<java.io.File> itr = FileUtils.iterateFilesAndDirs(repo.getLocalPath().toFile(), filter, filter);
Map<File, FileType> files = new HashMap<>();

if (itr == null) {
return files;
}

while (itr.hasNext()) {
File nextFile = new File(itr.next(), repo);
Path nextPath = nextFile.toPath();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@ public void renameFile(Repository repository, FileMove fileMove) throws FileNotF
if (!repository.isValidFile(newFile)) {
throw new IllegalArgumentException("Existing path is not valid");
}
if (gitService.getFileByName(repository, newFile.getPath()).isPresent()) {
if (gitService.getFileByName(repository, newFile.toString()).isPresent()) {
throw new FileAlreadyExistsException("New path is not valid");
}
boolean isRenamed = existingFile.get().renameTo(newFile);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,11 @@

Path remoteDirPath = localVCRepositoryUri.getLocalRepositoryPath(localVCBasePath);

if (Files.exists(remoteDirPath)) {
log.debug("Local git repo {} at {} already exists – skipping creation", repositorySlug, remoteDirPath);
return;
}

try {
Files.createDirectories(remoteDirPath);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package de.tum.cit.aet.artemis.assessment;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.doReturn;

import java.time.ZonedDateTime;
import java.util.ArrayList;
Expand All @@ -12,14 +11,12 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.eclipse.jgit.lib.ObjectId;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.EnumSource;
import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.ArgumentMatchers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.test.context.support.WithMockUser;
Expand Down Expand Up @@ -186,8 +183,6 @@ void setupTest() {
result2.setFeedbacks(feedbacks2);
result2.setAssessmentType(AssessmentType.SEMI_AUTOMATIC);

String dummyHash = "9b3a9bd71a0d80e5bbc42204c319ed3d1d4f0d6d";
doReturn(ObjectId.fromString(dummyHash)).when(gitService).getLastCommitHash(ArgumentMatchers.any());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@
import static de.tum.cit.aet.artemis.core.connector.AthenaRequestMockProvider.ATHENA_RESTRICTED_MODULE_TEXT_TEST;
import static org.assertj.core.api.Assertions.assertThat;

import java.nio.file.Files;
import java.nio.file.Path;
import java.time.ZonedDateTime;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.FileUtils;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
Expand All @@ -33,6 +37,7 @@
import de.tum.cit.aet.artemis.exercise.domain.InitializationState;
import de.tum.cit.aet.artemis.exercise.domain.participation.StudentParticipation;
import de.tum.cit.aet.artemis.exercise.participation.util.ParticipationFactory;
import de.tum.cit.aet.artemis.exercise.participation.util.ParticipationUtilService;
import de.tum.cit.aet.artemis.exercise.test_repository.StudentParticipationTestRepository;
import de.tum.cit.aet.artemis.exercise.util.ExerciseUtilService;
import de.tum.cit.aet.artemis.modeling.domain.ModelingExercise;
Expand All @@ -42,12 +47,17 @@
import de.tum.cit.aet.artemis.modeling.util.ModelingExerciseUtilService;
import de.tum.cit.aet.artemis.programming.domain.ProgrammingExercise;
import de.tum.cit.aet.artemis.programming.domain.ProgrammingSubmission;
import de.tum.cit.aet.artemis.programming.domain.RepositoryType;
import de.tum.cit.aet.artemis.programming.icl.LocalVCLocalCITestService;
import de.tum.cit.aet.artemis.programming.service.GitService;
import de.tum.cit.aet.artemis.programming.service.localvc.LocalVCRepositoryUri;
import de.tum.cit.aet.artemis.programming.test_repository.ProgrammingExerciseStudentParticipationTestRepository;
import de.tum.cit.aet.artemis.programming.test_repository.ProgrammingExerciseTestRepository;
import de.tum.cit.aet.artemis.programming.test_repository.ProgrammingSubmissionTestRepository;
import de.tum.cit.aet.artemis.programming.util.LocalRepository;
import de.tum.cit.aet.artemis.programming.util.ProgrammingExerciseParticipationUtilService;
import de.tum.cit.aet.artemis.programming.util.ProgrammingExerciseUtilService;
import de.tum.cit.aet.artemis.programming.util.RepositoryExportTestUtil;
import de.tum.cit.aet.artemis.text.domain.TextExercise;
import de.tum.cit.aet.artemis.text.domain.TextSubmission;
import de.tum.cit.aet.artemis.text.repository.TextExerciseRepository;
Expand Down Expand Up @@ -100,6 +110,15 @@ class AthenaResourceIntegrationTest extends AbstractAthenaTest {
@Autowired
private LearnerProfileUtilService learnerProfileUtilService;

@Autowired
private LocalVCLocalCITestService localVCLocalCITestService;

@Autowired
private ProgrammingExerciseStudentParticipationTestRepository programmingExerciseStudentParticipationTestRepository;

@Autowired
private ParticipationUtilService participationUtilService;

private TextExercise textExercise;

private TextSubmission textSubmission;
Expand Down Expand Up @@ -155,6 +174,11 @@ protected void initTestCase() {
modelingSubmissionRepository.save(modelingSubmission);
}

@AfterEach
void cleanupRepositories() {
RepositoryExportTestUtil.cleanupTrackedRepositories();
}

@Test
@WithMockUser(username = TEST_PREFIX + "editor1", roles = "EDITOR")
void testGetAvailableProgrammingModulesSuccess_EmptyModules() throws Exception {
Expand Down Expand Up @@ -391,13 +415,12 @@ void testRepositoryExportEndpoint(String urlSuffix) throws Exception {
programmingExerciseParticipationUtilService.addSolutionParticipationForProgrammingExercise(programmingExercise);

// Seed a LocalVC bare repository with content
var sourceRepo = new LocalRepository(defaultBranch);
var sourceRepo = RepositoryExportTestUtil.trackRepository(new LocalRepository(defaultBranch));
sourceRepo.configureRepos(localVCBasePath, "athenaSrcLocalRepo", "athenaSrcOriginRepo");

// Ensure tests repository URI exists on the exercise
var testsSlug = programmingExercise.getProjectKey().toLowerCase() + "-tests";
var testsUri = new LocalVCRepositoryUri(localVCBaseUri, programmingExercise.getProjectKey(), testsSlug);
programmingExercise.setTestRepositoryUri(testsUri.toString());
var testsSlug = programmingExercise.getProjectKey().toLowerCase() + "-" + RepositoryType.TESTS.getName();
programmingExercise.setTestRepositoryUri(localVCLocalCITestService.buildLocalVCUri(null, null, programmingExercise.getProjectKey(), testsSlug));
programmingExerciseRepository.save(programmingExercise);

var sourceUri = new LocalVCRepositoryUri(localVCBaseUri, sourceRepo.remoteBareGitRepoFile.toPath());
Expand All @@ -422,6 +445,55 @@ void testRepositoryExportEndpoint(String urlSuffix) throws Exception {
assertThat(repoFiles).as("export returns exactly one file: README.md").isNotNull().hasSize(1).containsOnlyKeys("README.md").containsEntry("README.md", "Initial commit");
}

@Test
void testStudentRepositoryExportEndpoint() throws Exception {
// Enable Athena for the exercise
programmingExercise.setFeedbackSuggestionModule(ATHENA_MODULE_PROGRAMMING_TEST);
programmingExerciseRepository.save(programmingExercise);

// Create a programming student participation with a submission and result
var studentLogin = TEST_PREFIX + "student1";
var result = participationUtilService.addProgrammingParticipationWithResultForExercise(programmingExercise, studentLogin);
programmingSubmission = (ProgrammingSubmission) result.getSubmission();

// Prepare a LocalVC student repository and wire it to the participation referenced by the submission.
var projectKey = programmingExercise.getProjectKey();
String srcSlug = projectKey.toLowerCase() + "-athena-src";
var sourceRepo = RepositoryExportTestUtil.trackRepository(localVCLocalCITestService.createAndConfigureLocalRepository(projectKey, srcSlug));
// Remove default seed file (test.txt) from the working copy and commit deletion
var defaultSeed = sourceRepo.workingCopyGitRepoFile.toPath().resolve("test.txt");
if (Files.exists(defaultSeed)) {
Files.delete(defaultSeed);
sourceRepo.workingCopyGitRepo.add().addFilepattern(".").call();
GitService.commit(sourceRepo.workingCopyGitRepo).setMessage("Remove default seed").call();
sourceRepo.workingCopyGitRepo.push().setRemote("origin").call();
}
// Seed a README.md so the export contains the expected file
Path readme = sourceRepo.workingCopyGitRepoFile.toPath().resolve("README.md");
FileUtils.writeStringToFile(readme.toFile(), "Initial commit", java.nio.charset.StandardCharsets.UTF_8);
sourceRepo.workingCopyGitRepo.add().addFilepattern(".").call();
GitService.commit(sourceRepo.workingCopyGitRepo).setMessage("Initial commit").call();
sourceRepo.workingCopyGitRepo.push().setRemote("origin").call();
var studentRepoSlug = localVCLocalCITestService.getRepositorySlug(projectKey, studentLogin);
var studentLocalVCRepo = RepositoryExportTestUtil.seedLocalVcBareFrom(localVCLocalCITestService, projectKey, studentRepoSlug, sourceRepo);

// Persist repository URI on the participation
var programmingStudentParticipation = programmingExerciseStudentParticipationTestRepository.findById(programmingSubmission.getParticipation().getId()).orElseThrow();
programmingStudentParticipation.setRepositoryUri(localVCLocalCITestService.buildLocalVCUri(null, null, projectKey, studentRepoSlug));
programmingExerciseStudentParticipationTestRepository.save(programmingStudentParticipation);

// Call the internal endpoint with valid Athena auth and verify file map
var authHeaders = new HttpHeaders();
authHeaders.add(HttpHeaders.AUTHORIZATION, athenaSecret);

String json = request.get("/api/athena/internal/programming-exercises/" + programmingExercise.getId() + "/submissions/" + programmingSubmission.getId() + "/repository",
HttpStatus.OK, String.class, authHeaders);
Map<String, String> repoFiles = request.getObjectMapper().readValue(json, new TypeReference<Map<String, String>>() {
});
assertThat(repoFiles).as("student export returns exactly one file: README.md").isNotNull().hasSize(1).containsOnlyKeys("README.md").containsEntry("README.md",
"Initial commit");
}

@ParameterizedTest
@ValueSource(strings = { "repository/template", "repository/solution", "repository/tests" })
void testRepositoryExportEndpointsFailWhenAthenaNotEnabled(String urlSuffix) throws Exception {
Expand Down Expand Up @@ -458,4 +530,6 @@ void testRepositoryExportEndpointsFailWithInvalidRepositoryType(String urlSuffix

request.get("/api/athena/internal/programming-exercises/" + programmingExercise.getId() + "/" + urlSuffix, HttpStatus.NOT_FOUND, Result.class, authHeaders);
}

// Removed legacy public endpoint test that expected BAD_REQUEST for invalid repository type
}
Loading
Loading