Some checks failed
Server CI / Postgres (shard 0) (push) Has been skipped
Server CI / Postgres (shard 3) (push) Has been skipped
BuildEnv Docker Image / build-image (push) Failing after 4s
BuildEnv Docker Image / build-image-fips (push) Failing after 4s
Migration Review & Release Notes / Generate migration review & release notes (push) Failing after 3s
Server CI / Build Environment (push) Failing after 3s
Server CI / Postgres (shard 1) (push) Has been skipped
Tools CI / check-style (mattermost-govet) (push) Failing after 4s
Server CI / Postgres (shard 2) (push) Has been skipped
Tools CI / check-style (mmgotool) (push) Failing after 3s
Server CI / Elasticsearch v8 Compatibility (push) Has been skipped
Server CI / OpenSearch v2 Compatibility (push) Has been skipped
Server CI / Postgres FIPS (shard 0) (push) Has been skipped
Tools CI / Test (mattermost-govet) (push) Failing after 3s
Server CI / Postgres FIPS (shard 1) (push) Has been skipped
Server CI / Postgres FIPS (shard 2) (push) Has been skipped
Tools CI / Test (mmgotool) (push) Failing after 3s
Server CI / Postgres FIPS (shard 3) (push) Has been skipped
Server CI / Run mmctl tests (push) Has been skipped
Server CI / Run mmctl tests (FIPS) (push) Has been skipped
Server CI / Merge Postgres Test Results (push) Has been skipped
Server CI / Merge Postgres FIPS Test Results (push) Has been skipped
Server CI / Check backport migrations (push) Has been skipped
Server CI / Check generated files (push) Has been skipped
Server CI / check-style (push) Has been skipped
Server CI / Vet API (push) Has been skipped
Server CI / Build mattermost server app (push) Has been skipped
Server CI / Server CI Complete (push) Failing after 2s
Server CI / Server CI Artifacts (push) Has been skipped
Server CI / Sentry Upload (push) Has been skipped
Server CI / Server CI Report (push) Failing after 5m1s
Server CI Nightly Race / Race Detector (push) Has been skipped
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Webapp CI Cache Warm / Warm Webapp node_modules Cache (push) Has been cancelled
E2E CI Cache Warm / Warm E2E npm Registry Cache (push) Has been cancelled
API / build (push) Has been cancelled
Web App CI / check-types (push) Has been cancelled
Web App CI / check-lint (push) Has been cancelled
Web App CI / check-i18n (push) Has been cancelled
Web App CI / check-external-links (push) Has been cancelled
Web App CI / test (platform) (push) Has been cancelled
Web App CI / test (mattermost-redux) (push) Has been cancelled
Web App CI / test (channels shard 1/4) (push) Has been cancelled
Web App CI / test (channels shard 2/4) (push) Has been cancelled
Web App CI / test (channels shard 3/4) (push) Has been cancelled
Web App CI / test (channels shard 4/4) (push) Has been cancelled
Web App CI / upload-coverage (push) Has been cancelled
Web App CI / build (push) Has been cancelled
YAML Lint / yamllint (push) Has been cancelled
Push mirrored docker images / cd/Push mirrored docker images (push) Has been cancelled
docs-cd / Build and deploy docs (push) Has been cancelled
Docs CI / build (push) Has been cancelled
E2E Cache Warm: Cypress deps / Warm Cypress deps cache (push) Has been cancelled
Scorecards supply-chain security / Scorecard analysis (push) Has been cancelled
Server CI Weekly / Postgres FIPS (push) Has been skipped
Server CI Weekly / Run mmctl tests (FIPS) (push) Has been skipped
Server CI Weekly / Postgres with binary parameters (push) Has been skipped
Server CI Weekly / Build Environment (push) Failing after 1s
Server CI Cache Warm / Warm Go Module and Build Cache (push) Failing after 2s
Server CI Nightly Race / Build Environment (push) Failing after 1s
117 lines
4.9 KiB
Go
117 lines
4.9 KiB
Go
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
package sqlstore
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/mattermost/mattermost/server/public/model"
|
|
"github.com/mattermost/mattermost/server/public/shared/mlog"
|
|
)
|
|
|
|
func matviewExists(t *testing.T, s *SqlStore, name string) bool {
|
|
t.Helper()
|
|
var count int
|
|
err := s.GetMaster().Get(&count,
|
|
"SELECT COUNT(*) FROM pg_matviews WHERE lower(matviewname) = lower($1)", name)
|
|
require.NoError(t, err)
|
|
return count > 0
|
|
}
|
|
|
|
// TestMigration000216 verifies the split of AttributeView into per-object-type
|
|
// views: after the migration both UserAttributeView and ChannelAttributeView
|
|
// exist (and the combined AttributeView is gone), each filtering to its own
|
|
// ObjectType. The down migration restores the single combined view.
|
|
func TestMigration000216(t *testing.T) {
|
|
logger := mlog.CreateTestLogger(t)
|
|
|
|
settings, err := makeSqlSettings(model.DatabaseDriverPostgres)
|
|
if err != nil {
|
|
t.Skip(err)
|
|
}
|
|
|
|
store, err := New(*settings, logger, nil)
|
|
require.NoError(t, err)
|
|
defer store.Close()
|
|
|
|
// New() applies all migrations, so 000216 is already in effect.
|
|
require.True(t, matviewExists(t, store, "UserAttributeView"), "UserAttributeView should exist after migration")
|
|
require.True(t, matviewExists(t, store, "ChannelAttributeView"), "ChannelAttributeView should exist after migration")
|
|
require.False(t, matviewExists(t, store, "AttributeView"), "combined AttributeView should be gone after migration")
|
|
|
|
// Seed one user-scoped and one channel-scoped attribute in the same group.
|
|
group, err := store.PropertyGroup().Register(&model.PropertyGroup{Name: model.NewId(), Version: model.PropertyGroupVersionV1})
|
|
require.NoError(t, err)
|
|
groupID := group.ID
|
|
|
|
userField, err := store.PropertyField().Create(&model.PropertyField{
|
|
GroupID: groupID,
|
|
Name: "user_prop",
|
|
Type: model.PropertyFieldTypeText,
|
|
ObjectType: model.PropertyFieldObjectTypeUser,
|
|
TargetType: string(model.PropertyFieldTargetLevelSystem),
|
|
})
|
|
require.NoError(t, err)
|
|
channelField, err := store.PropertyField().Create(&model.PropertyField{
|
|
GroupID: groupID,
|
|
Name: "channel_prop",
|
|
Type: model.PropertyFieldTypeText,
|
|
ObjectType: model.PropertyFieldObjectTypeChannel,
|
|
TargetType: string(model.PropertyFieldTargetLevelSystem),
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
userTarget := model.NewId()
|
|
channelTarget := model.NewId()
|
|
userVal, err := store.PropertyValue().Create(&model.PropertyValue{
|
|
TargetID: userTarget, TargetType: model.PropertyValueTargetTypeUser,
|
|
GroupID: groupID, FieldID: userField.ID, Value: []byte(`"u"`),
|
|
})
|
|
require.NoError(t, err)
|
|
channelVal, err := store.PropertyValue().Create(&model.PropertyValue{
|
|
TargetID: channelTarget, TargetType: model.PropertyValueTargetTypeChannel,
|
|
GroupID: groupID, FieldID: channelField.ID, Value: []byte(`"c"`),
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
t.Cleanup(func() {
|
|
store.PropertyValue().Delete(groupID, userVal.ID) //nolint:errcheck
|
|
store.PropertyValue().Delete(groupID, channelVal.ID) //nolint:errcheck
|
|
store.PropertyField().Delete(groupID, userField.ID) //nolint:errcheck
|
|
store.PropertyField().Delete(groupID, channelField.ID) //nolint:errcheck
|
|
})
|
|
|
|
require.NoError(t, store.Attributes().RefreshAttributes())
|
|
|
|
countInView := func(view, targetID string) int {
|
|
var c int
|
|
gErr := store.GetMaster().Get(&c, "SELECT COUNT(*) FROM "+view+" WHERE TargetID = $1", targetID)
|
|
require.NoError(t, gErr)
|
|
return c
|
|
}
|
|
|
|
require.Equal(t, 1, countInView("UserAttributeView", userTarget), "user row should be in UserAttributeView")
|
|
require.Equal(t, 0, countInView("UserAttributeView", channelTarget), "channel row should not be in UserAttributeView")
|
|
require.Equal(t, 1, countInView("ChannelAttributeView", channelTarget), "channel row should be in ChannelAttributeView")
|
|
require.Equal(t, 0, countInView("ChannelAttributeView", userTarget), "user row should not be in ChannelAttributeView")
|
|
|
|
// Down then up round-trips the view topology.
|
|
downSQL := readMigrationSQL(t, "000216_split_attribute_view_by_object_type.down.sql")
|
|
upSQL := readMigrationSQL(t, "000216_split_attribute_view_by_object_type.up.sql")
|
|
|
|
_, err = store.GetMaster().Exec(downSQL)
|
|
require.NoError(t, err)
|
|
require.True(t, matviewExists(t, store, "AttributeView"), "down should recreate AttributeView")
|
|
require.False(t, matviewExists(t, store, "UserAttributeView"), "down should drop UserAttributeView")
|
|
require.False(t, matviewExists(t, store, "ChannelAttributeView"), "down should drop ChannelAttributeView")
|
|
|
|
_, err = store.GetMaster().Exec(upSQL)
|
|
require.NoError(t, err)
|
|
require.True(t, matviewExists(t, store, "UserAttributeView"), "up should recreate UserAttributeView")
|
|
require.True(t, matviewExists(t, store, "ChannelAttributeView"), "up should recreate ChannelAttributeView")
|
|
require.False(t, matviewExists(t, store, "AttributeView"), "up should drop AttributeView")
|
|
}
|