github.com/Tri-stone/burrow@v0.25.0/vent/sqlsol/projection_test.go (about) 1 package sqlsol_test 2 3 import ( 4 "testing" 5 6 "github.com/hyperledger/burrow/vent/sqlsol" 7 "github.com/hyperledger/burrow/vent/test" 8 "github.com/hyperledger/burrow/vent/types" 9 "github.com/stretchr/testify/require" 10 ) 11 12 func TestNewProjection(t *testing.T) { 13 t.Run("returns an error if the json is malformed", func(t *testing.T) { 14 badJSON := test.BadJSONConfFile(t) 15 16 byteValue := []byte(badJSON) 17 _, err := sqlsol.NewProjectionFromBytes(byteValue) 18 require.Error(t, err) 19 }) 20 21 t.Run("returns an error if needed json fields are missing", func(t *testing.T) { 22 missingFields := test.MissingFieldsJSONConfFile(t) 23 24 byteValue := []byte(missingFields) 25 _, err := sqlsol.NewProjectionFromBytes(byteValue) 26 require.Error(t, err) 27 }) 28 29 t.Run("successfully builds table structure based on json events config", func(t *testing.T) { 30 tableStruct, err := sqlsol.NewProjectionFromBytes([]byte(test.GoodJSONConfFile(t))) 31 require.NoError(t, err) 32 33 // columns map 34 tableName := "UserAccounts" 35 col, err := tableStruct.GetColumn(tableName, "username") 36 require.NoError(t, err) 37 require.Equal(t, false, col.Primary) 38 require.Equal(t, types.SQLColumnTypeText, col.Type) 39 require.Equal(t, "username", col.Name) 40 41 col, err = tableStruct.GetColumn(tableName, "address") 42 require.NoError(t, err) 43 require.Equal(t, true, col.Primary) 44 require.Equal(t, types.SQLColumnTypeVarchar, col.Type) 45 require.Equal(t, "address", col.Name) 46 47 col, err = tableStruct.GetColumn(tableName, types.SQLColumnLabelTxHash) 48 require.NoError(t, err) 49 require.Equal(t, false, col.Primary) 50 require.Equal(t, types.SQLColumnTypeText, col.Type) 51 52 col, err = tableStruct.GetColumn(tableName, types.SQLColumnLabelEventName) 53 require.NoError(t, err) 54 require.Equal(t, false, col.Primary) 55 require.Equal(t, types.SQLColumnTypeText, col.Type) 56 }) 57 58 t.Run("returns an error if the event type of a given column is unknown", func(t *testing.T) { 59 typeUnknownJSON := test.UnknownTypeJSONConfFile(t) 60 61 byteValue := []byte(typeUnknownJSON) 62 _, err := sqlsol.NewProjectionFromBytes(byteValue) 63 require.Error(t, err) 64 }) 65 66 t.Run("returns an error if there are duplicated column names for a given table in json file", func(t *testing.T) { 67 duplicatedColNameJSON := test.DuplicatedColNameJSONConfFile(t) 68 69 byteValue := []byte(duplicatedColNameJSON) 70 _, err := sqlsol.NewProjectionFromBytes(byteValue) 71 require.Error(t, err) 72 }) 73 74 } 75 76 func TestGetColumn(t *testing.T) { 77 projection, err := sqlsol.NewProjectionFromBytes([]byte(test.GoodJSONConfFile(t))) 78 require.NoError(t, err) 79 80 t.Run("successfully gets the mapping column info for a given table & column name", func(t *testing.T) { 81 column, err := projection.GetColumn("TEST_TABLE", "Block") 82 require.NoError(t, err) 83 require.Equal(t, "Block", column.Name) 84 require.Equal(t, types.SQLColumnTypeBigInt, column.Type) 85 require.Equal(t, false, column.Primary) 86 87 column, err = projection.GetColumn("TEST_TABLE", "Instance") 88 require.NoError(t, err) 89 require.Equal(t, "Instance", column.Name) 90 require.Equal(t, types.SQLColumnTypeBigInt, column.Type) 91 require.Equal(t, false, column.Primary) 92 93 }) 94 95 t.Run("unsuccessfully gets the mapping column info for a non existent table name", func(t *testing.T) { 96 _, err := projection.GetColumn("NOT_EXISTS", "userName") 97 require.Error(t, err) 98 }) 99 100 t.Run("unsuccessfully gets the mapping column info for a non existent column name", func(t *testing.T) { 101 _, err := projection.GetColumn("UpdateUserAccount", "NOT_EXISTS") 102 require.Error(t, err) 103 }) 104 } 105 106 func TestGetTables(t *testing.T) { 107 goodJSON := test.GoodJSONConfFile(t) 108 109 byteValue := []byte(goodJSON) 110 tableStruct, _ := sqlsol.NewProjectionFromBytes(byteValue) 111 112 t.Run("successfully returns event tables structures", func(t *testing.T) { 113 tables := tableStruct.Tables 114 require.Equal(t, 2, len(tables)) 115 require.Equal(t, "UserAccounts", tables["UserAccounts"].Name) 116 117 }) 118 } 119 120 func TestGetEventSpec(t *testing.T) { 121 goodJSON := test.GoodJSONConfFile(t) 122 123 byteValue := []byte(goodJSON) 124 tableStruct, _ := sqlsol.NewProjectionFromBytes(byteValue) 125 126 t.Run("successfully returns event specification structures", func(t *testing.T) { 127 eventSpec := tableStruct.EventSpec 128 require.Equal(t, 2, len(eventSpec)) 129 require.Equal(t, "LOG0 = 'UserAccounts'", eventSpec[0].Filter) 130 require.Equal(t, "UserAccounts", eventSpec[0].TableName) 131 132 require.Equal(t, "Log1Text = 'EVENT_TEST'", eventSpec[1].Filter) 133 require.Equal(t, "TEST_TABLE", eventSpec[1].TableName) 134 }) 135 } 136 137 func TestNewProjectionFromEventSpec(t *testing.T) { 138 tableName := "BurnNotices" 139 eventSpec := types.EventSpec{ 140 { 141 TableName: tableName, 142 Filter: "LOG1Text = 'CIA/burn'", 143 FieldMappings: []*types.EventFieldMapping{ 144 { 145 Field: "codename", 146 Type: types.EventFieldTypeString, 147 ColumnName: "name", 148 Notify: []string{"burn"}, 149 }, 150 { 151 Field: "burn", 152 Type: types.EventFieldTypeBool, 153 ColumnName: "burnt", 154 Notify: []string{"burn"}, 155 }, 156 { 157 Field: "dairy", 158 Type: types.EventFieldTypeString, 159 ColumnName: "coffee_milk", 160 Notify: []string{"mrs_doyle"}, 161 }, 162 { 163 Field: "datetime", 164 Type: types.EventFieldTypeInt, 165 ColumnName: "time_changed", 166 Notify: []string{"last_heard", "mrs_doyle"}, 167 }, 168 }, 169 }, 170 { 171 TableName: tableName, 172 Filter: "LOG1Text = 'MI5/burn'", 173 FieldMappings: []*types.EventFieldMapping{ 174 { 175 Field: "codename", 176 Type: types.EventFieldTypeString, 177 ColumnName: "name", 178 Notify: []string{"burn"}, 179 }, 180 { 181 Field: "unreliable", 182 Type: types.EventFieldTypeBool, 183 ColumnName: "burnt", 184 Notify: []string{"burn"}, 185 }, 186 { 187 Field: "sugars", 188 Type: types.EventFieldTypeInt, 189 ColumnName: "tea_sugars", 190 Notify: []string{"mrs_doyle"}, 191 }, 192 { 193 Field: "milk", 194 Type: types.EventFieldTypeBool, 195 ColumnName: "tea_milk", 196 Notify: []string{"mrs_doyle"}, 197 }, 198 { 199 Field: "datetime", 200 Type: types.EventFieldTypeInt, 201 ColumnName: "time_changed", 202 Notify: []string{"last_heard", "mrs_doyle"}, 203 }, 204 }, 205 }, 206 } 207 projection, err := sqlsol.NewProjectionFromEventSpec(eventSpec) 208 require.NoError(t, err, "burn and unreliable field mappings should unify to single column") 209 210 require.Equal(t, []string{"burnt", "name"}, projection.Tables[tableName].NotifyChannels["burn"]) 211 212 // Notify sugars on the burn channel 213 field := eventSpec[1].GetFieldMapping("sugars") 214 field.Notify = append(field.Notify, "burn") 215 216 projection, err = sqlsol.NewProjectionFromEventSpec(eventSpec) 217 require.NoError(t, err) 218 require.Equal(t, []string{"burnt", "name", "tea_sugars"}, projection.Tables[tableName].NotifyChannels["burn"]) 219 220 // Create a column conflict between burn and unreliable fields (both map to burnt so the SQL column def must be identical) 221 field = eventSpec[1].GetFieldMapping("unreliable") 222 field.Primary = !field.Primary 223 projection, err = sqlsol.NewProjectionFromEventSpec(eventSpec) 224 require.Error(t, err) 225 }