Skip to content

Commit 7628fc6

Browse files
committed
feat(tests): add unit tests for CrawlProcessor and JsonPathProcessor #379
1 parent 44715f1 commit 7628fc6

File tree

6 files changed

+350
-2
lines changed

6 files changed

+350
-2
lines changed

exts/devins-lang/src/main/kotlin/cc/unitmesh/devti/language/ast/action/PatternFuncProcessor.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ open class PatternFuncProcessor(open val myProject: Project, open val hole: Hobb
7474
inputArray.map { line ->
7575
regex.findAll(line)
7676
.map {
77-
if (it.groupValues.size >= 1) {
77+
if (it.groupValues.size > 1) {
7878
it.groupValues[1]
7979
} else {
8080
it.groupValues[0]
@@ -90,7 +90,7 @@ open class PatternFuncProcessor(open val myProject: Project, open val hole: Hobb
9090
val result = regexs.map { regex ->
9191
regex.findAll(lastResult)
9292
.map {
93-
if (it.groupValues.size >= 1) {
93+
if (it.groupValues.size > 1) {
9494
it.groupValues[1]
9595
} else {
9696
it.groupValues[0]
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package cc.unitmesh.devti.language.compiler.execute
2+
3+
import cc.unitmesh.devti.language.processor.CrawlProcessor
4+
import com.intellij.testFramework.fixtures.BasePlatformTestCase
5+
6+
class CrawlProcessorTest : BasePlatformTestCase() {
7+
fun testShouldParseLink() {
8+
val urls = arrayOf("https://shire.phodal.com/")
9+
val results = CrawlProcessor.execute(urls)
10+
assertEquals(results.size, 1)
11+
}
12+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package cc.unitmesh.devti.language.compiler.execute
2+
3+
import cc.unitmesh.devti.language.ast.action.PatternActionFunc
4+
import cc.unitmesh.devti.language.processor.JsonPathProcessor
5+
import com.intellij.testFramework.fixtures.BasePlatformTestCase
6+
import org.junit.Test
7+
8+
class JsonPathProcessorTest : BasePlatformTestCase() {
9+
fun testShouldParseJsonStringWithValidJsonPath() {
10+
// given
11+
val jsonStr = "{\"key\":\"value\"}"
12+
val action = PatternActionFunc.JsonPath(null, "key")
13+
14+
// when
15+
val result = JsonPathProcessor.execute(project, jsonStr, action)
16+
17+
// then
18+
assertEquals("value", result)
19+
}
20+
21+
fun testShouldReturnNullWhenJsonPathDoesNotExistInJsonString() {
22+
// given
23+
val jsonStr = "{\"key\":\"value\"}"
24+
val action = PatternActionFunc.JsonPath(null, "invalidKey")
25+
26+
// when
27+
val result = JsonPathProcessor.execute(project, jsonStr, action)
28+
29+
// then
30+
assertNull(result)
31+
}
32+
33+
fun testShouldParseSseResultWithValidJsonPath() {
34+
// given
35+
val sseInput =
36+
"data: {\"event\":\"agent_message\",\"conversation_id\":\"48929266-a58f-46cc-a5eb-33145e6a96ef\",\"message_id\":\"91ad550b-1109-4062-88f8-07be18238e0e\",\"created_at\":1725437154,\"task_id\":\"4f846104-8571-42f1-b04c-f6f034b2fe9e\",\"id\":\"91ad550b-1109-4062-88f8-07be18238e0e\",\"answer\":\"The\"}\n"
37+
val jsonPath = "answer"
38+
39+
// when
40+
val result = JsonPathProcessor.parseSSEResult(sseInput, jsonPath)
41+
42+
// then
43+
assertEquals("The", result)
44+
}
45+
46+
fun testShouldReturnEmptyStringWhenJsonPathDoesNotExistInSseResult() {
47+
// given
48+
val sseInput =
49+
"data: {\"event\":\"agent_message\",\"conversation_id\":\"48929266-a58f-46cc-a5eb-33145e6a96ef\",\"message_id\":\"91ad550b-1109-4062-88f8-07be18238e0e\",\"created_at\":1725437154,\"task_id\":\"4f846104-8571-42f1-b04c-f6f034b2fe9e\",\"id\":\"91ad550b-1109-4062-88f8-07be18238e0e\",\"answer\":\"The\"}\n"
50+
val jsonPath = "invalidKey"
51+
52+
// when
53+
val result = JsonPathProcessor.parseSSEResult(sseInput, jsonPath)
54+
55+
// then
56+
assertEquals("", result)
57+
}
58+
59+
fun testShouldParseMultipleSseDataLinesWithValidJsonPath() {
60+
// given
61+
val sseInput =
62+
"data: {\"event\":\"agent_message\",\"conversation_id\":\"48929266-a58f-46cc-a5eb-33145e6a96ef\",\"message_id\":\"91ad550b-1109-4062-88f8-07be18238e0e\",\"created_at\":1725437154,\"task_id\":\"4f846104-8571-42f1-b04c-f6f034b2fe9e\",\"id\":\"91ad550b-1109-4062-88f8-07be18238e0e\",\"answer\":\"The\"}\n" +
63+
"data: {\"event\":\"message_end\",\"conversation_id\":\"48929266-a58f-46cc-a5eb-33145e6a96ef\",\"message_id\":\"91ad550b-1109-4062-88f8-07be18238e0e\",\"created_at\":1725437154,\"task_id\":\"4f846104-8571-42f1-b04c-f6f034b2fe9e\",\"id\":\"91ad550b-1109-4062-88f8-07be18238e0e\"}\n"
64+
val jsonPath = "$.event"
65+
66+
// when
67+
val result = JsonPathProcessor.parseSSEResult(sseInput, jsonPath)
68+
69+
// then
70+
assertEquals("agent_messagemessage_end", result)
71+
}
72+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package cc.unitmesh.devti.language.compiler.execute
2+
3+
import cc.unitmesh.devti.language.processor.shell.ShireShellCommandRunner
4+
import com.intellij.testFramework.fixtures.BasePlatformTestCase
5+
import org.intellij.lang.annotations.Language
6+
7+
class ShireShellRunnerTest: BasePlatformTestCase() {
8+
fun testFill() {
9+
@Language("JSON")
10+
val jsonEnv = """
11+
{
12+
"development": {
13+
"name": "Phodal"
14+
}
15+
}
16+
""".trimIndent()
17+
18+
myFixture.addFileToProject("demo.autodevEnv.json", jsonEnv)
19+
20+
@Language("Shell Script")
21+
val content = """
22+
echo "Hello ${'$'}{name}, my name is ${'$'}{myName}!"
23+
""".trimIndent()
24+
25+
val file = myFixture.addFileToProject("demo.seh", content)
26+
27+
val fill = ShireShellCommandRunner.fill(
28+
project, file.virtualFile, mapOf(
29+
"myName" to "Shire"
30+
)
31+
)
32+
33+
assertEquals("echo \"Hello Phodal, my name is Shire!\"", fill)
34+
}
35+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package cc.unitmesh.devti.language.compiler.parser
2+
3+
import cc.unitmesh.devti.language.compiler.HobbitHoleParser
4+
import cc.unitmesh.devti.language.psi.DevInFile
5+
import com.intellij.testFramework.fixtures.BasePlatformTestCase
6+
import org.intellij.lang.annotations.Language
7+
8+
class HobbitHoleParserTest : BasePlatformTestCase() {
9+
fun testShouldParseFunctions() {
10+
@Language("DevIn")
11+
val code = """
12+
---
13+
functions:
14+
normal: "defaultOutput.py"(string)
15+
output: "multipleOutput.py"(string) -> content, size
16+
special: "accessFunctionIfSupport.py"::resize(string, number, number) -> image
17+
---
18+
""".trimIndent()
19+
20+
val file = myFixture.configureByText("test.devin", code)
21+
val hobbitHole = HobbitHoleParser.parse(file as DevInFile)!!
22+
23+
assertEquals(3, hobbitHole.foreignFunctions.size)
24+
val firstFunc = hobbitHole.foreignFunctions["normal"]!!
25+
assertEquals("normal", firstFunc.funcName)
26+
assertEquals("defaultOutput.py", firstFunc.funcPath)
27+
28+
val secondFunc = hobbitHole.foreignFunctions["output"]!!
29+
assertEquals("output", secondFunc.funcName)
30+
assertEquals("multipleOutput.py", secondFunc.funcPath)
31+
assertEquals(listOf("content", "size"), secondFunc.returnVars.keys.toList())
32+
33+
val thirdFunc = hobbitHole.foreignFunctions["special"]!!
34+
assertEquals("special", thirdFunc.funcName)
35+
assertEquals("accessFunctionIfSupport.py", thirdFunc.funcPath)
36+
assertEquals(listOf("image"), thirdFunc.returnVars.keys.toList())
37+
assertEquals(listOf("string", "number", "number"), thirdFunc.inputTypes)
38+
}
39+
}
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
package cc.unitmesh.devti.language.regression
2+
3+
import cc.unitmesh.devti.language.ast.variable.ShireVariableTemplateCompiler
4+
import cc.unitmesh.devti.language.compiler.DevInsCompiler
5+
import cc.unitmesh.devti.language.middleware.post.PostProcessorContext
6+
import cc.unitmesh.devti.language.psi.DevInFile
7+
import com.intellij.testFramework.fixtures.BasePlatformTestCase
8+
import kotlinx.coroutines.runBlocking
9+
import org.intellij.lang.annotations.Language
10+
import kotlin.text.get
11+
12+
class ShireCompileTest : BasePlatformTestCase() {
13+
val javaHelloController = """
14+
package com.phodal.shirelang.controller;
15+
16+
import org.springframework.web.bind.annotation.GetMapping;
17+
import org.springframework.web.bind.annotation.RestController;
18+
19+
@RestController
20+
public class HelloController {
21+
@GetMapping("/hello")
22+
public String hello() {
23+
return "Hello, World!";
24+
}
25+
}
26+
""".trimIndent()
27+
28+
val javaHelloEntity = """
29+
package com.phodal.shirelang.entity;
30+
31+
public class HelloEntity {
32+
private String name;
33+
34+
public String getName() {
35+
return name;
36+
}
37+
38+
public void setName(String name) {
39+
this.name = name;
40+
}
41+
}
42+
""".trimIndent()
43+
44+
fun testShouldReturnControllerCodeWithFindCat() {
45+
myFixture.addFileToProject(
46+
"src/main/java/com/phodal/shirelang/controller/HelloController.java",
47+
javaHelloController
48+
)
49+
myFixture.addFileToProject("src/main/java/com/phodal/shirelang/entity/HelloEntity.java", javaHelloEntity)
50+
51+
@Language("Shire")
52+
val code = """
53+
---
54+
name: "类图分析"
55+
variables:
56+
"controllers": /.*.java/ { find("Controller") | grep("src/main/java/.*") | cat }
57+
"outputFile": /any/ { print("name.adl") }
58+
onStreamingEnd: { parseCode | saveFile(${'$'}outputFile) }
59+
---
60+
61+
62+
请将下列信息原样输出,不要添加任何其他描述信息:
63+
64+
${'$'}controllers
65+
""".trimIndent()
66+
67+
val file = myFixture.configureByText("test.devin", code)
68+
val compile = runBlocking { DevInsCompiler(project, file as DevInFile, myFixture.editor).compile() }
69+
val hole = compile.config!!
70+
71+
val context = PostProcessorContext(
72+
genText = "User prompt:\n\n",
73+
)
74+
75+
runBlocking {
76+
val templateCompiler =
77+
ShireVariableTemplateCompiler(project, hole, compile.variableTable, code, myFixture.editor)
78+
val compiledVariables =
79+
templateCompiler.compileVariable(myFixture.editor, mutableMapOf())
80+
81+
context.compiledVariables = compiledVariables
82+
}
83+
84+
assertEquals(
85+
"""package com.phodal.shirelang.controller;
86+
87+
import org.springframework.web.bind.annotation.GetMapping;
88+
import org.springframework.web.bind.annotation.RestController;
89+
90+
@RestController
91+
public class HelloController {
92+
@GetMapping("/hello")
93+
public String hello() {
94+
return "Hello, World!";
95+
}
96+
}""", context.compiledVariables["controllers"]
97+
)
98+
}
99+
100+
fun testShouldReturnControllerCodeWithFindCatWithHead() {
101+
myFixture.addFileToProject(
102+
"src/main/java/com/phodal/shirelang/controller/HelloController.java",
103+
javaHelloController
104+
)
105+
myFixture.addFileToProject("src/main/java/com/phodal/shirelang/entity/HelloEntity.java", javaHelloEntity)
106+
107+
@Language("DevIn")
108+
val code = """
109+
---
110+
name: "类图分析"
111+
variables:
112+
"output": "name.adl"
113+
"con": /.*.java/ { print | head(1)}
114+
"controllers": /.*.java/ { find("Controller") | grep("src/main/java/.*") | head(1) | cat }
115+
"outputFile": /any/ { print("name.adl") }
116+
onStreamingEnd: { parseCode | saveFile(${'$'}outputFile) }
117+
118+
---
119+
120+
下面是你要执行转换的数据:
121+
${'$'}controllers
122+
""".trimIndent()
123+
124+
val file = myFixture.configureByText("test.devin", code)
125+
val compile = runBlocking { DevInsCompiler(project, file as DevInFile, myFixture.editor).compile() }
126+
val hole = compile.config!!
127+
128+
val context = PostProcessorContext(
129+
genText = "User prompt:\n\n",
130+
)
131+
132+
runBlocking {
133+
val templateCompiler = ShireVariableTemplateCompiler(project, hole, compile.variableTable, code, myFixture.editor)
134+
val compiledVariables =
135+
templateCompiler.compileVariable(myFixture.editor, mutableMapOf())
136+
137+
context.compiledVariables = compiledVariables
138+
}
139+
140+
assertEquals(
141+
"""/src/src/main/java/com/phodal/shirelang/entity/HelloEntity.java""",
142+
context.compiledVariables["con"]
143+
)
144+
assertEquals("package com.phodal.shirelang.controller;\n" +
145+
"\n" +
146+
"import org.springframework.web.bind.annotation.GetMapping;\n" +
147+
"import org.springframework.web.bind.annotation.RestController;\n" +
148+
"\n" +
149+
"@RestController\n" +
150+
"public class HelloController {\n" +
151+
" @GetMapping(\"/hello\")\n" +
152+
" public String hello() {\n" +
153+
" return \"Hello, World!\";\n" +
154+
" }\n" +
155+
"}", context.compiledVariables["controllers"])
156+
}
157+
158+
// fun testShouldCompileMarkdownHeader() {
159+
//
160+
// @Language("Shire")
161+
// val code = """
162+
// ## Header
163+
//
164+
// Body
165+
// """.trimIndent()
166+
//
167+
// val p: Properties = Properties()
168+
// p.setProperty("resource.loader", "class")
169+
// p.setProperty("class.resource.loader.description", "Velocity Classpath Resource Loader")
170+
// p.setProperty(
171+
// "class.resource.loader.class",
172+
// "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"
173+
// )
174+
// try {
175+
// Velocity.init(p);
176+
// } catch (e: Exception) {
177+
//// e.printStackTrace()
178+
// }
179+
//
180+
// val file = myFixture.configureByText("test.devin", code)
181+
// val compile = ShireSyntaxAnalyzer(project, file as DevInFile, myFixture.editor).parse()
182+
//
183+
// val result = runBlocking {
184+
// val templateCompiler = ShireTemplateCompiler(project, compile.config, compile.variableTable, code)
185+
// templateCompiler.compile()
186+
// }
187+
//
188+
// assertEquals("", result)
189+
// }
190+
}

0 commit comments

Comments
 (0)