How to use Save method of db Package

Best Syzkaller code snippet using db.Save

couchdb_test.go

Source:couchdb_test.go Github

copy

Full Screen

...153 //Test deleteIndex with bad connection154 err = badDB.deleteIndex("", "")155 require.Error(t, err, "Error should have been thrown with deleteIndex and invalid connection")156}157func TestDBCreateSaveWithoutRevision(t *testing.T) {158 config := testConfig()159 couchDBEnv.startCouchDB(t)160 config.Address = couchDBEnv.couchAddress161 defer couchDBEnv.cleanup(config)162 database := "testdbcreatesavewithoutrevision"163 //create a new instance and database object164 couchInstance, err := createCouchInstance(config, &disabled.Provider{})165 require.NoError(t, err, "Error when trying to create couch instance")166 db := couchDatabase{couchInstance: couchInstance, dbName: database}167 //create a new database168 errdb := db.createDatabaseIfNotExist()169 require.NoError(t, errdb, "Error when trying to create database")170 //Save the test document171 _, saveerr := db.saveDoc("2", "", &couchDoc{jsonValue: assetJSON, attachments: nil})172 require.NoError(t, saveerr, "Error when trying to save a document")173}174func TestDBCreateEnsureFullCommit(t *testing.T) {175 config := testConfig()176 couchDBEnv.startCouchDB(t)177 config.Address = couchDBEnv.couchAddress178 defer couchDBEnv.cleanup(config)179 database := "testdbensurefullcommit"180 //create a new instance and database object181 couchInstance, err := createCouchInstance(config, &disabled.Provider{})182 require.NoError(t, err, "Error when trying to create couch instance")183 db := couchDatabase{couchInstance: couchInstance, dbName: database}184 //create a new database185 errdb := db.createDatabaseIfNotExist()186 require.NoError(t, errdb, "Error when trying to create database")187 //Save the test document188 _, saveerr := db.saveDoc("2", "", &couchDoc{jsonValue: assetJSON, attachments: nil})189 require.NoError(t, saveerr, "Error when trying to save a document")190}191func TestIsEmpty(t *testing.T) {192 config := testConfig()193 couchDBEnv.startCouchDB(t)194 config.Address = couchDBEnv.couchAddress195 defer couchDBEnv.cleanup(config)196 couchInstance, err := createCouchInstance(config, &disabled.Provider{})197 require.NoError(t, err)198 ignore := []string{"_global_changes", "_replicator", "_users", "fabric__internal"}199 isEmpty, err := couchInstance.isEmpty(ignore)200 require.NoError(t, err)201 require.True(t, isEmpty)202 testdbs := []string{"testdb1", "testdb2"}203 couchDBEnv.cleanup(config)204 for _, d := range testdbs {205 db := couchDatabase{couchInstance: couchInstance, dbName: d}206 require.NoError(t, db.createDatabaseIfNotExist())207 }208 isEmpty, err = couchInstance.isEmpty(ignore)209 require.NoError(t, err)210 require.False(t, isEmpty)211 ignore = append(ignore, "testdb1")212 isEmpty, err = couchInstance.isEmpty(ignore)213 require.NoError(t, err)214 require.False(t, isEmpty)215 ignore = append(ignore, "testdb2")216 isEmpty, err = couchInstance.isEmpty(ignore)217 require.NoError(t, err)218 require.True(t, isEmpty)219 configCopy := *config220 configCopy.Address = "junk"221 configCopy.MaxRetries = 0222 couchInstance.conf = &configCopy223 _, err = couchInstance.isEmpty(ignore)224 require.Error(t, err)225 require.Regexp(t, `unable to connect to CouchDB, check the hostname and port: http error calling couchdb: Get "?http://junk/_all_dbs"?`, err.Error())226}227func TestDBBadDatabaseName(t *testing.T) {228 config := testConfig()229 couchDBEnv.startCouchDB(t)230 config.Address = couchDBEnv.couchAddress231 defer couchDBEnv.cleanup(config)232 //create a new instance and database object using a valid database name mixed case233 couchInstance, err := createCouchInstance(config, &disabled.Provider{})234 require.NoError(t, err, "Error when trying to create couch instance")235 _, dberr := createCouchDatabase(couchInstance, "testDB")236 require.Error(t, dberr, "Error should have been thrown for an invalid db name")237 //create a new instance and database object using a valid database name letters and numbers238 couchInstance, err = createCouchInstance(config, &disabled.Provider{})239 require.NoError(t, err, "Error when trying to create couch instance")240 _, dberr = createCouchDatabase(couchInstance, "test132")241 require.NoError(t, dberr, "Error when testing a valid database name")242 //create a new instance and database object using a valid database name - special characters243 couchInstance, err = createCouchInstance(config, &disabled.Provider{})244 require.NoError(t, err, "Error when trying to create couch instance")245 _, dberr = createCouchDatabase(couchInstance, "test1234~!@#$%^&*()[]{}.")246 require.Error(t, dberr, "Error should have been thrown for an invalid db name")247 //create a new instance and database object using a invalid database name - too long /*248 couchInstance, err = createCouchInstance(config, &disabled.Provider{})249 require.NoError(t, err, "Error when trying to create couch instance")250 _, dberr = createCouchDatabase(couchInstance, "a12345678901234567890123456789012345678901234"+251 "56789012345678901234567890123456789012345678901234567890123456789012345678901234567890"+252 "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456"+253 "78901234567890123456789012345678901234567890")254 require.Error(t, dberr, "Error should have been thrown for invalid database name")255}256func TestDBBadConnection(t *testing.T) {257 //create a new instance and database object258 //Limit the maxRetriesOnStartup to 3 in order to reduce time for the failure259 config := &ledger.CouchDBConfig{260 Address: badConnectURL,261 Username: "admin",262 Password: "adminpw",263 MaxRetries: 3,264 MaxRetriesOnStartup: 3,265 RequestTimeout: 35 * time.Second,266 }267 _, err := createCouchInstance(config, &disabled.Provider{})268 require.Error(t, err, "Error should have been thrown for a bad connection")269}270func TestBadDBCredentials(t *testing.T) {271 config := testConfig()272 couchDBEnv.startCouchDB(t)273 config.Address = couchDBEnv.couchAddress274 defer couchDBEnv.cleanup(config)275 badConfig := testConfig()276 badConfig.Address = config.Address277 badConfig.Username = "fred"278 badConfig.Password = "fred"279 //create a new instance and database object280 _, err := createCouchInstance(badConfig, &disabled.Provider{})281 require.Error(t, err, "Error should have been thrown for bad credentials")282}283func TestDBCreateDatabaseAndPersist(t *testing.T) {284 config := testConfig()285 couchDBEnv.startCouchDB(t)286 config.Address = couchDBEnv.couchAddress287 defer couchDBEnv.cleanup(config)288 //Test create and persist with default configured maxRetries289 testDBCreateDatabaseAndPersist(t, config)290 couchDBEnv.cleanup(config)291 //Test create and persist with 0 retries292 configCopy := *config293 configCopy.MaxRetries = 0294 testDBCreateDatabaseAndPersist(t, &configCopy)295 couchDBEnv.cleanup(config)296 //Test batch operations with default configured maxRetries297 testBatchBatchOperations(t, config)298 couchDBEnv.cleanup(config)299 //Test batch operations with 0 retries300 testBatchBatchOperations(t, config)301}302func testDBCreateDatabaseAndPersist(t *testing.T, config *ledger.CouchDBConfig) {303 database := "testdbcreatedatabaseandpersist"304 //create a new instance and database object305 couchInstance, err := createCouchInstance(config, &disabled.Provider{})306 require.NoError(t, err, "Error when trying to create couch instance")307 db := couchDatabase{couchInstance: couchInstance, dbName: database}308 //create a new database309 errdb := db.createDatabaseIfNotExist()310 require.NoError(t, errdb, "Error when trying to create database")311 //Retrieve the info for the new database and make sure the name matches312 dbResp, _, errdb := db.getDatabaseInfo()313 require.NoError(t, errdb, "Error when trying to retrieve database information")314 require.Equal(t, database, dbResp.DbName)315 //Save the test document316 _, saveerr := db.saveDoc("idWith/slash", "", &couchDoc{jsonValue: assetJSON, attachments: nil})317 require.NoError(t, saveerr, "Error when trying to save a document")318 //Retrieve the test document319 dbGetResp, _, geterr := db.readDoc("idWith/slash")320 require.NoError(t, geterr, "Error when trying to retrieve a document")321 //Unmarshal the document to Asset structure322 assetResp := &Asset{}323 geterr = json.Unmarshal(dbGetResp.jsonValue, &assetResp)324 require.NoError(t, geterr, "Error when trying to retrieve a document")325 //Verify the owner retrieved matches326 require.Equal(t, "jerry", assetResp.Owner)327 //Save the test document328 _, saveerr = db.saveDoc("1", "", &couchDoc{jsonValue: assetJSON, attachments: nil})329 require.NoError(t, saveerr, "Error when trying to save a document")330 //Retrieve the test document331 dbGetResp, _, geterr = db.readDoc("1")332 require.NoError(t, geterr, "Error when trying to retrieve a document")333 //Unmarshal the document to Asset structure334 assetResp = &Asset{}335 geterr = json.Unmarshal(dbGetResp.jsonValue, &assetResp)336 require.NoError(t, geterr, "Error when trying to retrieve a document")337 //Verify the owner retrieved matches338 require.Equal(t, "jerry", assetResp.Owner)339 //Change owner to bob340 assetResp.Owner = "bob"341 //create a byte array of the JSON342 assetDocUpdated, _ := json.Marshal(assetResp)343 //Save the updated test document344 _, saveerr = db.saveDoc("1", "", &couchDoc{jsonValue: assetDocUpdated, attachments: nil})345 require.NoError(t, saveerr, "Error when trying to save the updated document")346 //Retrieve the updated test document347 dbGetResp, _, geterr = db.readDoc("1")348 require.NoError(t, geterr, "Error when trying to retrieve a document")349 //Unmarshal the document to Asset structure350 assetResp = &Asset{}351 require.NoError(t, json.Unmarshal(dbGetResp.jsonValue, &assetResp))352 //Assert that the update was saved and retrieved353 require.Equal(t, "bob", assetResp.Owner)354 testBytes2 := []byte(`test attachment 2`)355 attachment2 := &attachmentInfo{}356 attachment2.AttachmentBytes = testBytes2357 attachment2.ContentType = "application/octet-stream"358 attachment2.Name = "data"359 attachments2 := []*attachmentInfo{}360 attachments2 = append(attachments2, attachment2)361 //Save the test document with an attachment362 _, saveerr = db.saveDoc("2", "", &couchDoc{jsonValue: nil, attachments: attachments2})363 require.NoError(t, saveerr, "Error when trying to save a document")364 //Retrieve the test document with attachments365 dbGetResp, _, geterr = db.readDoc("2")366 require.NoError(t, geterr, "Error when trying to retrieve a document")367 //verify the text from the attachment is correct368 testattach := dbGetResp.attachments[0].AttachmentBytes369 require.Equal(t, testBytes2, testattach)370 testBytes3 := []byte{}371 attachment3 := &attachmentInfo{}372 attachment3.AttachmentBytes = testBytes3373 attachment3.ContentType = "application/octet-stream"374 attachment3.Name = "data"375 attachments3 := []*attachmentInfo{}376 attachments3 = append(attachments3, attachment3)377 //Save the test document with a zero length attachment378 _, saveerr = db.saveDoc("3", "", &couchDoc{jsonValue: nil, attachments: attachments3})379 require.NoError(t, saveerr, "Error when trying to save a document")380 //Retrieve the test document with attachments381 dbGetResp, _, geterr = db.readDoc("3")382 require.NoError(t, geterr, "Error when trying to retrieve a document")383 //verify the text from the attachment is correct, zero bytes384 testattach = dbGetResp.attachments[0].AttachmentBytes385 require.Equal(t, testBytes3, testattach)386 testBytes4a := []byte(`test attachment 4a`)387 attachment4a := &attachmentInfo{}388 attachment4a.AttachmentBytes = testBytes4a389 attachment4a.ContentType = "application/octet-stream"390 attachment4a.Name = "data1"391 testBytes4b := []byte(`test attachment 4b`)392 attachment4b := &attachmentInfo{}393 attachment4b.AttachmentBytes = testBytes4b394 attachment4b.ContentType = "application/octet-stream"395 attachment4b.Name = "data2"396 attachments4 := []*attachmentInfo{}397 attachments4 = append(attachments4, attachment4a)398 attachments4 = append(attachments4, attachment4b)399 //Save the updated test document with multiple attachments400 _, saveerr = db.saveDoc("4", "", &couchDoc{jsonValue: assetJSON, attachments: attachments4})401 require.NoError(t, saveerr, "Error when trying to save the updated document")402 //Retrieve the test document with attachments403 dbGetResp, _, geterr = db.readDoc("4")404 require.NoError(t, geterr, "Error when trying to retrieve a document")405 for _, attach4 := range dbGetResp.attachments {406 currentName := attach4.Name407 if currentName == "data1" {408 require.Equal(t, testBytes4a, attach4.AttachmentBytes)409 }410 if currentName == "data2" {411 require.Equal(t, testBytes4b, attach4.AttachmentBytes)412 }413 }414 testBytes5a := []byte(`test attachment 5a`)415 attachment5a := &attachmentInfo{}416 attachment5a.AttachmentBytes = testBytes5a417 attachment5a.ContentType = "application/octet-stream"418 attachment5a.Name = "data1"419 testBytes5b := []byte{}420 attachment5b := &attachmentInfo{}421 attachment5b.AttachmentBytes = testBytes5b422 attachment5b.ContentType = "application/octet-stream"423 attachment5b.Name = "data2"424 attachments5 := []*attachmentInfo{}425 attachments5 = append(attachments5, attachment5a)426 attachments5 = append(attachments5, attachment5b)427 //Save the updated test document with multiple attachments and zero length attachments428 _, saveerr = db.saveDoc("5", "", &couchDoc{jsonValue: assetJSON, attachments: attachments5})429 require.NoError(t, saveerr, "Error when trying to save the updated document")430 //Retrieve the test document with attachments431 dbGetResp, _, geterr = db.readDoc("5")432 require.NoError(t, geterr, "Error when trying to retrieve a document")433 for _, attach5 := range dbGetResp.attachments {434 currentName := attach5.Name435 if currentName == "data1" {436 require.Equal(t, testBytes5a, attach5.AttachmentBytes)437 }438 if currentName == "data2" {439 require.Equal(t, testBytes5b, attach5.AttachmentBytes)440 }441 }442 //Attempt to save the document with an invalid id443 _, saveerr = db.saveDoc(string([]byte{0xff, 0xfe, 0xfd}), "", &couchDoc{jsonValue: assetJSON, attachments: nil})444 require.Error(t, saveerr, "Error should have been thrown when saving a document with an invalid ID")445 //Attempt to read a document with an invalid id446 _, _, readerr := db.readDoc(string([]byte{0xff, 0xfe, 0xfd}))447 require.Error(t, readerr, "Error should have been thrown when reading a document with an invalid ID")448 //Drop the database449 errdbdrop := db.dropDatabase()450 require.NoError(t, errdbdrop, "Error dropping database")451 //Make sure an error is thrown for getting info for a missing database452 _, _, errdbinfo := db.getDatabaseInfo()453 require.Error(t, errdbinfo, "Error should have been thrown for missing database")454 //Attempt to save a document to a deleted database455 _, saveerr = db.saveDoc("6", "", &couchDoc{jsonValue: assetJSON, attachments: nil})456 require.Error(t, saveerr, "Error should have been thrown while attempting to save to a deleted database")457 //Attempt to read from a deleted database458 _, _, geterr = db.readDoc("6")459 require.NoError(t, geterr, "Error should not have been thrown for a missing database, nil value is returned")460}461func TestDBRequestTimeout(t *testing.T) {462 config := testConfig()463 couchDBEnv.startCouchDB(t)464 config.Address = couchDBEnv.couchAddress465 defer couchDBEnv.cleanup(config)466 //create a new instance and database object with a timeout that will fail467 //Also use a maxRetriesOnStartup=3 to reduce the number of retries468 configCopy := *config469 configCopy.MaxRetriesOnStartup = 3470 //create an impossibly short timeout471 impossibleTimeout := time.Nanosecond472 configCopy.RequestTimeout = impossibleTimeout473 _, err := createCouchInstance(&configCopy, &disabled.Provider{})474 require.Error(t, err, "Error should have been thown while trying to create a couchdb instance with a connection timeout")475 //create a new instance and database object476 configCopy.MaxRetries = -1477 configCopy.MaxRetriesOnStartup = 3478 _, err = createCouchInstance(&configCopy, &disabled.Provider{})479 require.Error(t, err, "Error should have been thrown while attempting to create a database")480}481func TestDBTimeoutConflictRetry(t *testing.T) {482 config := testConfig()483 couchDBEnv.startCouchDB(t)484 config.Address = couchDBEnv.couchAddress485 defer couchDBEnv.cleanup(config)486 database := "testdbtimeoutretry"487 //create a new instance and database object488 configCopy := *config489 configCopy.MaxRetriesOnStartup = 3490 couchInstance, err := createCouchInstance(&configCopy, &disabled.Provider{})491 require.NoError(t, err, "Error when trying to create couch instance")492 db := couchDatabase{couchInstance: couchInstance, dbName: database}493 //create a new database494 errdb := db.createDatabaseIfNotExist()495 require.NoError(t, errdb, "Error when trying to create database")496 //Retrieve the info for the new database and make sure the name matches497 dbResp, _, errdb := db.getDatabaseInfo()498 require.NoError(t, errdb, "Error when trying to retrieve database information")499 require.Equal(t, database, dbResp.DbName)500 //Save the test document501 _, saveerr := db.saveDoc("1", "", &couchDoc{jsonValue: assetJSON, attachments: nil})502 require.NoError(t, saveerr, "Error when trying to save a document")503 //Retrieve the test document504 _, _, geterr := db.readDoc("1")505 require.NoError(t, geterr, "Error when trying to retrieve a document")506 //Save the test document with an invalid rev. This should cause a retry507 _, saveerr = db.saveDoc("1", "1-11111111111111111111111111111111", &couchDoc{jsonValue: assetJSON, attachments: nil})508 require.NoError(t, saveerr, "Error when trying to save a document with a revision conflict")509 //Delete the test document with an invalid rev. This should cause a retry510 deleteerr := db.deleteDoc("1", "1-11111111111111111111111111111111")511 require.NoError(t, deleteerr, "Error when trying to delete a document with a revision conflict")512}513func TestDBBadNumberOfRetries(t *testing.T) {514 config := testConfig()515 couchDBEnv.startCouchDB(t)516 config.Address = couchDBEnv.couchAddress517 defer couchDBEnv.cleanup(config)518 //create a new instance and database object519 configCopy := *config520 configCopy.MaxRetries = -1521 configCopy.MaxRetriesOnStartup = 3522 _, err := createCouchInstance(&configCopy, &disabled.Provider{})523 require.Error(t, err, "Error should have been thrown while attempting to create a database")524}525func TestDBBadJSON(t *testing.T) {526 config := testConfig()527 couchDBEnv.startCouchDB(t)528 config.Address = couchDBEnv.couchAddress529 defer couchDBEnv.cleanup(config)530 database := "testdbbadjson"531 //create a new instance and database object532 couchInstance, err := createCouchInstance(config, &disabled.Provider{})533 require.NoError(t, err, "Error when trying to create couch instance")534 db := couchDatabase{couchInstance: couchInstance, dbName: database}535 //create a new database536 errdb := db.createDatabaseIfNotExist()537 require.NoError(t, errdb, "Error when trying to create database")538 //Retrieve the info for the new database and make sure the name matches539 dbResp, _, errdb := db.getDatabaseInfo()540 require.NoError(t, errdb, "Error when trying to retrieve database information")541 require.Equal(t, database, dbResp.DbName)542 badJSON := []byte(`{"asset_name"}`)543 //Save the test document544 _, saveerr := db.saveDoc("1", "", &couchDoc{jsonValue: badJSON, attachments: nil})545 require.Error(t, saveerr, "Error should have been thrown for a bad JSON")546}547func TestPrefixScan(t *testing.T) {548 config := testConfig()549 couchDBEnv.startCouchDB(t)550 config.Address = couchDBEnv.couchAddress551 defer couchDBEnv.cleanup(config)552 database := "testprefixscan"553 //create a new instance and database object554 couchInstance, err := createCouchInstance(config, &disabled.Provider{})555 require.NoError(t, err, "Error when trying to create couch instance")556 db := couchDatabase{couchInstance: couchInstance, dbName: database}557 //create a new database558 errdb := db.createDatabaseIfNotExist()559 require.NoError(t, errdb, "Error when trying to create database")560 //Retrieve the info for the new database and make sure the name matches561 dbResp, _, errdb := db.getDatabaseInfo()562 require.NoError(t, errdb, "Error when trying to retrieve database information")563 require.Equal(t, database, dbResp.DbName)564 //Save documents565 for i := rune(0); i < 20; i++ {566 id1 := string([]rune{0, i, 0})567 id2 := string([]rune{0, i, 1})568 id3 := string([]rune{0, i, utf8.MaxRune - 1})569 _, saveerr := db.saveDoc(id1, "", &couchDoc{jsonValue: assetJSON, attachments: nil})570 require.NoError(t, saveerr, "Error when trying to save a document")571 _, saveerr = db.saveDoc(id2, "", &couchDoc{jsonValue: assetJSON, attachments: nil})572 require.NoError(t, saveerr, "Error when trying to save a document")573 _, saveerr = db.saveDoc(id3, "", &couchDoc{jsonValue: assetJSON, attachments: nil})574 require.NoError(t, saveerr, "Error when trying to save a document")575 }576 startKey := string([]rune{0, 10})577 endKey := startKey + string(utf8.MaxRune)578 _, _, geterr := db.readDoc(endKey)579 require.NoError(t, geterr, "Error when trying to get lastkey")580 resultsPtr, _, geterr := db.readDocRange(startKey, endKey, 1000)581 require.NoError(t, geterr, "Error when trying to perform a range scan")582 require.NotNil(t, resultsPtr)583 results := resultsPtr584 require.Equal(t, 3, len(results))585 require.Equal(t, string([]rune{0, 10, 0}), results[0].id)586 require.Equal(t, string([]rune{0, 10, 1}), results[1].id)587 require.Equal(t, string([]rune{0, 10, utf8.MaxRune - 1}), results[2].id)588 //Drop the database589 errdbdrop := db.dropDatabase()590 require.NoError(t, errdbdrop, "Error dropping database")591 // Drop again is not an error592 require.NoError(t, db.dropDatabase())593 //Retrieve the info for the new database and make sure the name matches594 _, _, errdbinfo := db.getDatabaseInfo()595 require.Error(t, errdbinfo, "Error should have been thrown for missing database")596}597func TestDBSaveAttachment(t *testing.T) {598 config := testConfig()599 couchDBEnv.startCouchDB(t)600 config.Address = couchDBEnv.couchAddress601 defer couchDBEnv.cleanup(config)602 database := "testdbsaveattachment"603 byteText := []byte(`This is a test document. This is only a test`)604 attachment := &attachmentInfo{}605 attachment.AttachmentBytes = byteText606 attachment.ContentType = "text/plain"607 attachment.Length = uint64(len(byteText))608 attachment.Name = "valueBytes"609 attachments := []*attachmentInfo{}610 attachments = append(attachments, attachment)611 //create a new instance and database object612 couchInstance, err := createCouchInstance(config, &disabled.Provider{})613 require.NoError(t, err, "Error when trying to create couch instance")614 db := couchDatabase{couchInstance: couchInstance, dbName: database}615 //create a new database616 errdb := db.createDatabaseIfNotExist()617 require.NoError(t, errdb, "Error when trying to create database")618 //Save the test document619 _, saveerr := db.saveDoc("10", "", &couchDoc{jsonValue: nil, attachments: attachments})620 require.NoError(t, saveerr, "Error when trying to save a document")621 //Attempt to retrieve the updated test document with attachments622 couchDoc, _, geterr2 := db.readDoc("10")623 require.NoError(t, geterr2, "Error when trying to retrieve a document with attachment")624 require.NotNil(t, couchDoc.attachments)625 require.Equal(t, byteText, couchDoc.attachments[0].AttachmentBytes)626 require.Equal(t, attachment.Length, couchDoc.attachments[0].Length)627}628func TestDBDeleteDocument(t *testing.T) {629 config := testConfig()630 couchDBEnv.startCouchDB(t)631 config.Address = couchDBEnv.couchAddress632 defer couchDBEnv.cleanup(config)633 database := "testdbdeletedocument"634 //create a new instance and database object635 couchInstance, err := createCouchInstance(config, &disabled.Provider{})636 require.NoError(t, err, "Error when trying to create couch instance")637 db := couchDatabase{couchInstance: couchInstance, dbName: database}638 //create a new database639 errdb := db.createDatabaseIfNotExist()640 require.NoError(t, errdb, "Error when trying to create database")641 //Save the test document642 _, saveerr := db.saveDoc("2", "", &couchDoc{jsonValue: assetJSON, attachments: nil})643 require.NoError(t, saveerr, "Error when trying to save a document")644 //Attempt to retrieve the test document645 _, _, readErr := db.readDoc("2")646 require.NoError(t, readErr, "Error when trying to retrieve a document with attachment")647 //Delete the test document648 deleteErr := db.deleteDoc("2", "")649 require.NoError(t, deleteErr, "Error when trying to delete a document")650 //Attempt to retrieve the test document651 readValue, _, _ := db.readDoc("2")652 require.Nil(t, readValue)653}654func TestDBDeleteNonExistingDocument(t *testing.T) {655 config := testConfig()656 couchDBEnv.startCouchDB(t)657 config.Address = couchDBEnv.couchAddress658 defer couchDBEnv.cleanup(config)659 database := "testdbdeletenonexistingdocument"660 //create a new instance and database object661 couchInstance, err := createCouchInstance(config, &disabled.Provider{})662 require.NoError(t, err, "Error when trying to create couch instance")663 db := couchDatabase{couchInstance: couchInstance, dbName: database}664 //create a new database665 errdb := db.createDatabaseIfNotExist()666 require.NoError(t, errdb, "Error when trying to create database")667 //Save the test document668 deleteErr := db.deleteDoc("2", "")669 require.NoError(t, deleteErr, "Error when trying to delete a non existing document")670}671func TestCouchDBVersion(t *testing.T) {672 config := testConfig()673 couchDBEnv.startCouchDB(t)674 config.Address = couchDBEnv.couchAddress675 defer couchDBEnv.cleanup(config)676 err := checkCouchDBVersion("2.0.0")677 require.NoError(t, err, "Error should not have been thrown for valid version")678 err = checkCouchDBVersion("4.5.0")679 require.NoError(t, err, "Error should not have been thrown for valid version")680 err = checkCouchDBVersion("1.6.5.4")681 require.Error(t, err, "Error should have been thrown for invalid version")682 err = checkCouchDBVersion("0.0.0.0")683 require.Error(t, err, "Error should have been thrown for invalid version")684}685func TestIndexOperations(t *testing.T) {686 config := testConfig()687 couchDBEnv.startCouchDB(t)688 config.Address = couchDBEnv.couchAddress689 defer couchDBEnv.cleanup(config)690 database := "testindexoperations"691 byteJSON1 := []byte(`{"_id":"1", "asset_name":"marble1","color":"blue","size":1,"owner":"jerry"}`)692 byteJSON2 := []byte(`{"_id":"2", "asset_name":"marble2","color":"red","size":2,"owner":"tom"}`)693 byteJSON3 := []byte(`{"_id":"3", "asset_name":"marble3","color":"green","size":3,"owner":"jerry"}`)694 byteJSON4 := []byte(`{"_id":"4", "asset_name":"marble4","color":"purple","size":4,"owner":"tom"}`)695 byteJSON5 := []byte(`{"_id":"5", "asset_name":"marble5","color":"blue","size":5,"owner":"jerry"}`)696 byteJSON6 := []byte(`{"_id":"6", "asset_name":"marble6","color":"white","size":6,"owner":"tom"}`)697 byteJSON7 := []byte(`{"_id":"7", "asset_name":"marble7","color":"white","size":7,"owner":"tom"}`)698 byteJSON8 := []byte(`{"_id":"8", "asset_name":"marble8","color":"white","size":8,"owner":"tom"}`)699 byteJSON9 := []byte(`{"_id":"9", "asset_name":"marble9","color":"white","size":9,"owner":"tom"}`)700 byteJSON10 := []byte(`{"_id":"10", "asset_name":"marble10","color":"white","size":10,"owner":"tom"}`)701 //create a new instance and database object --------------------------------------------------------702 couchInstance, err := createCouchInstance(config, &disabled.Provider{})703 require.NoError(t, err, "Error when trying to create couch instance")704 db := couchDatabase{couchInstance: couchInstance, dbName: database}705 //create a new database706 errdb := db.createDatabaseIfNotExist()707 require.NoError(t, errdb, "Error when trying to create database")708 batchUpdateDocs := []*couchDoc{}709 batchUpdateDocs = append(batchUpdateDocs, &couchDoc{jsonValue: byteJSON1, attachments: nil})710 batchUpdateDocs = append(batchUpdateDocs, &couchDoc{jsonValue: byteJSON2, attachments: nil})711 batchUpdateDocs = append(batchUpdateDocs, &couchDoc{jsonValue: byteJSON3, attachments: nil})712 batchUpdateDocs = append(batchUpdateDocs, &couchDoc{jsonValue: byteJSON4, attachments: nil})713 batchUpdateDocs = append(batchUpdateDocs, &couchDoc{jsonValue: byteJSON5, attachments: nil})714 batchUpdateDocs = append(batchUpdateDocs, &couchDoc{jsonValue: byteJSON6, attachments: nil})715 batchUpdateDocs = append(batchUpdateDocs, &couchDoc{jsonValue: byteJSON7, attachments: nil})716 batchUpdateDocs = append(batchUpdateDocs, &couchDoc{jsonValue: byteJSON8, attachments: nil})717 batchUpdateDocs = append(batchUpdateDocs, &couchDoc{jsonValue: byteJSON9, attachments: nil})718 batchUpdateDocs = append(batchUpdateDocs, &couchDoc{jsonValue: byteJSON10, attachments: nil})719 _, err = db.batchUpdateDocuments(batchUpdateDocs)720 require.NoError(t, err, "Error adding batch of documents")721 //Create an index definition722 indexDefSize := `{"index":{"fields":[{"size":"desc"}]},"ddoc":"indexSizeSortDoc", "name":"indexSizeSortName","type":"json"}`723 //Create the index724 _, err = db.createIndex(indexDefSize)725 require.NoError(t, err, "Error thrown while creating an index")726 //Retrieve the list of indexes727 //Delay for 100ms since CouchDB index list is updated async after index create/drop728 time.Sleep(100 * time.Millisecond)729 listResult, err := db.listIndex()730 require.NoError(t, err, "Error thrown while retrieving indexes")731 //There should only be one item returned732 require.Equal(t, 1, len(listResult))733 //Verify the returned definition734 for _, elem := range listResult {735 require.Equal(t, "indexSizeSortDoc", elem.DesignDocument)736 require.Equal(t, "indexSizeSortName", elem.Name)737 //ensure the index definition is correct, CouchDB 2.1.1 will also return "partial_filter_selector":{}738 require.Equal(t, true, strings.Contains(elem.Definition, `"fields":[{"size":"desc"}]`))739 }740 //Create an index definition with no DesignDocument or name741 indexDefColor := `{"index":{"fields":[{"color":"desc"}]}}`742 //Create the index743 _, err = db.createIndex(indexDefColor)744 require.NoError(t, err, "Error thrown while creating an index")745 //Retrieve the list of indexes746 //Delay for 100ms since CouchDB index list is updated async after index create/drop747 time.Sleep(100 * time.Millisecond)748 listResult, err = db.listIndex()749 require.NoError(t, err, "Error thrown while retrieving indexes")750 //There should be two indexes returned751 require.Equal(t, 2, len(listResult))752 //Delete the named index753 err = db.deleteIndex("indexSizeSortDoc", "indexSizeSortName")754 require.NoError(t, err, "Error thrown while deleting an index")755 //Retrieve the list of indexes756 //Delay for 100ms since CouchDB index list is updated async after index create/drop757 time.Sleep(100 * time.Millisecond)758 listResult, err = db.listIndex()759 require.NoError(t, err, "Error thrown while retrieving indexes")760 //There should be one index returned761 require.Equal(t, 1, len(listResult))762 //Delete the unnamed index763 for _, elem := range listResult {764 err = db.deleteIndex(elem.DesignDocument, elem.Name)765 require.NoError(t, err, "Error thrown while deleting an index")766 }767 //Retrieve the list of indexes768 //Delay for 100ms since CouchDB index list is updated async after index create/drop769 time.Sleep(100 * time.Millisecond)770 listResult, err = db.listIndex()771 require.NoError(t, err, "Error thrown while retrieving indexes")772 require.Equal(t, 0, len(listResult))773 //Create a query string with a descending sort, this will require an index774 queryString := `{"selector":{"size": {"$gt": 0}},"fields": ["_id", "_rev", "owner", "asset_name", "color", "size"], "sort":[{"size":"desc"}], "limit": 10,"skip": 0}`775 //Execute a query with a sort, this should throw the exception776 _, _, err = db.queryDocuments(queryString)777 require.Error(t, err, "Error should have thrown while querying without a valid index")778 //Create the index779 _, err = db.createIndex(indexDefSize)780 require.NoError(t, err, "Error thrown while creating an index")781 //Delay for 100ms since CouchDB index list is updated async after index create/drop782 time.Sleep(100 * time.Millisecond)783 //Execute a query with an index, this should succeed784 _, _, err = db.queryDocuments(queryString)785 require.NoError(t, err, "Error thrown while querying with an index")786 //Create another index definition787 indexDefSize = `{"index":{"fields":[{"data.size":"desc"},{"data.owner":"desc"}]},"ddoc":"indexSizeOwnerSortDoc", "name":"indexSizeOwnerSortName","type":"json"}`788 //Create the index789 dbResp, err := db.createIndex(indexDefSize)790 require.NoError(t, err, "Error thrown while creating an index")791 //verify the response is "created" for an index creation792 require.Equal(t, "created", dbResp.Result)793 //Delay for 100ms since CouchDB index list is updated async after index create/drop794 time.Sleep(100 * time.Millisecond)795 //Update the index796 dbResp, err = db.createIndex(indexDefSize)797 require.NoError(t, err, "Error thrown while creating an index")798 //verify the response is "exists" for an update799 require.Equal(t, "exists", dbResp.Result)800 //Retrieve the list of indexes801 //Delay for 100ms since CouchDB index list is updated async after index create/drop802 time.Sleep(100 * time.Millisecond)803 listResult, err = db.listIndex()804 require.NoError(t, err, "Error thrown while retrieving indexes")805 //There should only be two definitions806 require.Equal(t, 2, len(listResult))807 //Create an invalid index definition with an invalid JSON808 indexDefSize = `{"index"{"fields":[{"data.size":"desc"},{"data.owner":"desc"}]},"ddoc":"indexSizeOwnerSortDoc", "name":"indexSizeOwnerSortName","type":"json"}`809 //Create the index810 _, err = db.createIndex(indexDefSize)811 require.Error(t, err, "Error should have been thrown for an invalid index JSON")812 //Create an invalid index definition with a valid JSON and an invalid index definition813 indexDefSize = `{"index":{"fields2":[{"data.size":"desc"},{"data.owner":"desc"}]},"ddoc":"indexSizeOwnerSortDoc", "name":"indexSizeOwnerSortName","type":"json"}`814 //Create the index815 _, err = db.createIndex(indexDefSize)816 require.Error(t, err, "Error should have been thrown for an invalid index definition")817}818func TestRichQuery(t *testing.T) {819 config := testConfig()820 couchDBEnv.startCouchDB(t)821 config.Address = couchDBEnv.couchAddress822 defer couchDBEnv.cleanup(config)823 byteJSON01 := []byte(`{"asset_name":"marble01","color":"blue","size":1,"owner":"jerry"}`)824 byteJSON02 := []byte(`{"asset_name":"marble02","color":"red","size":2,"owner":"tom"}`)825 byteJSON03 := []byte(`{"asset_name":"marble03","color":"green","size":3,"owner":"jerry"}`)826 byteJSON04 := []byte(`{"asset_name":"marble04","color":"purple","size":4,"owner":"tom"}`)827 byteJSON05 := []byte(`{"asset_name":"marble05","color":"blue","size":5,"owner":"jerry"}`)828 byteJSON06 := []byte(`{"asset_name":"marble06","color":"white","size":6,"owner":"tom"}`)829 byteJSON07 := []byte(`{"asset_name":"marble07","color":"white","size":7,"owner":"tom"}`)830 byteJSON08 := []byte(`{"asset_name":"marble08","color":"white","size":8,"owner":"tom"}`)831 byteJSON09 := []byte(`{"asset_name":"marble09","color":"white","size":9,"owner":"tom"}`)832 byteJSON10 := []byte(`{"asset_name":"marble10","color":"white","size":10,"owner":"tom"}`)833 byteJSON11 := []byte(`{"asset_name":"marble11","color":"green","size":11,"owner":"tom"}`)834 byteJSON12 := []byte(`{"asset_name":"marble12","color":"green","size":12,"owner":"frank"}`)835 attachment1 := &attachmentInfo{}836 attachment1.AttachmentBytes = []byte(`marble01 - test attachment`)837 attachment1.ContentType = "application/octet-stream"838 attachment1.Name = "data"839 attachments1 := []*attachmentInfo{}840 attachments1 = append(attachments1, attachment1)841 attachment2 := &attachmentInfo{}842 attachment2.AttachmentBytes = []byte(`marble02 - test attachment`)843 attachment2.ContentType = "application/octet-stream"844 attachment2.Name = "data"845 attachments2 := []*attachmentInfo{}846 attachments2 = append(attachments2, attachment2)847 attachment3 := &attachmentInfo{}848 attachment3.AttachmentBytes = []byte(`marble03 - test attachment`)849 attachment3.ContentType = "application/octet-stream"850 attachment3.Name = "data"851 attachments3 := []*attachmentInfo{}852 attachments3 = append(attachments3, attachment3)853 attachment4 := &attachmentInfo{}854 attachment4.AttachmentBytes = []byte(`marble04 - test attachment`)855 attachment4.ContentType = "application/octet-stream"856 attachment4.Name = "data"857 attachments4 := []*attachmentInfo{}858 attachments4 = append(attachments4, attachment4)859 attachment5 := &attachmentInfo{}860 attachment5.AttachmentBytes = []byte(`marble05 - test attachment`)861 attachment5.ContentType = "application/octet-stream"862 attachment5.Name = "data"863 attachments5 := []*attachmentInfo{}864 attachments5 = append(attachments5, attachment5)865 attachment6 := &attachmentInfo{}866 attachment6.AttachmentBytes = []byte(`marble06 - test attachment`)867 attachment6.ContentType = "application/octet-stream"868 attachment6.Name = "data"869 attachments6 := []*attachmentInfo{}870 attachments6 = append(attachments6, attachment6)871 attachment7 := &attachmentInfo{}872 attachment7.AttachmentBytes = []byte(`marble07 - test attachment`)873 attachment7.ContentType = "application/octet-stream"874 attachment7.Name = "data"875 attachments7 := []*attachmentInfo{}876 attachments7 = append(attachments7, attachment7)877 attachment8 := &attachmentInfo{}878 attachment8.AttachmentBytes = []byte(`marble08 - test attachment`)879 attachment8.ContentType = "application/octet-stream"880 attachment7.Name = "data"881 attachments8 := []*attachmentInfo{}882 attachments8 = append(attachments8, attachment8)883 attachment9 := &attachmentInfo{}884 attachment9.AttachmentBytes = []byte(`marble09 - test attachment`)885 attachment9.ContentType = "application/octet-stream"886 attachment9.Name = "data"887 attachments9 := []*attachmentInfo{}888 attachments9 = append(attachments9, attachment9)889 attachment10 := &attachmentInfo{}890 attachment10.AttachmentBytes = []byte(`marble10 - test attachment`)891 attachment10.ContentType = "application/octet-stream"892 attachment10.Name = "data"893 attachments10 := []*attachmentInfo{}894 attachments10 = append(attachments10, attachment10)895 attachment11 := &attachmentInfo{}896 attachment11.AttachmentBytes = []byte(`marble11 - test attachment`)897 attachment11.ContentType = "application/octet-stream"898 attachment11.Name = "data"899 attachments11 := []*attachmentInfo{}900 attachments11 = append(attachments11, attachment11)901 attachment12 := &attachmentInfo{}902 attachment12.AttachmentBytes = []byte(`marble12 - test attachment`)903 attachment12.ContentType = "application/octet-stream"904 attachment12.Name = "data"905 attachments12 := []*attachmentInfo{}906 attachments12 = append(attachments12, attachment12)907 database := "testrichquery"908 //create a new instance and database object --------------------------------------------------------909 couchInstance, err := createCouchInstance(config, &disabled.Provider{})910 require.NoError(t, err, "Error when trying to create couch instance")911 db := couchDatabase{couchInstance: couchInstance, dbName: database}912 //create a new database913 errdb := db.createDatabaseIfNotExist()914 require.NoError(t, errdb, "Error when trying to create database")915 //Save the test document916 _, saveerr := db.saveDoc("marble01", "", &couchDoc{jsonValue: byteJSON01, attachments: attachments1})917 require.NoError(t, saveerr, "Error when trying to save a document")918 //Save the test document919 _, saveerr = db.saveDoc("marble02", "", &couchDoc{jsonValue: byteJSON02, attachments: attachments2})920 require.NoError(t, saveerr, "Error when trying to save a document")921 //Save the test document922 _, saveerr = db.saveDoc("marble03", "", &couchDoc{jsonValue: byteJSON03, attachments: attachments3})923 require.NoError(t, saveerr, "Error when trying to save a document")924 //Save the test document925 _, saveerr = db.saveDoc("marble04", "", &couchDoc{jsonValue: byteJSON04, attachments: attachments4})926 require.NoError(t, saveerr, "Error when trying to save a document")927 //Save the test document928 _, saveerr = db.saveDoc("marble05", "", &couchDoc{jsonValue: byteJSON05, attachments: attachments5})929 require.NoError(t, saveerr, "Error when trying to save a document")930 //Save the test document931 _, saveerr = db.saveDoc("marble06", "", &couchDoc{jsonValue: byteJSON06, attachments: attachments6})932 require.NoError(t, saveerr, "Error when trying to save a document")933 //Save the test document934 _, saveerr = db.saveDoc("marble07", "", &couchDoc{jsonValue: byteJSON07, attachments: attachments7})935 require.NoError(t, saveerr, "Error when trying to save a document")936 //Save the test document937 _, saveerr = db.saveDoc("marble08", "", &couchDoc{jsonValue: byteJSON08, attachments: attachments8})938 require.NoError(t, saveerr, "Error when trying to save a document")939 //Save the test document940 _, saveerr = db.saveDoc("marble09", "", &couchDoc{jsonValue: byteJSON09, attachments: attachments9})941 require.NoError(t, saveerr, "Error when trying to save a document")942 //Save the test document943 _, saveerr = db.saveDoc("marble10", "", &couchDoc{jsonValue: byteJSON10, attachments: attachments10})944 require.NoError(t, saveerr, "Error when trying to save a document")945 //Save the test document946 _, saveerr = db.saveDoc("marble11", "", &couchDoc{jsonValue: byteJSON11, attachments: attachments11})947 require.NoError(t, saveerr, "Error when trying to save a document")948 //Save the test document949 _, saveerr = db.saveDoc("marble12", "", &couchDoc{jsonValue: byteJSON12, attachments: attachments12})950 require.NoError(t, saveerr, "Error when trying to save a document")951 //Test query with invalid JSON -------------------------------------------------------------------952 queryString := `{"selector":{"owner":}}`953 _, _, err = db.queryDocuments(queryString)954 require.Error(t, err, "Error should have been thrown for bad json")955 //Test query with object -------------------------------------------------------------------956 queryString = `{"selector":{"owner":{"$eq":"jerry"}}}`957 queryResult, _, err := db.queryDocuments(queryString)958 require.NoError(t, err, "Error when attempting to execute a query")959 //There should be 3 results for owner="jerry"960 require.Equal(t, 3, len(queryResult))961 //Test query with implicit operator --------------------------------------------------------------962 queryString = `{"selector":{"owner":"jerry"}}`...

