DockerCodeSandBoxTest.java 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. package space.anyi.codesandbox;
  2. import org.junit.jupiter.api.BeforeAll;
  3. import org.junit.jupiter.api.Test;
  4. import space.anyi.codesandbox.docker.DockerClientFactory;
  5. import space.anyi.serve.entity.contest.Submission;
  6. import java.util.List;
  7. import static org.junit.jupiter.api.Assertions.assertEquals;
  8. /**
  9. * @fileName: DockerCodeSandBoxTest
  10. * @projectName: serve
  11. * @package: space.anyi.codesandbox
  12. * @author: yangyi
  13. * @date:14/10/2026 6:00 pm
  14. * @description: Docker 代码沙箱测试,需本机 Docker daemon 运行中,判题镜像缺失时自动拉取
  15. */
  16. class DockerCodeSandBoxTest {
  17. private static DockerCodeSandBox dockerCodeSandBox;
  18. @BeforeAll
  19. static void setUp() {
  20. dockerCodeSandBox = new DockerCodeSandBox(new DockerClientFactory().dockerClient());
  21. }
  22. @Test
  23. void testAcAndMultiLineOutput() {
  24. String code = "public class Main {\n" +
  25. " public static void main(String[] args) {\n" +
  26. " java.util.Scanner in = new java.util.Scanner(System.in);\n" +
  27. " int a = in.nextInt();\n" +
  28. " int b = in.nextInt();\n" +
  29. " System.out.println(a + b);\n" +
  30. " }\n" +
  31. "}";
  32. List<TestCase> testCases = List.of(new TestCase(1L, "1 2", "3"), new TestCase(2L, "2 2", "4"));
  33. CodeContext codeContext = new CodeContext(1L, code, "java", 2000L, 256 * 1024L, testCases);
  34. CodeResponse codeResponse = dockerCodeSandBox.process(codeContext);
  35. assertEquals(Submission.STATUS_AC, codeResponse.status());
  36. assertEquals(2, codeResponse.testCaseResponses().size());
  37. }
  38. @Test
  39. void testCompileError() {
  40. String code = "public class Main {\n" +
  41. " public static void main(String[] args) {\n" +
  42. " int x = \"类型不匹配\";\n" +
  43. " }\n" +
  44. "}";
  45. CodeContext codeContext = new CodeContext(2L, code, "java", 2000L, 256 * 1024L,
  46. List.of(new TestCase(1L, "", "")));
  47. CodeResponse codeResponse = dockerCodeSandBox.process(codeContext);
  48. assertEquals(Submission.STATUS_CE, codeResponse.status());
  49. }
  50. @Test
  51. void testRuntimeError() {
  52. String code = "public class Main {\n" +
  53. " public static void main(String[] args) {\n" +
  54. " int x = 1 / 0;\n" +
  55. " System.out.println(x);\n" +
  56. " }\n" +
  57. "}";
  58. CodeContext codeContext = new CodeContext(3L, code, "java", 2000L, 256 * 1024L,
  59. List.of(new TestCase(1L, "", "")));
  60. CodeResponse codeResponse = dockerCodeSandBox.process(codeContext);
  61. assertEquals(Submission.STATUS_RE, codeResponse.status());
  62. }
  63. @Test
  64. void testWrongAnswer() {
  65. String code = "public class Main {\n" +
  66. " public static void main(String[] args) {\n" +
  67. " System.out.println(9);\n" +
  68. " }\n" +
  69. "}";
  70. CodeContext codeContext = new CodeContext(4L, code, "java", 2000L, 256 * 1024L,
  71. List.of(new TestCase(1L, "", "3")));
  72. CodeResponse codeResponse = dockerCodeSandBox.process(codeContext);
  73. assertEquals(Submission.STATUS_WA, codeResponse.status());
  74. }
  75. @Test
  76. void testTrailingWhitespaceIgnored() {
  77. String code = "public class Main {\n" +
  78. " public static void main(String[] args) {\n" +
  79. " System.out.println(\"3 \\t\");\n" +
  80. " }\n" +
  81. "}";
  82. CodeContext codeContext = new CodeContext(5L, code, "java", 2000L, 256 * 1024L,
  83. List.of(new TestCase(1L, "", "3")));
  84. CodeResponse codeResponse = dockerCodeSandBox.process(codeContext);
  85. assertEquals(Submission.STATUS_AC, codeResponse.status());
  86. }
  87. @Test
  88. void testMultiByteUtf8Output() {
  89. String code = "public class Main {\n" +
  90. " public static void main(String[] args) {\n" +
  91. " System.out.println(\"你好,世界!\");\n" +
  92. " }\n" +
  93. "}";
  94. CodeContext codeContext = new CodeContext(7L, code, "java", 2000L, 256 * 1024L,
  95. List.of(new TestCase(1L, "", "你好,世界!")));
  96. CodeResponse codeResponse = dockerCodeSandBox.process(codeContext);
  97. assertEquals(Submission.STATUS_AC, codeResponse.status());
  98. }
  99. @Test
  100. void testInfiniteLoopTle() {
  101. String code = "public class Main {\n" +
  102. " public static void main(String[] args) {\n" +
  103. " while (true) {}\n" +
  104. " }\n" +
  105. "}";
  106. CodeContext codeContext = new CodeContext(6L, code, "java", 1000L, 256 * 1024L,
  107. List.of(new TestCase(1L, "", "")));
  108. long start = System.currentTimeMillis();
  109. CodeResponse codeResponse = dockerCodeSandBox.process(codeContext);
  110. long elapsed = System.currentTimeMillis() - start;
  111. assertEquals(Submission.STATUS_TLE, codeResponse.status());
  112. assertEquals(1, codeResponse.testCaseResponses().size());
  113. // 超时应及时生效,允许容器创建/清理的开销
  114. assertEquals(true, elapsed < 15_000, "TLE 超时未生效,实际耗时:" + elapsed + "ms");
  115. }
  116. }