Skip to content

Commit

Permalink
fix(store): fix inf.Dec and big.Int compare
Browse files Browse the repository at this point in the history
changes in check of responses rows procces:
*rows data unmarshalling into byte slices/arrays.
*rows data compare as byte slices/arrays, without transformation to 'GO' types.
*rows diff information now more user friendly and can be customed. Diff collect row by row to string slice and can be transferred anywhere with better readable.
  • Loading branch information
illia-li committed Sep 6, 2023
1 parent 5595709 commit c3e5c7b
Show file tree
Hide file tree
Showing 29 changed files with 2,257 additions and 142 deletions.
61 changes: 61 additions & 0 deletions pkg/response/comp/delete_equal.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright 2019 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 (
"github.com/scylladb/gemini/pkg/response"
"github.com/scylladb/gemini/pkg/response/rrows"
)

// easyDeleteEqualRows delete equal rows one by one. Its usual way, but not optimal.
// Fewer Rows must be in resp1.
func easyDeleteEqualRows(resp1, resp2 *response.Data) int {
idx := 0
for _, row := range resp1.Rows {
if row.Equal(resp2.Rows[idx]) {
idx++
continue
}
break
}
//delete rows

Check failure on line 33 in pkg/response/comp/delete_equal.go

View workflow job for this annotation

GitHub Actions / Lint Test and Build

commentFormatting: put a space between `//` and comment text (gocritic)
resp1.Rows = resp1.Rows[idx:]
resp2.Rows = resp2.Rows[idx:]
return idx
}

// usualDeleteEqualRows delete equal rows. Its usual way, but not optimal.
// Fewer Rows must be in resp1.
func usualDeleteEqualRows(resp1, resp2 *response.Data) int {
equalRowsCount := easyDeleteEqualRows(resp1, resp2)
if len(resp1.Rows) == 0 || len(resp2.Rows) == 0 {
return equalRowsCount
}
idx1 := 0
tmpOut := make(rrows.Rows, 0)
for _, row := range resp1.Rows {
if idx2 := resp2.Rows.FindEqual(*row); idx2 != -1 {
//delete rows

Check failure on line 50 in pkg/response/comp/delete_equal.go

View workflow job for this annotation

GitHub Actions / Lint Test and Build

commentFormatting: put a space between `//` and comment text (gocritic)
resp2.Rows[idx2] = resp2.Rows[len(resp2.Rows)-1]
resp2.Rows = resp2.Rows[:len(resp2.Rows)-1]
equalRowsCount++
continue
}
tmpOut = append(tmpOut, row)
idx1++
}
resp1.Rows = tmpOut
return equalRowsCount
}
107 changes: 107 additions & 0 deletions pkg/response/comp/delete_equal_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// Copyright 2019 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 (
"reflect"
"testing"
"time"

"golang.org/x/exp/rand"

"github.com/scylladb/gemini/pkg/response"
"github.com/scylladb/gemini/pkg/response/rcols"
"github.com/scylladb/gemini/pkg/response/rrows"
"github.com/scylladb/gemini/pkg/utils"
)

var rnd = rand.New(rand.NewSource(uint64(time.Now().UnixMilli())))

func TestTryEasyDeleteEqualRows(t *testing.T) {
row1 := getRandomRawRow(20, 20)
row2 := getRandomRawRow(20, 20)
rows1 := getRandomRawRows(20, 20, 20)
rows2 := make(rrows.Rows, 20)
copy(rows2, rows1)
rows1[10] = &row1
rows2[11] = &row2
testRows1 := response.Data{
Rows: rows1,
}
testRows2 := response.Data{
Rows: rows2,
}

expected1 := rows1[10:]
expected2 := rows2[10:]

deleteCount := easyDeleteEqualRows(&testRows1, &testRows2)

if !reflect.DeepEqual(testRows1.Rows, expected1) {
t.Fatalf("wrong easyDeleteEqualRows work. \nreceived:%+v \nexpected:%+v", testRows1.Rows, expected1)
}
if !reflect.DeepEqual(testRows2.Rows, expected2) {
t.Fatalf("wrong easyDeleteEqualRows work. \nreceived:%+v \nexpected:%+v", testRows1.Rows, expected2)
}
if deleteCount != 10 {
t.Fatalf("wrong easyDeleteEqualRows work. deletes count %d, but should %d ", deleteCount, 10)
}
}

func TestTryUsualDeleteEqualRows(t *testing.T) {
row1 := getRandomRawRow(20, 20)
row2 := getRandomRawRow(20, 20)
rows1 := getRandomRawRows(20, 20, 20)
rows2 := make(rrows.Rows, 20)
copy(rows2, rows1)
rows1[10] = &row1
rows2[10] = &row2

testRows1 := response.Data{
Rows: rows1,
}
testRows2 := response.Data{
Rows: rows2,
}

usualDeleteEqualRows(&testRows1, &testRows2)

if !reflect.DeepEqual(*testRows1.Rows[0], row1) || len(testRows1.Rows) != 1 {
t.Fatalf("wrong diff.deleteEqualRowsDiffLen work. \nreceived:%d \nexpected:%d", testRows1.LenRows(), 1)
}
if !reflect.DeepEqual(*testRows2.Rows[0], row2) || len(testRows2.Rows) != 1 {
t.Fatalf("wrong diff.deleteEqualRowsDiffLen work. \nreceived:%d \nexpected:%d", testRows2.LenColumns(), 1)
}
}

func getRandomRawRows(rowsCount, columns, columnLen int) rrows.Rows {
out := make(rrows.Rows, rowsCount)
for idx := range out {
tmp := getRandomRawRow(columns, columnLen)
out[idx] = &tmp
}
return out
}

