2023-04-10 15:36:59 +00:00
|
|
|
// Copyright (c) HashiCorp, Inc.
|
|
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
|
2015-08-11 21:27:14 +00:00
|
|
|
package state
|
2015-07-04 00:48:02 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"testing"
|
|
|
|
|
2019-01-15 19:46:12 +00:00
|
|
|
memdb "github.com/hashicorp/go-memdb"
|
2022-03-15 12:42:43 +00:00
|
|
|
"github.com/hashicorp/nomad/ci"
|
2020-09-29 21:57:46 +00:00
|
|
|
"github.com/hashicorp/nomad/nomad/mock"
|
2019-11-14 13:18:29 +00:00
|
|
|
"github.com/stretchr/testify/require"
|
2015-07-04 00:48:02 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestStateStoreSchema(t *testing.T) {
|
2022-03-15 12:42:43 +00:00
|
|
|
ci.Parallel(t)
|
|
|
|
|
2015-07-04 00:48:02 +00:00
|
|
|
schema := stateStoreSchema()
|
|
|
|
_, err := memdb.NewMemDB(schema)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
}
|
2019-11-14 13:18:29 +00:00
|
|
|
|
|
|
|
func TestState_singleRecord(t *testing.T) {
|
2022-03-15 12:42:43 +00:00
|
|
|
ci.Parallel(t)
|
|
|
|
|
2019-11-14 13:18:29 +00:00
|
|
|
require := require.New(t)
|
|
|
|
|
|
|
|
const (
|
|
|
|
singletonTable = "cluster_meta"
|
|
|
|
singletonIDIdx = "id"
|
|
|
|
)
|
|
|
|
|
|
|
|
db, err := memdb.NewMemDB(&memdb.DBSchema{
|
|
|
|
Tables: map[string]*memdb.TableSchema{
|
|
|
|
singletonTable: clusterMetaTableSchema(),
|
|
|
|
},
|
|
|
|
})
|
|
|
|
require.NoError(err)
|
|
|
|
|
|
|
|
// numRecords in table counts all the items in the table, which is expected
|
|
|
|
// to always be 1 since that's the point of the singletonRecord Indexer.
|
|
|
|
numRecordsInTable := func() int {
|
|
|
|
txn := db.Txn(false)
|
|
|
|
defer txn.Abort()
|
|
|
|
|
|
|
|
iter, err := txn.Get(singletonTable, singletonIDIdx)
|
|
|
|
require.NoError(err)
|
|
|
|
|
|
|
|
num := 0
|
|
|
|
for item := iter.Next(); item != nil; item = iter.Next() {
|
|
|
|
num++
|
|
|
|
}
|
|
|
|
return num
|
|
|
|
}
|
|
|
|
|
|
|
|
// setSingleton "updates" the singleton record in the singletonTable,
|
|
|
|
// which requires that the singletonRecord Indexer is working as
|
|
|
|
// expected.
|
|
|
|
setSingleton := func(s string) {
|
|
|
|
txn := db.Txn(true)
|
|
|
|
err := txn.Insert(singletonTable, s)
|
|
|
|
require.NoError(err)
|
|
|
|
txn.Commit()
|
|
|
|
}
|
|
|
|
|
|
|
|
// first retrieves the one expected entry in the singletonTable - use the
|
|
|
|
// numRecordsInTable helper function to make the cardinality assertion,
|
|
|
|
// this is just for fetching the value.
|
|
|
|
first := func() string {
|
|
|
|
txn := db.Txn(false)
|
|
|
|
defer txn.Abort()
|
|
|
|
record, err := txn.First(singletonTable, singletonIDIdx)
|
|
|
|
require.NoError(err)
|
|
|
|
s, ok := record.(string)
|
|
|
|
require.True(ok)
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure that multiple Insert & Commit calls result in only
|
|
|
|
// a single "singleton" record existing in the table.
|
|
|
|
|
|
|
|
setSingleton("one")
|
|
|
|
require.Equal(1, numRecordsInTable())
|
|
|
|
require.Equal("one", first())
|
|
|
|
|
|
|
|
setSingleton("two")
|
|
|
|
require.Equal(1, numRecordsInTable())
|
|
|
|
require.Equal("two", first())
|
|
|
|
|
|
|
|
setSingleton("three")
|
|
|
|
require.Equal(1, numRecordsInTable())
|
|
|
|
require.Equal("three", first())
|
|
|
|
}
|
2020-09-29 21:57:46 +00:00
|
|
|
|
|
|
|
func TestState_ScalingPolicyTargetFieldIndex_FromObject(t *testing.T) {
|
2022-03-15 12:42:43 +00:00
|
|
|
ci.Parallel(t)
|
|
|
|
|
2020-09-29 21:57:46 +00:00
|
|
|
require := require.New(t)
|
|
|
|
|
|
|
|
policy := mock.ScalingPolicy()
|
|
|
|
policy.Target["TestField"] = "test"
|
|
|
|
|
|
|
|
// Create test indexers
|
|
|
|
indexersAllowMissingTrue := &ScalingPolicyTargetFieldIndex{Field: "TestField", AllowMissing: true}
|
|
|
|
indexersAllowMissingFalse := &ScalingPolicyTargetFieldIndex{Field: "TestField", AllowMissing: false}
|
|
|
|
|
|
|
|
// Check if box indexers can find the test field
|
|
|
|
ok, val, err := indexersAllowMissingTrue.FromObject(policy)
|
|
|
|
require.True(ok)
|
|
|
|
require.NoError(err)
|
|
|
|
require.Equal("test\x00", string(val))
|
|
|
|
|
|
|
|
ok, val, err = indexersAllowMissingFalse.FromObject(policy)
|
|
|
|
require.True(ok)
|
|
|
|
require.NoError(err)
|
|
|
|
require.Equal("test\x00", string(val))
|
|
|
|
|
|
|
|
// Check for empty field
|
|
|
|
policy.Target["TestField"] = ""
|
|
|
|
|
|
|
|
ok, val, err = indexersAllowMissingTrue.FromObject(policy)
|
|
|
|
require.True(ok)
|
|
|
|
require.NoError(err)
|
|
|
|
require.Equal("\x00", string(val))
|
|
|
|
|
|
|
|
ok, val, err = indexersAllowMissingFalse.FromObject(policy)
|
|
|
|
require.True(ok)
|
|
|
|
require.NoError(err)
|
|
|
|
require.Equal("\x00", string(val))
|
|
|
|
|
|
|
|
// Check for missing field
|
|
|
|
delete(policy.Target, "TestField")
|
|
|
|
|
|
|
|
ok, val, err = indexersAllowMissingTrue.FromObject(policy)
|
|
|
|
require.True(ok)
|
|
|
|
require.NoError(err)
|
|
|
|
require.Equal("\x00", string(val))
|
|
|
|
|
|
|
|
ok, val, err = indexersAllowMissingFalse.FromObject(policy)
|
|
|
|
require.False(ok)
|
|
|
|
require.NoError(err)
|
|
|
|
require.Equal("", string(val))
|
|
|
|
|
|
|
|
// Check for invalid input
|
|
|
|
ok, val, err = indexersAllowMissingTrue.FromObject("not-a-scaling-policy")
|
|
|
|
require.False(ok)
|
|
|
|
require.Error(err)
|
|
|
|
require.Equal("", string(val))
|
|
|
|
|
|
|
|
ok, val, err = indexersAllowMissingFalse.FromObject("not-a-scaling-policy")
|
|
|
|
require.False(ok)
|
|
|
|
require.Error(err)
|
|
|
|
require.Equal("", string(val))
|
|
|
|
}
|