Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(store): fix inf.Dec and big.Int compare #406

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 123 additions & 0 deletions pkg/store/comp/compare_info.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// Copyright 2023 ScyllaDB
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package comp

import (
"fmt"
"strings"
)

// Info contains information about responses difference.
type Info []string

func (d *Info) Len() int {
return len(*d)
}

func (d *Info) Add(in ...string) {
*d = append(*d, in...)
}

func (d *Info) String() string {
return strings.Join(*d, "\n")
}

func GetCompareInfoSimple(d Results) Info {
lenTest := d.LenRowsTest()
lenOracle := d.LenRowsOracle()
switch {
case lenTest == 0 && lenOracle == 0:
return nil
// responses don`t have rows
case lenTest == lenOracle:
// responses have rows and have same rows count
equalRowsCount := equalRowsSameLen(d)
// equalRowsSameLen function simultaneously deletes equal rows in Test and Oracle stores.
// So we can check rows only one of the stores.
if d.LenRowsTest() < 1 {
return nil
}
return Info{fmt.Sprintf("responses have %d equal rows and unequal rows %d", equalRowsCount, d.LenRowsTest())}
default:
// responses have different rows count
return Info{fmt.Sprintf("different rows count in responses: from test store-%d, from oracle store-%d", lenTest, lenOracle)}
}
}

func GetCompareInfoDetailed(d Results) Info {
lenTest := d.LenRowsTest()
lenOracle := d.LenRowsOracle()
switch {
case lenTest == 0 && lenOracle == 0:
return nil
// responses don`t have rows
case lenTest < 1 || lenOracle < 1:
// one of the responses without rows.
diff := make(Info, 0)
diff.Add(fmt.Sprintf("different rows count in responses: from test store-%d, from oracle store-%d", lenTest, lenOracle))
diff.Add(d.StringAllRows("unequal")...)
return diff
case lenTest == lenOracle:
// responses have rows and have same rows count
equalRowsCount := equalRowsSameLen(d)
// equalRowsSameLen function simultaneously deletes equal rows in Test and Oracle stores.
// So we can check rows only one of the stores.
if d.LenRowsTest() < 1 {
return nil
}
diff := make(Info, 0)
diff.Add(fmt.Sprintf("responses have %d equal rows and unequal rows: test store %d; oracle store %d", equalRowsCount, d.LenRowsTest(), d.LenRowsOracle()))
diff.Add(d.StringAllRows("unequal")...)
return diff
default:
// responses have rows and have different rows count
diff := make(Info, 0)
equalRowsCount := equalRowsDiffLen(d)
diff.Add(fmt.Sprintf("responses have %d equal rows and unequal rows: test store %d; oracle store %d", equalRowsCount, d.LenRowsTest(), d.LenRowsOracle()))
diff.Add(d.StringAllRows("unequal")...)
return diff
}
}

// equalRowsSameLen returns count of equal rows of stores simultaneously deletes equal rows.
// Applies when oracle and test stores have same rows count.
func equalRowsSameLen(d Results) int {
if d.LenRowsTest() == 1 {
return d.EqualSingeRow()
}
equalRowsCount := d.EasyEqualRowsTest()
if d.LenRowsTest() != 0 {
equalRowsCount += d.EqualRowsTest()
}
return equalRowsCount
}

// equalRowsDiffLen returns count of equal rows of stores simultaneously deletes equal rows.
// Applies when oracle and test stores have different rows count.
func equalRowsDiffLen(d Results) int {
equalRowsCount := 0
if d.LenRowsTest() > d.LenRowsOracle() {
equalRowsCount = d.EasyEqualRowsOracle()
if d.LenRowsOracle() > 0 {
equalRowsCount += d.EqualRowsOracle()
}
} else {
equalRowsCount = d.EasyEqualRowsTest()
if d.LenRowsTest() > 0 {
equalRowsCount += d.EqualRowsTest()
}
}
return equalRowsCount
}
137 changes: 137 additions & 0 deletions pkg/store/comp/compare_info_mv_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
// Copyright 2023 ScyllaDB
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//nolint:thelper

package comp

import (
"fmt"
"testing"

"github.com/scylladb/gemini/pkg/store/mv"
"github.com/scylladb/gemini/pkg/store/sv"
)

