|
8 | 8 | "fmt" |
9 | 9 | "io" |
10 | 10 | "io/fs" |
| 11 | + "os" |
11 | 12 | "path/filepath" |
12 | 13 | "strings" |
13 | 14 | "testing" |
@@ -1375,3 +1376,85 @@ func extractSchemaFromOpenAPI(openAPIDoc *openapi.OpenAPI, pointer string) (*oas |
1375 | 1376 |
|
1376 | 1377 | return schema, nil |
1377 | 1378 | } |
| 1379 | + |
| 1380 | +func TestInline_EmailParser_PagerDuty_Success(t *testing.T) { |
| 1381 | + t.Parallel() |
| 1382 | + |
| 1383 | + // This test reproduces the bug with EmailParser schema from pagerduty.json |
| 1384 | + // The EmailParser schema contains a reference to MatchPredicate, which has a circular reference |
| 1385 | + // through its "children" property that references back to itself |
| 1386 | + ctx := t.Context() |
| 1387 | + |
| 1388 | + // Read the pagerduty.json file content |
| 1389 | + pagerDutyContent, err := os.ReadFile("testdata/pagerduty.json") |
| 1390 | + require.NoError(t, err, "failed to read pagerduty.json") |
| 1391 | + |
| 1392 | + // Parse as OpenAPI document |
| 1393 | + pagerDutyDoc, err := parseJSONToOpenAPI(ctx, string(pagerDutyContent)) |
| 1394 | + require.NoError(t, err, "failed to parse pagerduty.json as OpenAPI") |
| 1395 | + |
| 1396 | + // Extract multiple schemas that all use the Integration schema to trigger the bug |
| 1397 | + // when the same MatchPredicate gets processed multiple times in the same session |
| 1398 | + |
| 1399 | + // PUT /services/{id}/integrations/{integration_id} requestBody |
| 1400 | + putRequestBodySchema, err := extractSchemaFromOpenAPI(pagerDutyDoc, "/paths/~1services~1{id}~1integrations~1{integration_id}/put/requestBody/content/application~1json/schema") |
| 1401 | + require.NoError(t, err, "failed to extract PUT requestBody schema") |
| 1402 | + |
| 1403 | + // POST /services/{id}/integrations requestBody (same Integration schema) |
| 1404 | + postRequestBodySchema, err := extractSchemaFromOpenAPI(pagerDutyDoc, "/paths/~1services~1{id}~1integrations/post/requestBody/content/application~1json/schema") |
| 1405 | + require.NoError(t, err, "failed to extract POST requestBody schema") |
| 1406 | + |
| 1407 | + // POST /services/{id}/integrations 201 response (also uses Integration schema) |
| 1408 | + postResponseSchema, err := extractSchemaFromOpenAPI(pagerDutyDoc, "/paths/~1services~1{id}~1integrations/post/responses/201/content/application~1json/schema") |
| 1409 | + require.NoError(t, err, "failed to extract POST 201 response schema") |
| 1410 | + |
| 1411 | + // Create resolve options using the pagerduty document as the root document |
| 1412 | + opts := oas3.InlineOptions{ |
| 1413 | + ResolveOptions: oas3.ResolveOptions{ |
| 1414 | + TargetLocation: "testdata/pagerduty.json", |
| 1415 | + RootDocument: pagerDutyDoc, |
| 1416 | + }, |
| 1417 | + RemoveUnusedDefs: true, |
| 1418 | + } |
| 1419 | + |
| 1420 | + // First, inline the PUT requestBody schema |
| 1421 | + inlined1, err := oas3.Inline(ctx, putRequestBodySchema, opts) |
| 1422 | + require.NoError(t, err, "first inlining should succeed for PUT requestBody schema") |
| 1423 | + require.NotNil(t, inlined1, "first inlined schema should not be nil") |
| 1424 | + |
| 1425 | + // Then, inline the POST requestBody schema in the same session |
| 1426 | + // This should trigger the bug because MatchPredicate gets processed again |
| 1427 | + inlined2, err := oas3.Inline(ctx, postRequestBodySchema, opts) |
| 1428 | + require.NoError(t, err, "second inlining should succeed for POST requestBody schema") |
| 1429 | + require.NotNil(t, inlined2, "second inlined schema should not be nil") |
| 1430 | + |
| 1431 | + // Finally, inline the POST response schema in the same session |
| 1432 | + // This is the third time the same Integration->EmailParser->MatchPredicate chain gets processed |
| 1433 | + inlined3, err := oas3.Inline(ctx, postResponseSchema, opts) |
| 1434 | + require.NoError(t, err, "third inlining should succeed for POST response schema") |
| 1435 | + require.NotNil(t, inlined3, "third inlined schema should not be nil") |
| 1436 | + |
| 1437 | + // Verify all results are valid |
| 1438 | + actualJSON1, err := schemaToJSON(ctx, inlined1) |
| 1439 | + require.NoError(t, err, "failed to convert first inlined result to JSON") |
| 1440 | + require.NotEmpty(t, actualJSON1, "first inlined JSON should not be empty") |
| 1441 | + |
| 1442 | + actualJSON2, err := schemaToJSON(ctx, inlined2) |
| 1443 | + require.NoError(t, err, "failed to convert second inlined result to JSON") |
| 1444 | + require.NotEmpty(t, actualJSON2, "second inlined JSON should not be empty") |
| 1445 | + |
| 1446 | + actualJSON3, err := schemaToJSON(ctx, inlined3) |
| 1447 | + require.NoError(t, err, "failed to convert third inlined result to JSON") |
| 1448 | + require.NotEmpty(t, actualJSON3, "third inlined JSON should not be empty") |
| 1449 | + |
| 1450 | + // All schemas should contain the Integration structure with EmailParser inlined |
| 1451 | + for i, actualJSON := range []string{actualJSON1, actualJSON2, actualJSON3} { |
| 1452 | + assert.Contains(t, actualJSON, `"integration"`, "schema %d should contain integration property", i+1) |
| 1453 | + assert.Contains(t, actualJSON, `"action"`, "schema %d should contain action property from inlined EmailParser", i+1) |
| 1454 | + assert.Contains(t, actualJSON, `"match_predicate"`, "schema %d should contain match_predicate property", i+1) |
| 1455 | + } |
| 1456 | + |
| 1457 | + t.Logf("Successfully inlined 3 schemas with shared Integration->EmailParser->MatchPredicate references") |
| 1458 | + t.Logf("PUT request: %d chars, POST request: %d chars, POST response: %d chars", |
| 1459 | + len(actualJSON1), len(actualJSON2), len(actualJSON3)) |
| 1460 | +} |
0 commit comments