func (self *sqlTests) Run(runner SqlTestRunner, T *testing.T) (rtn bool) { // Shortcut; stop if we're not in testing mode if !RUN_DRIVER_TESTS { return true } var current = "None" defer func() { var e = recover() if e != nil { n.Log("Failed while running test \"%s\": %s", current, e) n.Log("%s", debug.Stack()) rtn = false } }() var tt = reflect.TypeOf(self) var tv = reflect.ValueOf(self) var mc = tt.NumMethod() for i := 0; i < mc; i++ { var test_method = tt.Method(i) var test_name = test_method.Name if strings.HasPrefix(test_name, "Test_") { current = test_name var test_method_instance = tv.Method(i) var test_method_args = []reflect.Value{reflect.ValueOf(runner), reflect.ValueOf(T)} test_method_instance.Call(test_method_args) } } return true }
// Get the next row, return nil when none left func (self *Rowset) Next() map[string]interface{} { var rtn map[string]interface{} = nil if self.Rows != nil { var cols, cerr = self.Rows.Columns() if cerr != nil { n.Log("Failed to query column list on db rows: %s", cerr.Error()) } else if len(cols) == 0 { n.Log("Failed to query column list on db rows: No columns in result set") } else { if self.Rows.Next() { rtn = Scan(self.Rows) self.Worker.ApplySchema(self, rtn) } } return rtn } // No rows? Ok! Return a value var tmp = self.Values.Front() if tmp != nil { self.Values.Remove(tmp) rtn = tmp.Value.(map[string]interface{}) self.Worker.ApplySchema(self, rtn) } return rtn }
// Return an int64 url value func (self *url) Int64(id string) int64 { var rtn int64 = 0 var raw, found = self.c.vars[id] if found { var _, err = fmt.Sscanf(raw, "%d", &rtn) if err != nil { n.Log("Failed reading incoming url param: %s is not int64", raw[0]) n.Log(err.Error()) } } return rtn }
// Return an int64 form value or 0 func (self *form) Int64(id string) int64 { var rtn int64 = 0 self.c.Request.ParseForm() var raw, found = self.c.Request.Form[id] if found { var _, err = fmt.Sscanf(raw[0], "%d", &rtn) if err != nil { n.Log("Failed reading incoming form param: %s is not int64", raw[0]) n.Log(err.Error()) } } return rtn }
func (self *sqlTestRunner) Setup(T *testing.T) (test.Assert, nsql.Sql) { var assert = test.New.Assert(T) var instance = New.Sql(TEST_ROOT_URI) var _, err = instance.Raw("CREATE DATABASE testing") if err != nil { // n.Log("Failed to create database: %s", err.Error()) } instance.Close() instance = New.Sql(TEST_URI) instance.Raw("DROP TABLE IF EXISTS " + self.Table()) _, err = instance.Raw("CREATE TABLE " + self.Table() + ` ( id SERIAL, string_value VARCHAR(100), int_value INT, long_value INT, double_value DOUBLE PRECISION, bool_value BOOL, datetime_value TIMESTAMP, text_value TEXT, PRIMARY KEY (id) )`) if err != nil { n.Log("Failed to create table: %s", err.Error()) } return assert, instance }
// Arbitrary limit; max of 100 index or we're doing something weird. func (self *index) Delete(id int64) { var items, err = self.db.All("worker.Index", 0, 100) if err != nil { n.Log("Failed to remove index: %s", err.Error()) } for _, v := range items { var index = v.(*model.Index) var tmp = make([]int64, index.Size, index.Size) var update = false var offset = 0 for j := 0; j < index.Size; j++ { if index.Ids[j] != id { tmp[offset] = index.Ids[j] offset++ } else { update = true } } if update { index.Ids = tmp self.set(index) } } }
// Scan values from the database func scan(cols []string, rows *sql.Rows) map[string]interface{} { var rtn = map[string]interface{}{} // Create scanner array var values []interface{} var generic = reflect.TypeOf(values).Elem() for i := 0; i < len(cols); i++ { values = append(values, reflect.New(generic).Interface()) } // Scan! var err = rows.Scan(values...) if err != nil { n.Log("Driver failed to scan values: %s", err.Error()) return nil } // Convert into native types for i := 0; i < len(cols); i++ { var raw_value = *(values[i].(*interface{})) var raw_type = reflect.TypeOf(raw_value) switch { case raw_type == reflect.TypeOf(int64(0)): rtn[cols[i]] = raw_value.(int64) } } return rtn }
// Init stuff func (self *recordSet) Init() error { var err = os.MkdirAll(self.RecordsPath(), 0755) if err != nil { n.Log("Error creating record set: %s", err) } return err }
func (self *recordSet) Keys(offset int, count int) []int64 { _ = self.Init() var sofar = 0 var hits = 0 var all = make([]int64, count) filepath.Walk(self.RecordsPath(), func(path string, info os.FileInfo, err error) error { if err != nil { n.Log("Error walking record set: %s", err) } if info != nil { if !info.IsDir() { if strings.Count(info.Name(), ".") == 1 { if sofar >= offset { var _, file = filepath.Split(path) var key int64 var _, err = fmt.Sscanf(file, "R%d.json", &key) if err == nil && hits < count { all[hits] = key hits++ } } sofar++ } } } return nil }) all = all[:hits] return all }
// The sql api isn't very friendly; this function reads a single row from // the database and converts it into native driver types. // // You may want to extend this to provide complex type mapping like // DATETIME for sqlite, etc. // // Pass in a rows() that already has had next called on it; this function // does not invoke Next(). // // If unable to process the given rowset, the return is nil. func Scan(rows *sql.Rows) map[string]interface{} { var rtn map[string]interface{} = nil if rows != nil { var cols, cerr = rows.Columns() if cerr != nil { n.Log("Failed to query column list on db rows: %s", cerr.Error()) } else if len(cols) == 0 { n.Log("Failed to query column list on db rows: No columns in result set") } else { rtn = scan(cols, rows) } } else { n.Log("Invalid row set: nil") } return rtn }
// Render a template with a layout file. // Use {{define ""}} .. {{end}} in the template. func (self *ControllerBase) View(templates []string, data map[string]interface{}, w http.ResponseWriter) { self.templates = nil for _, v := range templates { var err = self.loadTemplate(v, v) if err != nil { return } } var ee = self.templates.Execute(w, data) if ee != nil { // TODO: Controller common error handling. n.Log("\nError: failed executing templates: %s", templates[0]) n.Log("%s", ee.Error()) } }
// Return path for a records func (self *recordSet) RecordsPath() string { var root, err = filepath.Abs("data") if err != nil { n.Log("Failed to resolve base path: %s", err) } var rtn = filepath.Join(root, self.Type.Name()) return rtn }
func newSql(uri string) nsql.Sql { var db, err = gsql.Open("mysql", uri) if err != nil { n.Log("Failed to open database connection: %s", err.Error()) return nil } return &sql{ db: db, factory: newSqlFactory(), } }
func (self *configBase) Validate() bool { var failed = false for k, _ := range self.requires { if !self.Has(k) { var _, found = self.defaults[k] if !found { n.Log("Missing config key: %s", k) failed = true } } } return !failed }
func newStore(drivers ...interface{} /* Driver */) (out Store) { defer func() { var f = recover() if f != nil { n.Log("Failed to create Store: %s", f) out = nil } }() // Try resolving a driver if one isn't provided var raw = n.Resolve(rf.TypeOf((*Driver)(nil)), 0, drivers...) if raw == nil { n.Log("Failed to create Store: No binding for Driver found") return nil } var rtn = &store{ types: make(map[string]rf.Type), driver: raw.(Driver), } return rtn }
// Invoke action on controller func Resolve(controller string, action string, vars map[string]string, w http.ResponseWriter, r *http.Request) { var binding, found = actions[controller] if found { var handler, found = binding.Map[action] if found { var c = web.New.Context(w, r, vars) var v = rf.ValueOf(handler) var args = []rf.Value{rf.ValueOf(binding.Instance), rf.ValueOf(c)} v.Call(args) return } } fmt.Fprintf(w, "Not found") n.Log(": No match for %s::%s", controller, action) }
func (self *recordSet) Count() int { _ = self.Init() var count = 0 filepath.Walk(self.RecordsPath(), func(path string, info os.FileInfo, err error) error { if err != nil { n.Log("Error walking record set: %s", err) } if info != nil { if !info.IsDir() { if strings.Count(info.Name(), ".") == 1 { count++ } } } return nil }) return count }
func (self *recordSet) Key() int64 { var rtn int64 = 0 var found = false var tries = 0 for !found { var key = rand.Int63() if self.ValidKey(key) { rtn = key found = true } else { tries++ } if tries > 100 { n.Log("Unable to find unused key") break } } return rtn }
func newIndex(args ...interface{} /* Store */) Index { var raw = n.Resolve(rf.TypeOf((*data.Store)(nil)), 0, args...) if raw == nil { n.Log("Failed to create index service: No Store binding") return nil } var rtn = &index{ db: raw.(data.Store), } // Register types we're going to have to work with. { var t model.Index rtn.db.Register(rf.TypeOf(&t), "worker.Index") } return rtn }
func newFragments(args ...interface{} /* Store */) Fragments { var raw = n.Resolve(rf.TypeOf((*data.Store)(nil)), 0, args...) if raw == nil { n.Log("Failed to create fragment service: No Store binding") return nil } var rtn = &fragments{ db: raw.(data.Store), index: newIndex(), } // Register types we're going to have to work with. { var t model.Tags rtn.db.Register(rf.TypeOf(&t), "worker.Tags") } { var t model.Stars rtn.db.Register(rf.TypeOf(&t), "worker.Stars") } { var t model.TagCloud rtn.db.Register(rf.TypeOf(&t), "worker.TagCloud") } { var t model.Fragment rtn.db.Register(rf.TypeOf(&t), "worker.Fragment") } { var t model.StarIndex rtn.db.Register(rf.TypeOf(&t), "worker.StarIndex") } { var t model.Index rtn.db.Register(rf.TypeOf(&t), "worker.Index") } return rtn }
func (self *sqlTestRunner) Setup(T *testing.T) (test.Assert, nsql.Sql) { var assert = test.New.Assert(T) var instance = New.Sql(TEST_URI) instance.Raw("DROP TABLE IF EXISTS " + self.Table()) _, err := instance.Raw("CREATE TABLE " + self.Table() + ` ( id INTEGER PRIMARY KEY, string_value VARCHAR(100), int_value INT, long_value INT, double_value REAL, bool_value INT, datetime_value INTEGER, text_value TEXT )`) if err != nil { n.Log("Failed to create table: %s", err.Error()) } return assert, instance }
// Get or create record func (self *index) get(key string, size int) *model.Index { var index *model.Index var set, ierr = self.db.Filter("worker.Index", 0, 1, []string{}, func(record interface{}) bool { var data = record.(*model.Index) return data.Name == key }) if ierr != nil { n.Log("Index error: %s", ierr.Error()) } if len(set) == 0 { index = &model.Index{ Name: key, Size: size, Ids: make([]int64, size, size), } } else { for k, v := range set { index = v.(*model.Index) index.Id = k break } } return index }
// Load a template and attach the given name to it. func (self *ControllerBase) loadTemplate(path string, id string) error { var template_path = _path.Join(self.templatePath, path) var raw, re = ioutil.ReadFile(template_path) if re != nil { // TODO: Controller common error handling. n.Log("\nError: failed to load template: %s", path) n.Log("%s", re.Error()) return n.Fail(1, "Invalid template") } var t *template.Template = self.templates if t == nil { var t, te = template.New(id).Parse(string(raw)) if te != nil { // TODO: Controller common error handling. n.Log("\nError: invalid template: %s", path) n.Log("%s", te.Error()) return n.Fail(1, "Invalid template") } else { self.templates = t } } else { var _, te = self.templates.New(id).Parse(string(raw)) if te != nil { // TODO: Controller common error handling. n.Log("\nError: invalid template: %s", path) n.Log("%s", te.Error()) return n.Fail(1, "Invalid template") } } // DEBUG // n.Log("Registered template id: %s -> %s", id, template_path) return nil }
// Apply the schema and convert types to schema types func (self *schema) ApplySchema(rows *utils.Rowset, rtn map[string]interface{}) error { n.Log("Applying schema") return nil }