mirror of
https://github.com/chaisql/chai.git
synced 2025-10-07 00:23:17 +08:00
Test FieldBuffer
This commit is contained in:
11
doc.go
11
doc.go
@@ -4,7 +4,7 @@ Genji supports various engines that write data on-disk, like BoltDB or Badger, a
|
||||
|
||||
It provides a complete framework with multiple APIs that can be used to manipulate, manage, read and write data.
|
||||
|
||||
Genji tables are schemaless and can be manipulated using the table package, which is a low-level functional API
|
||||
Genji tables are schemaless and can be manipulated using the table package, which is a low-level streaming API
|
||||
or by using the query package which is a powerful SQL like query engine.
|
||||
|
||||
Tables can be mapped to Go structures without reflection: Genji relies on code generation to translate data to and from Go structures.
|
||||
@@ -49,8 +49,7 @@ Field, Record, and Table
|
||||
Genji defines its own semantic to describe data.
|
||||
Data stored in Genji being schemaless, the usual SQL triplet "column", "row", "table" wasn't chosen
|
||||
for the vocabulary of this library. Also, Genji is a database written in Go for Go, and its primary goal
|
||||
is to map structures and maps to tables, though it's not limited to that. The semantics were to be as close as possible
|
||||
to what people are used to in this language.
|
||||
is to map structures and maps to tables, though it's not limited to that.
|
||||
|
||||
That's why the triplet "field", "record" and "table" was chosen.
|
||||
|
||||
@@ -116,10 +115,8 @@ The genji command line can be used as follows to generate the code:
|
||||
|
||||
This will generate a file named user.genji.go containing the following types and methods
|
||||
|
||||
// user.genji.go
|
||||
|
||||
// The User type gets new methods that implement some Genji interfaces.
|
||||
func (u *User) Field(name string) (field.Field, error) {}
|
||||
func (u *User) GetField(name string) (field.Field, error) {}
|
||||
func (u *User) Iterate(fn func(field.Field) error) error {}
|
||||
func (u *User) ScanRecord(rec record.Record) error {}
|
||||
func (u *User) PrimaryKey() ([]byte, error) {}
|
||||
@@ -133,5 +130,7 @@ This will generate a file named user.genji.go containing the following types and
|
||||
}
|
||||
func NewUserFields() UserFields {}
|
||||
|
||||
The User type now implements all the interfaces needed to interact correctly with the database APIs.
|
||||
See the examples in this page to see how it can be used.
|
||||
*/
|
||||
package genji
|
||||
|
@@ -25,6 +25,11 @@ type Scanner interface {
|
||||
// FieldBuffer is slice of fields which implements the Record interface.
|
||||
type FieldBuffer []field.Field
|
||||
|
||||
// NewFieldBuffer creates a FieldBuffer with the given fields.
|
||||
func NewFieldBuffer(fields ...field.Field) FieldBuffer {
|
||||
return FieldBuffer(fields)
|
||||
}
|
||||
|
||||
// Add a field to the buffer.
|
||||
func (fb *FieldBuffer) Add(f field.Field) {
|
||||
*fb = append(*fb, f)
|
||||
@@ -50,10 +55,11 @@ func (fb FieldBuffer) GetField(name string) (field.Field, error) {
|
||||
}
|
||||
|
||||
// Set replaces a field if it already exists or creates one if not.
|
||||
func (fb FieldBuffer) Set(f field.Field) {
|
||||
for i := range fb {
|
||||
if fb[i].Name == f.Name {
|
||||
fb[i] = f
|
||||
func (fb *FieldBuffer) Set(f field.Field) {
|
||||
s := *fb
|
||||
for i := range s {
|
||||
if s[i].Name == f.Name {
|
||||
(*fb)[i] = f
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -87,7 +93,7 @@ func (fb *FieldBuffer) Delete(name string) error {
|
||||
return fmt.Errorf("field %q not found", name)
|
||||
}
|
||||
|
||||
// Replace the field with the given by f.
|
||||
// Replace the field with the given name by f.
|
||||
func (fb *FieldBuffer) Replace(name string, f field.Field) error {
|
||||
s := *fb
|
||||
for i := range s {
|
||||
@@ -98,7 +104,7 @@ func (fb *FieldBuffer) Replace(name string, f field.Field) error {
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("field %q not found", name)
|
||||
return fmt.Errorf("field %q not found", f.Name)
|
||||
}
|
||||
|
||||
// DumpRecord is helper that dumps the content of a record into the given writer.
|
||||
|
@@ -11,20 +11,120 @@ import (
|
||||
var _ record.Record = new(record.FieldBuffer)
|
||||
|
||||
func TestFieldBuffer(t *testing.T) {
|
||||
b := record.FieldBuffer([]field.Field{
|
||||
buf := record.NewFieldBuffer(
|
||||
field.NewInt64("a", 10),
|
||||
field.NewString("b", "hello"),
|
||||
})
|
||||
)
|
||||
|
||||
t.Run("Iterate", func(t *testing.T) {
|
||||
var i int
|
||||
err := b.Iterate(func(f field.Field) error {
|
||||
err := buf.Iterate(func(f field.Field) error {
|
||||
require.NotEmpty(t, f)
|
||||
require.Equal(t, f, b[i])
|
||||
require.Equal(t, f, buf[i])
|
||||
i++
|
||||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 2, i)
|
||||
})
|
||||
|
||||
t.Run("Add", func(t *testing.T) {
|
||||
buf := record.NewFieldBuffer(
|
||||
field.NewInt64("a", 10),
|
||||
field.NewString("b", "hello"),
|
||||
)
|
||||
|
||||
c := field.NewBool("c", true)
|
||||
buf.Add(c)
|
||||
require.Len(t, buf, 3)
|
||||
require.Equal(t, buf[2], c)
|
||||
})
|
||||
|
||||
t.Run("ScanRecord", func(t *testing.T) {
|
||||
buf1 := record.NewFieldBuffer(
|
||||
field.NewInt64("a", 10),
|
||||
field.NewString("b", "hello"),
|
||||
)
|
||||
|
||||
buf2 := record.NewFieldBuffer(
|
||||
field.NewInt64("a", 20),
|
||||
field.NewString("b", "bye"),
|
||||
field.NewBool("c", true),
|
||||
)
|
||||
|
||||
err := buf1.ScanRecord(buf2)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, record.NewFieldBuffer(
|
||||
field.NewInt64("a", 10),
|
||||
field.NewString("b", "hello"),
|
||||
field.NewInt64("a", 20),
|
||||
field.NewString("b", "bye"),
|
||||
field.NewBool("c", true),
|
||||
), buf1)
|
||||
})
|
||||
|
||||
t.Run("GetField", func(t *testing.T) {
|
||||
f, err := buf.GetField("a")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, field.NewInt64("a", 10), f)
|
||||
|
||||
f, err = buf.GetField("not existing")
|
||||
require.Error(t, err)
|
||||
require.Zero(t, f)
|
||||
})
|
||||
|
||||
t.Run("Set", func(t *testing.T) {
|
||||
buf1 := record.NewFieldBuffer(
|
||||
field.NewInt64("a", 10),
|
||||
field.NewString("b", "hello"),
|
||||
)
|
||||
|
||||
buf1.Set(field.NewInt64("a", 11))
|
||||
require.Equal(t, field.NewInt64("a", 11), buf1[0])
|
||||
|
||||
buf1.Set(field.NewInt64("c", 12))
|
||||
require.Len(t, buf1, 3)
|
||||
require.Equal(t, field.NewInt64("c", 12), buf1[2])
|
||||
})
|
||||
|
||||
t.Run("Delete", func(t *testing.T) {
|
||||
buf1 := record.NewFieldBuffer(
|
||||
field.NewInt64("a", 10),
|
||||
field.NewString("b", "hello"),
|
||||
)
|
||||
|
||||
err := buf1.Delete("a")
|
||||
require.NoError(t, err)
|
||||
require.Len(t, buf1, 1)
|
||||
require.Equal(t, record.NewFieldBuffer(
|
||||
field.NewString("b", "hello"),
|
||||
), buf1)
|
||||
|
||||
err = buf1.Delete("b")
|
||||
require.NoError(t, err)
|
||||
require.Len(t, buf1, 0)
|
||||
|
||||
err = buf1.Delete("b")
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("Replace", func(t *testing.T) {
|
||||
buf1 := record.NewFieldBuffer(
|
||||
field.NewInt64("a", 10),
|
||||
field.NewString("b", "hello"),
|
||||
)
|
||||
|
||||
err := buf1.Replace("a", field.NewInt64("c", 10))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, record.NewFieldBuffer(
|
||||
field.NewInt64("c", 10),
|
||||
field.NewString("b", "hello"),
|
||||
), buf1)
|
||||
|
||||
err = buf1.Replace("d", field.NewInt64("c", 11))
|
||||
require.Error(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestNewFromMap(t *testing.T) {
|
||||
|
@@ -1,9 +1,8 @@
|
||||
package genji_test
|
||||
package table_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -12,32 +11,12 @@ import (
|
||||
"github.com/asdine/genji/field"
|
||||
"github.com/asdine/genji/record"
|
||||
"github.com/asdine/genji/table"
|
||||
"github.com/asdine/genji/table/tabletest"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func tableBuilder(t testing.TB) func() (table.Table, func()) {
|
||||
return func() (table.Table, func()) {
|
||||
db, err := genji.New(memory.NewEngine())
|
||||
require.NoError(t, err)
|
||||
var _ table.Reader = (*genji.Table)(nil)
|
||||
|
||||
tx, err := db.Begin(true)
|
||||
require.NoError(t, err)
|
||||
|
||||
tb, err := tx.CreateTable("test")
|
||||
require.NoError(t, err)
|
||||
|
||||
return tb, func() {
|
||||
tx.Rollback()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTable(t *testing.T) {
|
||||
tabletest.TestSuite(t, tableBuilder(t))
|
||||
}
|
||||
|
||||
func TestTableString(t *testing.T) {
|
||||
func TestDump(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
expected string
|
||||
@@ -79,30 +58,3 @@ name(String): "John 2", age(Int): 12
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func ExampleDB() {
|
||||
ng := memory.NewEngine()
|
||||
db, err := genji.New(ng)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
err = db.Update(func(tx *genji.Tx) error {
|
||||
t, err := tx.CreateTable("Table")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r := record.FieldBuffer{
|
||||
field.NewString("Name", "foo"),
|
||||
field.NewInt("Age", 10),
|
||||
}
|
||||
|
||||
_, err = t.Insert(r)
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
62
table_test.go
Normal file
62
table_test.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package genji_test
|
||||
|
||||
import (
|
||||
"log"
|
||||
"testing"
|
||||
|
||||
"github.com/asdine/genji"
|
||||
"github.com/asdine/genji/engine/memory"
|
||||
"github.com/asdine/genji/field"
|
||||
"github.com/asdine/genji/record"
|
||||
"github.com/asdine/genji/table"
|
||||
"github.com/asdine/genji/table/tabletest"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func tableBuilder(t testing.TB) func() (table.Table, func()) {
|
||||
return func() (table.Table, func()) {
|
||||
db, err := genji.New(memory.NewEngine())
|
||||
require.NoError(t, err)
|
||||
|
||||
tx, err := db.Begin(true)
|
||||
require.NoError(t, err)
|
||||
|
||||
tb, err := tx.CreateTable("test")
|
||||
require.NoError(t, err)
|
||||
|
||||
return tb, func() {
|
||||
tx.Rollback()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTable(t *testing.T) {
|
||||
tabletest.TestSuite(t, tableBuilder(t))
|
||||
}
|
||||
|
||||
func ExampleDB() {
|
||||
ng := memory.NewEngine()
|
||||
db, err := genji.New(ng)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
err = db.Update(func(tx *genji.Tx) error {
|
||||
t, err := tx.CreateTable("Table")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r := record.FieldBuffer{
|
||||
field.NewString("Name", "foo"),
|
||||
field.NewInt("Age", 10),
|
||||
}
|
||||
|
||||
_, err = t.Insert(r)
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user