func getRandomRawRow(columns, columnLen int) rrows.Row {
out := make(rrows.Row, columns)
for idx := range out {
col := utils.RandBytes(rnd, columnLen)
out[idx] = *(*rcols.ColumnLongRaw)(&col)
}
return out
}
144 changes: 144 additions & 0 deletions pkg/response/comp/diff_info.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
// Copyright 2019 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"

"github.com/scylladb/gemini/pkg/response"
"github.com/scylladb/gemini/pkg/response/diffs"
)

// Info represent 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 (d *Info) addMissingRows(test, oracle *response.Data) {
if test.LenRows() != 0 {
d.Add("unequal test store rows:")
d.Add(test.RowsToStrings()...)
}
if oracle.LenRows() != 0 {
d.Add("unequal oracle store rows:")
d.Add(oracle.RowsToStrings()...)
}
}

func (d *Info) AddUnequalRowsInfo(test, oracle *response.Data) {
d.Add(diffs.GetList(test, oracle).StringsRaw(test.Types, test.Names)...)
}

// GetCompareInfo returns empty Info if responses are equal in other case returns information about responses difference.
func GetCompareInfo(test, oracle *response.Data, detailedDiff bool) Info {
diff := make(Info, 0)
lenTest := test.LenRows()
lenOracle := oracle.LenRows()
equalRowsCount := 0
if lenTest == 0 && lenOracle == 0 {
// no rows in responses from test and oracle stores, nothing to compare.
return diff
}
if !detailedDiff {
if lenTest == 0 || lenOracle == 0 {
diff.Add(fmt.Sprintf("different rows count in responses: from test store-%d, from oracle store-%d", lenTest, lenOracle))
return diff
}
if lenTest != lenOracle {
diff.Add(fmt.Sprintf("different rows count in responses: from test store-%d, from oracle store-%d", lenTest, lenOracle))
return diff
}
equalRowsCount = deleteEqualRowsDiffLen(test, oracle)
if len(test.Rows) != 0 {
diff.Add(fmt.Sprintf("responses have %d equal rows and not equal rows %d", equalRowsCount, test.LenRows()))
}
return diff
}

if lenTest == 0 || lenOracle == 0 {
diff.Add(fmt.Sprintf("different rows count in responses: from test store-%d, from oracle store-%d", lenTest, lenOracle))
diff.addMissingRows(test, oracle)
return diff
}
// case with same len
if lenTest == lenOracle {
equalRowsCount = deleteEqualRowsSameLen(test, oracle)
if test.LenRows() == 0 {
return diff
}
diff.Add(fmt.Sprintf("responses have %d equal rows and not equal rows: test store %d; oracle store %d", equalRowsCount, test.LenRows(), oracle.LenRows()))
diff.AddUnequalRowsInfo(test, oracle)
return diff
}
// case with different len
equalRowsCount = deleteEqualRowsDiffLen(test, oracle)
diff.Add(fmt.Sprintf("responses have %d equal rows and not equal rows: test store %d; oracle store %d", equalRowsCount, test.LenRows(), oracle.LenRows()))
if test.LenRows() == 0 || oracle.LenRows() == 0 {
diff.addMissingRows(test, oracle)
return diff
}
diff.AddUnequalRowsInfo(test, oracle)
return diff
}

// deleteEqualRowsDiffLen returns true if responses rows equal.
// Task of this function - chose optimal way for equal rows.
func deleteEqualRowsDiffLen(test, oracle *response.Data) int {
equalRowsCount := 0
if test.LenRows() < oracle.LenRows() {
// case test rows fewer
equalRowsCount += easyDeleteEqualRows(test, oracle)
if test.LenRows() != 0 {
equalRowsCount += usualDeleteEqualRows(test, oracle)
}
return equalRowsCount
}
// case oracle rows fewer
equalRowsCount += easyDeleteEqualRows(oracle, test)
if oracle.LenRows() != 0 {
equalRowsCount += usualDeleteEqualRows(oracle, test)
}
return equalRowsCount
}

// deleteEqualRowsDiffLen returns true if responses rows equal.
// Task of this function - chose optimal way for equal rows.
func deleteEqualRowsSameLen(test, oracle *response.Data) int {
if test.LenRows() == 1 {
if test.Rows[0].Equal(oracle.Rows[0]) {
//delete rows

Check failure on line 132 in pkg/response/comp/diff_info.go

View workflow job for this annotation

GitHub Actions / Lint Test and Build

commentFormatting: put a space between `//` and comment text (gocritic)
test.Rows = nil
oracle.Rows = nil
return 1
}
return 0
}
equalRowsCount := easyDeleteEqualRows(test, oracle)
if test.LenRows() != 0 {
equalRowsCount += usualDeleteEqualRows(test, oracle)
}
return equalRowsCount
}
54 changes: 54 additions & 0 deletions pkg/response/data.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright 2019 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 response

import (
"github.com/gocql/gocql"

"github.com/scylladb/gemini/pkg/response/rrows"
)

type Data struct {
Types []gocql.TypeInfo
Names []string
Rows rrows.Rows
}

func (d *Data) LenColumns() int {
return len(d.Names)
}

func (d *Data) LenRows() int {
return len(d.Rows)
}

func (d *Data) RowsToStrings() []string {
return d.Rows.Strings(d.Types, d.Names)
}

func (d *Data) EqualColumns(d2 []string) bool {
if len(d.Names) != len(d2) {
return false
}
if len(d2) == 0 {
return true
}
for idx := range d.Names {
if d.Names[idx] != d2[idx] {
return false
}
}
return true
}
Loading

0 comments on commit c3e5c7b

Please sign in to comment.