package database import ( "context" "regexp" "testing" "modelRT/common" "modelRT/orm" "github.com/DATA-DOG/go-sqlmock" "github.com/gofrs/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gorm.io/driver/postgres" "gorm.io/gorm" ) func TestBuildParameterComponentQuery(t *testing.T) { tests := []struct { name string token string wantArgs []any wantWhere string wantErr bool }{ { name: "seven-part parameter", token: "grid.zone.station.nspath.component.stable.attribute", wantArgs: []any{"grid", "zone", "station", "nspath", "component"}, wantWhere: "WHERE g.tagname = ?", }, { name: "four-part local parameter", token: "nspath.component.rated.attribute", wantArgs: []any{"nspath", "component"}, wantWhere: "s.is_local = TRUE", }, { name: "measurement token", token: "nspath.component.bay.measurement", wantErr: true, }, { name: "empty segment", token: "nspath..stable.attribute", wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { query, args, _, err := buildParameterComponentQuery(tt.token) if tt.wantErr { require.Error(t, err) assert.ErrorIs(t, err, common.ErrInvalidParameterToken) return } require.NoError(t, err) assert.Contains(t, query, "INNER JOIN station AS s ON s.id = c.station_id") assert.Contains(t, query, tt.wantWhere) assert.Equal(t, tt.wantArgs, args) assert.NotContains(t, query, "\n") assert.NotContains(t, query, "\t") }) } } func TestQueryParameterByDataObjectToken(t *testing.T) { sqlDB, mock, err := sqlmock.New() require.NoError(t, err) t.Cleanup(func() { _ = sqlDB.Close() }) db, err := gorm.Open(postgres.New(postgres.Config{Conn: sqlDB}), &gorm.Config{}) require.NoError(t, err) const ( token = "grid.zone.station.nspath.component.stable.rated_voltage" componentUUID = "70c190f2-8a60-42a9-b143-ec5f87e0aa6b" ) mock.ExpectQuery(`(?s)SELECT c\.\*.*WHERE g\.tagname = \$1.*AND c\.tag = \$5.*LIMIT 2`). WithArgs("grid", "zone", "station", "nspath", "component"). WillReturnRows(sqlmock.NewRows([]string{ "global_uuid", "nspath", "tag", "model_name", "station_id", }).AddRow(componentUUID, "nspath", "component", "bus_1", int64(10))) mock.ExpectQuery(`SELECT \* FROM "project_manager" WHERE tag = \$1 AND group_name = \$2 LIMIT \$3`). WithArgs("bus_1", "stable", 2). WillReturnRows(sqlmock.NewRows([]string{ "id", "name", "tag", "meta_model", "group_name", "link_type", "check_state", "ispublic", }).AddRow( int32(1), "bus_bus_1_stable", "bus_1", "bus", "stable", int32(0), `{"checkState":[{"name":"rated_voltage","checked":1}]}`, false, )) mock.ExpectQuery(`(?s)SELECT pg_catalog\.format_type.*pg_catalog\.pg_attribute.*c\.relname = \$1.*a\.attname = \$2.*LIMIT 1`). WithArgs("bus_bus_1_stable", "rated_voltage"). WillReturnRows(sqlmock.NewRows([]string{"format_type"}).AddRow("double precision")) mock.ExpectQuery(regexp.QuoteMeta(`SELECT count(*) FROM "bus_bus_1_stable" WHERE global_uuid = $1 AND attribute_group = $2`)). WithArgs(componentUUID, "stable"). WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(int64(1))) parameter, err := QueryParameterByDataObjectToken(context.Background(), db, token) require.NoError(t, err) assert.Equal(t, "component", parameter.Component.Tag) assert.Equal(t, "bus_bus_1_stable", parameter.Project.Name) assert.Equal(t, "bus_bus_1_stable", parameter.TableName) assert.Equal(t, "stable", parameter.AttributeGroup) assert.Equal(t, "rated_voltage", parameter.AttributeName) assert.Equal(t, "DOUBLE PRECISION", parameter.AttributeType) require.NoError(t, mock.ExpectationsWereMet()) } func TestQueryParameterDataObjectValue(t *testing.T) { sqlDB, mock, err := sqlmock.New() require.NoError(t, err) t.Cleanup(func() { _ = sqlDB.Close() }) db, err := gorm.Open(postgres.New(postgres.Config{Conn: sqlDB}), &gorm.Config{}) require.NoError(t, err) const componentUUID = "70c190f2-8a60-42a9-b143-ec5f87e0aa6b" parsedUUID, err := uuid.FromString(componentUUID) require.NoError(t, err) parameter := &ParameterDataObject{ Component: orm.Component{GlobalUUID: parsedUUID}, Project: orm.ProjectManager{ Name: "bus_bus_1_stable", }, TableName: "bus_bus_1_stable", AttributeGroup: "stable", AttributeName: "rated_voltage", } mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "bus_bus_1_stable" WHERE global_uuid = $1 AND attribute_group = $2 LIMIT $3`)). WithArgs(componentUUID, "stable", 1). WillReturnRows(sqlmock.NewRows([]string{ "global_uuid", "attribute_group", "rated_voltage", }).AddRow(componentUUID, "stable", float64(220))) value, err := QueryParameterDataObjectValue(context.Background(), db, parameter) require.NoError(t, err) assert.Equal(t, float64(220), value) require.NoError(t, mock.ExpectationsWereMet()) } func TestQueryComponentParameterByDataObjectToken(t *testing.T) { sqlDB, mock, err := sqlmock.New() require.NoError(t, err) t.Cleanup(func() { _ = sqlDB.Close() }) db, err := gorm.Open(postgres.New(postgres.Config{Conn: sqlDB}), &gorm.Config{}) require.NoError(t, err) const ( token = "grid.zone.station.nspath.component.component.description" componentUUID = "70c190f2-8a60-42a9-b143-ec5f87e0aa6b" ) mock.ExpectQuery(`(?s)SELECT c\.\*.*WHERE g\.tagname = \$1.*AND c\.tag = \$5.*LIMIT 2`). WithArgs("grid", "zone", "station", "nspath", "component"). WillReturnRows(sqlmock.NewRows([]string{ "global_uuid", "nspath", "tag", "model_name", "grid", "zone", "station", "station_id", }).AddRow(componentUUID, "nspath", "component", "bus_1", "grid", "zone", "station", int64(10))) mock.ExpectQuery(`(?s)SELECT pg_catalog\.format_type.*c\.relname = \$1.*a\.attname = \$2.*LIMIT 1`). WithArgs("component", "description"). WillReturnRows(sqlmock.NewRows([]string{"format_type"}).AddRow("character varying(512)")) parameter, err := QueryParameterByDataObjectToken(context.Background(), db, token) require.NoError(t, err) assert.Equal(t, "component", parameter.TableName) assert.Equal(t, "component", parameter.AttributeGroup) assert.Equal(t, "description", parameter.AttributeName) assert.Equal(t, "CHARACTER VARYING(512)", parameter.AttributeType) assert.Empty(t, parameter.Project.Name) require.NoError(t, mock.ExpectationsWereMet()) } func TestQueryComponentParameterValue(t *testing.T) { sqlDB, mock, err := sqlmock.New() require.NoError(t, err) t.Cleanup(func() { _ = sqlDB.Close() }) db, err := gorm.Open(postgres.New(postgres.Config{Conn: sqlDB}), &gorm.Config{}) require.NoError(t, err) parameter := &ParameterDataObject{ Component: orm.Component{Tag: "component"}, TableName: "component", AttributeGroup: "component", AttributeName: "description", } mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "component" WHERE tag = $1 LIMIT $2`)). WithArgs("component", 1). WillReturnRows(sqlmock.NewRows([]string{"tag", "description"}).AddRow("component", "测试组件")) value, err := QueryParameterDataObjectValue(context.Background(), db, parameter) require.NoError(t, err) assert.Equal(t, "测试组件", value) require.NoError(t, mock.ExpectationsWereMet()) } func TestQueryParameterAttributeDescription(t *testing.T) { sqlDB, mock, err := sqlmock.New() require.NoError(t, err) t.Cleanup(func() { _ = sqlDB.Close() }) db, err := gorm.Open(postgres.New(postgres.Config{Conn: sqlDB}), &gorm.Config{}) require.NoError(t, err) mock.ExpectQuery(`(?s)SELECT attribute_name.*FROM basic\.attribute.*WHERE attribute = \$1.*LIMIT 2`). WithArgs("rated_voltage"). WillReturnRows(sqlmock.NewRows([]string{"attribute_name"}).AddRow("额定电压")) description, err := QueryParameterAttributeDescription(context.Background(), db, "rated_voltage") require.NoError(t, err) assert.Equal(t, "额定电压", description) require.NoError(t, mock.ExpectationsWereMet()) } func TestQueryParameterByDataObjectTokenComponentNotFound(t *testing.T) { sqlDB, mock, err := sqlmock.New() require.NoError(t, err) t.Cleanup(func() { _ = sqlDB.Close() }) db, err := gorm.Open(postgres.New(postgres.Config{Conn: sqlDB}), &gorm.Config{}) require.NoError(t, err) mock.ExpectQuery(`(?s)SELECT c\.\*.*WHERE c\.nspath = \$1.*AND c\.tag = \$2.*s\.is_local = TRUE.*LIMIT 2`). WithArgs("nspath", "component"). WillReturnRows(sqlmock.NewRows([]string{"global_uuid"})) _, err = QueryParameterByDataObjectToken( context.Background(), db, "nspath.component.stable.rated_voltage", ) require.Error(t, err) assert.ErrorIs(t, err, common.ErrParameterTokenNotFound) require.NoError(t, mock.ExpectationsWereMet()) }