Skip to content
GitLab
Explore
Projects
Groups
Snippets
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
CoTA
cota-backend
Commits
acd8c826
Commit
acd8c826
authored
1 year ago
by
Lückemeyer
Browse files
Options
Download
Email Patches
Plain Diff
removed dtt remnants
parent
d1fab229
master
amg-dev-volumes
amg-svn+ssh
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
src/main/java/de/hftstuttgart/dtabackend/rest/v1/task/TaskUpload.java
+2
-2
...a/de/hftstuttgart/dtabackend/rest/v1/task/TaskUpload.java
src/main/java/de/hftstuttgart/dtabackend/rest/v1/unittest/UnitTestUpload.java
+131
-131
...stuttgart/dtabackend/rest/v1/unittest/UnitTestUpload.java
src/main/java/de/hftstuttgart/dtabackend/utils/RegexUtil.java
+78
-78
...main/java/de/hftstuttgart/dtabackend/utils/RegexUtil.java
src/main/java/de/hftstuttgart/dtabackend/utils/UnifiedTicketingUtil.java
+288
-288
...e/hftstuttgart/dtabackend/utils/UnifiedTicketingUtil.java
src/main/resources/application.properties
+1
-1
src/main/resources/application.properties
with
500 additions
and
500 deletions
+500
-500
src/main/java/de/hftstuttgart/dtabackend/rest/v1/task/TaskUpload.java
+
2
-
2
View file @
acd8c826
...
@@ -52,7 +52,7 @@ public class TaskUpload {
...
@@ -52,7 +52,7 @@ public class TaskUpload {
LOG
.
info
(
"submission for testing received"
);
LOG
.
info
(
"submission for testing received"
);
LOG
.
debug
(
"creating new temporary directory"
);
LOG
.
debug
(
"creating new temporary directory"
);
Path
workDirectory
=
Files
.
createTempDirectory
(
testTmpPath
,
"dt
t
"
);
Path
workDirectory
=
Files
.
createTempDirectory
(
testTmpPath
,
"dt
a
"
);
LOG
.
debug
(
String
.
format
(
"working dir for test is: %s"
,
workDirectory
.
toAbsolutePath
().
toString
()));
LOG
.
debug
(
String
.
format
(
"working dir for test is: %s"
,
workDirectory
.
toAbsolutePath
().
toString
()));
// define paths for the test, the submission and where the result is to be expected afterwards
// define paths for the test, the submission and where the result is to be expected afterwards
...
@@ -61,7 +61,7 @@ public class TaskUpload {
...
@@ -61,7 +61,7 @@ public class TaskUpload {
String
mimeInfo
=
new
Tika
().
detect
(
taskFileRef
.
getInputStream
());
String
mimeInfo
=
new
Tika
().
detect
(
taskFileRef
.
getInputStream
());
switch
(
mimeInfo
)
{
switch
(
mimeInfo
)
{
case
"text/plain"
:
case
"text/plain"
:
LOG
.
debug
(
"textfile uploaded, searching for dt
t
config"
);
LOG
.
debug
(
"textfile uploaded, searching for dt
a
config"
);
// find URI in config file
// find URI in config file
Matcher
config
=
RegexUtil
.
findStudentConfig
(
taskFileRef
.
getInputStream
());
Matcher
config
=
RegexUtil
.
findStudentConfig
(
taskFileRef
.
getInputStream
());
...
...
This diff is collapsed.
Click to expand it.
src/main/java/de/hftstuttgart/dtabackend/rest/v1/unittest/UnitTestUpload.java
+
131
-
131
View file @
acd8c826
package
de.hftstuttgart.dtabackend.rest.v1.unittest
;
package
de.hftstuttgart.dtabackend.rest.v1.unittest
;
import
de.hftstuttgart.dtabackend.utils.JGitUtil
;
import
de.hftstuttgart.dtabackend.utils.JGitUtil
;
import
org.apache.logging.log4j.LogManager
;
import
org.apache.logging.log4j.LogManager
;
import
org.apache.logging.log4j.Logger
;
import
org.apache.logging.log4j.Logger
;
import
org.springframework.core.env.Environment
;
import
org.springframework.core.env.Environment
;
import
org.springframework.util.FileSystemUtils
;
import
org.springframework.util.FileSystemUtils
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RequestMethod
;
import
org.springframework.web.bind.annotation.RequestMethod
;
import
org.springframework.web.bind.annotation.RequestParam
;
import
org.springframework.web.bind.annotation.RequestParam
;
import
org.springframework.web.bind.annotation.RestController
;
import
org.springframework.web.bind.annotation.RestController
;
import
org.springframework.web.multipart.MultipartFile
;
import
org.springframework.web.multipart.MultipartFile
;
import
jakarta.servlet.annotation.MultipartConfig
;
import
jakarta.servlet.annotation.MultipartConfig
;
import
java.io.*
;
import
java.io.*
;
import
java.nio.file.Path
;
import
java.nio.file.Path
;
import
java.nio.file.Paths
;
import
java.nio.file.Paths
;
import
java.util.regex.Matcher
;
import
java.util.regex.Matcher
;
import
java.util.regex.Pattern
;
import
java.util.regex.Pattern
;
/**
/**
* Rest controller for anything related to the TEST files.
* Rest controller for anything related to the TEST files.
*/
*/
@RestController
@RestController
@RequestMapping
(
"/v1/unittest"
)
@RequestMapping
(
"/v1/unittest"
)
@MultipartConfig
@MultipartConfig
public
class
UnitTestUpload
{
public
class
UnitTestUpload
{
private
static
final
Logger
LOG
=
LogManager
.
getLogger
(
UnitTestUpload
.
class
);
private
static
final
Logger
LOG
=
LogManager
.
getLogger
(
UnitTestUpload
.
class
);
public
final
static
String
TESTCONFIGREGEX
=
"^dtt::(.*)::(.*|none)::(.*|none)::(.*)$"
;
public
final
static
String
TESTCONFIGREGEX
=
"^dtt::(.*)::(.*|none)::(.*|none)::(.*)$"
;
public
final
static
String
SUBMISSIONCONFIGREGEX
=
"^dtt::(.*)::(.*|none)::(.*|none)$"
;
public
final
static
String
SUBMISSIONCONFIGREGEX
=
"^dtt::(.*)::(.*|none)::(.*|none)$"
;
private
final
JGitUtil
jGitUtil
;
private
final
JGitUtil
jGitUtil
;
private
final
String
assignmentBasePath
;
private
final
String
assignmentBasePath
;
public
UnitTestUpload
(
Environment
env
,
JGitUtil
jGitUtil
)
{
public
UnitTestUpload
(
Environment
env
,
JGitUtil
jGitUtil
)
{
this
.
jGitUtil
=
jGitUtil
;
this
.
jGitUtil
=
jGitUtil
;
Path
p
=
Paths
.
get
(
env
.
getProperty
(
"data.dir"
),
env
.
getProperty
(
"data.dir.test.folder.name"
));
Path
p
=
Paths
.
get
(
env
.
getProperty
(
"data.dir"
),
env
.
getProperty
(
"data.dir.test.folder.name"
));
this
.
assignmentBasePath
=
p
.
toAbsolutePath
().
toString
();
this
.
assignmentBasePath
=
p
.
toAbsolutePath
().
toString
();
}
}
/**
/**
* Create a subfolder for the specific assignment.
* Create a subfolder for the specific assignment.
* This is called when the teacher creates an assignment and uploads the JUnit test files
* This is called when the teacher creates an assignment and uploads the JUnit test files
*
*
* @param unitTestFileRef The text file which contains the JUnit tests meta data
* @param unitTestFileRef The text file which contains the JUnit tests meta data
* @param assignmentId ID of the created assignment. Generated by Moodle
* @param assignmentId ID of the created assignment. Generated by Moodle
*/
*/
@RequestMapping
(
method
=
RequestMethod
.
POST
)
@RequestMapping
(
method
=
RequestMethod
.
POST
)
public
void
uploadUnitTestFile
(
public
void
uploadUnitTestFile
(
@RequestParam
(
"unitTestFile"
)
MultipartFile
unitTestFileRef
,
@RequestParam
(
"unitTestFile"
)
MultipartFile
unitTestFileRef
,
@RequestParam
(
"assignmentId"
)
String
assignmentId
@RequestParam
(
"assignmentId"
)
String
assignmentId
)
throws
IOException
{
)
throws
IOException
{
LOG
.
info
(
"received new assignment"
);
LOG
.
info
(
"received new assignment"
);
File
file
=
Paths
.
get
(
File
file
=
Paths
.
get
(
this
.
assignmentBasePath
,
this
.
assignmentBasePath
,
assignmentId
+
".txt"
)
assignmentId
+
".txt"
)
.
toFile
();
.
toFile
();
file
.
mkdirs
();
file
.
mkdirs
();
// save assignment config
// save assignment config
unitTestFileRef
.
transferTo
(
file
);
unitTestFileRef
.
transferTo
(
file
);
LOG
.
debug
(
String
.
format
(
"saved config file to: %s"
,
file
.
getAbsolutePath
()));
LOG
.
debug
(
String
.
format
(
"saved config file to: %s"
,
file
.
getAbsolutePath
()));
Pattern
pattern
=
Pattern
.
compile
(
TESTCONFIGREGEX
);
Pattern
pattern
=
Pattern
.
compile
(
TESTCONFIGREGEX
);
Matcher
config
=
null
;
Matcher
config
=
null
;
LOG
.
debug
(
"reading test configuration file"
);
LOG
.
debug
(
"reading test configuration file"
);
// open saved config in a try-with
// open saved config in a try-with
try
(
BufferedReader
br
=
new
BufferedReader
(
try
(
BufferedReader
br
=
new
BufferedReader
(
new
InputStreamReader
(
new
InputStreamReader
(
new
FileInputStream
(
file
))))
{
new
FileInputStream
(
file
))))
{
String
line
;
String
line
;
// search for a URI while none is found and there are lines left
// search for a URI while none is found and there are lines left
while
(
config
==
null
&&
(
line
=
br
.
readLine
())
!=
null
)
{
while
(
config
==
null
&&
(
line
=
br
.
readLine
())
!=
null
)
{
Matcher
matcher
=
pattern
.
matcher
(
line
);
Matcher
matcher
=
pattern
.
matcher
(
line
);
if
(
matcher
.
matches
())
{
if
(
matcher
.
matches
())
{
LOG
.
debug
(
String
.
format
(
"found dt
t
test line: %s"
,
line
));
LOG
.
debug
(
String
.
format
(
"found dt
a
test line: %s"
,
line
));
config
=
matcher
;
config
=
matcher
;
}
}
}
}
}
catch
(
IOException
e
)
{
}
catch
(
IOException
e
)
{
LOG
.
error
(
"Error while reading repo config"
,
e
);
LOG
.
error
(
"Error while reading repo config"
,
e
);
}
}
finally
{
finally
{
if
(
config
==
null
)
{
if
(
config
==
null
)
{
throw
new
RuntimeException
(
"couldn't find repo config for unittest clone"
);
throw
new
RuntimeException
(
"couldn't find repo config for unittest clone"
);
}
}
}
}
LOG
.
debug
(
"calling test repo clone"
);
LOG
.
debug
(
"calling test repo clone"
);
// cloning assignment repo to persistent space
// cloning assignment repo to persistent space
jGitUtil
.
cloneRepository
(
jGitUtil
.
cloneRepository
(
config
,
config
,
Paths
.
get
(
this
.
assignmentBasePath
,
assignmentId
).
toAbsolutePath
().
toString
());
Paths
.
get
(
this
.
assignmentBasePath
,
assignmentId
).
toAbsolutePath
().
toString
());
LOG
.
info
(
String
.
format
(
"stored new assignment: %s"
,
file
.
getAbsolutePath
()));
LOG
.
info
(
String
.
format
(
"stored new assignment: %s"
,
file
.
getAbsolutePath
()));
}
}
/**
/**
* Delete the folder for the assignment.
* Delete the folder for the assignment.
* Called when the teacher deletes the JUnitTest assignment
* Called when the teacher deletes the JUnitTest assignment
* <p>
* <p>
* {{url}}:8080/v1/unittest?assignmentId=111
* {{url}}:8080/v1/unittest?assignmentId=111
*
*
* @param assignmentId ID of the assignment to delete. Generated by Moodle
* @param assignmentId ID of the assignment to delete. Generated by Moodle
*/
*/
@RequestMapping
(
method
=
RequestMethod
.
DELETE
)
@RequestMapping
(
method
=
RequestMethod
.
DELETE
)
public
void
deleteUnitTestFiles
(
@RequestParam
(
"assignmentId"
)
String
assignmentId
)
{
public
void
deleteUnitTestFiles
(
@RequestParam
(
"assignmentId"
)
String
assignmentId
)
{
LOG
.
info
(
String
.
format
(
"received deletion order for assignment %s"
,
assignmentId
));
LOG
.
info
(
String
.
format
(
"received deletion order for assignment %s"
,
assignmentId
));
// deleting config file
// deleting config file
File
file
=
Paths
.
get
(
File
file
=
Paths
.
get
(
this
.
assignmentBasePath
,
this
.
assignmentBasePath
,
assignmentId
+
".txt"
)
assignmentId
+
".txt"
)
.
toFile
();
.
toFile
();
file
.
delete
();
file
.
delete
();
// deleting local copy of repository
// deleting local copy of repository
file
=
Paths
.
get
(
file
=
Paths
.
get
(
this
.
assignmentBasePath
,
this
.
assignmentBasePath
,
assignmentId
).
toFile
();
assignmentId
).
toFile
();
FileSystemUtils
.
deleteRecursively
(
file
);
FileSystemUtils
.
deleteRecursively
(
file
);
LOG
.
info
(
String
.
format
(
"assignment %s deletion complete"
,
assignmentId
));
LOG
.
info
(
String
.
format
(
"assignment %s deletion complete"
,
assignmentId
));
}
}
}
}
This diff is collapsed.
Click to expand it.
src/main/java/de/hftstuttgart/dtabackend/utils/RegexUtil.java
+
78
-
78
View file @
acd8c826
package
de.hftstuttgart.dtabackend.utils
;
package
de.hftstuttgart.dtabackend.utils
;
import
org.apache.logging.log4j.LogManager
;
import
org.apache.logging.log4j.LogManager
;
import
org.apache.logging.log4j.Logger
;
import
org.apache.logging.log4j.Logger
;
import
de.hftstuttgart.dtabackend.rest.v1.unittest.UnitTestUpload
;
import
de.hftstuttgart.dtabackend.rest.v1.unittest.UnitTestUpload
;
import
java.io.BufferedReader
;
import
java.io.BufferedReader
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.InputStream
;
import
java.io.InputStreamReader
;
import
java.io.InputStreamReader
;
import
java.util.regex.Matcher
;
import
java.util.regex.Matcher
;
import
java.util.regex.Pattern
;
import
java.util.regex.Pattern
;
public
class
RegexUtil
{
public
class
RegexUtil
{
public
enum
ConfigType
{
public
enum
ConfigType
{
TEACHER
,
TEACHER
,
STUDENT
,
STUDENT
,
}
}
private
static
final
Logger
LOG
=
LogManager
.
getLogger
(
RegexUtil
.
class
);
private
static
final
Logger
LOG
=
LogManager
.
getLogger
(
RegexUtil
.
class
);
public
static
Matcher
findStudentConfig
(
InputStream
is
)
{
public
static
Matcher
findStudentConfig
(
InputStream
is
)
{
return
findConfig
(
is
,
ConfigType
.
STUDENT
);
return
findConfig
(
is
,
ConfigType
.
STUDENT
);
}
}
public
static
Matcher
findProfessorConfig
(
InputStream
is
)
{
public
static
Matcher
findProfessorConfig
(
InputStream
is
)
{
return
findConfig
(
is
,
ConfigType
.
TEACHER
);
return
findConfig
(
is
,
ConfigType
.
TEACHER
);
}
}
public
static
Matcher
findConfig
(
InputStream
is
,
ConfigType
configType
)
{
public
static
Matcher
findConfig
(
InputStream
is
,
ConfigType
configType
)
{
Pattern
pattern
;
Pattern
pattern
;
switch
(
configType
)
{
switch
(
configType
)
{
case
TEACHER:
case
TEACHER:
pattern
=
Pattern
.
compile
(
UnitTestUpload
.
TESTCONFIGREGEX
);
pattern
=
Pattern
.
compile
(
UnitTestUpload
.
TESTCONFIGREGEX
);
break
;
break
;
case
STUDENT:
case
STUDENT:
pattern
=
Pattern
.
compile
(
UnitTestUpload
.
SUBMISSIONCONFIGREGEX
);
pattern
=
Pattern
.
compile
(
UnitTestUpload
.
SUBMISSIONCONFIGREGEX
);
break
;
break
;
default
:
default
:
String
msg
=
String
.
format
(
"unknown config type: %s"
,
configType
.
name
());
String
msg
=
String
.
format
(
"unknown config type: %s"
,
configType
.
name
());
LOG
.
error
(
msg
);
LOG
.
error
(
msg
);
throw
new
RuntimeException
(
msg
);
throw
new
RuntimeException
(
msg
);
}
}
Matcher
config
=
null
;
Matcher
config
=
null
;
LOG
.
debug
(
"reading config file"
);
LOG
.
debug
(
"reading config file"
);
// open received file in a try-with
// open received file in a try-with
try
(
BufferedReader
br
=
new
BufferedReader
(
try
(
BufferedReader
br
=
new
BufferedReader
(
new
InputStreamReader
(
new
InputStreamReader
(
is
)))
{
is
)))
{
String
line
;
String
line
;
// as long as we haven't found a configuration and have lines left, search
// as long as we haven't found a configuration and have lines left, search
while
(
config
==
null
&&
(
line
=
br
.
readLine
())
!=
null
)
{
while
(
config
==
null
&&
(
line
=
br
.
readLine
())
!=
null
)
{
Matcher
matcher
=
pattern
.
matcher
(
line
);
Matcher
matcher
=
pattern
.
matcher
(
line
);
if
(
matcher
.
matches
())
{
if
(
matcher
.
matches
())
{
LOG
.
debug
(
String
.
format
(
"found dt
t
line: %s"
,
line
));
LOG
.
debug
(
String
.
format
(
"found dt
a
line: %s"
,
line
));
config
=
matcher
;
config
=
matcher
;
}
}
}
}
}
catch
(
IOException
e
)
{
}
catch
(
IOException
e
)
{
LOG
.
error
(
"Error while reading repo config"
,
e
);
LOG
.
error
(
"Error while reading repo config"
,
e
);
}
}
finally
{
finally
{
if
(
config
==
null
)
{
if
(
config
==
null
)
{
throw
new
RuntimeException
(
"couldn't find repo config for clone"
);
throw
new
RuntimeException
(
"couldn't find repo config for clone"
);
}
}
}
}
return
config
;
return
config
;
}
}
}
}
This diff is collapsed.
Click to expand it.
src/main/java/de/hftstuttgart/dtabackend/utils/UnifiedTicketingUtil.java
+
288
-
288
View file @
acd8c826
package
de.hftstuttgart.dtabackend.utils
;
package
de.hftstuttgart.dtabackend.utils
;
import
de.hftstuttgart.dtabackend.models.Result
;
import
de.hftstuttgart.dtabackend.models.Result
;
import
de.hftstuttgart.dtabackend.models.ResultSummary
;
import
de.hftstuttgart.dtabackend.models.ResultSummary
;
import
de.hftstuttgart.unifiedticketing.core.Filter
;
import
de.hftstuttgart.unifiedticketing.core.Filter
;
import
de.hftstuttgart.unifiedticketing.core.Ticket
;
import
de.hftstuttgart.unifiedticketing.core.Ticket
;
import
de.hftstuttgart.unifiedticketing.core.TicketBuilder
;
import
de.hftstuttgart.unifiedticketing.core.TicketBuilder
;
import
de.hftstuttgart.unifiedticketing.core.TicketSystem
;
import
de.hftstuttgart.unifiedticketing.core.TicketSystem
;
import
de.hftstuttgart.unifiedticketing.exceptions.UnifiedticketingException
;
import
de.hftstuttgart.unifiedticketing.exceptions.UnifiedticketingException
;
import
org.apache.logging.log4j.LogManager
;
import
org.apache.logging.log4j.LogManager
;
import
org.apache.logging.log4j.Logger
;
import
org.apache.logging.log4j.Logger
;
import
java.io.BufferedReader
;
import
java.io.BufferedReader
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.InputStream
;
import
java.io.InputStreamReader
;
import
java.io.InputStreamReader
;
import
java.nio.charset.StandardCharsets
;
import
java.nio.charset.StandardCharsets
;
import
java.security.MessageDigest
;
import
java.security.MessageDigest
;
import
java.security.NoSuchAlgorithmException
;
import
java.security.NoSuchAlgorithmException
;
import
java.util.Collections
;
import
java.util.Collections
;
import
java.util.HashSet
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.List
;
import
java.util.Set
;
import
java.util.Set
;
public
class
UnifiedTicketingUtil
{
public
class
UnifiedTicketingUtil
{
private
final
static
Logger
LOG
=
LogManager
.
getLogger
(
UnifiedTicketingUtil
.
class
);
private
final
static
Logger
LOG
=
LogManager
.
getLogger
(
UnifiedTicketingUtil
.
class
);
private
final
static
String
LABEL
=
"DT
T
created"
;
private
final
static
String
LABEL
=
"DT
A
created"
;
private
final
static
String
TITLE
=
" | "
+
LABEL
;
private
final
static
String
TITLE
=
" | "
+
LABEL
;
public
static
String
createTicketDescriptionFromResult
(
TicketSystem
ts
,
Result
result
,
boolean
compilationError
)
{
public
static
String
createTicketDescriptionFromResult
(
TicketSystem
ts
,
Result
result
,
boolean
compilationError
)
{
StringBuilder
sb
=
new
StringBuilder
();
StringBuilder
sb
=
new
StringBuilder
();
// heading
// heading
if
(
compilationError
)
{
if
(
compilationError
)
{
sb
.
append
(
String
.
format
(
"# %s is not compilable"
,
result
.
name
));
sb
.
append
(
String
.
format
(
"# %s is not compilable"
,
result
.
name
));
}
else
{
}
else
{
sb
.
append
(
String
.
format
(
"# Unittest for %s fails"
,
result
.
name
));
sb
.
append
(
String
.
format
(
"# Unittest for %s fails"
,
result
.
name
));
}
}
sb
.
append
(
"\n\n"
);
sb
.
append
(
"\n\n"
);
// meta data table
// meta data table
sb
.
append
(
"|||\n"
);
sb
.
append
(
"|||\n"
);
sb
.
append
(
"|:-|:-|\n"
);
sb
.
append
(
"|:-|:-|\n"
);
if
(
compilationError
)
{
if
(
compilationError
)
{
sb
.
append
(
String
.
format
(
"|File|`%s`|\n"
,
result
.
name
));
sb
.
append
(
String
.
format
(
"|File|`%s`|\n"
,
result
.
name
));
}
else
{
}
else
{
sb
.
append
(
String
.
format
(
"|Test|`%s`|\n"
,
result
.
name
));
sb
.
append
(
String
.
format
(
"|Test|`%s`|\n"
,
result
.
name
));
}
}
sb
.
append
(
String
.
format
(
"|Reason|`%s`|\n"
,
result
.
failureReason
));
sb
.
append
(
String
.
format
(
"|Reason|`%s`|\n"
,
result
.
failureReason
));
if
(
compilationError
)
{
if
(
compilationError
)
{
sb
.
append
(
String
.
format
(
"|Line|`%s`|\n"
,
result
.
lineNumber
));
sb
.
append
(
String
.
format
(
"|Line|`%s`|\n"
,
result
.
lineNumber
));
sb
.
append
(
String
.
format
(
"|Column|`%s`|\n"
,
result
.
columnNumber
));
sb
.
append
(
String
.
format
(
"|Column|`%s`|\n"
,
result
.
columnNumber
));
sb
.
append
(
String
.
format
(
"|Position|`%s`|\n"
,
result
.
position
));
sb
.
append
(
String
.
format
(
"|Position|`%s`|\n"
,
result
.
position
));
}
else
{
}
else
{
sb
.
append
(
String
.
format
(
"|Type|`%s`|\n"
,
result
.
failureType
));
sb
.
append
(
String
.
format
(
"|Type|`%s`|\n"
,
result
.
failureType
));
}
}
sb
.
append
(
"\n\n"
);
sb
.
append
(
"\n\n"
);
// stacktrace
// stacktrace
sb
.
append
(
"<details>\n\n"
);
sb
.
append
(
"<details>\n\n"
);
sb
.
append
(
"<summary>show stacktrace</summary>\n\n"
);
sb
.
append
(
"<summary>show stacktrace</summary>\n\n"
);
sb
.
append
(
"```"
);
sb
.
append
(
"```"
);
sb
.
append
(
result
.
stacktrace
);
sb
.
append
(
result
.
stacktrace
);
sb
.
append
(
"\n```"
);
sb
.
append
(
"\n```"
);
sb
.
append
(
"\n\n</details>\n"
);
sb
.
append
(
"\n\n</details>\n"
);
return
sb
.
toString
();
return
sb
.
toString
();
}
}
public
static
String
createTicketTitleFromResult
(
TicketSystem
ts
,
Result
result
,
boolean
compilationError
)
{
public
static
String
createTicketTitleFromResult
(
TicketSystem
ts
,
Result
result
,
boolean
compilationError
)
{
StringBuilder
sb
=
new
StringBuilder
();
StringBuilder
sb
=
new
StringBuilder
();
String
separator
=
" | "
;
String
separator
=
" | "
;
if
(
compilationError
)
sb
.
append
(
"compilation fails"
);
if
(
compilationError
)
sb
.
append
(
"compilation fails"
);
else
sb
.
append
(
"test method fails"
);
else
sb
.
append
(
"test method fails"
);
sb
.
append
(
separator
);
sb
.
append
(
separator
);
sb
.
append
(
result
.
name
);
sb
.
append
(
result
.
name
);
if
(!
compilationError
)
{
if
(!
compilationError
)
{
sb
.
append
(
separator
);
sb
.
append
(
separator
);
sb
.
append
(
result
.
failureReason
);
sb
.
append
(
result
.
failureReason
);
}
}
// if label-support is not present, place global identifier into title
// if label-support is not present, place global identifier into title
if
(!
ts
.
hasLabelSupport
())
sb
.
append
(
TITLE
);
if
(!
ts
.
hasLabelSupport
())
sb
.
append
(
TITLE
);
sb
.
append
(
separator
);
sb
.
append
(
separator
);
sb
.
append
(
getHashForFailure
(
result
));
sb
.
append
(
getHashForFailure
(
result
));
return
sb
.
toString
();
return
sb
.
toString
();
}
}
public
static
Ticket
createTicketFromResult
(
TicketSystem
ts
,
Result
result
,
boolean
compilationError
)
{
public
static
Ticket
createTicketFromResult
(
TicketSystem
ts
,
Result
result
,
boolean
compilationError
)
{
TicketBuilder
tb
=
ts
.
createTicket
()
TicketBuilder
tb
=
ts
.
createTicket
()
.
title
(
createTicketTitleFromResult
(
ts
,
result
,
compilationError
))
.
title
(
createTicketTitleFromResult
(
ts
,
result
,
compilationError
))
.
description
(
createTicketDescriptionFromResult
(
ts
,
result
,
compilationError
));
.
description
(
createTicketDescriptionFromResult
(
ts
,
result
,
compilationError
));
if
(
ts
.
hasLabelSupport
())
tb
.
labels
(
Collections
.
singleton
(
LABEL
));
if
(
ts
.
hasLabelSupport
())
tb
.
labels
(
Collections
.
singleton
(
LABEL
));
return
tb
.
create
();
return
tb
.
create
();
}
}
public
static
Set
<
Ticket
>
fetchExistingTickets
(
TicketSystem
ts
)
{
public
static
Set
<
Ticket
>
fetchExistingTickets
(
TicketSystem
ts
)
{
Set
<
Ticket
>
ret
=
new
HashSet
<>();
Set
<
Ticket
>
ret
=
new
HashSet
<>();
Filter
f
=
ts
.
find
();
Filter
f
=
ts
.
find
();
// depending on label support, identify tickets by label or title containing string
// depending on label support, identify tickets by label or title containing string
if
(
ts
.
hasLabelSupport
())
{
if
(
ts
.
hasLabelSupport
())
{
LOG
.
debug
(
String
.
format
(
LOG
.
debug
(
String
.
format
(
"ticketsystem has label support, using label %s to find dt
t
tickets"
,
LABEL
));
"ticketsystem has label support, using label %s to find dt
a
tickets"
,
LABEL
));
f
.
withLabel
(
LABEL
);
f
.
withLabel
(
LABEL
);
}
}
else
{
else
{
LOG
.
debug
(
String
.
format
(
LOG
.
debug
(
String
.
format
(
"ticketsystem without labels, searching for ticket titles containing %s"
,
TITLE
));
"ticketsystem without labels, searching for ticket titles containing %s"
,
TITLE
));
f
.
withTitleContain
(
TITLE
);
f
.
withTitleContain
(
TITLE
);
}
}
LOG
.
debug
(
"prepare pagination cycling"
);
LOG
.
debug
(
"prepare pagination cycling"
);
// set first page and page size for pagination
// set first page and page size for pagination
int
page
=
1
;
int
page
=
1
;
int
pageSize
=
10
;
int
pageSize
=
10
;
f
.
setPageSize
(
pageSize
);
f
.
setPageSize
(
pageSize
);
LOG
.
debug
(
String
.
format
(
"using pagination with %s elements per page"
,
pageSize
));
LOG
.
debug
(
String
.
format
(
"using pagination with %s elements per page"
,
pageSize
));
// declare list for received tickets
// declare list for received tickets
List
<
Ticket
>
received
;
List
<
Ticket
>
received
;
// go into do-while to evaluate after receiving if another round is needed
// go into do-while to evaluate after receiving if another round is needed
do
{
do
{
LOG
.
debug
(
String
.
format
(
"calling page %s"
,
page
));
LOG
.
debug
(
String
.
format
(
"calling page %s"
,
page
));
f
.
setPage
(
page
++);
f
.
setPage
(
page
++);
received
=
f
.
get
();
received
=
f
.
get
();
ret
.
addAll
(
received
);
ret
.
addAll
(
received
);
}
while
(
f
.
getLastReceivedItemCount
()
>=
pageSize
);
}
while
(
f
.
getLastReceivedItemCount
()
>=
pageSize
);
return
ret
;
return
ret
;
}
}
public
static
String
getHashForFailure
(
Result
result
)
{
public
static
String
getHashForFailure
(
Result
result
)
{
MessageDigest
digest
;
MessageDigest
digest
;
try
{
try
{
digest
=
MessageDigest
.
getInstance
(
"SHA-512"
);
digest
=
MessageDigest
.
getInstance
(
"SHA-512"
);
}
catch
(
NoSuchAlgorithmException
e
)
{
}
catch
(
NoSuchAlgorithmException
e
)
{
throw
new
UnifiedticketingException
(
e
);
throw
new
UnifiedticketingException
(
e
);
}
}
byte
[]
data
=
digest
.
digest
(
result
.
name
.
getBytes
(
StandardCharsets
.
UTF_8
));
byte
[]
data
=
digest
.
digest
(
result
.
name
.
getBytes
(
StandardCharsets
.
UTF_8
));
StringBuilder
hexString
=
new
StringBuilder
(
2
*
data
.
length
);
StringBuilder
hexString
=
new
StringBuilder
(
2
*
data
.
length
);
for
(
byte
character:
data
)
for
(
byte
character:
data
)
{
{
String
hex
=
Integer
.
toHexString
(
0xff
&
character
);
String
hex
=
Integer
.
toHexString
(
0xff
&
character
);
if
(
hex
.
length
()
==
1
)
if
(
hex
.
length
()
==
1
)
{
{
hexString
.
append
(
'0'
);
hexString
.
append
(
'0'
);
}
}
hexString
.
append
(
hex
);
hexString
.
append
(
hex
);
}
}
return
hexString
.
substring
(
hexString
.
length
()
-
9
,
hexString
.
length
()
-
1
);
return
hexString
.
substring
(
hexString
.
length
()
-
9
,
hexString
.
length
()
-
1
);
}
}
public
static
void
processResult
(
TicketSystem
ts
,
Set
<
Ticket
>
tickets
,
Result
result
,
boolean
compilationError
)
{
public
static
void
processResult
(
TicketSystem
ts
,
Set
<
Ticket
>
tickets
,
Result
result
,
boolean
compilationError
)
{
LOG
.
debug
(
String
.
format
(
"retrieving hash for %s"
,
result
.
name
));
LOG
.
debug
(
String
.
format
(
"retrieving hash for %s"
,
result
.
name
));
String
hash
=
getHashForFailure
(
result
);
String
hash
=
getHashForFailure
(
result
);
// check if corresponding ticket exists yet, otherwise create new one
// check if corresponding ticket exists yet, otherwise create new one
Ticket
ticket
=
tickets
.
stream
()
Ticket
ticket
=
tickets
.
stream
()
.
filter
(
t
->
t
.
getTitle
().
endsWith
(
hash
))
.
filter
(
t
->
t
.
getTitle
().
endsWith
(
hash
))
.
findFirst
()
.
findFirst
()
.
orElse
(
null
);
.
orElse
(
null
);
if
(
ticket
!=
null
)
{
if
(
ticket
!=
null
)
{
// if yet existing, remove from found list
// if yet existing, remove from found list
LOG
.
debug
(
"found ticket with matching hash, removing from collection"
);
LOG
.
debug
(
"found ticket with matching hash, removing from collection"
);
tickets
.
remove
(
ticket
);
tickets
.
remove
(
ticket
);
LOG
.
debug
(
"updating ticket with new result"
);
LOG
.
debug
(
"updating ticket with new result"
);
updateTicketFromResult
(
ts
,
ticket
,
result
,
compilationError
);
updateTicketFromResult
(
ts
,
ticket
,
result
,
compilationError
);
}
else
{
}
else
{
LOG
.
debug
(
"no ticket found, creating new one"
);
LOG
.
debug
(
"no ticket found, creating new one"
);
createTicketFromResult
(
ts
,
result
,
compilationError
);
createTicketFromResult
(
ts
,
result
,
compilationError
);
}
}
}
}
/**
/**
* search file for unified-ticketing URI's and report to every set ticket system,
* search file for unified-ticketing URI's and report to every set ticket system,
* not waiting for it to finish and catching an eventually interrupted thread.
* not waiting for it to finish and catching an eventually interrupted thread.
*
*
* @param meta student uploaded file
* @param meta student uploaded file
* @param resultSummary summary from the testrunner container
* @param resultSummary summary from the testrunner container
*/
*/
public
static
void
reportResults
(
InputStream
meta
,
ResultSummary
resultSummary
)
{
public
static
void
reportResults
(
InputStream
meta
,
ResultSummary
resultSummary
)
{
try
{
try
{
reportResults
(
meta
,
resultSummary
,
false
);
reportResults
(
meta
,
resultSummary
,
false
);
}
catch
(
InterruptedException
e
)
{
}
catch
(
InterruptedException
e
)
{
LOG
.
error
(
String
.
format
(
"Unified-Ticketing got interrupted with: %s"
,
e
.
getMessage
()));
LOG
.
error
(
String
.
format
(
"Unified-Ticketing got interrupted with: %s"
,
e
.
getMessage
()));
}
}
}
}
/**
/**
* report all failures and compilation errors to all configured ticket systems.
* report all failures and compilation errors to all configured ticket systems.
* You can optionally wait for the ticket creation to finish, which is done in a separate thread.
* You can optionally wait for the ticket creation to finish, which is done in a separate thread.
*
*
* @param meta student uploaded file
* @param meta student uploaded file
* @param resultSummary summary from the testrunner container
* @param resultSummary summary from the testrunner container
* @param wait if we should block until the ticket creation has finished
* @param wait if we should block until the ticket creation has finished
* @throws InterruptedException
* @throws InterruptedException
*/
*/
public
static
void
reportResults
(
InputStream
meta
,
ResultSummary
resultSummary
,
boolean
wait
)
throws
InterruptedException
{
public
static
void
reportResults
(
InputStream
meta
,
ResultSummary
resultSummary
,
boolean
wait
)
throws
InterruptedException
{
LOG
.
debug
(
"preparing thread for ticket result submitting"
);
LOG
.
debug
(
"preparing thread for ticket result submitting"
);
Thread
unifiedTicketingUtil
=
new
Thread
(()
->
{
Thread
unifiedTicketingUtil
=
new
Thread
(()
->
{
// read student transmitted file
// read student transmitted file
try
(
BufferedReader
br
=
new
BufferedReader
(
new
InputStreamReader
(
meta
)))
{
try
(
BufferedReader
br
=
new
BufferedReader
(
new
InputStreamReader
(
meta
)))
{
String
line
=
null
;
String
line
=
null
;
while
((
line
=
br
.
readLine
())
!=
null
)
{
while
((
line
=
br
.
readLine
())
!=
null
)
{
TicketSystem
ts
=
null
;
TicketSystem
ts
=
null
;
// try each line as URI for a unified-ticketing instantiation
// try each line as URI for a unified-ticketing instantiation
try
{
try
{
ts
=
TicketSystem
.
fromUri
(
line
);
ts
=
TicketSystem
.
fromUri
(
line
);
LOG
.
info
(
String
.
format
(
"ticket system for reporting found: %s"
,
ts
.
baseUrl
));
LOG
.
info
(
String
.
format
(
"ticket system for reporting found: %s"
,
ts
.
baseUrl
));
}
catch
(
UnifiedticketingException
e
)
{
}
catch
(
UnifiedticketingException
e
)
{
// ignore if line didn't match a unified-ticketing URI
// ignore if line didn't match a unified-ticketing URI
}
}
// if a ticketsystem got instantiated, start the submission.
// if a ticketsystem got instantiated, start the submission.
// If errors occur, log it this time.
// If errors occur, log it this time.
try
{
try
{
if
(
ts
!=
null
)
reportToTicketsystem
(
ts
,
resultSummary
);
if
(
ts
!=
null
)
reportToTicketsystem
(
ts
,
resultSummary
);
}
catch
(
UnifiedticketingException
e
)
{
}
catch
(
UnifiedticketingException
e
)
{
LOG
.
warn
(
String
.
format
(
LOG
.
warn
(
String
.
format
(
"reporting fails to ticketsystem %s failed with: "
,
"reporting fails to ticketsystem %s failed with: "
,
ts
.
baseUrl
,
ts
.
baseUrl
,
e
.
getMessage
()));
e
.
getMessage
()));
}
}
}
}
}
catch
(
IOException
e
)
{
}
catch
(
IOException
e
)
{
LOG
.
error
(
String
.
format
(
"couldn't read config to find lines for ticket reporting: %s"
,
e
.
getMessage
()));
LOG
.
error
(
String
.
format
(
"couldn't read config to find lines for ticket reporting: %s"
,
e
.
getMessage
()));
}
}
});
});
LOG
.
debug
(
"starting ticket submitting thread"
);
LOG
.
debug
(
"starting ticket submitting thread"
);
unifiedTicketingUtil
.
start
();
unifiedTicketingUtil
.
start
();
if
(
wait
)
{
if
(
wait
)
{
LOG
.
debug
(
"wait for ticket submission completion"
);
LOG
.
debug
(
"wait for ticket submission completion"
);
unifiedTicketingUtil
.
join
();
unifiedTicketingUtil
.
join
();
}
else
{
}
else
{
LOG
.
debug
(
"tickets will be submitted in background"
);
LOG
.
debug
(
"tickets will be submitted in background"
);
}
}
}
}
public
static
void
reportToTicketsystem
(
TicketSystem
ts
,
ResultSummary
resultSummary
)
{
public
static
void
reportToTicketsystem
(
TicketSystem
ts
,
ResultSummary
resultSummary
)
{
// tickets existing yet
// tickets existing yet
LOG
.
debug
(
"fetching existing tickets"
);
LOG
.
debug
(
"fetching existing tickets"
);
Set
<
Ticket
>
tickets
=
fetchExistingTickets
(
ts
);
Set
<
Ticket
>
tickets
=
fetchExistingTickets
(
ts
);
// for each fail or compile error
// for each fail or compile error
LOG
.
debug
(
"start failed tests reporting"
);
LOG
.
debug
(
"start failed tests reporting"
);
resultSummary
.
results
.
stream
()
resultSummary
.
results
.
stream
()
.
filter
(
r
->
r
.
state
==
Result
.
State
.
FAILURE
.
ordinal
())
.
filter
(
r
->
r
.
state
==
Result
.
State
.
FAILURE
.
ordinal
())
.
forEach
(
f
->
processResult
(
ts
,
tickets
,
f
,
false
));
.
forEach
(
f
->
processResult
(
ts
,
tickets
,
f
,
false
));
LOG
.
debug
(
"start compilation errors reporting"
);
LOG
.
debug
(
"start compilation errors reporting"
);
resultSummary
.
results
.
stream
()
resultSummary
.
results
.
stream
()
.
filter
(
r
->
r
.
state
==
Result
.
State
.
COMPILATIONERROR
.
ordinal
())
.
filter
(
r
->
r
.
state
==
Result
.
State
.
COMPILATIONERROR
.
ordinal
())
.
forEach
(
c
->
processResult
(
ts
,
tickets
,
c
,
true
));
.
forEach
(
c
->
processResult
(
ts
,
tickets
,
c
,
true
));
LOG
.
debug
(
"closing all remaining tickets, no longer appeared"
);
LOG
.
debug
(
"closing all remaining tickets, no longer appeared"
);
tickets
.
forEach
(
ticket
->
ticket
.
close
().
save
());
tickets
.
forEach
(
ticket
->
ticket
.
close
().
save
());
}
}
public
static
Ticket
updateTicketFromResult
(
TicketSystem
ts
,
Ticket
ticket
,
Result
result
,
boolean
compilationError
)
{
public
static
Ticket
updateTicketFromResult
(
TicketSystem
ts
,
Ticket
ticket
,
Result
result
,
boolean
compilationError
)
{
ticket
ticket
.
open
()
.
open
()
.
setTitle
(
createTicketTitleFromResult
(
ts
,
result
,
compilationError
))
.
setTitle
(
createTicketTitleFromResult
(
ts
,
result
,
compilationError
))
.
setDescription
(
createTicketDescriptionFromResult
(
ts
,
result
,
compilationError
));
.
setDescription
(
createTicketDescriptionFromResult
(
ts
,
result
,
compilationError
));
if
(
ts
.
hasLabelSupport
())
ticket
.
addLabel
(
LABEL
);
if
(
ts
.
hasLabelSupport
())
ticket
.
addLabel
(
LABEL
);
return
ticket
.
save
();
return
ticket
.
save
();
}
}
}
}
This diff is collapsed.
Click to expand it.
src/main/resources/application.properties
+
1
-
1
View file @
acd8c826
...
@@ -7,7 +7,7 @@ spring.http.multipart.max-file-size=5Mb
...
@@ -7,7 +7,7 @@ spring.http.multipart.max-file-size=5Mb
###############################################
###############################################
# Holds the uploaded Zip-Files
# Holds the uploaded Zip-Files
tests.tmp.dir
=
/tmp
/dta-tests
tests.tmp.dir
=
~
/dta-tests
host.tests.tmp.dir
=
${tests.tmp.dir}
host.tests.tmp.dir
=
${tests.tmp.dir}
data.dir
=
/data
data.dir
=
/data
data.dir.test.folder.name
=
UnitTests
data.dir.test.folder.name
=
UnitTests
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment
Menu
Explore
Projects
Groups
Snippets