gemini

package module
v1.7.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 1, 2020 License: Apache-2.0 Imports: 28 Imported by: 0

README

Gemini

An automatic random testing suite for Scylla and Apache Cassandra.

How does Gemini work?

Gemini operates on two clusters, a system under test (SUT) and a test oracle, by generating random mutations (INSERT, UPDATE) and verifying them (SELECT) using the CQL protocol and query language. As the mutations are performed on both systems, their client-visible state is assumed to be the same, unless either of the systems (usually system under test) have bugs. If a verification step fails, Gemini reports the CQL query and its results for further analysis.

Getting started with Gemini

TLDR: Running with default arguments

  1. Download a release from http://downloads.scylladb.com/gemini/

  2. Make sure you have two scylla clusters setup from here on referred to as ORACLE_CLUSTER and TEST_CLUSTER

  3. Unzip the tarball and run ./gemini --oracle-cluster=<ORACLE_CLUSTER> --test-cluster=<TEST_CLUSTER>

Enjoy!

Further CLI arguments

Execute ./gemini --help to see the entire list of arguments available. Their explanation in some detail is available the CLI arguments.

Features

  • Random schema generation
  • Data generation using uniform, normal, and zipf distributions
  • Materialized views
  • Secondary indexes
  • Counters

Contributing

Gemini is already being used for testing Scylla releases, but there's still plenty to do. To contribute to Gemini, please fork the repository and send a pull request.

Documentation

License

Gemini is distributed under the Apache 2.0 license. See LICENSE for more information.

Documentation

Index

Constants

View Source
const (
	TYPE_ASCII     = SimpleType("ascii")
	TYPE_BIGINT    = SimpleType("bigint")
	TYPE_BLOB      = SimpleType("blob")
	TYPE_BOOLEAN   = SimpleType("boolean")
	TYPE_DATE      = SimpleType("date")
	TYPE_DECIMAL   = SimpleType("decimal")
	TYPE_DOUBLE    = SimpleType("double")
	TYPE_DURATION  = SimpleType("duration")
	TYPE_FLOAT     = SimpleType("float")
	TYPE_INET      = SimpleType("inet")
	TYPE_INT       = SimpleType("int")
	TYPE_SMALLINT  = SimpleType("smallint")
	TYPE_TEXT      = SimpleType("text")
	TYPE_TIME      = SimpleType("time")
	TYPE_TIMESTAMP = SimpleType("timestamp")
	TYPE_TIMEUUID  = SimpleType("timeuuid")
	TYPE_TINYINT   = SimpleType("tinyint")
	TYPE_UUID      = SimpleType("uuid")
	TYPE_VARCHAR   = SimpleType("varchar")
	TYPE_VARINT    = SimpleType("varint")
)

Variables

View Source
var (
	SchemaConfigInvalidPK   = errors.New("max number of partition keys must be bigger than min number of partition keys")
	SchemaConfigInvalidCK   = errors.New("max number of clustering keys must be bigger than min number of clustering keys")
	SchemaConfigInvalidCols = errors.New("max number of columns must be bigger than min number of columns")
)

Functions

This section is empty.

Types

type AlterTableBuilder

type AlterTableBuilder struct {
	// contains filtered or unexported fields
}

func (*AlterTableBuilder) ToCql

func (atb *AlterTableBuilder) ToCql() (string, []string)

type BagType

type BagType struct {
	Kind   string     `json:"kind"` // We need to differentiate between sets and lists
	Type   SimpleType `json:"type"`
	Frozen bool       `json:"frozen"`
}

func (BagType) CQLDef

func (ct BagType) CQLDef() string

func (BagType) CQLHolder

func (ct BagType) CQLHolder() string

func (BagType) CQLPretty

func (ct BagType) CQLPretty(query string, value []interface{}) (string, int)

func (BagType) CQLType

func (st BagType) CQLType() gocql.TypeInfo

func (BagType) GenValue

func (ct BagType) GenValue(r *rand.Rand, p PartitionRangeConfig) []interface{}

func (BagType) Indexable

func (ct BagType) Indexable() bool

func (BagType) Name

func (ct BagType) Name() string

type CQLFeature

