-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(store): fix inf.Dec and big.Int compare
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
Showing
29 changed files
with
2,257 additions
and
142 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
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 | ||
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
test.Rows = nil | ||
oracle.Rows = nil | ||
return 1 | ||
} | ||
return 0 | ||
} | ||
equalRowsCount := easyDeleteEqualRows(test, oracle) | ||
if test.LenRows() != 0 { | ||
equalRowsCount += usualDeleteEqualRows(test, oracle) | ||
} | ||
return equalRowsCount | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
Oops, something went wrong.