Skip to content

Commit fdfe9f4

Browse files
committed
Convert test/qa-tests/jstests/import/import_document_validation.js to Go
1 parent e96d0a3 commit fdfe9f4

2 files changed

Lines changed: 141 additions & 153 deletions

File tree

mongoimport/mongoimport_test.go

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3016,3 +3016,144 @@ func writeFieldFile(t *testing.T, dir, name string, fields []string) string {
30163016
require.NoError(t, os.WriteFile(path, []byte(strings.Join(fields, "\n")+"\n"), 0o644))
30173017
return path
30183018
}
3019+
3020+
// TestImportDocumentValidation verifies mongoimport behavior with collection
3021+
// validators: normal import skips invalid docs, --bypassDocumentValidation
3022+
// imports all, --stopOnError and --maintainInsertionOrder fail on validation
3023+
// errors.
3024+
func TestImportDocumentValidation(t *testing.T) {
3025+
testtype.SkipUnlessTestType(t, testtype.IntegrationTestType)
3026+
3027+
const dbName = "mongoimport_docvalidation_test"
3028+
const collName = "bar"
3029+
3030+
sessionProvider, _, err := testutil.GetBareSessionProvider()
3031+
require.NoError(t, err)
3032+
client, err := sessionProvider.GetSession()
3033+
require.NoError(t, err)
3034+
t.Cleanup(func() {
3035+
if err := client.Database(dbName).Drop(context.Background()); err != nil {
3036+
t.Errorf("dropping test database: %v", err)
3037+
}
3038+
})
3039+
3040+
db := client.Database(dbName)
3041+
3042+
// 1000 docs: even-indexed lack `baz` (invalid), odd-indexed have `baz` (valid).
3043+
docs := make([]any, 1000)
3044+
for i := range 1000 {
3045+
if i%2 == 0 {
3046+
docs[i] = bson.D{{"_id", int32(i)}, {"num", int32(i + 1)}, {"s", fmt.Sprintf("%d", i)}}
3047+
} else {
3048+
docs[i] = bson.D{{"_id", int32(i)}, {"num", int32(i + 1)}, {"s", fmt.Sprintf("%d", i)}, {"baz", int32(i)}}
3049+
}
3050+
}
3051+
_, err = db.Collection(collName).InsertMany(t.Context(), docs)
3052+
require.NoError(t, err)
3053+
3054+
exportToolOptions, err := testutil.GetToolOptions()
3055+
require.NoError(t, err)
3056+
exportToolOptions.Namespace = &options.Namespace{DB: dbName, Collection: collName}
3057+
me, err := mongoexport.New(mongoexport.Options{
3058+
ToolOptions: exportToolOptions,
3059+
OutputFormatOptions: &mongoexport.OutputFormatOptions{
3060+
Type: "json",
3061+
JSONFormat: "canonical",
3062+
},
3063+
InputOptions: &mongoexport.InputOptions{},
3064+
})
3065+
require.NoError(t, err)
3066+
defer me.Close()
3067+
tmpFile, err := os.CreateTemp(t.TempDir(), "export-*.json")
3068+
require.NoError(t, err)
3069+
_, err = me.Export(tmpFile)
3070+
require.NoError(t, err)
3071+
require.NoError(t, tmpFile.Close())
3072+
3073+
validator := bson.D{{"baz", bson.D{{"$exists", true}}}}
3074+
ns := &options.Namespace{DB: dbName, Collection: collName}
3075+
3076+
t.Run("no validator imports all docs", func(t *testing.T) {
3077+
require.NoError(t, db.Drop(t.Context()))
3078+
require.NoError(t, importWithIngestOpts(t, ns, tmpFile.Name(), IngestOptions{}))
3079+
n, err := db.Collection(collName).CountDocuments(t.Context(), bson.D{})
3080+
require.NoError(t, err)
3081+
assert.EqualValues(t, 1000, n, "import without validation should import all 1000 documents")
3082+
})
3083+
3084+
t.Run("validator skips invalid docs", func(t *testing.T) {
3085+
recreateWithValidator(t, db, validator)
3086+
require.NoError(t, importWithIngestOpts(t, ns, tmpFile.Name(), IngestOptions{}))
3087+
n, err := db.Collection(collName).CountDocuments(t.Context(), bson.D{})
3088+
require.NoError(t, err)
3089+
assert.EqualValues(t, 500, n, "only valid documents should be imported")
3090+
})
3091+
3092+
t.Run("stopOnError fails on validation errors", func(t *testing.T) {
3093+
recreateWithValidator(t, db, validator)
3094+
err := importWithIngestOpts(t, ns, tmpFile.Name(), IngestOptions{StopOnError: true})
3095+
assertValidationError(t, err, "import with --stopOnError should fail on validation errors")
3096+
})
3097+
3098+
t.Run("maintainInsertionOrder fails on validation errors", func(t *testing.T) {
3099+
recreateWithValidator(t, db, validator)
3100+
err := importWithIngestOpts(
3101+
t, ns, tmpFile.Name(), IngestOptions{MaintainInsertionOrder: true},
3102+
)
3103+
assertValidationError(
3104+
t, err, "import with --maintainInsertionOrder should fail on validation errors",
3105+
)
3106+
})
3107+
3108+
t.Run("bypassDocumentValidation imports all docs", func(t *testing.T) {
3109+
recreateWithValidator(t, db, validator)
3110+
require.NoError(t, importWithIngestOpts(
3111+
t, ns, tmpFile.Name(), IngestOptions{BypassDocumentValidation: true},
3112+
))
3113+
n, err := db.Collection(collName).CountDocuments(t.Context(), bson.D{})
3114+
require.NoError(t, err)
3115+
assert.EqualValues(
3116+
t, 1000, n, "all documents should be imported with --bypassDocumentValidation",
3117+
)
3118+
})
3119+
}
3120+
3121+
func recreateWithValidator(t *testing.T, db *mongo.Database, validator any) {
3122+
t.Helper()
3123+
require.NoError(t, db.Drop(context.Background()))
3124+
require.NoError(
3125+
t,
3126+
db.CreateCollection(
3127+
context.Background(), "bar", mopt.CreateCollection().SetValidator(validator),
3128+
),
3129+
)
3130+
}
3131+
3132+
func assertValidationError(t *testing.T, err error, msg string) {
3133+
t.Helper()
3134+
var bwe mongo.BulkWriteException
3135+
if assert.ErrorAs(t, err, &bwe, msg) {
3136+
assert.NotEmpty(t, bwe.WriteErrors, "should have at least one write error")
3137+
assert.Equal(t, 121, bwe.WriteErrors[0].Code, "should be DocumentValidationFailure (121)")
3138+
}
3139+
}
3140+
3141+
func importWithIngestOpts(
3142+
t *testing.T,
3143+
ns *options.Namespace,
3144+
filePath string,
3145+
ingestOpts IngestOptions,
3146+
) error {
3147+
t.Helper()
3148+
toolOptions, err := testutil.GetToolOptions()
3149+
require.NoError(t, err)
3150+
toolOptions.Namespace = ns
3151+
mi, err := New(Options{
3152+
ToolOptions: toolOptions,
3153+
InputOptions: &InputOptions{File: filePath, ParseGrace: "stop"},
3154+
IngestOptions: &ingestOpts,
3155+
})
3156+
require.NoError(t, err)
3157+
_, _, err = mi.ImportDocuments()
3158+
return err
3159+
}

test/qa-tests/jstests/import/import_document_validation.js

Lines changed: 0 additions & 153 deletions
This file was deleted.

0 commit comments

Comments
 (0)