type CQLFeature int
const (
	CQL_FEATURE_BASIC CQLFeature = iota + 1
	CQL_FEATURE_NORMAL
	CQL_FEATURE_ALL

	KnownIssuesJsonWithTuples = "https://github.com/scylladb/scylla/issues/3708"
)

type ColumnDef

type ColumnDef struct {
	Name string `json:"name"`
	Type Type   `json:"type"`
}

func (*ColumnDef) UnmarshalJSON

func (cd *ColumnDef) UnmarshalJSON(data []byte) error

type Columns

type Columns []ColumnDef

func (Columns) Names

func (c Columns) Names() []string

func (Columns) ToJSONMap

func (cs Columns) ToJSONMap(values map[string]interface{}, r *rand.Rand, p PartitionRangeConfig) map[string]interface{}

type CounterType

type CounterType struct {
	Value int64
}

func (CounterType) CQLDef

func (ct CounterType) CQLDef() string

func (CounterType) CQLHolder

func (ct CounterType) CQLHolder() string

func (CounterType) CQLPretty

func (ct CounterType) CQLPretty(query string, value []interface{}) (string, int)

func (CounterType) CQLType

func (ct CounterType) CQLType() gocql.TypeInfo

func (CounterType) GenValue

func (ct CounterType) GenValue(r *rand.Rand, p PartitionRangeConfig) []interface{}

func (CounterType) Indexable

func (ct CounterType) Indexable() bool

func (CounterType) Name

func (ct CounterType) Name() string

type DistributionFunc

type DistributionFunc func() TokenIndex

type Generator

type Generator struct {
	// contains filtered or unexported fields
}

func NewGenerator

func NewGenerator(ctx context.Context, table *Table, config *GeneratorConfig, logger *zap.Logger) *Generator

func (Generator) Get

func (g Generator) Get() (ValueWithToken, bool)

func (Generator) GetOld

func (g Generator) GetOld() (ValueWithToken, bool)

GetOld returns a previously used value and token or a new if the old queue is empty.

func (*Generator) GiveOld

func (g *Generator) GiveOld(v ValueWithToken)

GiveOld returns the supplied value for later reuse unless the value is empty in which case it removes the corresponding token from the in-flight tracking.

type GeneratorConfig

type GeneratorConfig struct {
	PartitionsRangeConfig      PartitionRangeConfig
	PartitionsCount            uint64
	PartitionsDistributionFunc DistributionFunc
	Seed                       uint64
	PkUsedBufferSize           uint64
}

type IndexDef

type IndexDef struct {
	Name      string `json:"name"`
	Column    string `json:"column"`
	ColumnIdx int    `json:"column_idx"`
}

type Keyspace

type Keyspace struct {
	Name              string                   `json:"name"`
	Replication       *replication.Replication `json:"replication"`
	OracleReplication *replication.Replication `json:"oracle_replication"`
}

type MapType

type MapType struct {
	KeyType   SimpleType `json:"key_type"`
	ValueType SimpleType `json:"value_type"`
	Frozen    bool       `json:"frozen"`
}

func (MapType) CQLDef

func (mt MapType) CQLDef() string

func (MapType) CQLHolder

func (mt MapType) CQLHolder() string

func (MapType) CQLPretty

func (mt MapType) CQLPretty(query string, value []interface{}) (string, int)

func (MapType) CQLType

func (st MapType) CQLType() gocql.TypeInfo

func (MapType) GenValue

func (mt MapType) GenValue(r *rand.Rand, p PartitionRangeConfig) []interface{}

func (MapType) Indexable

func (mt MapType) Indexable() bool

func (MapType) Name

func (mt MapType) Name() string

type MaterializedView

type MaterializedView struct {
	Name           string  `json:"name"`
	PartitionKeys  Columns `json:"partition_keys"`
	ClusteringKeys Columns `json:"clustering_keys"`
}

type Partition

type Partition struct {
	// contains filtered or unexported fields
}

type PartitionRangeConfig

type PartitionRangeConfig struct {
	MaxBlobLength   int
	MinBlobLength   int
	MaxStringLength int
	MinStringLength int
	UseLWT          bool
}

type RoutingKeyCreator

type RoutingKeyCreator struct {
	// contains filtered or unexported fields
}

func (*RoutingKeyCreator) CreateRoutingKey

