Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
org.gradle.caching=true
org.gradle.parallel=true
org.gradle.workers.max=4
org.gradle.jvmargs=-Xmx4g -Xms4g -XX:MaxMetaspaceSize=1g -XX:+UseParallelGC -XX:+HeapDumpOnOutOfMemoryError
2 changes: 1 addition & 1 deletion src/main/kotlin/mcp/code/analysis/service/CodeAnalyzer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ data class CodeAnalyzer(
logger.info("Collected ${snippets.size} code snippets from ${repoDir.absolutePath}")
logger.debug(
"""Snippets Found:
|${snippets.joinToString("\n")}"""
|${snippets.joinToString("\n")}"""
.trimIndent()
)
}
Expand Down
58 changes: 47 additions & 11 deletions src/test/kotlin/mcp/code/analysis/service/CodeAnalyzerTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,20 @@ class CodeAnalyzerTest {
analyzer = CodeAnalyzer(logger = logger)
}

// Test cases for findReadmeFile function
data class ReadmeTestCase(
val name: String,
val files: Map<String, String>,
val expectedContent: String,
val containsLogMessage: String,
)

data class SnippetsTestCase(
val name: String,
val files: Map<String, String>,
val expectedSnippetCount: Int,
val shouldContainFiles: List<String>,
)

@Test
fun `test findReadmeFile with various scenarios`() {
val testCases =
Expand Down Expand Up @@ -87,20 +93,33 @@ class CodeAnalyzerTest {
}
}

// Test cases for analyzeStructure function
@Test
fun `test analyzeStructure with different directory structures`() {
// Arrange
val subDir = File(tempDir, "src").apply { mkdir() }
File(subDir, "Helper.java").apply { writeText("public class Helper { public void help() {} }") }
File(tempDir, "main.kt").apply { writeText("""fun main() { println("Hello") }""") }
File(tempDir, "main.kt").apply { writeText("""fun main() { println("Hello from Kotlin") }""") }
File(tempDir, "main.scala").apply {
writeText("""object Main { def main(args: Array[String]): Unit = println("Hello from Scala") }""")
}
File(tempDir, "main.py").apply { writeText("""print("Hello from Python")""") }
File(tempDir, "main.go").apply { writeText("""import "fmt"; func main() { fmt.Println("Hello from Go!") }""") }
File(tempDir, "main.ts").apply { writeText("""console.log("Hello from TypeScript")""") }
File(tempDir, "main.js").apply { writeText("""console.log("Hello from JavaScript")""") }
File(tempDir, "main.rb").apply { writeText("""puts "Hello from Ruby"""") }

// Act
val result = analyzer.analyzeStructure(tempDir)

// Assert
assertTrue(result.containsKey("main.kt"), "Should contain main.kt file")
assertTrue(result.containsKey("src"), "Should contain src directory")
assertTrue(result.containsKey("main.kt"), "Should contain main.kt file")
assertTrue(result.containsKey("main.scala"), "Should contain main.scala file")
assertTrue(result.containsKey("main.py"), "Should contain main.py file")
assertTrue(result.containsKey("main.go"), "Should contain main.go file")
assertTrue(result.containsKey("main.ts"), "Should contain main.ts file")
assertTrue(result.containsKey("main.rb"), "Should contain main.rb file")
assertTrue(result.containsKey("main.js"), "Should contain main.js file")

val srcContent = result["src"] as? Map<*, *>
assertNotNull(srcContent, "src should be a map")
Expand All @@ -109,14 +128,31 @@ class CodeAnalyzerTest {
val mainKtInfo = result["main.kt"] as? Map<*, *>
assertNotNull(mainKtInfo, "main.kt should have metadata")
assertEquals("kotlin", mainKtInfo!!["language"], "Should identify Kotlin language")
}

data class SnippetsTestCase(
val name: String,
val files: Map<String, String>,
val expectedSnippetCount: Int,
val shouldContainFiles: List<String>,
)
val mainScalaInfo = result["main.scala"] as? Map<*, *>
assertNotNull(mainScalaInfo, "main.scala should have metadata")
assertEquals("scala", mainScalaInfo!!["language"], "Should identify Scala language")

val mainPyInfo = result["main.py"] as? Map<*, *>
assertNotNull(mainPyInfo, "main.py should have metadata")
assertEquals("python", mainPyInfo!!["language"], "Should identify Python language")

val mainGoInfo = result["main.go"] as? Map<*, *>
assertNotNull(mainGoInfo, "main.go should have metadata")
assertEquals("go", mainGoInfo!!["language"], "Should identify Go language")

val mainTsInfo = result["main.ts"] as? Map<*, *>
assertNotNull(mainTsInfo, "main.ts should have metadata")
assertEquals("typescript", mainTsInfo!!["language"], "Should identify TypeScript language")

val mainJsInfo = result["main.js"] as? Map<*, *>
assertNotNull(mainJsInfo, "main.js should have metadata")
assertEquals("javascript", mainJsInfo!!["language"], "Should identify JavaScript language")

val mainRbInfo = result["main.rb"] as? Map<*, *>
assertNotNull(mainRbInfo, "main.rb should have metadata")
assertEquals("ruby", mainRbInfo!!["language"], "Should identify Ruby language")
}

@Test
fun `test collectAllCodeSnippets with different file types`() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,31 @@ class ModelContextServiceTest {
private lateinit var mockHttpClient: HttpClient
private lateinit var service: ModelContextService

// Test cases for buildInsightsPrompt function
data class InsightsPromptTestCase(
val name: String,
val readmeContent: String,
val expectedContains: List<String>,
val shouldNotContain: List<String> = listOf(),
)

// Test cases for generateResponse function
data class ResponseTestCase(
val name: String,
val prompt: String,
val mockResponse: String,
val expectedResult: String,
)

// Test cases for generateSummary function
data class SummaryTestCase(
val name: String,
val codeStructure: Map<String, Any>,
val codeSnippets: List<String>,
val insights: String,
val expectedPromptContains: List<String>,
)

@BeforeEach
fun setUp() {
logger = mockk(relaxed = true)
Expand Down Expand Up @@ -58,14 +83,6 @@ class ModelContextServiceTest {
service = ModelContextService(config = config, httpClient = mockHttpClient, logger = logger)
}

// Test cases for buildInsightsPrompt function
data class InsightsPromptTestCase(
val name: String,
val readmeContent: String,
val expectedContains: List<String>,
val shouldNotContain: List<String> = listOf(),
)

@Test
fun `test buildInsightsPrompt formats README correctly`() {
val testCases =
Expand Down Expand Up @@ -133,22 +150,6 @@ class ModelContextServiceTest {
}
}

// Test cases for parseInsights function
data class InsightParsingTestCase(
val name: String,
val input: String,
val expectedCount: Int,
val expectedContains: List<String>,
)

// Test cases for generateResponse function
data class ResponseTestCase(
val name: String,
val prompt: String,
val mockResponse: String,
val expectedResult: String,
)

@Test
fun `test generateResponse returns model response`() = runBlocking {
val testCases =
Expand Down Expand Up @@ -203,15 +204,6 @@ class ModelContextServiceTest {
}
}

// Test cases for generateSummary function
data class SummaryTestCase(
val name: String,
val codeStructure: Map<String, Any>,
val codeSnippets: List<String>,
val insights: String,
val expectedPromptContains: List<String>,
)

@Test
fun `test generateSummary builds combined prompt with code and insights`() = runBlocking {
// Arrange
Expand Down