import CodexBarCoreimport Foundationimport Testing /// Tests for the lightweight JetBrains XML scanner used on Linux./// These tests verify that the non-libxml2 implementation correctly parses/// JetBrains AI Assistant quota files.@Suitestruct JetBrainsParserLinuxTests { @Test func parsesQuotaXMLWithBothOptions() throws { let quotaInfo = [ "{ "type": "Available",", " "current": "7478.3",", " "maximum": "1000000",", " "until": "2026-11-09T21:00:00Z",", " "tariffQuota": {", " "current": "7478.3",", " "maximum": "1000000",", " "available": "992521.7"", " } }", ].joined() let nextRefill = [ "{ "type": "Known",", " "next": "2026-01-16T14:00:54.939Z",", " "tariff": {", " "amount": "1000000",", " "duration": "PT720H"", " } }", ].joined() let xml = """ <?xml version="1.0" encoding="UTF-8"?> <application> <component name="AIAssistantQuotaManager2"> <option name="quotaInfo" value="\(quotaInfo)" /> <option name="nextRefill" value="\(nextRefill)" /> </component> </application> """ let data = Data(xml.utf8) let snapshot = try JetBrainsStatusProbe.parseXMLData(data, detectedIDE: nil) #expect(snapshot.quotaInfo.type == "Available") #expect(snapshot.quotaInfo.used == 7478.3) #expect(snapshot.quotaInfo.maximum == 1_000_000) #expect(snapshot.quotaInfo.available == 992_521.7) #expect(snapshot.refillInfo?.type == "Known") #expect(snapshot.refillInfo?.amount == 1_000_000) } @Test func parsesQuotaXMLWithOnlyQuotaInfo() throws { let quotaInfo = "{"type":"free","current":"5000","maximum":"100000"}" let xml = """ <?xml version="1.0" encoding="UTF-8"?> <application> <component name="AIAssistantQuotaManager2"> <option name="quotaInfo" value="\(quotaInfo)" /> </component> </application> """ let data = Data(xml.utf8) let snapshot = try JetBrainsStatusProbe.parseXMLData(data, detectedIDE: nil) #expect(snapshot.quotaInfo.type == "free") #expect(snapshot.quotaInfo.used == 5000) #expect(snapshot.quotaInfo.maximum == 100_000) #expect(snapshot.refillInfo == nil) } @Test func parsesXMLWithReversedAttributeOrder() throws { // Test that parser handles value before name (different attribute order) let quotaInfo = "{"type":"paid","current":"1000","maximum":"50000"}" let xml = """ <?xml version="1.0" encoding="UTF-8"?> <application> <component name="AIAssistantQuotaManager2"> <option value="\(quotaInfo)" name="quotaInfo" /> </component> </application> """ let data = Data(xml.utf8) let snapshot = try JetBrainsStatusProbe.parseXMLData(data, detectedIDE: nil) #expect(snapshot.quotaInfo.type == "paid") #expect(snapshot.quotaInfo.used == 1000) #expect(snapshot.quotaInfo.maximum == 50000) } @Test func handlesHTMLEntities() throws { let quotaInfo = [ "{"type":"test"", ","current":"0"", ","maximum":"50000"}", ].joined() let xml = """ <?xml version="1.0" encoding="UTF-8"?> <application> <component name="AIAssistantQuotaManager2"> <option name="quotaInfo" value="\(quotaInfo)" /> </component> </application> """ let data = Data(xml.utf8) let snapshot = try JetBrainsStatusProbe.parseXMLData(data, detectedIDE: nil) #expect(snapshot.quotaInfo.type == "test") #expect(snapshot.quotaInfo.maximum == 50000) } @Test func throwsOnMissingQuotaInfo() throws { let xml = """ <?xml version="1.0" encoding="UTF-8"?> <application> <component name="AIAssistantQuotaManager2"> </component> </application> """ let data = Data(xml.utf8) #expect(throws: JetBrainsStatusProbeError.noQuotaInfo) { _ = try JetBrainsStatusProbe.parseXMLData(data, detectedIDE: nil) } } @Test func throwsOnMissingComponent() throws { let xml = """ <?xml version="1.0" encoding="UTF-8"?> <application> <component name="SomeOtherComponent"> <option name="quotaInfo" value="{}" /> </component> </application> """ let data = Data(xml.utf8) #expect(throws: JetBrainsStatusProbeError.noQuotaInfo) { _ = try JetBrainsStatusProbe.parseXMLData(data, detectedIDE: nil) } } @Test func throwsOnEmptyQuotaInfo() throws { let xml = """ <?xml version="1.0" encoding="UTF-8"?> <application> <component name="AIAssistantQuotaManager2"> <option name="quotaInfo" value="" /> </component> </application> """ let data = Data(xml.utf8) #expect(throws: JetBrainsStatusProbeError.noQuotaInfo) { _ = try JetBrainsStatusProbe.parseXMLData(data, detectedIDE: nil) } } @Test func parsesXMLWithSingleQuotes() throws { let quotaInfo = "{"type":"single","current":"100","maximum":"10000"}" let xml = """ <?xml version="1.0" encoding="UTF-8"?> <application> <component name='AIAssistantQuotaManager2'> <option name='quotaInfo' value='\(quotaInfo)' /> </component> </application> """ let data = Data(xml.utf8) let snapshot = try JetBrainsStatusProbe.parseXMLData(data, detectedIDE: nil) #expect(snapshot.quotaInfo.type == "single") #expect(snapshot.quotaInfo.maximum == 10000) } @Test func parsesXMLWithComments() throws { let quotaInfo = "{"type":"comment","current":"10","maximum":"100"}" let xml = """ <?xml version="1.0" encoding="UTF-8"?> <!-- top comment --> <application> <component name="AIAssistantQuotaManager2"> <!-- inside comment --> <option name="quotaInfo" value="\(quotaInfo)" /> </component> </application> """ let data = Data(xml.utf8) let snapshot = try JetBrainsStatusProbe.parseXMLData(data, detectedIDE: nil) #expect(snapshot.quotaInfo.type == "comment") #expect(snapshot.quotaInfo.maximum == 100) } @Test func parsesXMLWithMultipleComponentsUsesCorrectOne() throws { let otherQuota = "{"type":"wrong","current":"1","maximum":"2"}" let quotaInfo = "{"type":"right","current":"42","maximum":"100"}" let xml = """ <?xml version="1.0" encoding="UTF-8"?> <application> <component name="OtherComponent"> <option name="quotaInfo" value="\(otherQuota)" /> </component> <component name="AIAssistantQuotaManager2"> <option name="quotaInfo" value="\(quotaInfo)" /> </component> </application> """ let data = Data(xml.utf8) let snapshot = try JetBrainsStatusProbe.parseXMLData(data, detectedIDE: nil) #expect(snapshot.quotaInfo.type == "right") #expect(snapshot.quotaInfo.used == 42) } @Test func parsesXMLWithNextRefillBeforeQuotaInfo() throws { let quotaInfo = "{"type":"order","current":"5","maximum":"50"}" let nextRefill = "{"type":"Known","next":"2026-01-16T14:00:54.939Z","amount":"100"}" let xml = """ <?xml version="1.0" encoding="UTF-8"?> <application> <component name="AIAssistantQuotaManager2"> <option name="nextRefill" value="\(nextRefill)" /> <option name="quotaInfo" value="\(quotaInfo)" /> </component> </application> """ let data = Data(xml.utf8) let snapshot = try JetBrainsStatusProbe.parseXMLData(data, detectedIDE: nil) #expect(snapshot.quotaInfo.type == "order") #expect(snapshot.refillInfo?.amount == 100) }}
import CodexBarCore
import Foundation
import Testing
/// Tests for the lightweight JetBrains XML scanner used on Linux.
/// These tests verify that the non-libxml2 implementation correctly parses
/// JetBrains AI Assistant quota files.
@Suite
struct JetBrainsParserLinuxTests {
@Test
func parsesQuotaXMLWithBothOptions() throws {
let quotaInfo = [
"{ "type": "Available",",
" "current": "7478.3",",
" "maximum": "1000000",",
" "until": "2026-11-09T21:00:00Z",",
" "tariffQuota": {",
" "current": "7478.3",",
" "maximum": "1000000",",
" "available": "992521.7"",
" } }",
].joined()
let nextRefill = [
"{ "type": "Known",",
" "next": "2026-01-16T14:00:54.939Z",",
" "tariff": {",
" "amount": "1000000",",
" "duration": "PT720H"",
" } }",
].joined()
let xml = """
<?xml version="1.0" encoding="UTF-8"?>
<application>
<component name="AIAssistantQuotaManager2">
<option name="quotaInfo" value="\(quotaInfo)" />
<option name="nextRefill" value="\(nextRefill)" />
</component>
</application>
"""
let data = Data(xml.utf8)
let snapshot = try JetBrainsStatusProbe.parseXMLData(data, detectedIDE: nil)
#expect(snapshot.quotaInfo.type == "Available")
#expect(snapshot.quotaInfo.used == 7478.3)
#expect(snapshot.quotaInfo.maximum == 1_000_000)
#expect(snapshot.quotaInfo.available == 992_521.7)
#expect(snapshot.refillInfo?.type == "Known")
#expect(snapshot.refillInfo?.amount == 1_000_000)
}
@Test
func parsesQuotaXMLWithOnlyQuotaInfo() throws {
let quotaInfo = "{"type":"free","current":"5000","maximum":"100000"}"
let xml = """
<?xml version="1.0" encoding="UTF-8"?>
<application>
<component name="AIAssistantQuotaManager2">
<option name="quotaInfo" value="\(quotaInfo)" />
</component>
</application>
"""
let data = Data(xml.utf8)
let snapshot = try JetBrainsStatusProbe.parseXMLData(data, detectedIDE: nil)
#expect(snapshot.quotaInfo.type == "free")
#expect(snapshot.quotaInfo.used == 5000)
#expect(snapshot.quotaInfo.maximum == 100_000)
#expect(snapshot.refillInfo == nil)
}
@Test
func parsesXMLWithReversedAttributeOrder() throws {
// Test that parser handles value before name (different attribute order)
let quotaInfo = "{"type":"paid","current":"1000","maximum":"50000"}"
let xml = """
<?xml version="1.0" encoding="UTF-8"?>
<application>
<component name="AIAssistantQuotaManager2">
<option value="\(quotaInfo)" name="quotaInfo" />
</component>
</application>
"""
let data = Data(xml.utf8)
let snapshot = try JetBrainsStatusProbe.parseXMLData(data, detectedIDE: nil)
#expect(snapshot.quotaInfo.type == "paid")
#expect(snapshot.quotaInfo.used == 1000)
#expect(snapshot.quotaInfo.maximum == 50000)
}
@Test
func handlesHTMLEntities() throws {
let quotaInfo = [
"{"type":"test"",
","current":"0"",
","maximum":"50000"}",
].joined()
let xml = """
<?xml version="1.0" encoding="UTF-8"?>
<application>
<component name="AIAssistantQuotaManager2">
<option name="quotaInfo" value="\(quotaInfo)" />
</component>
</application>
"""
let data = Data(xml.utf8)
let snapshot = try JetBrainsStatusProbe.parseXMLData(data, detectedIDE: nil)
#expect(snapshot.quotaInfo.type == "test")
#expect(snapshot.quotaInfo.maximum == 50000)
}
@Test
func throwsOnMissingQuotaInfo() throws {
let xml = """
<?xml version="1.0" encoding="UTF-8"?>
<application>
<component name="AIAssistantQuotaManager2">
</component>
</application>
"""
let data = Data(xml.utf8)
#expect(throws: JetBrainsStatusProbeError.noQuotaInfo) {
_ = try JetBrainsStatusProbe.parseXMLData(data, detectedIDE: nil)
}
}
@Test
func throwsOnMissingComponent() throws {
let xml = """
<?xml version="1.0" encoding="UTF-8"?>
<application>
<component name="SomeOtherComponent">
<option name="quotaInfo" value="{}" />
</component>
</application>
"""
let data = Data(xml.utf8)
#expect(throws: JetBrainsStatusProbeError.noQuotaInfo) {
_ = try JetBrainsStatusProbe.parseXMLData(data, detectedIDE: nil)
}
}
@Test
func throwsOnEmptyQuotaInfo() throws {
let xml = """
<?xml version="1.0" encoding="UTF-8"?>
<application>
<component name="AIAssistantQuotaManager2">
<option name="quotaInfo" value="" />
</component>
</application>
"""
let data = Data(xml.utf8)
#expect(throws: JetBrainsStatusProbeError.noQuotaInfo) {
_ = try JetBrainsStatusProbe.parseXMLData(data, detectedIDE: nil)
}
}
@Test
func parsesXMLWithSingleQuotes() throws {
let quotaInfo = "{"type":"single","current":"100","maximum":"10000"}"
let xml = """
<?xml version="1.0" encoding="UTF-8"?>
<application>
<component name='AIAssistantQuotaManager2'>
<option name='quotaInfo' value='\(quotaInfo)' />
</component>
</application>
"""
let data = Data(xml.utf8)
let snapshot = try JetBrainsStatusProbe.parseXMLData(data, detectedIDE: nil)
#expect(snapshot.quotaInfo.type == "single")
#expect(snapshot.quotaInfo.maximum == 10000)
}
@Test
func parsesXMLWithComments() throws {
let quotaInfo = "{"type":"comment","current":"10","maximum":"100"}"
let xml = """
<?xml version="1.0" encoding="UTF-8"?>
<!-- top comment -->
<application>
<component name="AIAssistantQuotaManager2">
<!-- inside comment -->
<option name="quotaInfo" value="\(quotaInfo)" />
</component>
</application>
"""
let data = Data(xml.utf8)
let snapshot = try JetBrainsStatusProbe.parseXMLData(data, detectedIDE: nil)
#expect(snapshot.quotaInfo.type == "comment")
#expect(snapshot.quotaInfo.maximum == 100)
}
@Test
func parsesXMLWithMultipleComponentsUsesCorrectOne() throws {
let otherQuota = "{"type":"wrong","current":"1","maximum":"2"}"
let quotaInfo = "{"type":"right","current":"42","maximum":"100"}"
let xml = """
<?xml version="1.0" encoding="UTF-8"?>
<application>
<component name="OtherComponent">
<option name="quotaInfo" value="\(otherQuota)" />
</component>
<component name="AIAssistantQuotaManager2">
<option name="quotaInfo" value="\(quotaInfo)" />
</component>
</application>
"""
let data = Data(xml.utf8)
let snapshot = try JetBrainsStatusProbe.parseXMLData(data, detectedIDE: nil)
#expect(snapshot.quotaInfo.type == "right")
#expect(snapshot.quotaInfo.used == 42)
}
@Test
func parsesXMLWithNextRefillBeforeQuotaInfo() throws {
let quotaInfo = "{"type":"order","current":"5","maximum":"50"}"
let nextRefill = "{"type":"Known","next":"2026-01-16T14:00:54.939Z","amount":"100"}"
let xml = """
<?xml version="1.0" encoding="UTF-8"?>
<application>
<component name="AIAssistantQuotaManager2">
<option name="nextRefill" value="\(nextRefill)" />
<option name="quotaInfo" value="\(quotaInfo)" />
</component>
</application>
"""
let data = Data(xml.utf8)
let snapshot = try JetBrainsStatusProbe.parseXMLData(data, detectedIDE: nil)
#expect(snapshot.quotaInfo.type == "order")
#expect(snapshot.refillInfo?.amount == 100)
}
}