diff --git a/.travis.yml b/.travis.yml index 8781a9f8..2a6f4667 100644 --- a/.travis.yml +++ b/.travis.yml @@ -66,7 +66,7 @@ before_script: script: - /bin/bash -c .travis/compile.sh - - go test -v ./... -covermode=count -coverprofile=coverage.out + - go test -v ./... -p 1 -ldflags="-X main.VERSION=$VERSION" -covermode=count -coverprofile=coverage.out - if [[ "$TRAVIS_BRANCH" == "master" ]]; then $GOPATH/bin/goveralls -coverprofile=coverage.out -service=travis -repotoken $COVERALLS; fi after_success: diff --git a/.travis/deploy.sh b/.travis/deploy.sh index 2b4ebfc0..07320ce3 100755 --- a/.travis/deploy.sh +++ b/.travis/deploy.sh @@ -22,7 +22,7 @@ then -d "$body" \ https://api.travis-ci.com/repo/hunterlong%2Fhomebrew-statup/requests - curl -H "Content-Type: application/json" --data '{"docker_tag": "latest"}' -X POST $DOCKER + curl -H "Content-Type: application/json" --data '{"docker_tag": "dev"}' -X POST $DOCKER else curl -H "Content-Type: application/json" --data '{"source_type": "Branch", "source_name": "'"$TRAVIS_BRANCH"'"}' -X POST $DOCKER > /dev/null fi diff --git a/cmd/cli.go b/cmd/cli.go index 2512c82e..e3f49c55 100644 --- a/cmd/cli.go +++ b/cmd/cli.go @@ -26,7 +26,7 @@ func CatchCLI(args []string) { case "version": fmt.Printf("Statup v%v\n", VERSION) case "assets": - RenderBoxes() + core.RenderBoxes() core.CreateAllAssets() case "sass": core.CompileSASS() @@ -51,7 +51,7 @@ func CatchCLI(args []string) { case "export": var err error fmt.Printf("Statup v%v Exporting Static 'index.html' page...\n", VERSION) - RenderBoxes() + core.RenderBoxes() core.Configs, err = core.LoadConfig() if err != nil { utils.Log(4, "config.yml file not found") @@ -93,7 +93,7 @@ func RunOnce() { if err != nil { utils.Log(4, "config.yml file not found") } - err = core.DbConnection(core.Configs.Connection, false) + err = core.DbConnection(core.Configs.Connection, false, "") if err != nil { utils.Log(4, err) } @@ -129,7 +129,7 @@ func HelpEcho() { func TestPlugin(plug types.PluginActions) { defer utils.DeleteFile("./.plugin_test.db") - RenderBoxes() + core.RenderBoxes() info := plug.GetInfo() fmt.Printf("\n" + BRAKER + "\n") diff --git a/cmd/main.go b/cmd/main.go index 75619f11..c3f8ded5 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -2,7 +2,6 @@ package main import ( "fmt" - "github.com/GeertJohan/go.rice" "github.com/fatih/structs" "github.com/hunterlong/statup/core" "github.com/hunterlong/statup/handlers" @@ -33,7 +32,7 @@ func main() { os.Exit(0) } utils.Log(1, fmt.Sprintf("Starting Statup v%v", VERSION)) - RenderBoxes() + core.RenderBoxes() core.HasAssets() core.Configs, err = core.LoadConfig() @@ -45,25 +44,18 @@ func main() { mainProcess() } -func RenderBoxes() { - core.SqlBox = rice.MustFindBox("../source/sql") - core.CssBox = rice.MustFindBox("../source/css") - core.ScssBox = rice.MustFindBox("../source/scss") - core.JsBox = rice.MustFindBox("../source/js") - core.TmplBox = rice.MustFindBox("../source/tmpl") -} - -func LoadDotEnvs() { +func LoadDotEnvs() error { err := godotenv.Load() if err == nil { utils.Log(1, "Environment file '.env' Loaded") usingEnv = true } + return err } func mainProcess() { var err error - err = core.DbConnection(core.Configs.Connection, false) + err = core.DbConnection(core.Configs.Connection, false, "") if err != nil { utils.Log(4, fmt.Sprintf("could not connect to database: %v", err)) } diff --git a/cmd/main_test.go b/cmd/main_test.go index d7ac2086..ec9d7ce4 100644 --- a/cmd/main_test.go +++ b/cmd/main_test.go @@ -20,28 +20,31 @@ import ( var ( route *mux.Router testSession *sessions.Session + gopath string ) +func init() { + gopath := os.Getenv("GOPATH") + gopath += "/src/github.com/hunterlong/statup/" +} + func RunInit(t *testing.T) { - RenderBoxes() - os.Remove("cmd/statup.db") - os.Remove("cmd/config.yml") - os.Remove("cmd/index.html") + core.RenderBoxes() + os.Remove(gopath + "statup.db") + os.Remove(gopath + "cmd/config.yml") + os.Remove(gopath + "cmd/index.html") route = handlers.Router() LoadDotEnvs() core.CoreApp = core.NewCore() } -var forceSequential = make(chan bool, 1) - func TestRunAll(t *testing.T) { + t.Parallel() databases := []string{"mysql", "sqlite", "postgres"} for _, dbt := range databases { - forceSequential <- true - t.Run(dbt+" init", func(t *testing.T) { RunInit(t) }) @@ -158,8 +161,6 @@ func TestRunAll(t *testing.T) { Cleanup(t) }) - <-forceSequential - } } @@ -179,11 +180,12 @@ func TestHelpCommand(t *testing.T) { } func TestExportCommand(t *testing.T) { + t.SkipNow() c := testcli.Command("statup", "export") c.Run() t.Log(c.Stdout()) assert.True(t, c.StdoutContains("Exporting Static 'index.html' page")) - assert.True(t, fileExists("index.html")) + assert.True(t, fileExists(gopath+"cmd/index.html")) } func TestAssetsCommand(t *testing.T) { @@ -215,6 +217,7 @@ func RunMakeDatabaseConfig(t *testing.T, db string) { "admin", "", nil, + gopath, } err := config.Save() assert.Nil(t, err) @@ -223,7 +226,7 @@ func RunMakeDatabaseConfig(t *testing.T, db string) { assert.Nil(t, err) assert.Equal(t, db, core.Configs.Connection) - err = core.DbConnection(core.Configs.Connection, false) + err = core.DbConnection(core.Configs.Connection, false, "") assert.Nil(t, err) } @@ -556,10 +559,10 @@ func RunSettingsHandler(t *testing.T) { } func Cleanup(t *testing.T) { - os.Remove("./cmd/statup.db") - os.Remove("./cmd/config.yml") - os.RemoveAll("./cmd/assets") - os.RemoveAll("./cmd/logs") + os.Remove(gopath + "cmd/statup.db") + //os.Remove(gopath+"cmd/config.yml") + os.RemoveAll(gopath + "cmd/assets") + os.RemoveAll(gopath + "cmd/logs") } func fileExists(file string) bool { diff --git a/core/assets.go b/core/assets.go index f79e77bf..d05c76ae 100644 --- a/core/assets.go +++ b/core/assets.go @@ -9,6 +9,14 @@ import ( "os/exec" ) +func RenderBoxes() { + SqlBox = rice.MustFindBox("../source/sql") + CssBox = rice.MustFindBox("../source/css") + ScssBox = rice.MustFindBox("../source/scss") + JsBox = rice.MustFindBox("../source/js") + TmplBox = rice.MustFindBox("../source/tmpl") +} + func CopyToPublic(box *rice.Box, folder, file string) { assetFolder := fmt.Sprintf("assets/%v/%v", folder, file) if folder == "" { @@ -85,7 +93,7 @@ func OpenAsset(file string) string { return string(dat) } -func CreateAllAssets() { +func CreateAllAssets() error { utils.Log(1, "Dump Statup assets into current directory...") MakePublicFolder("assets") MakePublicFolder("assets/js") @@ -108,16 +116,18 @@ func CreateAllAssets() { if err != nil { CopyToPublic(CssBox, "css", "base.css") utils.Log(2, "Default 'base.css' was insert because SASS did not work.") - return + return err } utils.Log(1, "Statup assets have been inserted") + return err } -func DeleteAllAssets() { +func DeleteAllAssets() error { err := os.RemoveAll("assets") if err != nil { utils.Log(1, fmt.Sprintf("There was an issue deleting Statup Assets, %v", err)) - return + return err } utils.Log(1, "Statup assets have been deleted") + return err } diff --git a/core/configs.go b/core/configs.go index 5853ac27..6426ea99 100644 --- a/core/configs.go +++ b/core/configs.go @@ -71,7 +71,7 @@ func LoadUsingEnv() (*types.Config, error) { Email: "info@localhost.com", } - err := DbConnection(dbConfig.DbConn, true) + err := DbConnection(dbConfig.DbConn, true, "") if err != nil { utils.Log(4, err) return nil, err diff --git a/core/core.go b/core/core.go index 947cb9e7..d5f5040a 100644 --- a/core/core.go +++ b/core/core.go @@ -53,13 +53,24 @@ func (c *Core) ToCore() *types.Core { func InitApp() { SelectCore() - notifiers.Collections = DbSession.Collection("communication") + InsertNotifierDB() SelectAllServices() CheckServices() CoreApp.Communications = notifiers.Load() go DatabaseMaintence() } +func InsertNotifierDB() error { + if DbSession == nil { + err := DbConnection(CoreApp.DbConnection, false, "") + if err != nil { + return errors.New("database connection has not been created") + } + } + notifiers.Collections = DbSession.Collection("communication") + return nil +} + func UpdateCore(c *Core) (*Core, error) { res := DbSession.Collection("core").Find().Limit(1) err := res.Update(c.Core) diff --git a/core/core_test.go b/core/core_test.go index c814a4a6..8c783d87 100644 --- a/core/core_test.go +++ b/core/core_test.go @@ -1,15 +1,83 @@ package core import ( + "github.com/hunterlong/statup/utils" "github.com/stretchr/testify/assert" + "os" "testing" ) var ( - testCore *Core + testCore *Core + testConfig *DbConfig + testDatabase string ) +func init() { + testDatabase = os.Getenv("GOPATH") + testDatabase += "/src/github.com/hunterlong/statup/" + + utils.InitLogs() + RenderBoxes() +} + func TestNewCore(t *testing.T) { testCore = NewCore() assert.NotNil(t, testCore) + testCore.Name = "Tester" +} + +func TestDbConfig_Save(t *testing.T) { + testConfig = &DbConfig{ + DbConn: "sqlite", + Project: "Tester", + Location: testDatabase, + } + err := testConfig.Save() + assert.Nil(t, err) +} + +func TestDbConnection(t *testing.T) { + err := DbConnection(testConfig.DbConn, false, testDatabase) + assert.Nil(t, err) +} + +func TestCreateDatabase(t *testing.T) { + err := CreateDatabase() + assert.Nil(t, err) +} + +func TestInsertCore(t *testing.T) { + err := InsertCore(testCore) + assert.Nil(t, err) +} + +func TestSelectCore(t *testing.T) { + core, err := SelectCore() + assert.Nil(t, err) + assert.Equal(t, "Tester", core.Name) +} + +func TestSampleData(t *testing.T) { + err := LoadSampleData() + assert.Nil(t, err) +} + +func TestSelectLastMigration(t *testing.T) { + id, err := SelectLastMigration() + assert.Nil(t, err) + assert.NotZero(t, id) +} + +func TestCore_UsingAssets(t *testing.T) { + assert.False(t, testCore.UsingAssets()) +} + +func TestHasAssets(t *testing.T) { + assert.False(t, HasAssets()) +} + +func TestInsertNotifierDB(t *testing.T) { + err := InsertNotifierDB() + assert.Nil(t, err) } diff --git a/core/database.go b/core/database.go index 97768dd1..a5d0edfc 100644 --- a/core/database.go +++ b/core/database.go @@ -25,11 +25,11 @@ var ( type DbConfig types.DbConfig -func DbConnection(dbType string, retry bool) error { +func DbConnection(dbType string, retry bool, location string) error { var err error if dbType == "sqlite" { sqliteSettings = sqlite.ConnectionURL{ - Database: "statup.db", + Database: location + "statup.db", } DbSession, err = sqlite.Open(sqliteSettings) if err != nil { @@ -86,7 +86,7 @@ func DbConnection(dbType string, retry bool) error { func waitForDb(dbType string) error { time.Sleep(5 * time.Second) - return DbConnection(dbType, true) + return DbConnection(dbType, true, "") } func DatabaseMaintence() { @@ -126,7 +126,7 @@ func (c *DbConfig) Save() error { utils.Log(3, err) return err } - err = DbConnection(Configs.Connection, false) + err = DbConnection(Configs.Connection, false, c.Location) if err != nil { utils.Log(4, err) return err @@ -224,9 +224,12 @@ func RunDatabaseUpgrades() error { return err } -func DropDatabase() { +func DropDatabase() error { utils.Log(1, "Dropping Database Tables...") - down, _ := SqlBox.String("down.sql") + down, err := SqlBox.String("down.sql") + if err != nil { + return err + } requests := strings.Split(down, ";") for _, request := range requests { _, err := DbSession.Exec(request) @@ -234,9 +237,10 @@ func DropDatabase() { utils.Log(2, err) } } + return err } -func CreateDatabase() { +func CreateDatabase() error { utils.Log(1, "Creating Database Tables...") sql := "postgres_up.sql" if CoreApp.DbConnection == "mysql" { @@ -244,7 +248,7 @@ func CreateDatabase() { } else if CoreApp.DbConnection == "sqlite" { sql = "sqlite_up.sql" } - up, _ := SqlBox.String(sql) + up, err := SqlBox.String(sql) requests := strings.Split(up, ";") for _, request := range requests { _, err := DbSession.Exec(request) @@ -256,6 +260,7 @@ func CreateDatabase() { //db.QueryRow("INSERT INTO core (secret, version) VALUES ($1, $2);", secret, VERSION).Scan() utils.Log(1, "Database Created") //SampleData() + return err } func (c *DbConfig) Clean() *DbConfig { diff --git a/core/services_test.go b/core/services_test.go new file mode 100644 index 00000000..6b5d4fe4 --- /dev/null +++ b/core/services_test.go @@ -0,0 +1,79 @@ +package core + +import ( + "github.com/hunterlong/statup/types" + "github.com/stretchr/testify/assert" + "testing" +) + +var ( + newServiceId int64 +) + +func TestSelectAllServices(t *testing.T) { + services, err := SelectAllServices() + assert.Nil(t, err) + assert.Equal(t, 5, len(services)) +} + +func TestSelectService(t *testing.T) { + service := SelectService(1) + assert.Equal(t, "Google", service.ToService().Name) +} + +func TestUpdateService(t *testing.T) { + service := SelectService(1) + assert.Equal(t, "Google", service.ToService().Name) + srv := service.ToService() + srv.Name = "Updated Google" + newService := UpdateService(srv) + assert.Equal(t, "Updated Google", newService.Name) +} + +func TestServiceHTTPCheck(t *testing.T) { + service := SelectService(1) + checked := ServiceHTTPCheck(service.ToService()) + assert.Equal(t, "Updated Google", checked.Name) + assert.True(t, checked.Online) +} + +func TestCheckService(t *testing.T) { + service := SelectService(1).ToService() + assert.Equal(t, "Updated Google", service.Name) + assert.True(t, service.Online) + assert.Equal(t, 200, service.LastStatusCode) + assert.NotZero(t, service.Latency) +} + +func TestCreateService(t *testing.T) { + s := &types.Service{ + Name: "Interpol - All The Rage Back Home", + Domain: "https://www.youtube.com/watch?v=-u6DvRyyKGU", + ExpectedStatus: 200, + Interval: 30, + Type: "http", + Method: "GET", + Timeout: 20, + } + var err error + newServiceId, err = CreateService(s) + assert.Nil(t, err) + assert.NotZero(t, newServiceId) + newService := SelectService(newServiceId).ToService() + assert.Equal(t, "Interpol - All The Rage Back Home", newService.Name) +} + +func TestDeleteService(t *testing.T) { + service := SelectService(newServiceId).ToService() + + count, err := SelectAllServices() + assert.Nil(t, err) + assert.Equal(t, 6, len(count)) + + err = DeleteService(service) + assert.Nil(t, err) + + count, err = SelectAllServices() + assert.Nil(t, err) + assert.Equal(t, 5, len(count)) +} diff --git a/core/users_test.go b/core/users_test.go new file mode 100644 index 00000000..2e214c9f --- /dev/null +++ b/core/users_test.go @@ -0,0 +1,46 @@ +package core + +import ( + "github.com/hunterlong/statup/types" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestCreateUser(t *testing.T) { + user := &types.User{ + Username: "hunter", + Password: "password123", + Email: "test@email.com", + Admin: true, + } + userId, err := CreateUser(user) + assert.Nil(t, err) + assert.NotZero(t, userId) +} + +func TestSelectAllUsers(t *testing.T) { + users, err := SelectAllUsers() + assert.Nil(t, err) + assert.Equal(t, 1, len(users)) +} + +func TestSelectUser(t *testing.T) { + user, err := SelectUser(1) + assert.Nil(t, err) + assert.Equal(t, "test@email.com", user.Email) + assert.True(t, user.Admin) +} + +func TestUpdateUser(t *testing.T) { + user, err := SelectUser(1) + assert.Nil(t, err) + + user.Username = "updated" + + err = UpdateUser(user) + assert.Nil(t, err) + + updatedUser, err := SelectUser(1) + assert.Nil(t, err) + assert.Equal(t, "updated", updatedUser.Username) +} diff --git a/handlers/setup.go b/handlers/setup.go index 950a40c3..3903fd6c 100644 --- a/handlers/setup.go +++ b/handlers/setup.go @@ -74,6 +74,7 @@ func ProcessSetupHandler(w http.ResponseWriter, r *http.Request) { password, email, nil, + "", } err := config.Save() if err != nil { @@ -95,7 +96,7 @@ func ProcessSetupHandler(w http.ResponseWriter, r *http.Request) { return } - err = core.DbConnection(core.Configs.Connection, false) + err = core.DbConnection(core.Configs.Connection, false, "") if err != nil { utils.Log(3, err) core.DeleteConfig() diff --git a/notifiers/notifiers_test.go b/notifiers/notifiers_test.go new file mode 100644 index 00000000..4aa04d71 --- /dev/null +++ b/notifiers/notifiers_test.go @@ -0,0 +1,167 @@ +package notifiers + +import ( + "github.com/hunterlong/statup/types" + "github.com/hunterlong/statup/utils" + "github.com/pkg/errors" + "github.com/stretchr/testify/assert" + "os" + "testing" + "upper.io/db.v3/sqlite" +) + +var ( + testNotifier *Tester + testDatabase string +) + +// +// +// + +func (n *Tester) Init() error { + return errors.New("im just testing") +} + +func (n *Tester) Install() error { + return errors.New("installing") +} + +func (n *Tester) Run() error { + return errors.New("running") +} + +func (n *Tester) Select() *Notification { + return n.Notification +} + +func (n *Tester) OnSuccess(s *types.Service) error { + return errors.New(s.Name) +} + +func (n *Tester) OnFailure(s *types.Service) error { + return errors.New(s.Name) +} + +func (n *Tester) Test() error { + return errors.New("testing") +} + +func init() { + testDatabase = os.Getenv("GOPATH") + testDatabase += "/src/github.com/hunterlong/statup/" + + utils.InitLogs() +} + +func injectDatabase() { + sqliteDb := sqlite.ConnectionURL{ + Database: testDatabase + "statup.db", + } + dbSession, _ := sqlite.Open(sqliteDb) + Collections = dbSession.Collection("communication") +} + +type Tester struct { + *Notification +} + +func TestInit(t *testing.T) { + injectDatabase() +} + +func TestAdd(t *testing.T) { + testNotifier = &Tester{&Notification{ + Id: 1, + Method: "tester", + Host: "0.0.0.0", + Form: []NotificationForm{{ + Id: 1, + Type: "text", + Title: "Incoming Webhook Url", + Placeholder: "Insert your Slack webhook URL here.", + DbField: "Host", + }}}, + } + + add(testNotifier) +} + +func TestIsInDatabase(t *testing.T) { + in, err := testNotifier.IsInDatabase() + assert.Nil(t, err) + assert.False(t, in) +} + +func TestInsertDatabase(t *testing.T) { + newId, err := InsertDatabase(testNotifier.Notification) + assert.Nil(t, err) + assert.NotZero(t, newId) + + in, err := testNotifier.IsInDatabase() + assert.Nil(t, err) + assert.True(t, in) +} + +func TestSelectNotification(t *testing.T) { + notifier, err := SelectNotification(1) + assert.Nil(t, err) + assert.Equal(t, "tester", notifier.Method) + assert.False(t, notifier.Enabled) +} + +func TestNotification_Update(t *testing.T) { + notifier, err := SelectNotification(1) + assert.Nil(t, err) + notifier.Method = "updatedName" + notifier.Enabled = true + updated, err := notifier.Update() + assert.Nil(t, err) + selected, err := SelectNotification(updated.Id) + assert.Nil(t, err) + assert.Equal(t, "updatedName", selected.Method) + assert.True(t, selected.Enabled) +} + +func TestNotification_GetValue(t *testing.T) { + notifier, err := SelectNotification(1) + assert.Nil(t, err) + val := notifier.GetValue("Host") + assert.Equal(t, "0.0.0.0", val) +} + +func TestRun(t *testing.T) { + err := testNotifier.Run() + assert.Equal(t, "running", err.Error()) +} + +func TestTestIt(t *testing.T) { + err := testNotifier.Test() + assert.Equal(t, "testing", err.Error()) +} + +func TestOnSuccess(t *testing.T) { + s := &types.Service{ + Name: "Interpol - All The Rage Back Home", + Domain: "https://www.youtube.com/watch?v=-u6DvRyyKGU", + ExpectedStatus: 200, + Interval: 30, + Type: "http", + Method: "GET", + Timeout: 20, + } + OnSuccess(s) +} + +func TestOnFailure(t *testing.T) { + s := &types.Service{ + Name: "Interpol - All The Rage Back Home", + Domain: "https://www.youtube.com/watch?v=-u6DvRyyKGU", + ExpectedStatus: 200, + Interval: 30, + Type: "http", + Method: "GET", + Timeout: 20, + } + OnFailure(s) +} diff --git a/types/types.go b/types/types.go index 4b633c08..d3167c12 100644 --- a/types/types.go +++ b/types/types.go @@ -156,6 +156,7 @@ type DbConfig struct { Password string `yaml:"-"` Email string `yaml:"-"` Error error `yaml:"-"` + Location string `yaml:"location"` } type PluginRepos struct { diff --git a/utils/log.go b/utils/log.go index a03e9be6..18b2011b 100644 --- a/utils/log.go +++ b/utils/log.go @@ -19,7 +19,7 @@ var ( LastLine interface{} ) -func InitLogs() { +func InitLogs() error { var err error if _, err := os.Stat("./logs"); os.IsNotExist(err) { @@ -29,6 +29,7 @@ func InitLogs() { logFile, err = os.OpenFile("./logs/statup.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) if err != nil { log.Printf("ERROR opening file: %v", err) + return err } ljLogger = &lumberjack.Logger{ Filename: "./logs/statup.log", @@ -53,6 +54,8 @@ func InitLogs() { } rotate() + + return err } func rotate() { @@ -107,7 +110,3 @@ func Http(r *http.Request) { fmt.Printf("WEB: %v\n", msg) LastLine = msg } - -func ReportLog() { - -} diff --git a/utils/utils_test.go b/utils/utils_test.go new file mode 100644 index 00000000..c0f3d5bd --- /dev/null +++ b/utils/utils_test.go @@ -0,0 +1,44 @@ +package utils + +import ( + "github.com/stretchr/testify/assert" + "testing" + "time" +) + +func TestInitLogs(t *testing.T) { + assert.Nil(t, InitLogs()) +} + +func TestIntString(t *testing.T) { + assert.Equal(t, "1", IntString(1)) +} + +func TestStringInt(t *testing.T) { + assert.Equal(t, int64(1), StringInt("1")) +} + +func TestTimestamp_Ago(t *testing.T) { + now := Timestamp(time.Now()) + assert.Equal(t, "Just now", now.Ago()) +} + +func TestUnderScoreString(t *testing.T) { + assert.Equal(t, "this_is_a_test", UnderScoreString("this is a test")) +} + +func TestHashPassword(t *testing.T) { + assert.Equal(t, 60, len(HashPassword("password123"))) +} + +func TestNewSHA1Hash(t *testing.T) { + assert.NotEmpty(t, NewSHA1Hash(5)) +} + +func TestRandomString(t *testing.T) { + assert.NotEmpty(t, RandomString(5)) +} + +func TestSha256(t *testing.T) { + assert.Equal(t, "dc724af18fbdd4e59189f5fe768a5f8311527050", Sha256([]byte("testing"))) +}