github.com/true-sqn/fabric@v2.1.1+incompatible/core/ledger/util/couchdb/couchdbutil_test.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package couchdb 8 9 import ( 10 "encoding/hex" 11 "testing" 12 13 "github.com/hyperledger/fabric/common/metrics/disabled" 14 "github.com/hyperledger/fabric/common/util" 15 "github.com/stretchr/testify/assert" 16 ) 17 18 //Unit test of couch db util functionality 19 func TestCreateCouchDBConnectionAndDB(t *testing.T) { 20 startCouchDB() 21 database := "testcreatecouchdbconnectionanddb" 22 cleanup(database) 23 defer cleanup(database) 24 //create a new connection 25 couchInstance, err := CreateCouchInstance(testConfig(), &disabled.Provider{}) 26 assert.NoError(t, err, "Error when trying to CreateCouchInstance") 27 28 _, err = CreateCouchDatabase(couchInstance, database) 29 assert.NoError(t, err, "Error when trying to CreateCouchDatabase") 30 31 } 32 33 //Unit test of couch db util functionality 34 func TestNotCreateCouchGlobalChangesDB(t *testing.T) { 35 startCouchDB() 36 config := testConfig() 37 config.CreateGlobalChangesDB = false 38 database := "_global_changes" 39 cleanup(database) 40 defer cleanup(database) 41 42 //create a new connection 43 couchInstance, err := CreateCouchInstance(config, &disabled.Provider{}) 44 assert.NoError(t, err, "Error when trying to CreateCouchInstance") 45 46 db := CouchDatabase{CouchInstance: couchInstance, DBName: database} 47 48 //Retrieve the info for the new database and make sure the name matches 49 _, _, errdb := db.GetDatabaseInfo() 50 assert.NotNil(t, errdb) 51 } 52 53 //Unit test of couch db util functionality 54 func TestCreateCouchDBSystemDBs(t *testing.T) { 55 startCouchDB() 56 database := "testcreatecouchdbsystemdb" 57 cleanup(database) 58 defer cleanup(database) 59 60 //create a new connection 61 couchInstance, err := CreateCouchInstance(testConfig(), &disabled.Provider{}) 62 63 assert.NoError(t, err, "Error when trying to CreateCouchInstance") 64 65 err = CreateSystemDatabasesIfNotExist(couchInstance) 66 assert.NoError(t, err, "Error when trying to create system databases") 67 68 db := CouchDatabase{CouchInstance: couchInstance, DBName: "_users"} 69 70 //Retrieve the info for the new database and make sure the name matches 71 dbResp, _, errdb := db.GetDatabaseInfo() 72 assert.NoError(t, errdb, "Error when trying to retrieve _users database information") 73 assert.Equal(t, "_users", dbResp.DbName) 74 75 db = CouchDatabase{CouchInstance: couchInstance, DBName: "_replicator"} 76 77 //Retrieve the info for the new database and make sure the name matches 78 dbResp, _, errdb = db.GetDatabaseInfo() 79 assert.NoError(t, errdb, "Error when trying to retrieve _replicator database information") 80 assert.Equal(t, "_replicator", dbResp.DbName) 81 82 db = CouchDatabase{CouchInstance: couchInstance, DBName: "_global_changes"} 83 84 //Retrieve the info for the new database and make sure the name matches 85 dbResp, _, errdb = db.GetDatabaseInfo() 86 assert.NoError(t, errdb, "Error when trying to retrieve _global_changes database information") 87 assert.Equal(t, "_global_changes", dbResp.DbName) 88 89 } 90 91 func TestDatabaseMapping(t *testing.T) { 92 //create a new instance and database object using a database name mixed case 93 _, err := mapAndValidateDatabaseName("testDB") 94 assert.Error(t, err, "Error expected because the name contains capital letters") 95 96 //create a new instance and database object using a database name with special characters 97 _, err = mapAndValidateDatabaseName("test1234/1") 98 assert.Error(t, err, "Error expected because the name contains illegal chars") 99 100 //create a new instance and database object using a database name with special characters 101 _, err = mapAndValidateDatabaseName("5test1234") 102 assert.Error(t, err, "Error expected because the name starts with a number") 103 104 //create a new instance and database object using an empty string 105 _, err = mapAndValidateDatabaseName("") 106 assert.Error(t, err, "Error should have been thrown for an invalid name") 107 108 _, err = mapAndValidateDatabaseName("a12345678901234567890123456789012345678901234" + 109 "56789012345678901234567890123456789012345678901234567890123456789012345678901234567890" + 110 "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456" + 111 "78901234567890123456789012345678901234567890") 112 assert.Error(t, err, "Error should have been thrown for an invalid name") 113 114 transformedName, err := mapAndValidateDatabaseName("test.my.db-1") 115 assert.NoError(t, err, "") 116 assert.Equal(t, "test$my$db-1", transformedName) 117 } 118 119 func TestConstructMetadataDBName(t *testing.T) { 120 // Allowed pattern for chainName: [a-z][a-z0-9.-] 121 chainName := "tob2g.y-z0f.qwp-rq5g4-ogid5g6oucyryg9sc16mz0t4vuake5q557esz7sn493nf0ghch0xih6dwuirokyoi4jvs67gh6r5v6mhz3-292un2-9egdcs88cstg3f7xa9m1i8v4gj0t3jedsm-woh3kgiqehwej6h93hdy5tr4v.1qmmqjzz0ox62k.507sh3fkw3-mfqh.ukfvxlm5szfbwtpfkd1r4j.cy8oft5obvwqpzjxb27xuw6" 122 123 truncatedChainName := "tob2g.y-z0f.qwp-rq5g4-ogid5g6oucyryg9sc16mz0t4vuak" 124 assert.Equal(t, chainNameAllowedLength, len(truncatedChainName)) 125 126 // <first 50 chars (i.e., chainNameAllowedLength) of chainName> + 1 char for '(' + <64 chars for SHA256 hash 127 // (hex encoding) of untruncated chainName> + 1 char for ')' + 1 char for '_' = 117 chars 128 hash := hex.EncodeToString(util.ComputeSHA256([]byte(chainName))) 129 expectedDBName := truncatedChainName + "(" + hash + ")" + "_" 130 expectedDBNameLength := 117 131 132 constructedDBName := ConstructMetadataDBName(chainName) 133 assert.Equal(t, expectedDBNameLength, len(constructedDBName)) 134 assert.Equal(t, expectedDBName, constructedDBName) 135 } 136 137 func TestConstructedNamespaceDBName(t *testing.T) { 138 // === SCENARIO 1: chainName_ns$$coll === 139 140 // Allowed pattern for chainName: [a-z][a-z0-9.-] 141 chainName := "tob2g.y-z0f.qwp-rq5g4-ogid5g6oucyryg9sc16mz0t4vuake5q557esz7sn493nf0ghch0xih6dwuirokyoi4jvs67gh6r5v6mhz3-292un2-9egdcs88cstg3f7xa9m1i8v4gj0t3jedsm-woh3kgiqehwej6h93hdy5tr4v.1qmmqjzz0ox62k.507sh3fkw3-mfqh.ukfvxlm5szfbwtpfkd1r4j.cy8oft5obvwqpzjxb27xuw6" 142 143 // Allowed pattern for namespace and collection: [a-zA-Z0-9_-] 144 ns := "wMCnSXiV9YoIqNQyNvFVTdM8XnUtvrOFFIWsKelmP5NEszmNLl8YhtOKbFu3P_NgwgsYF8PsfwjYCD8f1XRpANQLoErDHwLlweryqXeJ6vzT2x0pS_GwSx0m6tBI0zOmHQOq_2De8A87x6zUOPwufC2T6dkidFxiuq8Sey2-5vUo_iNKCij3WTeCnKx78PUIg_U1gp4_0KTvYVtRBRvH0kz5usizBxPaiFu3TPhB9XLviScvdUVSbSYJ0Z" 145 // first letter 'p' denotes private data namespace. We can use 'h' to denote hashed data namespace as defined in 146 // privacyenabledstate/common_storage_db.go 147 coll := "pvWjtfSTXVK8WJus5s6zWoMIciXd7qHRZIusF9SkOS6m8XuHCiJDE9cCRuVerq22Na8qBL2ywDGFpVMIuzfyEXLjeJb0mMuH4cwewT6r1INOTOSYwrikwOLlT_fl0V1L7IQEwUBB8WCvRqSdj6j5-E5aGul_pv_0UeCdwWiyA_GrZmP7ocLzfj2vP8btigrajqdH-irLO2ydEjQUAvf8fiuxru9la402KmKRy457GgI98UHoUdqV3f3FCdR" 148 149 truncatedChainName := "tob2g.y-z0f.qwp-rq5g4-ogid5g6oucyryg9sc16mz0t4vuak" 150 truncatedEscapedNs := "w$m$cn$s$xi$v9$yo$iq$n$qy$nv$f$v$td$m8$xn$utvr$o$f" 151 truncatedEscapedColl := "pv$wjtf$s$t$x$v$k8$w$jus5s6z$wo$m$ici$xd7q$h$r$z$i" 152 assert.Equal(t, chainNameAllowedLength, len(truncatedChainName)) 153 assert.Equal(t, namespaceNameAllowedLength, len(truncatedEscapedNs)) 154 assert.Equal(t, collectionNameAllowedLength, len(truncatedEscapedColl)) 155 156 untruncatedDBName := chainName + "_" + ns + "$$" + coll 157 hash := hex.EncodeToString(util.ComputeSHA256([]byte(untruncatedDBName))) 158 expectedDBName := truncatedChainName + "_" + truncatedEscapedNs + "$$" + truncatedEscapedColl + "(" + hash + ")" 159 // <first 50 chars (i.e., chainNameAllowedLength) of chainName> + 1 char for '_' + <first 50 chars 160 // (i.e., namespaceNameAllowedLength) of escaped namespace> + 2 chars for '$$' + <first 50 chars 161 // (i.e., collectionNameAllowedLength) of escaped collection> + 1 char for '(' + <64 chars for SHA256 hash 162 // (hex encoding) of untruncated chainName_ns$$coll> + 1 char for ')' = 219 chars 163 expectedDBNameLength := 219 164 165 namespace := ns + "$$" + coll 166 constructedDBName := ConstructNamespaceDBName(chainName, namespace) 167 assert.Equal(t, expectedDBNameLength, len(constructedDBName)) 168 assert.Equal(t, expectedDBName, constructedDBName) 169 170 // === SCENARIO 2: chainName_ns === 171 172 untruncatedDBName = chainName + "_" + ns 173 hash = hex.EncodeToString(util.ComputeSHA256([]byte(untruncatedDBName))) 174 expectedDBName = truncatedChainName + "_" + truncatedEscapedNs + "(" + hash + ")" 175 // <first 50 chars (i.e., chainNameAllowedLength) of chainName> + 1 char for '_' + <first 50 chars 176 // (i.e., namespaceNameAllowedLength) of escaped namespace> + 1 char for '(' + <64 chars for SHA256 hash 177 // (hex encoding) of untruncated chainName_ns> + 1 char for ')' = 167 chars 178 expectedDBNameLength = 167 179 180 namespace = ns 181 constructedDBName = ConstructNamespaceDBName(chainName, namespace) 182 assert.Equal(t, expectedDBNameLength, len(constructedDBName)) 183 assert.Equal(t, expectedDBName, constructedDBName) 184 }