Full Screen

Full Screen

association_test.go

Source:association_test.go Github

copy

Full Screen

...13 Body: "body belongs to",14 Category: Category{Name: "Category 1"},15 MainCategory: Category{Name: "Main Category 1"},16 }17 if err := DB.Save(&post).Error; err != nil {18 t.Error("Got errors when save post", err)19 }20 if post.Category.ID == 0 || post.MainCategory.ID == 0 {21 t.Errorf("Category's primary key should be updated")22 }23 if post.CategoryId.Int64 == 0 || post.MainCategoryId == 0 {24 t.Errorf("post's foreign key should be updated")25 }26 // Query27 var category1 Category28 DB.Model(&post).Association("Category").Find(&category1)29 if category1.Name != "Category 1" {30 t.Errorf("Query belongs to relations with Association")31 }32 var mainCategory1 Category33 DB.Model(&post).Association("MainCategory").Find(&mainCategory1)34 if mainCategory1.Name != "Main Category 1" {35 t.Errorf("Query belongs to relations with Association")36 }37 var category11 Category38 DB.Model(&post).Related(&category11)39 if category11.Name != "Category 1" {40 t.Errorf("Query belongs to relations with Related")41 }42 if DB.Model(&post).Association("Category").Count() != 1 {43 t.Errorf("Post's category count should be 1")44 }45 if DB.Model(&post).Association("MainCategory").Count() != 1 {46 t.Errorf("Post's main category count should be 1")47 }48 // Append49 var category2 = Category{50 Name: "Category 2",51 }52 DB.Model(&post).Association("Category").Append(&category2)53 if category2.ID == 0 {54 t.Errorf("Category should has ID when created with Append")55 }56 var category21 Category57 DB.Model(&post).Related(&category21)58 if category21.Name != "Category 2" {59 t.Errorf("Category should be updated with Append")60 }61 if DB.Model(&post).Association("Category").Count() != 1 {62 t.Errorf("Post's category count should be 1")63 }64 // Replace65 var category3 = Category{66 Name: "Category 3",67 }68 DB.Model(&post).Association("Category").Replace(&category3)69 if category3.ID == 0 {70 t.Errorf("Category should has ID when created with Replace")71 }72 var category31 Category73 DB.Model(&post).Related(&category31)74 if category31.Name != "Category 3" {75 t.Errorf("Category should be updated with Replace")76 }77 if DB.Model(&post).Association("Category").Count() != 1 {78 t.Errorf("Post's category count should be 1")79 }80 // Delete81 DB.Model(&post).Association("Category").Delete(&category2)82 if DB.Model(&post).Related(&Category{}).RecordNotFound() {83 t.Errorf("Should not delete any category when Delete a unrelated Category")84 }85 if post.Category.Name == "" {86 t.Errorf("Post's category should not be reseted when Delete a unrelated Category")87 }88 DB.Model(&post).Association("Category").Delete(&category3)89 if post.Category.Name != "" {90 t.Errorf("Post's category should be reseted after Delete")91 }92 var category41 Category93 DB.Model(&post).Related(&category41)94 if category41.Name != "" {95 t.Errorf("Category should be deleted with Delete")96 }97 if count := DB.Model(&post).Association("Category").Count(); count != 0 {98 t.Errorf("Post's category count should be 0 after Delete, but got %v", count)99 }100 // Clear101 DB.Model(&post).Association("Category").Append(&Category{102 Name: "Category 2",103 })104 if DB.Model(&post).Related(&Category{}).RecordNotFound() {105 t.Errorf("Should find category after append")106 }107 if post.Category.Name == "" {108 t.Errorf("Post's category should has value after Append")109 }110 DB.Model(&post).Association("Category").Clear()111 if post.Category.Name != "" {112 t.Errorf("Post's category should be cleared after Clear")113 }114 if !DB.Model(&post).Related(&Category{}).RecordNotFound() {115 t.Errorf("Should not find any category after Clear")116 }117 if count := DB.Model(&post).Association("Category").Count(); count != 0 {118 t.Errorf("Post's category count should be 0 after Clear, but got %v", count)119 }120 // Check Association mode with soft delete121 category6 := Category{122 Name: "Category 6",123 }124 DB.Model(&post).Association("Category").Append(&category6)125 if count := DB.Model(&post).Association("Category").Count(); count != 1 {126 t.Errorf("Post's category count should be 1 after Append, but got %v", count)127 }128 DB.Delete(&category6)129 if count := DB.Model(&post).Association("Category").Count(); count != 0 {130 t.Errorf("Post's category count should be 0 after the category has been deleted, but got %v", count)131 }132 if err := DB.Model(&post).Association("Category").Find(&Category{}).Error; err == nil {133 t.Errorf("Post's category is not findable after Delete")134 }135 if count := DB.Unscoped().Model(&post).Association("Category").Count(); count != 1 {136 t.Errorf("Post's category count should be 1 when query with Unscoped, but got %v", count)137 }138 if err := DB.Unscoped().Model(&post).Association("Category").Find(&Category{}).Error; err != nil {139 t.Errorf("Post's category should be findable when query with Unscoped, got %v", err)140 }141}142func TestBelongsToOverrideForeignKey1(t *testing.T) {143 type Profile struct {144 gorm.Model145 Name string146 }147 type User struct {148 gorm.Model149 Profile Profile `gorm:"ForeignKey:ProfileRefer"`150 ProfileRefer int151 }152 if relation, ok := DB.NewScope(&User{}).FieldByName("Profile"); ok {153 if relation.Relationship.Kind != "belongs_to" ||154 !reflect.DeepEqual(relation.Relationship.ForeignFieldNames, []string{"ProfileRefer"}) ||155 !reflect.DeepEqual(relation.Relationship.AssociationForeignFieldNames, []string{"ID"}) {156 t.Errorf("Override belongs to foreign key with tag")157 }158 }159}160func TestBelongsToOverrideForeignKey2(t *testing.T) {161 type Profile struct {162 gorm.Model163 Refer string164 Name string165 }166 type User struct {167 gorm.Model168 Profile Profile `gorm:"ForeignKey:ProfileID;AssociationForeignKey:Refer"`169 ProfileID int170 }171 if relation, ok := DB.NewScope(&User{}).FieldByName("Profile"); ok {172 if relation.Relationship.Kind != "belongs_to" ||173 !reflect.DeepEqual(relation.Relationship.ForeignFieldNames, []string{"ProfileID"}) ||174 !reflect.DeepEqual(relation.Relationship.AssociationForeignFieldNames, []string{"Refer"}) {175 t.Errorf("Override belongs to foreign key with tag")176 }177 }178}179func TestHasOne(t *testing.T) {180 user := User{181 Name: "has one",182 CreditCard: CreditCard{Number: "411111111111"},183 }184 if err := DB.Save(&user).Error; err != nil {185 t.Error("Got errors when save user", err.Error())186 }187 if user.CreditCard.UserId.Int64 == 0 {188 t.Errorf("CreditCard's foreign key should be updated")189 }190 // Query191 var creditCard1 CreditCard192 DB.Model(&user).Related(&creditCard1)193 if creditCard1.Number != "411111111111" {194 t.Errorf("Query has one relations with Related")195 }196 var creditCard11 CreditCard197 DB.Model(&user).Association("CreditCard").Find(&creditCard11)198 if creditCard11.Number != "411111111111" {199 t.Errorf("Query has one relations with Related")200 }201 if DB.Model(&user).Association("CreditCard").Count() != 1 {202 t.Errorf("User's credit card count should be 1")203 }204 // Append205 var creditcard2 = CreditCard{206 Number: "411111111112",207 }208 DB.Model(&user).Association("CreditCard").Append(&creditcard2)209 if creditcard2.ID == 0 {210 t.Errorf("Creditcard should has ID when created with Append")211 }212 var creditcard21 CreditCard213 DB.Model(&user).Related(&creditcard21)214 if creditcard21.Number != "411111111112" {215 t.Errorf("CreditCard should be updated with Append")216 }217 if DB.Model(&user).Association("CreditCard").Count() != 1 {218 t.Errorf("User's credit card count should be 1")219 }220 // Replace221 var creditcard3 = CreditCard{222 Number: "411111111113",223 }224 DB.Model(&user).Association("CreditCard").Replace(&creditcard3)225 if creditcard3.ID == 0 {226 t.Errorf("Creditcard should has ID when created with Replace")227 }228 var creditcard31 CreditCard229 DB.Model(&user).Related(&creditcard31)230 if creditcard31.Number != "411111111113" {231 t.Errorf("CreditCard should be updated with Replace")232 }233 if DB.Model(&user).Association("CreditCard").Count() != 1 {234 t.Errorf("User's credit card count should be 1")235 }236 // Delete237 DB.Model(&user).Association("CreditCard").Delete(&creditcard2)238 var creditcard4 CreditCard239 DB.Model(&user).Related(&creditcard4)240 if creditcard4.Number != "411111111113" {241 t.Errorf("Should not delete credit card when Delete a unrelated CreditCard")242 }243 if DB.Model(&user).Association("CreditCard").Count() != 1 {244 t.Errorf("User's credit card count should be 1")245 }246 DB.Model(&user).Association("CreditCard").Delete(&creditcard3)247 if !DB.Model(&user).Related(&CreditCard{}).RecordNotFound() {248 t.Errorf("Should delete credit card with Delete")249 }250 if DB.Model(&user).Association("CreditCard").Count() != 0 {251 t.Errorf("User's credit card count should be 0 after Delete")252 }253 // Clear254 var creditcard5 = CreditCard{255 Number: "411111111115",256 }257 DB.Model(&user).Association("CreditCard").Append(&creditcard5)258 if DB.Model(&user).Related(&CreditCard{}).RecordNotFound() {259 t.Errorf("Should added credit card with Append")260 }261 if DB.Model(&user).Association("CreditCard").Count() != 1 {262 t.Errorf("User's credit card count should be 1")263 }264 DB.Model(&user).Association("CreditCard").Clear()265 if !DB.Model(&user).Related(&CreditCard{}).RecordNotFound() {266 t.Errorf("Credit card should be deleted with Clear")267 }268 if DB.Model(&user).Association("CreditCard").Count() != 0 {269 t.Errorf("User's credit card count should be 0 after Clear")270 }271 // Check Association mode with soft delete272 var creditcard6 = CreditCard{273 Number: "411111111116",274 }275 DB.Model(&user).Association("CreditCard").Append(&creditcard6)276 if count := DB.Model(&user).Association("CreditCard").Count(); count != 1 {277 t.Errorf("User's credit card count should be 1 after Append, but got %v", count)278 }279 DB.Delete(&creditcard6)280 if count := DB.Model(&user).Association("CreditCard").Count(); count != 0 {281 t.Errorf("User's credit card count should be 0 after credit card deleted, but got %v", count)282 }283 if err := DB.Model(&user).Association("CreditCard").Find(&CreditCard{}).Error; err == nil {284 t.Errorf("User's creditcard is not findable after Delete")285 }286 if count := DB.Unscoped().Model(&user).Association("CreditCard").Count(); count != 1 {287 t.Errorf("User's credit card count should be 1 when query with Unscoped, but got %v", count)288 }289 if err := DB.Unscoped().Model(&user).Association("CreditCard").Find(&CreditCard{}).Error; err != nil {290 t.Errorf("User's creditcard should be findable when query with Unscoped, got %v", err)291 }292}293func TestHasOneOverrideForeignKey1(t *testing.T) {294 type Profile struct {295 gorm.Model296 Name string297 UserRefer uint298 }299 type User struct {300 gorm.Model301 Profile Profile `gorm:"ForeignKey:UserRefer"`302 }303 if relation, ok := DB.NewScope(&User{}).FieldByName("Profile"); ok {304 if relation.Relationship.Kind != "has_one" ||305 !reflect.DeepEqual(relation.Relationship.ForeignFieldNames, []string{"UserRefer"}) ||306 !reflect.DeepEqual(relation.Relationship.AssociationForeignFieldNames, []string{"ID"}) {307 t.Errorf("Override belongs to foreign key with tag")308 }309 }310}311func TestHasOneOverrideForeignKey2(t *testing.T) {312 type Profile struct {313 gorm.Model314 Name string315 UserID uint316 }317 type User struct {318 gorm.Model319 Refer string320 Profile Profile `gorm:"ForeignKey:UserID;AssociationForeignKey:Refer"`321 }322 if relation, ok := DB.NewScope(&User{}).FieldByName("Profile"); ok {323 if relation.Relationship.Kind != "has_one" ||324 !reflect.DeepEqual(relation.Relationship.ForeignFieldNames, []string{"UserID"}) ||325 !reflect.DeepEqual(relation.Relationship.AssociationForeignFieldNames, []string{"Refer"}) {326 t.Errorf("Override belongs to foreign key with tag")327 }328 }329}330func TestHasMany(t *testing.T) {331 post := Post{332 Title: "post has many",333 Body: "body has many",334 Comments: []*Comment{{Content: "Comment 1"}, {Content: "Comment 2"}},335 }336 if err := DB.Save(&post).Error; err != nil {337 t.Error("Got errors when save post", err)338 }339 for _, comment := range post.Comments {340 if comment.PostId == 0 {341 t.Errorf("comment's PostID should be updated")342 }343 }344 var compareComments = func(comments []Comment, contents []string) bool {345 var commentContents []string346 for _, comment := range comments {347 commentContents = append(commentContents, comment.Content)348 }349 sort.Strings(commentContents)350 sort.Strings(contents)351 return reflect.DeepEqual(commentContents, contents)352 }353 // Query354 if DB.First(&Comment{}, "content = ?", "Comment 1").Error != nil {355 t.Errorf("Comment 1 should be saved")356 }357 var comments1 []Comment358 DB.Model(&post).Association("Comments").Find(&comments1)359 if !compareComments(comments1, []string{"Comment 1", "Comment 2"}) {360 t.Errorf("Query has many relations with Association")361 }362 var comments11 []Comment363 DB.Model(&post).Related(&comments11)364 if !compareComments(comments11, []string{"Comment 1", "Comment 2"}) {365 t.Errorf("Query has many relations with Related")366 }367 if DB.Model(&post).Association("Comments").Count() != 2 {368 t.Errorf("Post's comments count should be 2")369 }370 // Append371 DB.Model(&post).Association("Comments").Append(&Comment{Content: "Comment 3"})372 var comments2 []Comment373 DB.Model(&post).Related(&comments2)374 if !compareComments(comments2, []string{"Comment 1", "Comment 2", "Comment 3"}) {375 t.Errorf("Append new record to has many relations")376 }377 if DB.Model(&post).Association("Comments").Count() != 3 {378 t.Errorf("Post's comments count should be 3 after Append")379 }380 // Delete381 DB.Model(&post).Association("Comments").Delete(comments11)382 var comments3 []Comment383 DB.Model(&post).Related(&comments3)384 if !compareComments(comments3, []string{"Comment 3"}) {385 t.Errorf("Delete an existing resource for has many relations")386 }387 if DB.Model(&post).Association("Comments").Count() != 1 {388 t.Errorf("Post's comments count should be 1 after Delete 2")389 }390 // Replace391 DB.Model(&Post{Id: 999}).Association("Comments").Replace()392 var comments4 []Comment393 DB.Model(&post).Related(&comments4)394 if len(comments4) == 0 {395 t.Errorf("Replace for other resource should not clear all comments")396 }397 DB.Model(&post).Association("Comments").Replace(&Comment{Content: "Comment 4"}, &Comment{Content: "Comment 5"})398 var comments41 []Comment399 DB.Model(&post).Related(&comments41)400 if !compareComments(comments41, []string{"Comment 4", "Comment 5"}) {401 t.Errorf("Replace has many relations")402 }403 // Clear404 DB.Model(&Post{Id: 999}).Association("Comments").Clear()405 var comments5 []Comment406 DB.Model(&post).Related(&comments5)407 if len(comments5) == 0 {408 t.Errorf("Clear should not clear all comments")409 }410 DB.Model(&post).Association("Comments").Clear()411 var comments51 []Comment412 DB.Model(&post).Related(&comments51)413 if len(comments51) != 0 {414 t.Errorf("Clear has many relations")415 }416 // Check Association mode with soft delete417 var comment6 = Comment{418 Content: "comment 6",419 }420 DB.Model(&post).Association("Comments").Append(&comment6)421 if count := DB.Model(&post).Association("Comments").Count(); count != 1 {422 t.Errorf("post's comments count should be 1 after Append, but got %v", count)423 }424 DB.Delete(&comment6)425 if count := DB.Model(&post).Association("Comments").Count(); count != 0 {426 t.Errorf("post's comments count should be 0 after comment been deleted, but got %v", count)427 }428 var comments6 []Comment429 if DB.Model(&post).Association("Comments").Find(&comments6); len(comments6) != 0 {430 t.Errorf("post's comments count should be 0 when find with Find, but got %v", len(comments6))431 }432 if count := DB.Unscoped().Model(&post).Association("Comments").Count(); count != 1 {433 t.Errorf("post's comments count should be 1 when query with Unscoped, but got %v", count)434 }435 var comments61 []Comment436 if DB.Unscoped().Model(&post).Association("Comments").Find(&comments61); len(comments61) != 1 {437 t.Errorf("post's comments count should be 1 when query with Unscoped, but got %v", len(comments61))438 }439}440func TestHasManyOverrideForeignKey1(t *testing.T) {441 type Profile struct {442 gorm.Model443 Name string444 UserRefer uint445 }446 type User struct {447 gorm.Model448 Profile []Profile `gorm:"ForeignKey:UserRefer"`449 }450 if relation, ok := DB.NewScope(&User{}).FieldByName("Profile"); ok {451 if relation.Relationship.Kind != "has_many" ||452 !reflect.DeepEqual(relation.Relationship.ForeignFieldNames, []string{"UserRefer"}) ||453 !reflect.DeepEqual(relation.Relationship.AssociationForeignFieldNames, []string{"ID"}) {454 t.Errorf("Override belongs to foreign key with tag")455 }456 }457}458func TestHasManyOverrideForeignKey2(t *testing.T) {459 type Profile struct {460 gorm.Model461 Name string462 UserID uint463 }464 type User struct {465 gorm.Model466 Refer string467 Profile []Profile `gorm:"ForeignKey:UserID;AssociationForeignKey:Refer"`468 }469 if relation, ok := DB.NewScope(&User{}).FieldByName("Profile"); ok {470 if relation.Relationship.Kind != "has_many" ||471 !reflect.DeepEqual(relation.Relationship.ForeignFieldNames, []string{"UserID"}) ||472 !reflect.DeepEqual(relation.Relationship.AssociationForeignFieldNames, []string{"Refer"}) {473 t.Errorf("Override belongs to foreign key with tag")474 }475 }476}477func TestManyToMany(t *testing.T) {478 DB.Raw("delete from languages")479 var languages = []Language{{Name: "ZH"}, {Name: "EN"}}480 user := User{Name: "Many2Many", Languages: languages}481 DB.Save(&user)482 // Query483 var newLanguages []Language484 DB.Model(&user).Related(&newLanguages, "Languages")485 if len(newLanguages) != len([]string{"ZH", "EN"}) {486 t.Errorf("Query many to many relations")487 }488 DB.Model(&user).Association("Languages").Find(&newLanguages)489 if len(newLanguages) != len([]string{"ZH", "EN"}) {490 t.Errorf("Should be able to find many to many relations")491 }492 if DB.Model(&user).Association("Languages").Count() != len([]string{"ZH", "EN"}) {493 t.Errorf("Count should return correct result")494 }495 // Append496 DB.Model(&user).Association("Languages").Append(&Language{Name: "DE"})497 if DB.Where("name = ?", "DE").First(&Language{}).RecordNotFound() {498 t.Errorf("New record should be saved when append")499 }500 languageA := Language{Name: "AA"}501 DB.Save(&languageA)502 DB.Model(&User{Id: user.Id}).Association("Languages").Append(&languageA)503 languageC := Language{Name: "CC"}504 DB.Save(&languageC)505 DB.Model(&user).Association("Languages").Append(&[]Language{{Name: "BB"}, languageC})506 DB.Model(&User{Id: user.Id}).Association("Languages").Append(&[]Language{{Name: "DD"}, {Name: "EE"}})507 totalLanguages := []string{"ZH", "EN", "DE", "AA", "BB", "CC", "DD", "EE"}508 if DB.Model(&user).Association("Languages").Count() != len(totalLanguages) {509 t.Errorf("All appended languages should be saved")510 }511 // Delete512 user.Languages = []Language{}513 DB.Model(&user).Association("Languages").Find(&user.Languages)514 var language Language515 DB.Where("name = ?", "EE").First(&language)516 DB.Model(&user).Association("Languages").Delete(language, &language)517 if DB.Model(&user).Association("Languages").Count() != len(totalLanguages)-1 || len(user.Languages) != len(totalLanguages)-1 {518 t.Errorf("Relations should be deleted with Delete")519 }520 if DB.Where("name = ?", "EE").First(&Language{}).RecordNotFound() {521 t.Errorf("Language EE should not be deleted")522 }523 DB.Where("name IN (?)", []string{"CC", "DD"}).Find(&languages)524 user2 := User{Name: "Many2Many_User2", Languages: languages}525 DB.Save(&user2)526 DB.Model(&user).Association("Languages").Delete(languages, &languages)527 if DB.Model(&user).Association("Languages").Count() != len(totalLanguages)-3 || len(user.Languages) != len(totalLanguages)-3 {528 t.Errorf("Relations should be deleted with Delete")529 }530 if DB.Model(&user2).Association("Languages").Count() == 0 {531 t.Errorf("Other user's relations should not be deleted")532 }533 // Replace534 var languageB Language535 DB.Where("name = ?", "BB").First(&languageB)536 DB.Model(&user).Association("Languages").Replace(languageB)537 if len(user.Languages) != 1 || DB.Model(&user).Association("Languages").Count() != 1 {538 t.Errorf("Relations should be replaced")539 }540 DB.Model(&user).Association("Languages").Replace()541 if len(user.Languages) != 0 || DB.Model(&user).Association("Languages").Count() != 0 {542 t.Errorf("Relations should be replaced with empty")543 }544 DB.Model(&user).Association("Languages").Replace(&[]Language{{Name: "FF"}, {Name: "JJ"}})545 if len(user.Languages) != 2 || DB.Model(&user).Association("Languages").Count() != len([]string{"FF", "JJ"}) {546 t.Errorf("Relations should be replaced")547 }548 // Clear549 DB.Model(&user).Association("Languages").Clear()550 if len(user.Languages) != 0 || DB.Model(&user).Association("Languages").Count() != 0 {551 t.Errorf("Relations should be cleared")552 }553 // Check Association mode with soft delete554 var language6 = Language{555 Name: "language 6",556 }557 DB.Model(&user).Association("Languages").Append(&language6)558 if count := DB.Model(&user).Association("Languages").Count(); count != 1 {559 t.Errorf("user's languages count should be 1 after Append, but got %v", count)560 }561 DB.Delete(&language6)562 if count := DB.Model(&user).Association("Languages").Count(); count != 0 {563 t.Errorf("user's languages count should be 0 after language been deleted, but got %v", count)564 }565 var languages6 []Language566 if DB.Model(&user).Association("Languages").Find(&languages6); len(languages6) != 0 {567 t.Errorf("user's languages count should be 0 when find with Find, but got %v", len(languages6))568 }569 if count := DB.Unscoped().Model(&user).Association("Languages").Count(); count != 1 {570 t.Errorf("user's languages count should be 1 when query with Unscoped, but got %v", count)571 }572 var languages61 []Language573 if DB.Unscoped().Model(&user).Association("Languages").Find(&languages61); len(languages61) != 1 {574 t.Errorf("user's languages count should be 1 when query with Unscoped, but got %v", len(languages61))575 }576}577func TestRelated(t *testing.T) {578 user := User{579 Name: "jinzhu",580 BillingAddress: Address{Address1: "Billing Address - Address 1"},581 ShippingAddress: Address{Address1: "Shipping Address - Address 1"},582 Emails: []Email{{Email: "jinzhu@example.com"}, {Email: "jinzhu-2@example@example.com"}},583 CreditCard: CreditCard{Number: "1234567890"},584 Company: Company{Name: "company1"},585 }586 if err := DB.Save(&user).Error; err != nil {587 t.Errorf("No error should happen when saving user")588 }589 if user.CreditCard.ID == 0 {590 t.Errorf("After user save, credit card should have id")591 }592 if user.BillingAddress.ID == 0 {593 t.Errorf("After user save, billing address should have id")594 }595 if user.Emails[0].Id == 0 {596 t.Errorf("After user save, billing address should have id")597 }598 var emails []Email599 DB.Model(&user).Related(&emails)600 if len(emails) != 2 {601 t.Errorf("Should have two emails")602 }603 var emails2 []Email604 DB.Model(&user).Where("email = ?", "jinzhu@example.com").Related(&emails2)605 if len(emails2) != 1 {606 t.Errorf("Should have two emails")607 }608 var emails3 []*Email609 DB.Model(&user).Related(&emails3)610 if len(emails3) != 2 {611 t.Errorf("Should have two emails")612 }613 var user1 User614 DB.Model(&user).Related(&user1.Emails)615 if len(user1.Emails) != 2 {616 t.Errorf("Should have only one email match related condition")617 }618 var address1 Address619 DB.Model(&user).Related(&address1, "BillingAddressId")620 if address1.Address1 != "Billing Address - Address 1" {621 t.Errorf("Should get billing address from user correctly")622 }623 user1 = User{}624 DB.Model(&address1).Related(&user1, "BillingAddressId")625 if DB.NewRecord(user1) {626 t.Errorf("Should get user from address correctly")627 }628 var user2 User629 DB.Model(&emails[0]).Related(&user2)630 if user2.Id != user.Id || user2.Name != user.Name {631 t.Errorf("Should get user from email correctly")632 }633 var creditcard CreditCard634 var user3 User635 DB.First(&creditcard, "number = ?", "1234567890")636 DB.Model(&creditcard).Related(&user3)637 if user3.Id != user.Id || user3.Name != user.Name {638 t.Errorf("Should get user from credit card correctly")639 }640 if !DB.Model(&CreditCard{}).Related(&User{}).RecordNotFound() {641 t.Errorf("RecordNotFound for Related")642 }643 var company Company644 if DB.Model(&user).Related(&company, "Company").RecordNotFound() || company.Name != "company1" {645 t.Errorf("RecordNotFound for Related")646 }647}648func TestForeignKey(t *testing.T) {649 for _, structField := range DB.NewScope(&User{}).GetStructFields() {650 for _, foreignKey := range []string{"BillingAddressID", "ShippingAddressId", "CompanyID"} {651 if structField.Name == foreignKey && !structField.IsForeignKey {652 t.Errorf(fmt.Sprintf("%v should be foreign key", foreignKey))653 }654 }655 }656 for _, structField := range DB.NewScope(&Email{}).GetStructFields() {657 for _, foreignKey := range []string{"UserId"} {658 if structField.Name == foreignKey && !structField.IsForeignKey {659 t.Errorf(fmt.Sprintf("%v should be foreign key", foreignKey))660 }661 }662 }663 for _, structField := range DB.NewScope(&Post{}).GetStructFields() {664 for _, foreignKey := range []string{"CategoryId", "MainCategoryId"} {665 if structField.Name == foreignKey && !structField.IsForeignKey {666 t.Errorf(fmt.Sprintf("%v should be foreign key", foreignKey))667 }668 }669 }670 for _, structField := range DB.NewScope(&Comment{}).GetStructFields() {671 for _, foreignKey := range []string{"PostId"} {672 if structField.Name == foreignKey && !structField.IsForeignKey {673 t.Errorf(fmt.Sprintf("%v should be foreign key", foreignKey))674 }675 }676 }677}678func testForeignKey(t *testing.T, source interface{}, sourceFieldName string, target interface{}, targetFieldName string) {679 if dialect := os.Getenv("GORM_DIALECT"); dialect == "" || dialect == "sqlite" {680 // sqlite does not support ADD CONSTRAINT in ALTER TABLE681 return682 }683 targetScope := DB.NewScope(target)684 targetTableName := targetScope.TableName()685 modelScope := DB.NewScope(source)686 modelField, ok := modelScope.FieldByName(sourceFieldName)687 if !ok {688 t.Fatalf(fmt.Sprintf("Failed to get field by name: %v", sourceFieldName))689 }690 targetField, ok := targetScope.FieldByName(targetFieldName)691 if !ok {692 t.Fatalf(fmt.Sprintf("Failed to get field by name: %v", targetFieldName))693 }694 dest := fmt.Sprintf("%v(%v)", targetTableName, targetField.DBName)695 err := DB.Model(source).AddForeignKey(modelField.DBName, dest, "CASCADE", "CASCADE").Error696 if err != nil {697 t.Fatalf(fmt.Sprintf("Failed to create foreign key: %v", err))698 }699}700func TestLongForeignKey(t *testing.T) {701 testForeignKey(t, &NotSoLongTableName{}, "ReallyLongThingID", &ReallyLongTableNameToTestMySQLNameLengthLimit{}, "ID")702}703func TestLongForeignKeyWithShortDest(t *testing.T) {704 testForeignKey(t, &ReallyLongThingThatReferencesShort{}, "ShortID", &Short{}, "ID")705}706func TestHasManyChildrenWithOneStruct(t *testing.T) {707 category := Category{708 Name: "main",709 Categories: []Category{710 {Name: "sub1"},711 {Name: "sub2"},712 },713 }714 DB.Save(&category)715}716func TestAutoSaveBelongsToAssociation(t *testing.T) {717 type Company struct {718 gorm.Model719 Name string720 }721 type User struct {722 gorm.Model723 Name string724 CompanyID uint725 Company Company `gorm:"association_autoupdate:false;association_autocreate:false;"`726 }727 DB.Where("name = ?", "auto_save_association").Delete(&Company{})728 DB.AutoMigrate(&Company{}, &User{})729 DB.Save(&User{Name: "jinzhu", Company: Company{Name: "auto_save_association"}})730 if !DB.Where("name = ?", "auto_save_association").First(&Company{}).RecordNotFound() {731 t.Errorf("Company auto_save_association should not have been saved when autosave is false")732 }733 // if foreign key is set, this should be saved even if association isn't734 company := Company{Name: "auto_save_association"}735 DB.Save(&company)736 company.Name = "auto_save_association_new_name"737 user := User{Name: "jinzhu", Company: company}738 DB.Save(&user)739 if !DB.Where("name = ?", "auto_save_association_new_name").First(&Company{}).RecordNotFound() {740 t.Errorf("Company should not have been updated")741 }742 if DB.Where("id = ? AND company_id = ?", user.ID, company.ID).First(&User{}).RecordNotFound() {743 t.Errorf("User's foreign key should have been saved")744 }745 user2 := User{Name: "jinzhu_2", Company: Company{Name: "auto_save_association_2"}}746 DB.Set("gorm:association_autocreate", true).Save(&user2)747 if DB.Where("name = ?", "auto_save_association_2").First(&Company{}).RecordNotFound() {748 t.Errorf("Company auto_save_association_2 should been created when autocreate is true")749 }750 user2.Company.Name = "auto_save_association_2_newname"751 DB.Set("gorm:association_autoupdate", true).Save(&user2)752 if DB.Where("name = ?", "auto_save_association_2_newname").First(&Company{}).RecordNotFound() {753 t.Errorf("Company should been updated")754 }755}756func TestAutoSaveHasOneAssociation(t *testing.T) {757 type Company struct {758 gorm.Model759 UserID uint760 Name string761 }762 type User struct {763 gorm.Model764 Name string765 Company Company `gorm:"association_autoupdate:false;association_autocreate:false;"`766 }767 DB.Where("name = ?", "auto_save_has_one_association").Delete(&Company{})768 DB.AutoMigrate(&Company{}, &User{})769 DB.Save(&User{Name: "jinzhu", Company: Company{Name: "auto_save_has_one_association"}})770 if !DB.Where("name = ?", "auto_save_has_one_association").First(&Company{}).RecordNotFound() {771 t.Errorf("Company auto_save_has_one_association should not have been saved when autosave is false")772 }773 company := Company{Name: "auto_save_has_one_association"}774 DB.Save(&company)775 company.Name = "auto_save_has_one_association_new_name"776 user := User{Name: "jinzhu", Company: company}777 DB.Save(&user)778 if !DB.Where("name = ?", "auto_save_has_one_association_new_name").First(&Company{}).RecordNotFound() {779 t.Errorf("Company should not have been updated")780 }781 if !DB.Where("name = ? AND user_id = ?", "auto_save_has_one_association", user.ID).First(&Company{}).RecordNotFound() {782 t.Errorf("Company should not have been updated")783 }784 if user.Company.UserID == 0 {785 t.Errorf("UserID should be assigned")786 }787 company.Name = "auto_save_has_one_association_2_new_name"788 DB.Set("gorm:association_autoupdate", true).Save(&user)789 if DB.Where("name = ? AND user_id = ?", "auto_save_has_one_association_new_name", user.ID).First(&Company{}).RecordNotFound() {790 t.Errorf("Company should been updated")791 }792 user2 := User{Name: "jinzhu_2", Company: Company{Name: "auto_save_has_one_association_2"}}793 DB.Set("gorm:association_autocreate", true).Save(&user2)794 if DB.Where("name = ?", "auto_save_has_one_association_2").First(&Company{}).RecordNotFound() {795 t.Errorf("Company auto_save_has_one_association_2 should been created when autocreate is true")796 }797}798func TestAutoSaveMany2ManyAssociation(t *testing.T) {799 type Company struct {800 gorm.Model801 Name string802 }803 type User struct {804 gorm.Model805 Name string806 Companies []Company `gorm:"many2many:user_companies;association_autoupdate:false;association_autocreate:false;"`807 }808 DB.AutoMigrate(&Company{}, &User{})809 DB.Save(&User{Name: "jinzhu", Companies: []Company{{Name: "auto_save_m2m_association"}}})810 if !DB.Where("name = ?", "auto_save_m2m_association").First(&Company{}).RecordNotFound() {811 t.Errorf("Company auto_save_m2m_association should not have been saved when autosave is false")812 }813 company := Company{Name: "auto_save_m2m_association"}814 DB.Save(&company)815 company.Name = "auto_save_m2m_association_new_name"816 user := User{Name: "jinzhu", Companies: []Company{company, {Name: "auto_save_m2m_association_new_name_2"}}}817 DB.Save(&user)818 if !DB.Where("name = ?", "auto_save_m2m_association_new_name").First(&Company{}).RecordNotFound() {819 t.Errorf("Company should not have been updated")820 }821 if !DB.Where("name = ?", "auto_save_m2m_association_new_name_2").First(&Company{}).RecordNotFound() {822 t.Errorf("Company should not been created")823 }824 if DB.Model(&user).Association("Companies").Count() != 1 {825 t.Errorf("Relationship should been saved")826 }827 DB.Set("gorm:association_autoupdate", true).Set("gorm:association_autocreate", true).Save(&user)828 if DB.Where("name = ?", "auto_save_m2m_association_new_name").First(&Company{}).RecordNotFound() {829 t.Errorf("Company should been updated")830 }831 if DB.Where("name = ?", "auto_save_m2m_association_new_name_2").First(&Company{}).RecordNotFound() {832 t.Errorf("Company should been created")833 }834 if DB.Model(&user).Association("Companies").Count() != 2 {835 t.Errorf("Relationship should been updated")836 }837}...

