blob: 464c49778330a68203bd11db37361576ed1cf1b8 [file] [log] [blame]
package parser
import (
"encoding/json"
"testing"
"github.com/KorAP/KoralPipe-TermMapper2/pkg/ast"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestParseJSON(t *testing.T) {
tests := []struct {
name string
input string
expected ast.Node
wantErr bool
}{
{
name: "Parse simple term",
input: `{
"@type": "koral:term",
"foundry": "opennlp",
"key": "DET",
"layer": "p",
"match": "match:eq"
}`,
expected: &ast.Term{
Foundry: "opennlp",
Key: "DET",
Layer: "p",
Match: ast.MatchEqual,
},
wantErr: false,
},
{
name: "Parse term group with AND relation",
input: `{
"@type": "koral:termGroup",
"operands": [
{
"@type": "koral:term",
"foundry": "opennlp",
"key": "DET",
"layer": "p",
"match": "match:eq"
},
{
"@type": "koral:term",
"foundry": "opennlp",
"key": "AdjType",
"layer": "m",
"match": "match:eq",
"value": "Pdt"
}
],
"relation": "relation:and"
}`,
expected: &ast.TermGroup{
Operands: []ast.Node{
&ast.Term{
Foundry: "opennlp",
Key: "DET",
Layer: "p",
Match: ast.MatchEqual,
},
&ast.Term{
Foundry: "opennlp",
Key: "AdjType",
Layer: "m",
Match: ast.MatchEqual,
Value: "Pdt",
},
},
Relation: ast.AndRelation,
},
wantErr: false,
},
{
name: "Parse token with wrapped term",
input: `{
"@type": "koral:token",
"wrap": {
"@type": "koral:term",
"foundry": "opennlp",
"key": "DET",
"layer": "p",
"match": "match:eq"
}
}`,
expected: &ast.Token{
Wrap: &ast.Term{
Foundry: "opennlp",
Key: "DET",
Layer: "p",
Match: ast.MatchEqual,
},
},
wantErr: false,
},
{
name: "Parse complex nested structure",
input: `{
"@type": "koral:token",
"wrap": {
"@type": "koral:termGroup",
"operands": [
{
"@type": "koral:term",
"foundry": "opennlp",
"key": "DET",
"layer": "p",
"match": "match:eq"
},
{
"@type": "koral:termGroup",
"operands": [
{
"@type": "koral:term",
"foundry": "opennlp",
"key": "AdjType",
"layer": "m",
"match": "match:eq",
"value": "Pdt"
},
{
"@type": "koral:term",
"foundry": "opennlp",
"key": "PronType",
"layer": "m",
"match": "match:ne",
"value": "Neg"
}
],
"relation": "relation:or"
}
],
"relation": "relation:and"
}
}`,
expected: &ast.Token{
Wrap: &ast.TermGroup{
Operands: []ast.Node{
&ast.Term{
Foundry: "opennlp",
Key: "DET",
Layer: "p",
Match: ast.MatchEqual,
},
&ast.TermGroup{
Operands: []ast.Node{
&ast.Term{
Foundry: "opennlp",
Key: "AdjType",
Layer: "m",
Match: ast.MatchEqual,
Value: "Pdt",
},
&ast.Term{
Foundry: "opennlp",
Key: "PronType",
Layer: "m",
Match: ast.MatchNotEqual,
Value: "Neg",
},
},
Relation: ast.OrRelation,
},
},
Relation: ast.AndRelation,
},
},
wantErr: false,
},
{
name: "Invalid JSON",
input: `{"invalid": json`,
wantErr: true,
},
{
name: "Empty JSON",
input: `{}`,
wantErr: true,
},
{
name: "Invalid node type",
input: `{
"@type": "koral:unknown",
"key": "value"
}`,
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := ParseJSON([]byte(tt.input))
if tt.wantErr {
assert.Error(t, err)
return
}
require.NoError(t, err)
assert.Equal(t, tt.expected, result)
})
}
}
func TestSerializeToJSON(t *testing.T) {
tests := []struct {
name string
input ast.Node
expected string
wantErr bool
}{
{
name: "Serialize simple term",
input: &ast.Term{
Foundry: "opennlp",
Key: "DET",
Layer: "p",
Match: ast.MatchEqual,
},
expected: `{
"@type": "koral:term",
"foundry": "opennlp",
"key": "DET",
"layer": "p",
"match": "match:eq"
}`,
wantErr: false,
},
{
name: "Serialize term group",
input: &ast.TermGroup{
Operands: []ast.Node{
&ast.Term{
Foundry: "opennlp",
Key: "DET",
Layer: "p",
Match: ast.MatchEqual,
},
&ast.Term{
Foundry: "opennlp",
Key: "AdjType",
Layer: "m",
Match: ast.MatchEqual,
Value: "Pdt",
},
},
Relation: ast.AndRelation,
},
expected: `{
"@type": "koral:termGroup",
"operands": [
{
"@type": "koral:term",
"foundry": "opennlp",
"key": "DET",
"layer": "p",
"match": "match:eq"
},
{
"@type": "koral:term",
"foundry": "opennlp",
"key": "AdjType",
"layer": "m",
"match": "match:eq",
"value": "Pdt"
}
],
"relation": "relation:and"
}`,
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := SerializeToJSON(tt.input)
if tt.wantErr {
assert.Error(t, err)
return
}
require.NoError(t, err)
// Compare JSON objects instead of raw strings to avoid whitespace issues
var expected, actual interface{}
err = json.Unmarshal([]byte(tt.expected), &expected)
require.NoError(t, err)
err = json.Unmarshal(result, &actual)
require.NoError(t, err)
assert.Equal(t, expected, actual)
})
}
}
func TestRoundTrip(t *testing.T) {
// Test that parsing and then serializing produces equivalent JSON
input := `{
"@type": "koral:token",
"wrap": {
"@type": "koral:termGroup",
"operands": [
{
"@type": "koral:term",
"foundry": "opennlp",
"key": "DET",
"layer": "p",
"match": "match:eq"
},
{
"@type": "koral:term",
"foundry": "opennlp",
"key": "AdjType",
"layer": "m",
"match": "match:eq",
"value": "Pdt"
}
],
"relation": "relation:and"
}
}`
// Parse JSON to AST
node, err := ParseJSON([]byte(input))
require.NoError(t, err)
// Serialize AST back to JSON
output, err := SerializeToJSON(node)
require.NoError(t, err)
// Compare JSON objects
var expected, actual interface{}
err = json.Unmarshal([]byte(input), &expected)
require.NoError(t, err)
err = json.Unmarshal(output, &actual)
require.NoError(t, err)
assert.Equal(t, expected, actual)
}