func (rc *RoutingKeyCreator) CreateRoutingKey(table *Table, values []interface{}) ([]byte, error)

type Schema

type Schema struct {
	Keyspace Keyspace `json:"keyspace"`
	Tables   []*Table `json:"tables"`
}

func GenSchema

func GenSchema(sc SchemaConfig) *Schema

func (*Schema) GenCheckStmt

func (s *Schema) GenCheckStmt(t *Table, g *Generator, r *rand.Rand, p PartitionRangeConfig) *Stmt

func (*Schema) GenDDLStmt

func (s *Schema) GenDDLStmt(t *Table, r *rand.Rand, p PartitionRangeConfig, sc *SchemaConfig) ([]*Stmt, func(), error)

func (*Schema) GenDeleteRows

func (s *Schema) GenDeleteRows(t *Table, g *Generator, r *rand.Rand, p PartitionRangeConfig) (*Stmt, error)

func (*Schema) GenInsertJsonStmt

func (s *Schema) GenInsertJsonStmt(t *Table, g *Generator, r *rand.Rand, p PartitionRangeConfig) (*Stmt, error)

func (*Schema) GenInsertStmt

func (s *Schema) GenInsertStmt(t *Table, g *Generator, r *rand.Rand, p PartitionRangeConfig) (*Stmt, error)

func (*Schema) GenMutateStmt

func (s *Schema) GenMutateStmt(t *Table, g *Generator, r *rand.Rand, p PartitionRangeConfig, deletes bool) (*Stmt, error)

func (*Schema) GetCreateKeyspaces added in v1.6.5

func (s *Schema) GetCreateKeyspaces() (string, string)

func (*Schema) GetCreateSchema

func (s *Schema) GetCreateSchema() []string

func (*Schema) GetDropSchema

func (s *Schema) GetDropSchema() []string

type SchemaBuilder

type SchemaBuilder interface {
	Keyspace(Keyspace) SchemaBuilder
	Table(*Table) SchemaBuilder
	Build() *Schema
}

func NewSchemaBuilder

func NewSchemaBuilder() SchemaBuilder

type SchemaConfig

type SchemaConfig struct {
	ReplicationStrategy              *replication.Replication
	OracleReplicationStrategy        *replication.Replication
	TableOptions                     []tableopts.Option
	MaxTables                        int
	MaxPartitionKeys                 int
	MinPartitionKeys                 int
	MaxClusteringKeys                int
	MinClusteringKeys                int
	MaxColumns                       int
	MinColumns                       int
	MaxUDTParts                      int
	MaxTupleParts                    int
	MaxBlobLength                    int
	MaxStringLength                  int
	MinBlobLength                    int
	MinStringLength                  int
	UseCounters                      bool
	UseLWT                           bool
	CQLFeature                       CQLFeature
	AsyncObjectStabilizationAttempts int
	AsyncObjectStabilizationDelay    time.Duration
}

func (*SchemaConfig) GetMaxClusteringKeys

func (sc *SchemaConfig) GetMaxClusteringKeys() int

func (*SchemaConfig) GetMaxColumns

func (sc *SchemaConfig) GetMaxColumns() int

func (*SchemaConfig) GetMaxPartitionKeys

func (sc *SchemaConfig) GetMaxPartitionKeys() int

func (*SchemaConfig) GetMaxTables

func (sc *SchemaConfig) GetMaxTables() int

func (*SchemaConfig) GetMinClusteringKeys

func (sc *SchemaConfig) GetMinClusteringKeys() int

func (*SchemaConfig) GetMinColumns

func (sc *SchemaConfig) GetMinColumns() int

func (*SchemaConfig) GetMinPartitionKeys

func (sc *SchemaConfig) GetMinPartitionKeys() int

func (*SchemaConfig) Valid

func (sc *SchemaConfig) Valid() error

type SimpleType

type SimpleType string

func (SimpleType) CQLDef

func (st SimpleType) CQLDef() string

func (SimpleType) CQLHolder

func (st SimpleType) CQLHolder() string

func (SimpleType) CQLPretty

func (st SimpleType) CQLPretty(query string, value []interface{}) (string, int)

func (SimpleType) CQLType

func (st SimpleType) CQLType() gocql.TypeInfo