Full Screen

Full Screen

base.go

Source:base.go Github

copy

Full Screen

...151 t.DB = t.ox152 t.transactionLevel = 0153 return tx154}155// Save update value in database, if the value doesn't have primary key, will insert it156func (t *DB) Save(value interface{}) *gorm.DB {157 if !t.tx {158 log.Panic("[orm] db.Save error: current connection not support modify data\n")159 }160 return t.DB.Save(value)161}162// FirstOrCreate find first matched record or create a new one with given conditions (only works with struct, map conditions)163func (t *DB) FirstOrCreate(out interface{}, where ...interface{}) *gorm.DB {164 if !t.tx {165 log.Panic("[orm] db.Save error: current connection not support modify data\n")166 }167 return t.DB.FirstOrCreate(out, where...)168}169// Update update attributes with callbacks170func (t *DB) Update(attrs ...interface{}) *gorm.DB {171 if !t.tx {172 log.Panic("[orm] db.Save error: current connection not support modify data\n")173 }174 return t.DB.Update(attrs...)175}176// Updates update attributes with callbacks177func (t *DB) Updates(values interface{}, ignoreProtectedAttrs ...bool) *gorm.DB {178 if !t.tx {179 log.Panic("[orm] db.Save error: current connection not support modify data\n")180 }181 return t.DB.Updates(values, ignoreProtectedAttrs...)182}183// UpdateColumn update attributes without callbacks184func (t *DB) UpdateColumn(attrs ...interface{}) *gorm.DB {185 if !t.tx {186 log.Panic("[orm] db.Save error: current connection not support modify data\n")187 }188 return t.DB.UpdateColumn(attrs...)189}190// UpdateColumns update attributes without callbacks191func (t *DB) UpdateColumns(values interface{}) *gorm.DB {192 if !t.tx {193 log.Panic("[orm] db.Save error: current connection not support modify data\n")194 }195 return t.DB.UpdateColumns(values)196}197// Delete delete value match given conditions, if the value has primary key, then will including the primary key as condition198func (t *DB) Delete(value interface{}, where ...interface{}) *gorm.DB {199 if !t.tx {200 log.Panic("[orm] db.Save error: current connection not support modify data\n")201 }202 return t.DB.Delete(value, where...)203}204// Create insert the value into database205func (t *DB) Create(value interface{}) *gorm.DB {206 if !t.tx {207 log.Panic("[orm] db.Save error: current connection not support create data\n")208 }209 return t.DB.Create(value)210}211// Raw use raw sql as conditions, won't run it unless invoked by other methods212// db.Raw("SELECT name, age FROM users WHERE name = ?", 3).Scan(&result)213// func (t *DB) Raw(sql string, values ...interface{}) *gorm.DB {214// if !t.tx {215// log.Panic("[orm] db.Save error: current connection not support raw sql\n")216// }217// return t.DB.Raw(sql, values...)218// }219// Exec execute raw sql220func (t *DB) Exec(sql string, values ...interface{}) *gorm.DB {221 if !t.tx {222 log.Panic("[orm] db.Save error: current connection not support raw sql\n")223 }224 return t.DB.Exec(sql, values...)225}226// Cacher 获取缓存控制227func Cacher() cache.Cacher {228 if c := baa.Default().GetDI("cache"); c != nil {229 return c.(cache.Cacher)230 }231 return nil232}...

Full Screen

Full Screen

Save

Using AI Code Generation

copy

Full Screen

1db.Save()2db.Save()3db.Save()4db.Save()5db.Save()6db.Save()7db.Save()8db.Save()9db.Save()10db.Save()11db.Save()12db.Save()13db.Save()14db.Save()15db.Save()16db.Save()17db.Save()18db.Save()19db.Save()20db.Save()21db.Save()22db.Save()23db.Save()24db.Save()25db.Save()26db.Save()27db.Save()28db.Save()29db.Save()30db.Save()31db.Save()32db.Save()33db.Save()34db.Save()35db.Save()

Full Screen

Full Screen

Save

Using AI Code Generation

copy

Full Screen

1func Save() {2}3func Save() {4}5func Save() {6}7func Save() {8}9func Save() {10}11func Save() {12}13func Save() {14}15func Save() {16}17func Save() {18}19func Save() {20}21func Save() {22}23func Save() {24}25func Save() {26}27func Save() {28}29func Save() {30}31func Save() {32}

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful