(t *testing.T)
| 188 | } |
| 189 | |
| 190 | func TestTemporalAtomNormalization(t *testing.T) { |
| 191 | // Identify predicates. |
| 192 | p := ast.PredicateSym{"p", 1} |
| 193 | q := ast.PredicateSym{"q", 1} |
| 194 | |
| 195 | // Declare p and q as temporal. |
| 196 | // We use a custom analyzer to bypass the parser and manually inject declarations and clauses. |
| 197 | analyzer, err := New(nil, nil, ErrorForBoundsMismatch) |
| 198 | if err != nil { |
| 199 | t.Fatalf("New() error = %v", err) |
| 200 | } |
| 201 | analyzer.decl[p] = ast.Decl{ |
| 202 | DeclaredAtom: ast.Atom{p, []ast.BaseTerm{ast.Variable{"X"}}}, |
| 203 | Descr: []ast.Atom{ast.NewAtom(ast.DescrTemporal)}, |
| 204 | } |
| 205 | analyzer.decl[q] = ast.Decl{ |
| 206 | DeclaredAtom: ast.Atom{q, []ast.BaseTerm{ast.Variable{"X"}}}, |
| 207 | Descr: []ast.Atom{ast.NewAtom(ast.DescrTemporal)}, |
| 208 | } |
| 209 | |
| 210 | // Helper to create *ast.Interval |
| 211 | mkInterval := func(start, end string) *ast.Interval { |
| 212 | i := ast.NewInterval(ast.NewVariableBound(ast.Variable{start}), ast.NewVariableBound(ast.Variable{end})) |
| 213 | return &i |
| 214 | } |
| 215 | |
| 216 | // Case 1: Valid TemporalAtom (should be normalized and pass) |
| 217 | // p(X) :- q(X) @[S, E] |
| 218 | validClause := ast.Clause{ |
| 219 | Head: ast.Atom{p, []ast.BaseTerm{ast.Variable{"X"}}}, |
| 220 | HeadTime: mkInterval("S", "E"), |
| 221 | Premises: []ast.Term{ |
| 222 | ast.TemporalAtom{ |
| 223 | Atom: ast.Atom{q, []ast.BaseTerm{ast.Variable{"X"}}}, |
| 224 | Interval: mkInterval("S", "E"), |
| 225 | }, |
| 226 | }, |
| 227 | } |
| 228 | |
| 229 | // Analyze the clause. |
| 230 | _, err = analyzer.Analyze([]ast.Clause{validClause}) |
| 231 | if err != nil { |
| 232 | t.Errorf("Analyze(validClause) unexpected error: %v", err) |
| 233 | } |
| 234 | |
| 235 | // Verify normalization |
| 236 | info, err := analyzer.Analyze([]ast.Clause{validClause}) |
| 237 | if err != nil { |
| 238 | t.Errorf("Analyze(validClause) unexpected error: %v", err) |
| 239 | } |
| 240 | if len(info.Rules) != 1 { |
| 241 | t.Fatalf("Expected 1 rule, got %d", len(info.Rules)) |
| 242 | } |
| 243 | rule := info.Rules[0] |
| 244 | if _, ok := rule.Premises[0].(ast.TemporalLiteral); !ok { |
| 245 | t.Errorf("Premise was not normalized to TemporalLiteral: %T", rule.Premises[0]) |
| 246 | } |
| 247 |
nothing calls this directly
no test coverage detected