Akron | 57ee558 | 2025-05-21 15:25:13 +0200 | [diff] [blame^] | 1 | package config |
| 2 | |
| 3 | import ( |
| 4 | "os" |
| 5 | "testing" |
| 6 | |
| 7 | "github.com/KorAP/KoralPipe-TermMapper2/pkg/ast" |
| 8 | "github.com/stretchr/testify/assert" |
| 9 | "github.com/stretchr/testify/require" |
| 10 | ) |
| 11 | |
| 12 | func TestLoadConfig(t *testing.T) { |
| 13 | // Create a temporary YAML file |
| 14 | content := ` |
| 15 | - id: opennlp-mapper |
| 16 | foundryA: opennlp |
| 17 | layerA: p |
| 18 | foundryB: upos |
| 19 | layerB: p |
| 20 | mappings: |
| 21 | - "[PIDAT] <> [opennlp/p=PIDAT & opennlp/p=AdjType:Pdt]" |
| 22 | - "[PAV] <> [ADV & PronType:Dem]" |
| 23 | |
| 24 | - id: simple-mapper |
| 25 | mappings: |
| 26 | - "[A] <> [B]" |
| 27 | ` |
| 28 | tmpfile, err := os.CreateTemp("", "config-*.yaml") |
| 29 | require.NoError(t, err) |
| 30 | defer os.Remove(tmpfile.Name()) |
| 31 | |
| 32 | _, err = tmpfile.WriteString(content) |
| 33 | require.NoError(t, err) |
| 34 | err = tmpfile.Close() |
| 35 | require.NoError(t, err) |
| 36 | |
| 37 | // Test loading the configuration |
| 38 | config, err := LoadConfig(tmpfile.Name()) |
| 39 | require.NoError(t, err) |
| 40 | |
| 41 | // Verify the configuration |
| 42 | require.Len(t, config.Lists, 2) |
| 43 | |
| 44 | // Check first mapping list |
| 45 | list1 := config.Lists[0] |
| 46 | assert.Equal(t, "opennlp-mapper", list1.ID) |
| 47 | assert.Equal(t, "opennlp", list1.FoundryA) |
| 48 | assert.Equal(t, "p", list1.LayerA) |
| 49 | assert.Equal(t, "upos", list1.FoundryB) |
| 50 | assert.Equal(t, "p", list1.LayerB) |
| 51 | require.Len(t, list1.Mappings, 2) |
| 52 | assert.Equal(t, "[PIDAT] <> [opennlp/p=PIDAT & opennlp/p=AdjType:Pdt]", string(list1.Mappings[0])) |
| 53 | assert.Equal(t, "[PAV] <> [ADV & PronType:Dem]", string(list1.Mappings[1])) |
| 54 | |
| 55 | // Check second mapping list |
| 56 | list2 := config.Lists[1] |
| 57 | assert.Equal(t, "simple-mapper", list2.ID) |
| 58 | assert.Empty(t, list2.FoundryA) |
| 59 | assert.Empty(t, list2.LayerA) |
| 60 | assert.Empty(t, list2.FoundryB) |
| 61 | assert.Empty(t, list2.LayerB) |
| 62 | require.Len(t, list2.Mappings, 1) |
| 63 | assert.Equal(t, "[A] <> [B]", string(list2.Mappings[0])) |
| 64 | } |
| 65 | |
| 66 | func TestParseMappings(t *testing.T) { |
| 67 | list := &MappingList{ |
| 68 | ID: "test-mapper", |
| 69 | FoundryA: "opennlp", |
| 70 | LayerA: "p", |
| 71 | FoundryB: "upos", |
| 72 | LayerB: "p", |
| 73 | Mappings: []MappingRule{ |
| 74 | "[PIDAT] <> [opennlp/p=PIDAT & opennlp/p=AdjType:Pdt]", |
| 75 | }, |
| 76 | } |
| 77 | |
| 78 | results, err := list.ParseMappings() |
| 79 | require.NoError(t, err) |
| 80 | require.Len(t, results, 1) |
| 81 | |
| 82 | // Check the parsed upper pattern |
| 83 | upper := results[0].Upper |
| 84 | require.NotNil(t, upper) |
| 85 | require.IsType(t, &ast.Token{}, upper) |
| 86 | upperTerm := upper.Wrap.(*ast.Term) |
| 87 | assert.Equal(t, "opennlp", upperTerm.Foundry) |
| 88 | assert.Equal(t, "p", upperTerm.Layer) |
| 89 | assert.Equal(t, "PIDAT", upperTerm.Key) |
| 90 | |
| 91 | // Check the parsed lower pattern |
| 92 | lower := results[0].Lower |
| 93 | require.NotNil(t, lower) |
| 94 | require.IsType(t, &ast.Token{}, lower) |
| 95 | lowerGroup := lower.Wrap.(*ast.TermGroup) |
| 96 | require.Len(t, lowerGroup.Operands, 2) |
| 97 | assert.Equal(t, ast.AndRelation, lowerGroup.Relation) |
| 98 | |
| 99 | // Check first operand |
| 100 | term1 := lowerGroup.Operands[0].(*ast.Term) |
| 101 | assert.Equal(t, "opennlp", term1.Foundry) |
| 102 | assert.Equal(t, "p", term1.Layer) |
| 103 | assert.Equal(t, "PIDAT", term1.Key) |
| 104 | |
| 105 | // Check second operand |
| 106 | term2 := lowerGroup.Operands[1].(*ast.Term) |
| 107 | assert.Equal(t, "opennlp", term2.Foundry) |
| 108 | assert.Equal(t, "p", term2.Layer) |
| 109 | assert.Equal(t, "AdjType", term2.Key) |
| 110 | assert.Equal(t, "Pdt", term2.Value) |
| 111 | } |
| 112 | |
| 113 | func TestLoadConfigValidation(t *testing.T) { |
| 114 | tests := []struct { |
| 115 | name string |
| 116 | content string |
| 117 | wantErr string |
| 118 | }{ |
| 119 | { |
| 120 | name: "Missing ID", |
| 121 | content: ` |
| 122 | - foundryA: opennlp |
| 123 | mappings: |
| 124 | - "[A] <> [B]" |
| 125 | `, |
| 126 | wantErr: "mapping list at index 0 is missing an ID", |
| 127 | }, |
| 128 | { |
| 129 | name: "Empty mappings", |
| 130 | content: ` |
| 131 | - id: test |
| 132 | foundryA: opennlp |
| 133 | mappings: [] |
| 134 | `, |
| 135 | wantErr: "mapping list 'test' has no mapping rules", |
| 136 | }, |
| 137 | { |
| 138 | name: "Empty rule", |
| 139 | content: ` |
| 140 | - id: test |
| 141 | mappings: |
| 142 | - "" |
| 143 | `, |
| 144 | wantErr: "mapping list 'test' rule at index 0 is empty", |
| 145 | }, |
| 146 | } |
| 147 | |
| 148 | for _, tt := range tests { |
| 149 | t.Run(tt.name, func(t *testing.T) { |
| 150 | tmpfile, err := os.CreateTemp("", "config-*.yaml") |
| 151 | require.NoError(t, err) |
| 152 | defer os.Remove(tmpfile.Name()) |
| 153 | |
| 154 | _, err = tmpfile.WriteString(tt.content) |
| 155 | require.NoError(t, err) |
| 156 | err = tmpfile.Close() |
| 157 | require.NoError(t, err) |
| 158 | |
| 159 | _, err = LoadConfig(tmpfile.Name()) |
| 160 | require.Error(t, err) |
| 161 | assert.Contains(t, err.Error(), tt.wantErr) |
| 162 | }) |
| 163 | } |
| 164 | } |