github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/core/ledger/util/couchdb/couchdb_test.go (about) 1 /* 2 Copyright IBM Corp. 2016, 2017 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package couchdb 18 19 import ( 20 "encoding/json" 21 "fmt" 22 "os" 23 "testing" 24 "unicode/utf8" 25 26 "github.com/hyperledger/fabric/common/ledger/testutil" 27 "github.com/hyperledger/fabric/core/ledger/ledgerconfig" 28 ledgertestutil "github.com/hyperledger/fabric/core/ledger/testutil" 29 "github.com/spf13/viper" 30 ) 31 32 //Basic setup to test couch 33 var connectURL = "couchdb:5984" 34 var badConnectURL = "couchdb:5990" 35 var username = "" 36 var password = "" 37 38 func cleanup(database string) error { 39 //create a new connection 40 couchInstance, err := CreateCouchInstance(connectURL, username, password) 41 if err != nil { 42 fmt.Println("Unexpected error", err) 43 return err 44 } 45 db := CouchDatabase{couchInstance: *couchInstance, dbName: database} 46 //drop the test database 47 db.DropDatabase() 48 return nil 49 } 50 51 type Asset struct { 52 ID string `json:"_id"` 53 Rev string `json:"_rev"` 54 AssetName string `json:"asset_name"` 55 Color string `json:"color"` 56 Size string `json:"size"` 57 Owner string `json:"owner"` 58 } 59 60 var assetJSON = []byte(`{"asset_name":"marble1","color":"blue","size":"35","owner":"jerry"}`) 61 62 func TestMain(m *testing.M) { 63 ledgertestutil.SetupCoreYAMLConfig("./../../../../peer") 64 viper.Set("ledger.state.stateDatabase", "CouchDB") 65 result := m.Run() 66 viper.Set("ledger.state.stateDatabase", "goleveldb") 67 os.Exit(result) 68 } 69 70 func TestDBConnectionDef(t *testing.T) { 71 72 //call a helper method to load the core.yaml 73 ledgertestutil.SetupCoreYAMLConfig("./../../../../peer") 74 75 //create a new connection 76 _, err := CreateConnectionDefinition(connectURL, "", "") 77 testutil.AssertNoError(t, err, fmt.Sprintf("Error when trying to create database connection definition")) 78 79 } 80 81 func TestDBBadConnectionDef(t *testing.T) { 82 83 //create a new connection 84 _, err := CreateConnectionDefinition("^^^localhost:5984", "", "") 85 testutil.AssertError(t, err, fmt.Sprintf("Did not receive error when trying to create database connection definition with a bad hostname")) 86 87 } 88 89 func TestDBCreateSaveWithoutRevision(t *testing.T) { 90 91 if ledgerconfig.IsCouchDBEnabled() == true { 92 93 database := "testdbcreatesavewithoutrevision" 94 err := cleanup(database) 95 testutil.AssertNoError(t, err, fmt.Sprintf("Error when trying to cleanup Error: %s", err)) 96 defer cleanup(database) 97 98 if err == nil { 99 //create a new instance and database object 100 couchInstance, err := CreateCouchInstance(connectURL, username, password) 101 testutil.AssertNoError(t, err, fmt.Sprintf("Error when trying to create couch instance")) 102 db := CouchDatabase{couchInstance: *couchInstance, dbName: database} 103 104 //create a new database 105 _, errdb := db.CreateDatabaseIfNotExist() 106 testutil.AssertNoError(t, errdb, fmt.Sprintf("Error when trying to create database")) 107 108 //Save the test document 109 _, saveerr := db.SaveDoc("2", "", &CouchDoc{JSONValue: assetJSON, Attachments: nil}) 110 testutil.AssertNoError(t, saveerr, fmt.Sprintf("Error when trying to save a document")) 111 } 112 } 113 } 114 115 func TestDBBadDatabaseName(t *testing.T) { 116 117 if ledgerconfig.IsCouchDBEnabled() == true { 118 119 //create a new instance and database object using a valid database name mixed case 120 couchInstance, err := CreateCouchInstance(connectURL, username, password) 121 testutil.AssertNoError(t, err, fmt.Sprintf("Error when trying to create couch instance")) 122 _, dberr := CreateCouchDatabase(*couchInstance, "testDB") 123 testutil.AssertNoError(t, dberr, fmt.Sprintf("Error when testing a valid database name")) 124 125 //create a new instance and database object using a valid database name letters and numbers 126 couchInstance, err = CreateCouchInstance(connectURL, username, password) 127 testutil.AssertNoError(t, err, fmt.Sprintf("Error when trying to create couch instance")) 128 _, dberr = CreateCouchDatabase(*couchInstance, "test132") 129 testutil.AssertNoError(t, dberr, fmt.Sprintf("Error when testing a valid database name")) 130 131 //create a new instance and database object using a valid database name - special characters 132 couchInstance, err = CreateCouchInstance(connectURL, username, password) 133 testutil.AssertNoError(t, err, fmt.Sprintf("Error when trying to create couch instance")) 134 _, dberr = CreateCouchDatabase(*couchInstance, "test1234~!@#$%^&*()[]{}.") 135 testutil.AssertNoError(t, dberr, fmt.Sprintf("Error when testing a valid database name")) 136 137 //create a new instance and database object using a invalid database name - too long /* 138 couchInstance, err = CreateCouchInstance(connectURL, username, password) 139 testutil.AssertNoError(t, err, fmt.Sprintf("Error when trying to create couch instance")) 140 _, dberr = CreateCouchDatabase(*couchInstance, "A12345678901234567890123456789012345678901234"+ 141 "56789012345678901234567890123456789012345678901234567890123456789012345678901234567890"+ 142 "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456"+ 143 "78901234567890123456789012345678901234567890") 144 testutil.AssertError(t, dberr, fmt.Sprintf("Error should have been thrown for invalid database name")) 145 146 } 147 148 } 149 150 func TestDBBadConnection(t *testing.T) { 151 152 if ledgerconfig.IsCouchDBEnabled() == true { 153 154 //create a new instance and database object 155 _, err := CreateCouchInstance(badConnectURL, username, password) 156 testutil.AssertError(t, err, fmt.Sprintf("Error should have been thrown for a bad connection")) 157 } 158 } 159 160 func TestDBCreateDatabaseAndPersist(t *testing.T) { 161 162 if ledgerconfig.IsCouchDBEnabled() == true { 163 164 database := "testdbcreatedatabaseandpersist" 165 err := cleanup(database) 166 testutil.AssertNoError(t, err, fmt.Sprintf("Error when trying to cleanup Error: %s", err)) 167 defer cleanup(database) 168 169 if err == nil { 170 //create a new instance and database object 171 couchInstance, err := CreateCouchInstance(connectURL, username, password) 172 testutil.AssertNoError(t, err, fmt.Sprintf("Error when trying to create couch instance")) 173 db := CouchDatabase{couchInstance: *couchInstance, dbName: database} 174 175 //create a new database 176 _, errdb := db.CreateDatabaseIfNotExist() 177 testutil.AssertNoError(t, errdb, fmt.Sprintf("Error when trying to create database")) 178 179 //Retrieve the info for the new database and make sure the name matches 180 dbResp, _, errdb := db.GetDatabaseInfo() 181 testutil.AssertNoError(t, errdb, fmt.Sprintf("Error when trying to retrieve database information")) 182 testutil.AssertEquals(t, dbResp.DbName, database) 183 184 //Save the test document 185 _, saveerr := db.SaveDoc("idWith/slash", "", &CouchDoc{JSONValue: assetJSON, Attachments: nil}) 186 testutil.AssertNoError(t, saveerr, fmt.Sprintf("Error when trying to save a document")) 187 188 //Retrieve the test document 189 dbGetResp, _, geterr := db.ReadDoc("idWith/slash") 190 testutil.AssertNoError(t, geterr, fmt.Sprintf("Error when trying to retrieve a document")) 191 192 //Unmarshal the document to Asset structure 193 assetResp := &Asset{} 194 geterr = json.Unmarshal(dbGetResp.JSONValue, &assetResp) 195 testutil.AssertNoError(t, geterr, fmt.Sprintf("Error when trying to retrieve a document")) 196 197 //Verify the owner retrieved matches 198 testutil.AssertEquals(t, assetResp.Owner, "jerry") 199 200 //Save the test document 201 _, saveerr = db.SaveDoc("1", "", &CouchDoc{JSONValue: assetJSON, Attachments: nil}) 202 testutil.AssertNoError(t, saveerr, fmt.Sprintf("Error when trying to save a document")) 203 204 //Retrieve the test document 205 dbGetResp, _, geterr = db.ReadDoc("1") 206 testutil.AssertNoError(t, geterr, fmt.Sprintf("Error when trying to retrieve a document")) 207 208 //Unmarshal the document to Asset structure 209 assetResp = &Asset{} 210 geterr = json.Unmarshal(dbGetResp.JSONValue, &assetResp) 211 testutil.AssertNoError(t, geterr, fmt.Sprintf("Error when trying to retrieve a document")) 212 213 //Verify the owner retrieved matches 214 testutil.AssertEquals(t, assetResp.Owner, "jerry") 215 216 //Change owner to bob 217 assetResp.Owner = "bob" 218 219 //create a byte array of the JSON 220 assetDocUpdated, _ := json.Marshal(assetResp) 221 222 //Save the updated test document 223 _, saveerr = db.SaveDoc("1", "", &CouchDoc{JSONValue: assetDocUpdated, Attachments: nil}) 224 testutil.AssertNoError(t, saveerr, fmt.Sprintf("Error when trying to save the updated document")) 225 226 //Retrieve the updated test document 227 dbGetResp, _, geterr = db.ReadDoc("1") 228 testutil.AssertNoError(t, geterr, fmt.Sprintf("Error when trying to retrieve a document")) 229 230 //Unmarshal the document to Asset structure 231 assetResp = &Asset{} 232 json.Unmarshal(dbGetResp.JSONValue, &assetResp) 233 234 //Assert that the update was saved and retrieved 235 testutil.AssertEquals(t, assetResp.Owner, "bob") 236 237 //Drop the database 238 _, errdbdrop := db.DropDatabase() 239 testutil.AssertNoError(t, errdbdrop, fmt.Sprintf("Error dropping database")) 240 241 //Retrieve the info for the new database and make sure the name matches 242 _, _, errdbinfo := db.GetDatabaseInfo() 243 testutil.AssertError(t, errdbinfo, fmt.Sprintf("Error should have been thrown for missing database")) 244 } 245 } 246 247 } 248 249 func TestDBBadJSON(t *testing.T) { 250 251 if ledgerconfig.IsCouchDBEnabled() == true { 252 253 database := "testdbbadjson" 254 err := cleanup(database) 255 testutil.AssertNoError(t, err, fmt.Sprintf("Error when trying to cleanup Error: %s", err)) 256 defer cleanup(database) 257 258 if err == nil { 259 260 //create a new instance and database object 261 couchInstance, err := CreateCouchInstance(connectURL, username, password) 262 testutil.AssertNoError(t, err, fmt.Sprintf("Error when trying to create couch instance")) 263 db := CouchDatabase{couchInstance: *couchInstance, dbName: database} 264 265 //create a new database 266 _, errdb := db.CreateDatabaseIfNotExist() 267 testutil.AssertNoError(t, errdb, fmt.Sprintf("Error when trying to create database")) 268 269 //Retrieve the info for the new database and make sure the name matches 270 dbResp, _, errdb := db.GetDatabaseInfo() 271 testutil.AssertNoError(t, errdb, fmt.Sprintf("Error when trying to retrieve database information")) 272 testutil.AssertEquals(t, dbResp.DbName, database) 273 274 badJSON := []byte(`{"asset_name"}`) 275 276 //Save the test document 277 _, saveerr := db.SaveDoc("1", "", &CouchDoc{JSONValue: badJSON, Attachments: nil}) 278 testutil.AssertError(t, saveerr, fmt.Sprintf("Error should have been thrown for a bad JSON")) 279 280 } 281 282 } 283 284 } 285 286 func TestPrefixScan(t *testing.T) { 287 if !ledgerconfig.IsCouchDBEnabled() { 288 return 289 } 290 database := "testprefixscan" 291 err := cleanup(database) 292 testutil.AssertNoError(t, err, fmt.Sprintf("Error when trying to cleanup Error: %s", err)) 293 defer cleanup(database) 294 295 if err == nil { 296 //create a new instance and database object 297 couchInstance, err := CreateCouchInstance(connectURL, username, password) 298 testutil.AssertNoError(t, err, fmt.Sprintf("Error when trying to create couch instance")) 299 db := CouchDatabase{couchInstance: *couchInstance, dbName: database} 300 301 //create a new database 302 _, errdb := db.CreateDatabaseIfNotExist() 303 testutil.AssertNoError(t, errdb, fmt.Sprintf("Error when trying to create database")) 304 305 //Retrieve the info for the new database and make sure the name matches 306 dbResp, _, errdb := db.GetDatabaseInfo() 307 testutil.AssertNoError(t, errdb, fmt.Sprintf("Error when trying to retrieve database information")) 308 testutil.AssertEquals(t, dbResp.DbName, database) 309 310 //Save documents 311 for i := 0; i < 20; i++ { 312 id1 := string(0) + string(i) + string(0) 313 id2 := string(0) + string(i) + string(1) 314 id3 := string(0) + string(i) + string(utf8.MaxRune-1) 315 _, saveerr := db.SaveDoc(id1, "", &CouchDoc{JSONValue: assetJSON, Attachments: nil}) 316 testutil.AssertNoError(t, saveerr, fmt.Sprintf("Error when trying to save a document")) 317 _, saveerr = db.SaveDoc(id2, "", &CouchDoc{JSONValue: assetJSON, Attachments: nil}) 318 testutil.AssertNoError(t, saveerr, fmt.Sprintf("Error when trying to save a document")) 319 _, saveerr = db.SaveDoc(id3, "", &CouchDoc{JSONValue: assetJSON, Attachments: nil}) 320 testutil.AssertNoError(t, saveerr, fmt.Sprintf("Error when trying to save a document")) 321 322 } 323 startKey := string(0) + string(10) 324 endKey := startKey + string(utf8.MaxRune) 325 _, _, geterr := db.ReadDoc(endKey) 326 testutil.AssertNoError(t, geterr, fmt.Sprintf("Error when trying to get lastkey")) 327 328 resultsPtr, geterr := db.ReadDocRange(startKey, endKey, 1000, 0) 329 testutil.AssertNoError(t, geterr, fmt.Sprintf("Error when trying to perform a range scan")) 330 testutil.AssertNotNil(t, resultsPtr) 331 results := *resultsPtr 332 testutil.AssertEquals(t, len(results), 3) 333 testutil.AssertEquals(t, results[0].ID, string(0)+string(10)+string(0)) 334 testutil.AssertEquals(t, results[1].ID, string(0)+string(10)+string(1)) 335 testutil.AssertEquals(t, results[2].ID, string(0)+string(10)+string(utf8.MaxRune-1)) 336 337 //Drop the database 338 _, errdbdrop := db.DropDatabase() 339 testutil.AssertNoError(t, errdbdrop, fmt.Sprintf("Error dropping database")) 340 341 //Retrieve the info for the new database and make sure the name matches 342 _, _, errdbinfo := db.GetDatabaseInfo() 343 testutil.AssertError(t, errdbinfo, fmt.Sprintf("Error should have been thrown for missing database")) 344 } 345 } 346 347 func TestDBSaveAttachment(t *testing.T) { 348 349 if ledgerconfig.IsCouchDBEnabled() == true { 350 351 database := "testdbsaveattachment" 352 err := cleanup(database) 353 testutil.AssertNoError(t, err, fmt.Sprintf("Error when trying to cleanup Error: %s", err)) 354 defer cleanup(database) 355 356 if err == nil { 357 358 byteText := []byte(`This is a test document. This is only a test`) 359 360 attachment := Attachment{} 361 attachment.AttachmentBytes = byteText 362 attachment.ContentType = "text/plain" 363 attachment.Name = "valueBytes" 364 365 attachments := []Attachment{} 366 attachments = append(attachments, attachment) 367 368 //create a new instance and database object 369 couchInstance, err := CreateCouchInstance(connectURL, username, password) 370 testutil.AssertNoError(t, err, fmt.Sprintf("Error when trying to create couch instance")) 371 db := CouchDatabase{couchInstance: *couchInstance, dbName: database} 372 373 //create a new database 374 _, errdb := db.CreateDatabaseIfNotExist() 375 testutil.AssertNoError(t, errdb, fmt.Sprintf("Error when trying to create database")) 376 377 //Save the test document 378 _, saveerr := db.SaveDoc("10", "", &CouchDoc{JSONValue: nil, Attachments: attachments}) 379 testutil.AssertNoError(t, saveerr, fmt.Sprintf("Error when trying to save a document")) 380 381 //Attempt to retrieve the updated test document with attachments 382 couchDoc, _, geterr2 := db.ReadDoc("10") 383 testutil.AssertNoError(t, geterr2, fmt.Sprintf("Error when trying to retrieve a document with attachment")) 384 testutil.AssertNotNil(t, couchDoc.Attachments) 385 testutil.AssertEquals(t, couchDoc.Attachments[0].AttachmentBytes, byteText) 386 } 387 388 } 389 } 390 391 func TestDBDeleteDocument(t *testing.T) { 392 393 if ledgerconfig.IsCouchDBEnabled() == true { 394 395 database := "testdbdeletedocument" 396 err := cleanup(database) 397 testutil.AssertNoError(t, err, fmt.Sprintf("Error when trying to cleanup Error: %s", err)) 398 defer cleanup(database) 399 400 if err == nil { 401 //create a new instance and database object 402 couchInstance, err := CreateCouchInstance(connectURL, username, password) 403 testutil.AssertNoError(t, err, fmt.Sprintf("Error when trying to create couch instance")) 404 db := CouchDatabase{couchInstance: *couchInstance, dbName: database} 405 406 //create a new database 407 _, errdb := db.CreateDatabaseIfNotExist() 408 testutil.AssertNoError(t, errdb, fmt.Sprintf("Error when trying to create database")) 409 410 //Save the test document 411 _, saveerr := db.SaveDoc("2", "", &CouchDoc{JSONValue: assetJSON, Attachments: nil}) 412 testutil.AssertNoError(t, saveerr, fmt.Sprintf("Error when trying to save a document")) 413 414 //Attempt to retrieve the test document 415 _, _, readErr := db.ReadDoc("2") 416 testutil.AssertNoError(t, readErr, fmt.Sprintf("Error when trying to retrieve a document with attachment")) 417 418 //Delete the test document 419 deleteErr := db.DeleteDoc("2", "") 420 testutil.AssertNoError(t, deleteErr, fmt.Sprintf("Error when trying to delete a document")) 421 422 //Attempt to retrieve the test document 423 readValue, _, _ := db.ReadDoc("2") 424 testutil.AssertNil(t, readValue) 425 } 426 } 427 } 428 429 func TestDBDeleteNonExistingDocument(t *testing.T) { 430 431 if ledgerconfig.IsCouchDBEnabled() == true { 432 433 database := "testdbdeletenonexistingdocument" 434 err := cleanup(database) 435 testutil.AssertNoError(t, err, fmt.Sprintf("Error when trying to cleanup Error: %s", err)) 436 defer cleanup(database) 437 438 if err == nil { 439 //create a new instance and database object 440 couchInstance, err := CreateCouchInstance(connectURL, username, password) 441 testutil.AssertNoError(t, err, fmt.Sprintf("Error when trying to create couch instance")) 442 db := CouchDatabase{couchInstance: *couchInstance, dbName: database} 443 444 //create a new database 445 _, errdb := db.CreateDatabaseIfNotExist() 446 testutil.AssertNoError(t, errdb, fmt.Sprintf("Error when trying to create database")) 447 448 //Save the test document 449 deleteErr := db.DeleteDoc("2", "") 450 testutil.AssertNoError(t, deleteErr, fmt.Sprintf("Error when trying to delete a non existing document")) 451 } 452 } 453 } 454 455 func TestCouchDBVersion(t *testing.T) { 456 457 err := checkCouchDBVersion("2.0.0") 458 testutil.AssertNoError(t, err, fmt.Sprintf("Error should not have been thrown for valid version")) 459 460 err = checkCouchDBVersion("4.5.0") 461 testutil.AssertNoError(t, err, fmt.Sprintf("Error should not have been thrown for valid version")) 462 463 err = checkCouchDBVersion("1.6.5.4") 464 testutil.AssertError(t, err, fmt.Sprintf("Error should have been thrown for invalid version")) 465 466 err = checkCouchDBVersion("0.0.0.0") 467 testutil.AssertError(t, err, fmt.Sprintf("Error should have been thrown for invalid version")) 468 469 }