Newer
Older
package mongo
import (
"fmt"
"github.com/gosexy/db"
"github.com/kr/pretty"
"time"
const wrapperName = "mongo"
const host = "127.0.0.1"
const socket = "/tmp/mongodb-27017.sock"
const username = "gouser"
const password = "gopass"
var settings = db.DataSource{
Database: dbname,
Host: host,
// https://bugs.launchpad.net/mgo/+bug/954436
//Socket: socket,
//User: username,
//Password: password,
}
// Structure for testing conversions.
type testValuesStruct struct {
Uint uint
Uint8 uint8
Uint16 uint16
Uint32 uint32
Uint64 uint64
Int int
Int8 int8
Int16 int16
Int32 int32
Int64 int64
Date time.Time
Time time.Duration
}
// Some test values.
var testValues = testValuesStruct{
1, 1, 1, 1, 1,
-1, -1, -1, -1, -1,
1.337, 1.337,
true,
"Hello world!",
time.Date(2012, 7, 28, 1, 2, 3, 0, time.Local),
// Outputs some information to stdout, useful for development.
func TestEnableDebug(t *testing.T) {
Debug = true
}
/*
// Trying to open an empty datasource, must fail.
func TestOpenFailed(t *testing.T) {
_, err := db.Open(wrapperName, db.DataSource{})
if err == nil {
t.Errorf("Could not open database.")
}
}
*/
// Truncates all collections/tables, one by one.
func TestTruncate(t *testing.T) {
sess, err := db.Open(wrapperName, settings)
for _, name := range collections {
col, _ := sess.Collection(name)
col.Truncate()
if err != nil {
t.Fatalf(err.Error())
}
if total != 0 {
t.Errorf("Could not truncate.")
}
}
// Appends maps and structs.
func TestAppend(t *testing.T) {
sess, err := db.Open(wrapperName, settings)
_, err = sess.Collection("doesnotexists")
if err == nil {
t.Fatalf("Collection should not exists.")
}
// To be inserted
names := []string{
"Juan",
"José",
"Pedro",
"María",
"Roberto",
"Manuel",
"Miguel",
// Append db.Item
people.Truncate()
for _, name := range names {
people.Append(db.Item{"name": name})
if total != len(names) {
t.Fatalf("Could not append all items.")
// Append map[string]string
people.Truncate()
for _, name := range names {
people.Append(map[string]string{"name": name})
if total != len(names) {
t.Fatalf("Could not append all items.")
}
// Append map[string]interface{}
people.Truncate()
for _, name := range names {
people.Append(map[string]interface{}{"name": name})
}
total, _ = people.Count()
if total != len(names) {
t.Fatalf("Could not append all items.")
}
// Append struct
people.Truncate()
for _, name := range names {
people.Append(struct{ Name string }{name})
}
total, _ = people.Count()
if total != len(names) {
t.Fatalf("Could not append all items.")
var err error
sess, err := db.Open(wrapperName, settings)
result := people.Find(db.Cond{"name": "José"})
if result["name"] != "José" {
t.Fatalf("Could not find a recently appended item.")
// Fetch into map slice.
dst := []map[string]string{}
err = people.FetchAll(&dst, db.Cond{"name": "José"})
if err != nil {
t.Fatalf(err.Error())
}
if len(dst) != 1 {
t.Fatalf("Could not find a recently appended item.")
}
if dst[0]["name"] != "José" {
t.Fatalf("Could not find a recently appended item.")
}
// Fetch into struct slice.
dst2 := []struct{ Name string }{}
err = people.FetchAll(&dst2, db.Cond{"name": "José"})
if len(dst2) != 1 {
t.Fatalf("Could not find a recently appended item.")
}
if dst2[0].Name != "José" {
t.Fatalf("Could not find a recently appended item.")
}
// Fetch into map.
dst3 := map[string]interface{}{}
err = people.Fetch(&dst3, db.Cond{"name": "José"})
if err != nil {
}
if dst3["name"] != "José" {
t.Fatalf("Could not find a recently appended item.")
}
// Fetch into struct.
dst4 := struct{ Name string }{}
err = people.Fetch(&dst4, db.Cond{"name": "José"})
if err != nil {
t.Fatalf(err.Error())
}
if dst4.Name != "José" {
t.Fatalf("Could not find a recently appended item.")
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
}
*/
// Tries to find and fetch rows.
func TestFind(t *testing.T) {
var err error
var res db.Result
sess, err := db.Open(wrapperName, settings)
if err != nil {
t.Fatalf(err.Error())
}
defer sess.Close()
people, _ := sess.Collection("people")
// Testing Find()
item, _ := people.Find(db.Cond{"name": "José"})
if item["name"] != "José" {
t.Fatalf("Could not find a recently appended item.")
}
// Fetch into map slice.
dst := []map[string]string{}
res, err = people.Query(db.Cond{"name": "José"})
if err != nil {
t.Fatalf(err.Error())
}
err = res.All(&dst)
if err != nil {
t.Fatalf(err.Error())
}
if len(dst) != 1 {
t.Fatalf("Could not find a recently appended item.")
}
if dst[0]["name"] != "José" {
t.Fatalf("Could not find a recently appended item.")
}
// Fetch into struct slice.
dst2 := []struct{ Name string }{}
res, err = people.Query(db.Cond{"name": "José"})
if err != nil {
t.Fatalf(err.Error())
}
err = res.All(&dst2)
if err != nil {
t.Fatalf(err.Error())
}
if len(dst2) != 1 {
t.Fatalf("Could not find a recently appended item.")
}
if dst2[0].Name != "José" {
t.Fatalf("Could not find a recently appended item.")
}
// Fetch into map.
dst3 := map[string]interface{}{}
res, err = people.Query(db.Cond{"name": "José"})
if err != nil {
t.Fatalf(err.Error())
}
err = res.One(&dst3)
if err != nil {
t.Fatalf(err.Error())
}
// Fetch into struct.
dst4 := struct{ Name string }{}
res, err = people.Query(db.Cond{"name": "José"})
if err != nil {
t.Fatalf(err.Error())
}
err = res.One(&dst4)
if err != nil {
t.Fatalf(err.Error())
}
if dst4.Name != "José" {
t.Fatalf("Could not find a recently appended item.")
}
// Makes a query and stores the result
res, err = people.Query(nil)
if err != nil {
t.Fatalf(err.Error())
}
dst5 := struct{ Name string }{}
found := false
for true {
err = res.Next(&dst5)
if err != nil {
break
}
if dst5.Name == "José" {
found = true
}
}
res.Close()
if found == false {
t.Fatalf("José was not found.")
}
// Tries to delete rows.
func TestDelete(t *testing.T) {
sess, err := db.Open(wrapperName, settings)
people, _ := sess.Collection("people")
people.Remove(db.Cond{"name": "Juan"})
if len(result) > 0 {
t.Fatalf("Could not remove a recently appended item.")
}
}
// Tries to update rows.
func TestUpdate(t *testing.T) {
sess, err := db.Open(wrapperName, settings)
if err != nil {
}
defer sess.Close()
people, _ := sess.Collection("people")
people.Update(db.Cond{"name": "José"}, db.Set{"name": "Joseph"})
result, _ := people.Find(db.Cond{"name": "Joseph"})
if len(result) == 0 {
t.Fatalf("Could not update a recently appended item.")
// Tries to add test data and relations.
sess, err := db.Open(wrapperName, settings)
people, _ := sess.Collection("people")
places, _ := sess.Collection("places")
children, _ := sess.Collection("children")
visits, _ := sess.Collection("visits")
values := []string{"Alaska", "Nebraska", "Alaska", "Acapulco", "Rome", "Singapore", "Alabama", "Cancún"}
for i, value := range values {
places.Append(db.Item{
"name": value,
db.Fields{"_id", "name"},
db.Sort{"name": "ASC", "_id": -1},
for _, person := range results {
// Has 5 children.
for j := 0; j < 5; j++ {
children.Append(db.Item{
"name": fmt.Sprintf("%s's child %d", person["name"], j+1),
})
}
// Lives in
people.Update(
db.Set{"place_code_id": int(rand.Float32() * float32(len(results)))},
)
// Has visited
"code_id": int(rand.Float32() * float32(len(results))),
visits.Append(db.Item{
"place_id": place["_id"],
"person_id": person["_id"],
})
}
}
}
// Tests relations between collections.
sess, err := db.Open(wrapperName, settings)
people, _ := sess.Collection("people")
db.Relate{
"lives_in": db.On{
},
},
db.RelateAll{
"has_children": db.On{
},
"has_visited": db.On{
db.Relate{
"place": db.On{
},
},
},
},
)
fmt.Printf("relations (1) %# v\n", pretty.Formatter(results))
// Tests relations between collections using structs.
func TestRelationStruct(t *testing.T) {
var err error
sess, err := db.Open(wrapperName, settings)
if err != nil {
t.Errorf(err.Error())
}
people := sess.ExistentCollection("people")
LivesIn struct {
Name string
}
HasChildren []struct {
Name string
}
HasVisited []struct {
Place struct {
Name string
}
}
}{}
db.Relate{
"LivesIn": db.On{
sess.ExistentCollection("places"),
db.Cond{"code_id": "{PlaceCodeId}"},
},
},
db.RelateAll{
"HasChildren": db.On{
sess.ExistentCollection("children"),
db.Cond{"parent_id": "{Id}"},
},
"HasVisited": db.On{
sess.ExistentCollection("visits"),
db.Cond{"person_id": "{Id}"},
db.Relate{
"Place": db.On{
sess.ExistentCollection("places"),
if err != nil {
t.Fatalf(err.Error())
}
err = res.All(&results)
if err != nil {
t.Fatalf(err.Error())
}
fmt.Printf("relations (2) %# v\n", pretty.Formatter(results))
}
// Tests datatype conversions.
func TestDataTypes(t *testing.T) {
sess, err := db.Open(wrapperName, settings)
if err != nil {
}
dataTypes.Truncate()
ids, err := dataTypes.Append(testValues)
if err != nil {
t.Fatalf(err.Error())
found, err := dataTypes.Count(db.Cond{"_id": db.Id(ids[0])})
if err != nil {
t.Fatalf(err.Error())
}
if found == 0 {
t.Errorf("Expecting an item.")
}
// Getting and reinserting (a db.Item).
_, err = dataTypes.Append(item)
if err == nil {
t.Fatalf("Expecting duplicated-key error.")
}
_, err = dataTypes.Append(item)
if err != nil {
t.Fatalf(err.Error())
}
// Testing struct
sresults := []testValuesStruct{}
res, err = dataTypes.Query()
if err != nil {
t.Fatalf(err.Error())
}
err = res.All(&sresults)
if err != nil {
t.Fatalf(err.Error())
}
// Testing struct equality
for _, item := range sresults {
if reflect.DeepEqual(item, testValues) == false {
t.Errorf("Struct is different.")
}
}
for _, item := range results {
for key, _ := range item {
switch key {
// Signed integers.
case
"_int",
"_int8",
"_int16",
"_int32",
"_int64":
if to.Int64(item[key]) != testValues.Int64 {
t.Fatalf("Wrong datatype %v.", key)
}
// Unsigned integers.
case
"_uint",
"_uint8",
"_uint16",
"_uint32",
"_uint64":
if to.Uint64(item[key]) != testValues.Uint64 {
t.Fatalf("Wrong datatype %v.", key)
}
// Floating point.
case "_float32":
case "_float64":
if to.Float64(item[key]) != testValues.Float64 {
t.Fatalf("Wrong datatype %v.", key)
}
// Boolean
case "_bool":
if to.Bool(item[key]) != testValues.Bool {
t.Fatalf("Wrong datatype %v.", key)
}
// String
case "_string":
if to.String(item[key]) != testValues.String {
t.Fatalf("Wrong datatype %v.", key)
}
// Date
case "_date":
if to.Time(item[key]).Equal(testValues.Date) == false {
t.Fatalf("Wrong datatype %v.", key)
}
}
}
}
}