func TestGetCompareInfoMV(t *testing.T) {
var test mv.Results
for idx := range testCases {
tests := 2
if testCases[idx].diffs > 0 {
tests = 4
}
for tests > 0 {
test.Test.Rows, test.Oracle.Rows, test.Test.Types, test.Oracle.Types = rndSameRowsMV(testCases[idx].test, testCases[idx].oracle)
// Add names
if len(test.Test.Rows) > 0 {
test.Test.Names = make([]string, len(test.Test.Rows[0]))
for col := range test.Test.Rows[0] {
test.Test.Names[col] = fmt.Sprintf("col%d", col)
}
}
if len(test.Oracle.Rows) > 0 {
test.Oracle.Names = make([]string, len(test.Oracle.Rows[0]))
for col := range test.Oracle.Rows[0] {
test.Oracle.Names[col] = fmt.Sprintf("col%d", col)
}
}
if testCases[idx].diffs > 0 {
if tests%2 == 0 {
corruptRows(&test.Test.Rows, testCases[idx].diffs)
} else {
corruptRows(&test.Oracle.Rows, testCases[idx].diffs)
}
}
result := Info{}
errFuncName := "GetCompareInfoDetailed"
if tests%2 == 0 {
errFuncName = "GetCompareInfoSimple"
result = GetCompareInfoSimple(&test)
} else {
result = GetCompareInfoDetailed(&test)
}
if len(result) > 0 && !testCases[idx].haveDif {
t.Fatalf("wrong %s work. test case:%+v \nresult should be empty, but have:%s\n"+
"mv.Results.Test.Rows:%+v\n"+
"mv.Results.Oracle.Rows:%+v", errFuncName, testCases[idx], result, test.Test.Rows, test.Oracle.Rows)
}
if len(result) == 0 && testCases[idx].haveDif {
t.Fatalf("wrong %s work. test case:%+v \nresult should be not empty\n"+
"mv.Results.Test.Rows:%+v\n"+
"mv.Results.Oracle.Rows:%+v", errFuncName, testCases[idx], test.Test.Rows, test.Oracle.Rows)
}
if len(result) > 0 {
fmt.Printf("%s from mv.Results of test case:%+v\n", errFuncName, testCases[idx])
fmt.Println(result.String())
}
tests--
}
}
}

func TestGetCompareInfoSV(t *testing.T) {
var test sv.Results
for idx := range testCases {
tests := 2
if testCases[idx].diffs > 0 {
tests = 4
}
for tests > 0 {
test.Test.Rows, test.Oracle.Rows, test.Test.Types, test.Oracle.Types = rndSameRowsSV(testCases[idx].test, testCases[idx].oracle)
// Add names
if len(test.Test.Rows) > 0 {
test.Test.Names = make([]string, len(test.Test.Rows[0]))
for col := range test.Test.Rows[0] {
test.Test.Names[col] = fmt.Sprintf("col%d", col)
}
}
if len(test.Oracle.Rows) > 0 {
test.Oracle.Names = make([]string, len(test.Oracle.Rows[0]))
for col := range test.Oracle.Rows[0] {
test.Oracle.Names[col] = fmt.Sprintf("col%d", col)
}
}
if testCases[idx].diffs > 0 {
if tests%2 == 0 {
corruptRowsSV(&test.Test.Rows, testCases[idx].diffs)
} else {
corruptRowsSV(&test.Oracle.Rows, testCases[idx].diffs)
}
}
result := Info{}
errFuncName := "GetCompareInfoDetailed"
if tests%2 == 0 {
errFuncName = "GetCompareInfoSimple"
result = GetCompareInfoSimple(&test)
} else {
result = GetCompareInfoDetailed(&test)
}
if len(result) > 0 && !testCases[idx].haveDif {
t.Fatalf("wrong %s work. test case:%+v \nresult should be empty, but have:%s\n"+
"mv.Results.Test.Rows:%+v\n"+
"mv.Results.Oracle.Rows:%+v", errFuncName, testCases[idx], result, test.Test.Rows, test.Oracle.Rows)
}
if len(result) == 0 && testCases[idx].haveDif {
t.Fatalf("wrong %s work. test case:%+v \nresult should be not empty\n"+
"mv.Results.Test.Rows:%+v\n"+
"mv.Results.Oracle.Rows:%+v", errFuncName, testCases[idx], test.Test.Rows, test.Oracle.Rows)
}
if len(result) > 0 {
fmt.Printf("%s from mv.Results of test case:%+v\n", errFuncName, testCases[idx])
fmt.Println(result.String())
}
tests--
}
}
}
44 changes: 44 additions & 0 deletions pkg/store/comp/interface.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright 2023 ScyllaDB
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package comp

// Results interface for comparison Test and Oracle rows
type Results interface {
// EqualSingeRow equals fist rows and deletes if equal, returns count of equal rows.
// Equals only the first Oracle and Test rows without `for` cycle.
// Most responses have only one row.
EqualSingeRow() int

// EasyEqualRowsTest returns count of equal rows into stores simultaneously deletes equal rows.
// Most cases have no difference between Oracle and Test rows, therefore the fastest compare way to compare
// Test and Oracle responses row by row.
// Travels through Test rows.
EasyEqualRowsTest() int
// EasyEqualRowsOracle same as EasyEqualRowsTest, but travels through Oracle rows.
EasyEqualRowsOracle() int

// EqualRowsTest equals all rows and deletes if equal, returns count of equal rows.
// For cases then EasyEqualRowsTest did not bring full success.
// Travels through Test rows.
EqualRowsTest() int
// EqualRowsOracle same as EqualRowsTest, but travels through Oracle rows.
EqualRowsOracle() int

LenRowsOracle() int
LenRowsTest() int

StringAllRows(prefix string) []string
HaveRows() bool
}
Loading
Loading