func (SimpleType) GenValue

func (st SimpleType) GenValue(r *rand.Rand, p PartitionRangeConfig) []interface{}

func (SimpleType) Indexable

func (st SimpleType) Indexable() bool

func (SimpleType) Name

func (st SimpleType) Name() string

type StatementType

type StatementType uint8
const (
	SelectStatementType StatementType = iota
	SelectRangeStatementType
	SelectByIndexStatementType
	SelectFromMaterializedViewStatementType
	DeleteStatementType
	InsertStatement
	AlterColumnStatementType
	DropColumnStatementType
)

func (StatementType) PossibleAsyncOperation

func (st StatementType) PossibleAsyncOperation() bool

type Stmt

type Stmt struct {
	Query     qb.Builder
	Values    func() (uint64, []interface{})
	Types     []Type
	QueryType StatementType
}

func (*Stmt) PrettyCQL

func (s *Stmt) PrettyCQL() string

type Table

type Table struct {
	Name              string             `json:"name"`
	PartitionKeys     Columns            `json:"partition_keys"`
	ClusteringKeys    Columns            `json:"clustering_keys"`
	Columns           Columns            `json:"columns"`
	Indexes           []IndexDef         `json:"indexes,omitempty"`
	MaterializedViews []MaterializedView `json:"materialized_views,omitempty"`
	KnownIssues       map[string]bool    `json:"known_issues"`
	TableOptions      []string           `json:"table_options,omitempty"`
	// contains filtered or unexported fields
}

func (*Table) GetCreateTable

func (t *Table) GetCreateTable(ks Keyspace) string

func (*Table) GetCreateTypes

func (t *Table) GetCreateTypes(keyspace Keyspace) []string

func (*Table) Lock

func (t *Table) Lock()

func (*Table) Unlock

func (t *Table) Unlock()

type TokenIndex

type TokenIndex uint64

TokenIndex represents the position of a token in the token ring. A token index is translated to a token by a generator. If the generator preserves the exact position, then the token index becomes the token; otherwise token index represents an approximation of the token.

We use a token index approach, because our generators actually generate partition keys, and map them to tokens. The generators, therefore, do not populate the full token ring space. With token index, we can approximate different token distributions from a sparse set of tokens.

type TupleType

type TupleType struct {
	Types  []SimpleType `json:"types"`
	Frozen bool         `json:"frozen"`
}

func (TupleType) CQLDef

func (tt TupleType) CQLDef() string

func (TupleType) CQLHolder

func (tt TupleType) CQLHolder() string

func (TupleType) CQLPretty

func (tt TupleType) CQLPretty(query string, value []interface{}) (string, int)

func (TupleType) CQLType

func (st TupleType) CQLType() gocql.TypeInfo

func (TupleType) GenValue

func (tt TupleType) GenValue(r *rand.Rand, p PartitionRangeConfig) []interface{}

func (TupleType) Indexable

func (st TupleType) Indexable() bool

func (TupleType) Name

func (tt TupleType) Name() string

type Type

type Type interface {
	Name() string
	CQLDef() string
	CQLHolder() string
	CQLPretty(string, []interface{}) (string, int)
	GenValue(*rand.Rand, PartitionRangeConfig) []interface{}
	Indexable() bool
	CQLType() gocql.TypeInfo
}

type UDTType

type UDTType struct {
	Types    map[string]SimpleType `json:"types"`
	TypeName string                `json:"type_name"`
	Frozen   bool                  `json:"frozen"`
}

func (UDTType) CQLDef

func (tt UDTType) CQLDef() string

func (UDTType) CQLHolder

func (tt UDTType) CQLHolder() string

func (UDTType) CQLPretty

func (tt UDTType) CQLPretty(query string, value []interface{}) (string, int)

func (UDTType) CQLType

func (st UDTType) CQLType() gocql.TypeInfo

func (UDTType) GenValue

func (tt UDTType) GenValue(r *rand.Rand, p PartitionRangeConfig) []interface{}

func (UDTType) Indexable

func (tt UDTType) Indexable() bool

func (UDTType) Name

func (tt UDTType) Name() string

type Value

type Value []interface{}

type ValueWithToken

type ValueWithToken struct {
	Token uint64
	Value Value
}

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL