From dabc9183641eef46fcc452340a18b75f598cc68f Mon Sep 17 00:00:00 2001 From: Ken Date: Sun, 27 Aug 2023 19:39:31 -0400 Subject: [PATCH] added addition functionality --- db/about.go | 91 +++++++++++++++ db/about_test.go | 219 ++++++++++++++++++++++++++++++++++++ db/coverage.out | 60 ++++++++++ db/db.go | 15 +++ db/model.go | 18 +++ db/queries.go | 31 ++++- db/rules.go | 91 +++++++++++++++ db/rules_test.go | 219 ++++++++++++++++++++++++++++++++++++ db/tos.go | 91 +++++++++++++++ db/tos_test.go | 219 ++++++++++++++++++++++++++++++++++++ handlers/handler.go | 10 ++ scripts/goMicroBlog.mwb | Bin 10305 -> 11455 bytes scripts/goMicroBlog.mwb.bak | Bin 10305 -> 11474 bytes scripts/goMicroBlog.sql | 32 +++++- 14 files changed, 1094 insertions(+), 2 deletions(-) create mode 100644 db/about.go create mode 100644 db/about_test.go create mode 100644 db/rules.go create mode 100644 db/rules_test.go create mode 100644 db/tos.go create mode 100644 db/tos_test.go diff --git a/db/about.go b/db/about.go new file mode 100644 index 0000000..9897b2d --- /dev/null +++ b/db/about.go @@ -0,0 +1,91 @@ +package db + +import ( + "strconv" +) + +/* + Copyright (C) 2023 Ulbora Labs LLC. (www.ulboralabs.com) + All rights reserved. + + Copyright (C) 2023 Ken Williamson + All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +*/ + +// AddAbout AddAbout +func (d *MyBlogDB) AddAbout(ab *About) (bool, int64) { + var suc bool + var id int64 + if !d.testConnection() { + d.DB.Connect() + } + if ab != nil { + var a []any + a = append(a, ab.Content) + suc, id = d.DB.Insert(insertAbout, a...) + d.Log.Debug("suc in add config", suc) + d.Log.Debug("id in add config", id) + } + return suc, id +} + +// UpdateAbout UpdateAbout +func (d *MyBlogDB) UpdateAbout(ab *About) bool { + var suc bool + if !d.testConnection() { + d.DB.Connect() + } + if ab != nil { + var a []any + a = append(a, ab.Content, ab.ID) + suc = d.DB.Update(updateAbout, a...) + d.Log.Debug("suc in update About", suc) + } + return suc +} + +// GetAbout GetAbout +func (d *MyBlogDB) GetAbout() *[]About { + if !d.testConnection() { + d.DB.Connect() + } + var rtn = []About{} + var a []any + a = append(a) + rows := d.DB.GetList(selectAbout, a...) + if rows != nil && len(rows.Rows) != 0 { + foundRows := rows.Rows + for r := range foundRows { + foundRow := foundRows[r] + rowContent := d.parseAboutRow(&foundRow) + rtn = append(rtn, *rowContent) + } + } + return &rtn +} + +func (d *MyBlogDB) parseAboutRow(foundRow *[]string) *About { + var rtn About + d.Log.Debug("foundRow in Tos", *foundRow) + if len(*foundRow) > 0 { + id, err := strconv.ParseInt((*foundRow)[0], 10, 64) + d.Log.Debug("id err in get About", err) + if err == nil { + rtn.ID = id + rtn.Content = (*foundRow)[1] + } + } + return &rtn +} diff --git a/db/about_test.go b/db/about_test.go new file mode 100644 index 0000000..1de755b --- /dev/null +++ b/db/about_test.go @@ -0,0 +1,219 @@ +package db + +import ( + "reflect" + "testing" + + lg "github.com/GolangToolKits/go-level-logger" + gdb "github.com/GolangToolKits/go-mysql" +) + +func TestMyBlogDB_AddAbout(t *testing.T) { + + // db := gdb.MyDB{ + // Host: "localhost:3306", + // User: "admin", + // Password: "admin", + // Database: "go_micro_blog", + // } + + db := gdb.MyDBMock{ + Host: "localhost:3306", + User: "admin", + Password: "admin", + Database: "go_micro_blog", + } + db.MockTestRow = &gdb.DbRow{ + //Row: []string{"0"}, + Row: []string{}, + } + db.MockConnectSuccess = true + db.MockInsertID1 = 1 + db.MockInsertSuccess1 = true + + var l lg.Logger + log := l.New() + log.SetLogLevel(lg.AllLevel) + + type fields struct { + DB gdb.Database + Log lg.Log + } + type args struct { + r *About + } + tests := []struct { + name string + fields fields + args args + want bool + want1 int64 + }{ + // TODO: Add test cases. + { + name: "test 1", + fields: fields{ + DB: db.New(), + Log: log, + }, + args: args{ + r: &About{ + Content: "test About content", + }, + }, + want: true, + want1: 1, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + d := &MyBlogDB{ + DB: tt.fields.DB, + Log: tt.fields.Log, + } + d.DB.Connect() + got, got1 := d.AddAbout(tt.args.r) + if got != tt.want { + t.Errorf("MyBlogDB.AddAbout() got = %v, want %v", got, tt.want) + } + if got1 != tt.want1 { + t.Errorf("MyBlogDB.AddAbout() got1 = %v, want %v", got1, tt.want1) + } + }) + } +} + +func TestMyBlogDB_UpdateAbout(t *testing.T) { + + // db := gdb.MyDB{ + // Host: "localhost:3306", + // User: "admin", + // Password: "admin", + // Database: "go_micro_blog", + // } + + db := gdb.MyDBMock{ + Host: "localhost:3306", + User: "admin", + Password: "admin", + Database: "go_micro_blog", + } + db.MockTestRow = &gdb.DbRow{ + //Row: []string{"0"}, + Row: []string{}, + } + db.MockConnectSuccess = true + db.MockUpdateSuccess1 = true + + var l lg.Logger + log := l.New() + log.SetLogLevel(lg.AllLevel) + + type fields struct { + DB gdb.Database + Log lg.Log + } + type args struct { + r *About + } + tests := []struct { + name string + fields fields + args args + want bool + }{ + // TODO: Add test cases. + { + name: "test 1", + fields: fields{ + DB: db.New(), + Log: log, + }, + args: args{ + r: &About{ + ID: 1, + Content: "test about content 1", + }, + }, + want: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + d := &MyBlogDB{ + DB: tt.fields.DB, + Log: tt.fields.Log, + } + d.DB.Connect() + if got := d.UpdateAbout(tt.args.r); got != tt.want { + t.Errorf("MyBlogDB.UpdateAbout() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestMyBlogDB_GetAbout(t *testing.T) { + // db := gdb.MyDB{ + // Host: "localhost:3306", + // User: "admin", + // Password: "admin", + // Database: "go_micro_blog", + // } + + db := gdb.MyDBMock{ + Host: "localhost:3306", + User: "admin", + Password: "admin", + Database: "go_micro_blog", + } + db.MockTestRow = &gdb.DbRow{ + //Row: []string{"0"}, + Row: []string{}, + } + + db.MockRows1 = &gdb.DbRows{ + Rows: [][]string{ + {"1", "test about content 1"}, + //{"2", "test content 3"}, + }, + } + + var l lg.Logger + log := l.New() + log.SetLogLevel(lg.AllLevel) + + type fields struct { + DB gdb.Database + Log lg.Log + } + tests := []struct { + name string + fields fields + want *[]About + }{ + // TODO: Add test cases. + { + name: "test 1", + fields: fields{ + DB: db.New(), + Log: log, + }, + want: &[]About{ + {1, "test about content 1"}, + // {3, "test Content 3"}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + d := &MyBlogDB{ + DB: tt.fields.DB, + Log: tt.fields.Log, + } + d.DB.Connect() + if got := d.GetAbout(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("MyBlogDB.GetAbout() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/db/coverage.out b/db/coverage.out index 594c299..1df1f54 100644 --- a/db/coverage.out +++ b/db/coverage.out @@ -1,4 +1,24 @@ mode: set +github.com/Ulbora/go-micro-blog/db/about.go:28.54,31.25 3 1 +github.com/Ulbora/go-micro-blog/db/about.go:31.25,33.3 1 1 +github.com/Ulbora/go-micro-blog/db/about.go:34.2,34.15 1 1 +github.com/Ulbora/go-micro-blog/db/about.go:34.15,40.3 5 1 +github.com/Ulbora/go-micro-blog/db/about.go:41.2,41.16 1 1 +github.com/Ulbora/go-micro-blog/db/about.go:45.48,47.25 2 1 +github.com/Ulbora/go-micro-blog/db/about.go:47.25,49.3 1 1 +github.com/Ulbora/go-micro-blog/db/about.go:50.2,50.15 1 1 +github.com/Ulbora/go-micro-blog/db/about.go:50.15,55.3 4 1 +github.com/Ulbora/go-micro-blog/db/about.go:56.2,56.12 1 1 +github.com/Ulbora/go-micro-blog/db/about.go:60.40,61.25 1 1 +github.com/Ulbora/go-micro-blog/db/about.go:61.25,63.3 1 1 +github.com/Ulbora/go-micro-blog/db/about.go:64.2,68.40 5 1 +github.com/Ulbora/go-micro-blog/db/about.go:68.40,70.28 2 1 +github.com/Ulbora/go-micro-blog/db/about.go:70.28,74.4 3 1 +github.com/Ulbora/go-micro-blog/db/about.go:76.2,76.13 1 1 +github.com/Ulbora/go-micro-blog/db/about.go:79.61,82.24 3 1 +github.com/Ulbora/go-micro-blog/db/about.go:82.24,85.17 3 1 +github.com/Ulbora/go-micro-blog/db/about.go:85.17,88.4 2 1 +github.com/Ulbora/go-micro-blog/db/about.go:90.2,90.13 1 1 github.com/Ulbora/go-micro-blog/db/blog.go:29.51,32.25 3 1 github.com/Ulbora/go-micro-blog/db/blog.go:32.25,34.3 1 1 github.com/Ulbora/go-micro-blog/db/blog.go:35.2,35.14 1 1 @@ -145,6 +165,46 @@ github.com/Ulbora/go-micro-blog/db/role.go:86.59,89.24 3 1 github.com/Ulbora/go-micro-blog/db/role.go:89.24,92.17 3 1 github.com/Ulbora/go-micro-blog/db/role.go:92.17,95.4 2 1 github.com/Ulbora/go-micro-blog/db/role.go:97.2,97.13 1 1 +github.com/Ulbora/go-micro-blog/db/rules.go:28.51,31.25 3 1 +github.com/Ulbora/go-micro-blog/db/rules.go:31.25,33.3 1 1 +github.com/Ulbora/go-micro-blog/db/rules.go:34.2,34.14 1 1 +github.com/Ulbora/go-micro-blog/db/rules.go:34.14,40.3 5 1 +github.com/Ulbora/go-micro-blog/db/rules.go:41.2,41.16 1 1 +github.com/Ulbora/go-micro-blog/db/rules.go:45.45,47.25 2 1 +github.com/Ulbora/go-micro-blog/db/rules.go:47.25,49.3 1 1 +github.com/Ulbora/go-micro-blog/db/rules.go:50.2,50.14 1 1 +github.com/Ulbora/go-micro-blog/db/rules.go:50.14,55.3 4 1 +github.com/Ulbora/go-micro-blog/db/rules.go:56.2,56.12 1 1 +github.com/Ulbora/go-micro-blog/db/rules.go:60.38,61.25 1 1 +github.com/Ulbora/go-micro-blog/db/rules.go:61.25,63.3 1 1 +github.com/Ulbora/go-micro-blog/db/rules.go:64.2,68.40 5 1 +github.com/Ulbora/go-micro-blog/db/rules.go:68.40,70.28 2 1 +github.com/Ulbora/go-micro-blog/db/rules.go:70.28,74.4 3 1 +github.com/Ulbora/go-micro-blog/db/rules.go:76.2,76.13 1 1 +github.com/Ulbora/go-micro-blog/db/rules.go:79.59,82.24 3 1 +github.com/Ulbora/go-micro-blog/db/rules.go:82.24,85.17 3 1 +github.com/Ulbora/go-micro-blog/db/rules.go:85.17,88.4 2 1 +github.com/Ulbora/go-micro-blog/db/rules.go:90.2,90.13 1 1 +github.com/Ulbora/go-micro-blog/db/tos.go:28.49,31.25 3 1 +github.com/Ulbora/go-micro-blog/db/tos.go:31.25,33.3 1 1 +github.com/Ulbora/go-micro-blog/db/tos.go:34.2,34.14 1 1 +github.com/Ulbora/go-micro-blog/db/tos.go:34.14,40.3 5 1 +github.com/Ulbora/go-micro-blog/db/tos.go:41.2,41.16 1 1 +github.com/Ulbora/go-micro-blog/db/tos.go:45.43,47.25 2 1 +github.com/Ulbora/go-micro-blog/db/tos.go:47.25,49.3 1 1 +github.com/Ulbora/go-micro-blog/db/tos.go:50.2,50.14 1 1 +github.com/Ulbora/go-micro-blog/db/tos.go:50.14,55.3 4 1 +github.com/Ulbora/go-micro-blog/db/tos.go:56.2,56.12 1 1 +github.com/Ulbora/go-micro-blog/db/tos.go:60.36,61.25 1 1 +github.com/Ulbora/go-micro-blog/db/tos.go:61.25,63.3 1 1 +github.com/Ulbora/go-micro-blog/db/tos.go:64.2,68.40 5 1 +github.com/Ulbora/go-micro-blog/db/tos.go:68.40,70.28 2 1 +github.com/Ulbora/go-micro-blog/db/tos.go:70.28,74.4 3 1 +github.com/Ulbora/go-micro-blog/db/tos.go:76.2,76.13 1 1 +github.com/Ulbora/go-micro-blog/db/tos.go:79.57,82.24 3 1 +github.com/Ulbora/go-micro-blog/db/tos.go:82.24,85.17 3 1 +github.com/Ulbora/go-micro-blog/db/tos.go:85.17,88.4 2 1 +github.com/Ulbora/go-micro-blog/db/tos.go:90.2,90.13 1 1 github.com/Ulbora/go-micro-blog/db/user.go:26.51,29.25 3 1 github.com/Ulbora/go-micro-blog/db/user.go:29.25,31.3 1 1 github.com/Ulbora/go-micro-blog/db/user.go:32.2,32.14 1 1 diff --git a/db/db.go b/db/db.go index 61630e8..d2b5336 100644 --- a/db/db.go +++ b/db/db.go @@ -77,4 +77,19 @@ type BlogDB interface { AddConfig(b *Config) (bool, int64) UpdateConfig(u *Config) bool GetConfig() *[]Config + + //rules + AddRule(r *Rule) (bool, int64) + UpdateRule(r *Rule) bool + GetRule() *[]Rule + + //Tos + AddTos(t *Tos) (bool, int64) + UpdateTos(t *Tos) bool + GetTos() *[]Tos + + //About + AddAbout(ab *About) (bool, int64) + UpdateAbout(ab *About) bool + GetAbout() *[]About } diff --git a/db/model.go b/db/model.go index 25fd9a0..70de7b8 100644 --- a/db/model.go +++ b/db/model.go @@ -81,3 +81,21 @@ type Config struct { AllowAutoPost bool `json:"allowAutoPost"` AllowAutoComment bool `json:"allowAutoComment"` } + +// Rule Rule +type Rule struct { + ID int64 `json:"id"` + Content string `json:"content"` +} + +// Tos Tos +type Tos struct { + ID int64 `json:"id"` + Content string `json:"content"` +} + +// About About +type About struct { + ID int64 `json:"id"` + Content string `json:"content"` +} diff --git a/db/queries.go b/db/queries.go index fa5163c..0f47b33 100644 --- a/db/queries.go +++ b/db/queries.go @@ -72,7 +72,9 @@ const ( selectBlogByName = " SELECT id, name, content, user_id, active, entered, updated " + " from blog " + // " order by name " + - " where name like ? LIMIT ?, ? " + " where name like ? " + + " order by entered desc " + + " LIMIT ?, ? " selectActiveBlogList = " SELECT b.id, b.name, b.content, b.user_id, b.active, b.entered, b.updated " + " from blog b " + @@ -138,4 +140,31 @@ const ( selectConfigList = " SELECT id, allow_auto_post, allow_auto_comment " + " from config " + + insertRule = "insert into rules (content) " + + " values (?) " + + updateRule = " UPDATE rules SET content = ? " + + " where id = ? " + + selectRules = " SELECT id, content " + + " from rules " + + insertTos = "insert into tos (content) " + + " values (?) " + + updateTos = " UPDATE tos SET content = ? " + + " where id = ? " + + selectTos = " SELECT id, content " + + " from tos " + + insertAbout = "insert into about (content) " + + " values (?) " + + updateAbout = " UPDATE about SET content = ? " + + " where id = ? " + + selectAbout = " SELECT id, content " + + " from about " ) diff --git a/db/rules.go b/db/rules.go new file mode 100644 index 0000000..1080a17 --- /dev/null +++ b/db/rules.go @@ -0,0 +1,91 @@ +package db + +import ( + "strconv" +) + +/* + Copyright (C) 2023 Ulbora Labs LLC. (www.ulboralabs.com) + All rights reserved. + + Copyright (C) 2023 Ken Williamson + All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +*/ + +// AddRule AddRule +func (d *MyBlogDB) AddRule(r *Rule) (bool, int64) { + var suc bool + var id int64 + if !d.testConnection() { + d.DB.Connect() + } + if r != nil { + var a []any + a = append(a, r.Content) + suc, id = d.DB.Insert(insertRule, a...) + d.Log.Debug("suc in add config", suc) + d.Log.Debug("id in add config", id) + } + return suc, id +} + +// UpdateRule UpdateRule +func (d *MyBlogDB) UpdateRule(r *Rule) bool { + var suc bool + if !d.testConnection() { + d.DB.Connect() + } + if r != nil { + var a []any + a = append(a, r.Content, r.ID) + suc = d.DB.Update(updateRule, a...) + d.Log.Debug("suc in update config", suc) + } + return suc +} + +// GetRule GetRule +func (d *MyBlogDB) GetRule() *[]Rule { + if !d.testConnection() { + d.DB.Connect() + } + var rtn = []Rule{} + var a []any + a = append(a) + rows := d.DB.GetList(selectRules, a...) + if rows != nil && len(rows.Rows) != 0 { + foundRows := rows.Rows + for r := range foundRows { + foundRow := foundRows[r] + rowContent := d.parseRuleRow(&foundRow) + rtn = append(rtn, *rowContent) + } + } + return &rtn +} + +func (d *MyBlogDB) parseRuleRow(foundRow *[]string) *Rule { + var rtn Rule + d.Log.Debug("foundRow in Rule", *foundRow) + if len(*foundRow) > 0 { + id, err := strconv.ParseInt((*foundRow)[0], 10, 64) + d.Log.Debug("id err in get config", err) + if err == nil { + rtn.ID = id + rtn.Content = (*foundRow)[1] + } + } + return &rtn +} diff --git a/db/rules_test.go b/db/rules_test.go new file mode 100644 index 0000000..bc0628e --- /dev/null +++ b/db/rules_test.go @@ -0,0 +1,219 @@ +package db + +import ( + "reflect" + "testing" + + lg "github.com/GolangToolKits/go-level-logger" + gdb "github.com/GolangToolKits/go-mysql" +) + +func TestMyBlogDB_AddRule(t *testing.T) { + + // db := gdb.MyDB{ + // Host: "localhost:3306", + // User: "admin", + // Password: "admin", + // Database: "go_micro_blog", + // } + + db := gdb.MyDBMock{ + Host: "localhost:3306", + User: "admin", + Password: "admin", + Database: "go_micro_blog", + } + db.MockTestRow = &gdb.DbRow{ + //Row: []string{"0"}, + Row: []string{}, + } + db.MockConnectSuccess = true + db.MockInsertID1 = 1 + db.MockInsertSuccess1 = true + + var l lg.Logger + log := l.New() + log.SetLogLevel(lg.AllLevel) + + type fields struct { + DB gdb.Database + Log lg.Log + } + type args struct { + r *Rule + } + tests := []struct { + name string + fields fields + args args + want bool + want1 int64 + }{ + // TODO: Add test cases. + { + name: "test 1", + fields: fields{ + DB: db.New(), + Log: log, + }, + args: args{ + r: &Rule{ + Content: "test content", + }, + }, + want: true, + want1: 1, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + d := &MyBlogDB{ + DB: tt.fields.DB, + Log: tt.fields.Log, + } + d.DB.Connect() + got, got1 := d.AddRule(tt.args.r) + if got != tt.want { + t.Errorf("MyBlogDB.AddRule() got = %v, want %v", got, tt.want) + } + if got1 != tt.want1 { + t.Errorf("MyBlogDB.AddRule() got1 = %v, want %v", got1, tt.want1) + } + }) + } +} + +func TestMyBlogDB_UpdateRule(t *testing.T) { + + // db := gdb.MyDB{ + // Host: "localhost:3306", + // User: "admin", + // Password: "admin", + // Database: "go_micro_blog", + // } + + db := gdb.MyDBMock{ + Host: "localhost:3306", + User: "admin", + Password: "admin", + Database: "go_micro_blog", + } + db.MockTestRow = &gdb.DbRow{ + //Row: []string{"0"}, + Row: []string{}, + } + db.MockConnectSuccess = true + db.MockUpdateSuccess1 = true + + var l lg.Logger + log := l.New() + log.SetLogLevel(lg.AllLevel) + + type fields struct { + DB gdb.Database + Log lg.Log + } + type args struct { + r *Rule + } + tests := []struct { + name string + fields fields + args args + want bool + }{ + // TODO: Add test cases. + { + name: "test 1", + fields: fields{ + DB: db.New(), + Log: log, + }, + args: args{ + r: &Rule{ + ID: 2, + Content: "test content 2", + }, + }, + want: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + d := &MyBlogDB{ + DB: tt.fields.DB, + Log: tt.fields.Log, + } + d.DB.Connect() + if got := d.UpdateRule(tt.args.r); got != tt.want { + t.Errorf("MyBlogDB.UpdateRule() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestMyBlogDB_GetRule(t *testing.T) { + // db := gdb.MyDB{ + // Host: "localhost:3306", + // User: "admin", + // Password: "admin", + // Database: "go_micro_blog", + // } + + db := gdb.MyDBMock{ + Host: "localhost:3306", + User: "admin", + Password: "admin", + Database: "go_micro_blog", + } + db.MockTestRow = &gdb.DbRow{ + //Row: []string{"0"}, + Row: []string{}, + } + + db.MockRows1 = &gdb.DbRows{ + Rows: [][]string{ + {"2", "test content 2"}, + //{"2", "test content 3"}, + }, + } + + var l lg.Logger + log := l.New() + log.SetLogLevel(lg.AllLevel) + + type fields struct { + DB gdb.Database + Log lg.Log + } + tests := []struct { + name string + fields fields + want *[]Rule + }{ + // TODO: Add test cases. + { + name: "test 1", + fields: fields{ + DB: db.New(), + Log: log, + }, + want: &[]Rule{ + {2, "test content 2"}, + // {3, "test Content 3"}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + d := &MyBlogDB{ + DB: tt.fields.DB, + Log: tt.fields.Log, + } + d.DB.Connect() + if got := d.GetRule(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("MyBlogDB.GetRule() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/db/tos.go b/db/tos.go new file mode 100644 index 0000000..7def737 --- /dev/null +++ b/db/tos.go @@ -0,0 +1,91 @@ +package db + +import ( + "strconv" +) + +/* + Copyright (C) 2023 Ulbora Labs LLC. (www.ulboralabs.com) + All rights reserved. + + Copyright (C) 2023 Ken Williamson + All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +*/ + +// AddTos AddTos +func (d *MyBlogDB) AddTos(t *Tos) (bool, int64) { + var suc bool + var id int64 + if !d.testConnection() { + d.DB.Connect() + } + if t != nil { + var a []any + a = append(a, t.Content) + suc, id = d.DB.Insert(insertTos, a...) + d.Log.Debug("suc in add config", suc) + d.Log.Debug("id in add config", id) + } + return suc, id +} + +// UpdateTos UpdateTos +func (d *MyBlogDB) UpdateTos(t *Tos) bool { + var suc bool + if !d.testConnection() { + d.DB.Connect() + } + if t != nil { + var a []any + a = append(a, t.Content, t.ID) + suc = d.DB.Update(updateTos, a...) + d.Log.Debug("suc in update config", suc) + } + return suc +} + +// GetTos GetTos +func (d *MyBlogDB) GetTos() *[]Tos { + if !d.testConnection() { + d.DB.Connect() + } + var rtn = []Tos{} + var a []any + a = append(a) + rows := d.DB.GetList(selectTos, a...) + if rows != nil && len(rows.Rows) != 0 { + foundRows := rows.Rows + for r := range foundRows { + foundRow := foundRows[r] + rowContent := d.parseTosRow(&foundRow) + rtn = append(rtn, *rowContent) + } + } + return &rtn +} + +func (d *MyBlogDB) parseTosRow(foundRow *[]string) *Tos { + var rtn Tos + d.Log.Debug("foundRow in Tos", *foundRow) + if len(*foundRow) > 0 { + id, err := strconv.ParseInt((*foundRow)[0], 10, 64) + d.Log.Debug("id err in get config", err) + if err == nil { + rtn.ID = id + rtn.Content = (*foundRow)[1] + } + } + return &rtn +} diff --git a/db/tos_test.go b/db/tos_test.go new file mode 100644 index 0000000..392b173 --- /dev/null +++ b/db/tos_test.go @@ -0,0 +1,219 @@ +package db + +import ( + "reflect" + "testing" + + lg "github.com/GolangToolKits/go-level-logger" + gdb "github.com/GolangToolKits/go-mysql" +) + +func TestMyBlogDB_AddTos(t *testing.T) { + + // db := gdb.MyDB{ + // Host: "localhost:3306", + // User: "admin", + // Password: "admin", + // Database: "go_micro_blog", + // } + + db := gdb.MyDBMock{ + Host: "localhost:3306", + User: "admin", + Password: "admin", + Database: "go_micro_blog", + } + db.MockTestRow = &gdb.DbRow{ + //Row: []string{"0"}, + Row: []string{}, + } + db.MockConnectSuccess = true + db.MockInsertID1 = 1 + db.MockInsertSuccess1 = true + + var l lg.Logger + log := l.New() + log.SetLogLevel(lg.AllLevel) + + type fields struct { + DB gdb.Database + Log lg.Log + } + type args struct { + r *Tos + } + tests := []struct { + name string + fields fields + args args + want bool + want1 int64 + }{ + // TODO: Add test cases. + { + name: "test 1", + fields: fields{ + DB: db.New(), + Log: log, + }, + args: args{ + r: &Tos{ + Content: "test Toc content", + }, + }, + want: true, + want1: 1, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + d := &MyBlogDB{ + DB: tt.fields.DB, + Log: tt.fields.Log, + } + d.DB.Connect() + got, got1 := d.AddTos(tt.args.r) + if got != tt.want { + t.Errorf("MyBlogDB.AddTos() got = %v, want %v", got, tt.want) + } + if got1 != tt.want1 { + t.Errorf("MyBlogDB.AddTos() got1 = %v, want %v", got1, tt.want1) + } + }) + } +} + +func TestMyBlogDB_UpdateTos(t *testing.T) { + + // db := gdb.MyDB{ + // Host: "localhost:3306", + // User: "admin", + // Password: "admin", + // Database: "go_micro_blog", + // } + + db := gdb.MyDBMock{ + Host: "localhost:3306", + User: "admin", + Password: "admin", + Database: "go_micro_blog", + } + db.MockTestRow = &gdb.DbRow{ + //Row: []string{"0"}, + Row: []string{}, + } + db.MockConnectSuccess = true + db.MockUpdateSuccess1 = true + + var l lg.Logger + log := l.New() + log.SetLogLevel(lg.AllLevel) + + type fields struct { + DB gdb.Database + Log lg.Log + } + type args struct { + r *Tos + } + tests := []struct { + name string + fields fields + args args + want bool + }{ + // TODO: Add test cases. + { + name: "test 1", + fields: fields{ + DB: db.New(), + Log: log, + }, + args: args{ + r: &Tos{ + ID: 1, + Content: "test tos content 1", + }, + }, + want: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + d := &MyBlogDB{ + DB: tt.fields.DB, + Log: tt.fields.Log, + } + d.DB.Connect() + if got := d.UpdateTos(tt.args.r); got != tt.want { + t.Errorf("MyBlogDB.UpdateTos() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestMyBlogDB_GetTos(t *testing.T) { + // db := gdb.MyDB{ + // Host: "localhost:3306", + // User: "admin", + // Password: "admin", + // Database: "go_micro_blog", + // } + + db := gdb.MyDBMock{ + Host: "localhost:3306", + User: "admin", + Password: "admin", + Database: "go_micro_blog", + } + db.MockTestRow = &gdb.DbRow{ + //Row: []string{"0"}, + Row: []string{}, + } + + db.MockRows1 = &gdb.DbRows{ + Rows: [][]string{ + {"1", "test tos content 1"}, + //{"2", "test content 3"}, + }, + } + + var l lg.Logger + log := l.New() + log.SetLogLevel(lg.AllLevel) + + type fields struct { + DB gdb.Database + Log lg.Log + } + tests := []struct { + name string + fields fields + want *[]Tos + }{ + // TODO: Add test cases. + { + name: "test 1", + fields: fields{ + DB: db.New(), + Log: log, + }, + want: &[]Tos{ + {1, "test tos content 1"}, + // {3, "test Content 3"}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + d := &MyBlogDB{ + DB: tt.fields.DB, + Log: tt.fields.Log, + } + d.DB.Connect() + if got := d.GetTos(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("MyBlogDB.GetTos() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/handlers/handler.go b/handlers/handler.go index 49fc2e2..2eef958 100644 --- a/handlers/handler.go +++ b/handlers/handler.go @@ -71,5 +71,15 @@ type Handler interface { UpdateConfig(w http.ResponseWriter, r *http.Request) GetConfig(w http.ResponseWriter, r *http.Request) + + //GetRules(w http.ResponseWriter, r *http.Request) + //SetRules(w http.ResponseWriter, r *http.Request) + + //GetTerms(w http.ResponseWriter, r *http.Request) + //SetTerms(w http.ResponseWriter, r *http.Request) + + //GetAbout(w http.ResponseWriter, r *http.Request) + //SetAbout((w http.ResponseWriter, r *http.Request)) + SetLogLevel(w http.ResponseWriter, r *http.Request) } diff --git a/scripts/goMicroBlog.mwb b/scripts/goMicroBlog.mwb index 51f3dd656d27cf2ed4192477843b6e133c44f90c..289913f2d1d2a7d40febdff28d8c59072dff6e65 100644 GIT binary patch literal 11455 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 literal 10305 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 literal 10305 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 r2P1O}7ZcDYCKhCye-uVXBXbiQ14nL