wisedog/ladybug

View on GitHub
database/gorm.go

Summary

Maintainability
C
1 day
Test Coverage
package database

import (
    "fmt"
    "math/rand"
    "time"

    "github.com/jinzhu/gorm"
    // pq library is used by gorm
    _ "github.com/lib/pq"
    "golang.org/x/crypto/bcrypt"

    "github.com/wisedog/ladybug/interfacer"
    "github.com/wisedog/ladybug/models"

    log "gopkg.in/inconshreveable/log15.v2"
)

// Database is an instance of connection to DB
var Database *gorm.DB

// InitDB initialize the database and create dummies if it needs
func InitDB(conf *interfacer.AppConfig) (*gorm.DB, error) {

    var err error
    Database, err = gorm.Open("postgres", getDialectArgs(conf))
    if err != nil {
        log.Info("Database", "msg", err.Error())
        return Database, err
    }
    //defer Database.Close()

    Database.AutoMigrate(&models.User{})
    Database.AutoMigrate(&models.TestCase{})
    Database.AutoMigrate(&models.TestPlan{})
    Database.AutoMigrate(&models.Build{})
    Database.AutoMigrate(&models.BuildItem{})
    Database.AutoMigrate(&models.Section{})
    Database.AutoMigrate(&models.Execution{})
    Database.AutoMigrate(&models.TestCaseResult{})
    Database.AutoMigrate(&models.Review{})
    Database.AutoMigrate(&models.Category{})
    Database.AutoMigrate(&models.Requirement{})
    Database.AutoMigrate(&models.Milestone{})
    Database.AutoMigrate(&models.ReqType{})
    createDummy()

    return Database, nil
}

func loadDefault() error {
    return nil
}

// getDialectArgs returns argument of dialect database.
func getDialectArgs(conf *interfacer.AppConfig) string {
    var args string
    // not set by argument
    if conf.GetDialect() == "" {
        driver := conf.GetValue("db.driver")
        username := conf.GetValue("db.username")
        pwd := conf.GetValue("db.password")
        port := conf.GetValue("db.port")
        address := conf.GetValue("db.address")
        dbname := conf.GetValue("db.database_name")
        //extraParam := conf.GetValue("db.extra_param")
        switch driver {
        case "postgres":
            args = fmt.Sprintf("postgres://%s:%s@%s:%s/%s?sslmode=disable", username, pwd, address, port, dbname)
        case "mysql":
            args = "" //TODO

        default:
            args = ""
        }
    } else {
        // set by argument
        args = conf.GetDialect()
    }

    return args
}

// createDummy creates dummy data for database
func createDummy() {

    // drop all table while on development phase
    Database.DropTable(&models.User{})
    Database.DropTable(&models.Project{})
    Database.DropTable(&models.TestCase{})
    Database.DropTable(&models.TestPlan{})
    Database.DropTable(&models.Build{})
    Database.DropTable(&models.BuildItem{})
    Database.DropTable(&models.Section{})
    Database.DropTable(&models.Execution{})
    Database.DropTable(&models.Review{})
    Database.DropTable(&models.TestCaseResult{})
    Database.DropTable(&models.Category{})
    Database.DropTable(&models.Requirement{})
    Database.DropTable(&models.Activity{})
    Database.DropTable(&models.History{})
    Database.DropTable(&models.Milestone{})
    Database.DropTable(&models.TcReqRelationHistory{})
    Database.DropTable(&models.ReqType{})

    // Create dummy users
    Database.AutoMigrate(&models.User{})

    bcryptPassword, _ := bcrypt.GenerateFromPassword(
        []byte("demo"), bcrypt.DefaultCost)

    demoUser := &models.User{
        Name: "Rey", Email: "demo@demo.com", Password: "demo",
        HashedPassword: bcryptPassword, Language: "en", Region: "US",
        LastLoginAt: time.Now(), Role: models.RoleAdmin,
        Photo: "rey_160x160", Location: "Jakku",
        Notes: "I know all about waiting. For my family. They'll be back, one day.",
    }
    Database.NewRecord(demoUser) // => returns `true` if primary key is blank
    Database.Create(&demoUser)

    demoUser1 := &models.User{Name: "Poe Dameron", Email: "wisedog@demo.com", Password: "demo",
        HashedPassword: bcryptPassword, Language: "en", Region: "US", LastLoginAt: time.Now(),
        Role: models.RoleManager, Photo: "poe_160x160",
        Location: "D'Qar", Notes: "Red squad, blue squad, take my lead.",
    }
    Database.NewRecord(demoUser1)
    Database.Create(&demoUser1)

    //Database.Model(tab).AddUniqueIndex("idx_user__gmail", "gmail")
    //Database.Model(tab).AddUniqueIndex("idx_user__pu_mail", "pu_mail")

    // Create dummy project
    Database.AutoMigrate(&models.Project{})

    prj := models.Project{
        Name:        "Sample Project",
        Status:      1,
        Description: "A sample project. If you are used to Ladybug, remove this project",
        Prefix:      "TC",
        Users:       []models.User{*demoUser, *demoUser1},
    }
    prj1 := models.Project{
        Name:        "Another Sample Project",
        Status:      1,
        Description: "Second sample project. If you are used to Ladybug, remove this project",
        Prefix:      "wise",
        Users:       []models.User{*demoUser, *demoUser1},
    }

    Database.NewRecord(prj)
    Database.Create(&prj)
    Database.NewRecord(prj1)
    Database.Create(&prj1)

    // Create dummy testcases
    Database.AutoMigrate(&models.TestCase{})

    now := time.Now()

    testcases := []*models.TestCase{
        &models.TestCase{
            Prefix: prj.Prefix, Seq: 1,
            Title: "Do not go gentle", Status: models.TcStatusActivate, Description: "Desc", SectionID: 2,
            ProjectID: prj.ID, Priority: models.PriorityHigh, CategoryID: 1,
            DisplayID: prj.Prefix + "-1", Estimated: 10,
        },
        &models.TestCase{
            Prefix: prj.Prefix, Seq: 2, Title: "The Mars rover should be tested",
            Status: models.TcStatusActivate, Description: "Desc", SectionID: 3,
            ProjectID: prj.
                ID, Priority: models.PriorityHighest,
            CategoryID: 1, DisplayID: prj.Prefix + "-2", Estimated: 1,
        },
        &models.TestCase{
            Prefix: prj.Prefix, Seq: 3, Title: "I'm still arive!", CategoryID: 3,
            Status: models.TcStatusActivate, Description: "Desc", SectionID: 4,
            ProjectID: prj.ID, Priority: models.PriorityMedium,
            DisplayID: prj.Prefix + "-3", Estimated: 4,
        },
        &models.TestCase{
            Prefix: prj.Prefix, Seq: 4, Status: models.TcStatusActivate, SectionID: 4, CategoryID: 2,
            Title:        "Copy operation should be supported",
            Description:  "Copy operation is essential feature for text editing.",
            Precondition: "None",
            Steps:        "1. Drag some texts on web browser to select text and CTRL + C\n2. Click TextArea and CTRL + V",
            Expected:     "Selected text are copied in TextArea",
            ProjectID:    prj.ID, Priority: models.PriorityHigh,
            DisplayID: prj.Prefix + "-4", Estimated: 5,
        },
        &models.TestCase{
            Prefix: prj.Prefix, Seq: 5, Status: models.TcStatusActivate, SectionID: 4, CategoryID: 1,
            Title:        "Paste operation should be supported",
            Description:  "Paste operation is essential feature for text editing.",
            Precondition: "None",
            Steps:        "1. Drag some texts on web browser to select text and CTRL + C\n2. Click TextArea and CTRL + V",
            Expected:     "Selected text are copied in TextArea",
            ProjectID:    prj.ID, Priority: models.PriorityLow,
            DisplayID: prj.Prefix + "-5",
        },
    }

    for _, tc := range testcases {
        Database.NewRecord(tc)
        Database.Create(&tc)
    }

    // belows are for sample purpose
    var tempTestCase []models.TestCase
    Database.Find(&tempTestCase)

    n1 := now.AddDate(0, 0, -3)
    n2 := now.AddDate(0, 0, -8)
    n3 := now.AddDate(0, 0, -15)
    n4 := now.AddDate(0, 0, -22)
    timeArray := [4]time.Time{n1, n2, n3, n4}

    for i := 0; i < len(tempTestCase); i++ {
        k := tempTestCase[i]
        n := timeArray[rand.Intn(4)]
        Database.Model(&k).Update("created_at", n)
    }

    // Create dummy testplan
    Database.AutoMigrate(&models.TestPlan{})

    // Create dummy test execution
    Database.AutoMigrate(&models.Execution{})

    // Create dummy test result
    Database.AutoMigrate(&models.TestCaseResult{})

    // Create dummy build
    Database.AutoMigrate(&models.Build{})
    b := []*models.Build{
        &models.Build{Name: "Millenium Falcon",
            Description: "Modeling files for Millenium Falcon",
            Project_id:  prj.ID, ToolName: "manual",
        },
    }

    for _, bi := range b {
        Database.NewRecord(bi)
        Database.Create(&bi)
    }

    // Create dummy build items
    Database.AutoMigrate(&models.BuildItem{})

    // Create dummy Review
    Database.AutoMigrate(&models.Review{})

    // Create dummy section
    Database.AutoMigrate(&models.Section{})
    sections := []*models.Section{
        &models.Section{Seq: 1, Title: "Coding Conventions", Status: 0, RootNode: true,
            Prefix: prj.Prefix, ProjectID: prj.ID, ForTestCase: true},
        &models.Section{Seq: 1, Title: "Theme and Design", Status: 0, RootNode: true,
            Prefix: prj.Prefix, ProjectID: prj.ID, ForTestCase: true},
        &models.Section{Seq: 1, Title: "Source code control", Status: 0, RootNode: true,
            Prefix: prj.Prefix, ProjectID: prj.ID, ForTestCase: true},
        &models.Section{Seq: 1, Title: "Go language", RootNode: false,
            ParentsID: 1, Prefix: prj.Prefix, ProjectID: prj.ID, ForTestCase: true},
        &models.Section{Seq: 2, Title: "Javascript", RootNode: false,
            ParentsID: 1, Prefix: prj.Prefix, ProjectID: prj.ID, ForTestCase: true},
        &models.Section{Seq: 1, Title: "SB Admin2", RootNode: false, ParentsID: 2,
            Prefix: prj.Prefix, ProjectID: prj.ID, ForTestCase: true},
        &models.Section{Seq: 1, Title: "Git", RootNode: false, ParentsID: 3,
            Prefix: prj.Prefix, ProjectID: prj.ID, ForTestCase: true},
        &models.Section{Seq: 1, Title: "AAA", RootNode: true,
            Prefix: prj1.Prefix, ProjectID: prj1.ID, ForTestCase: true},
        &models.Section{Seq: 1, Title: "BBB", RootNode: false, ParentsID: 8,
            Prefix: prj1.Prefix, ProjectID: prj1.ID, ForTestCase: true},
        &models.Section{Seq: 1, Title: "ccc", RootNode: true,
            Prefix: prj1.Prefix, ProjectID: prj1.ID, ForTestCase: true},
        &models.Section{Seq: 1, Title: "ddd", RootNode: false, ParentsID: 10,
            Prefix: prj1.Prefix, ProjectID: prj1.ID, ForTestCase: true},
        &models.Section{Seq: 1, Title: "Requirements", RootNode: true,
            Prefix: prj.Prefix, ProjectID: prj.ID, ForTestCase: false},
        &models.Section{Seq: 1, Title: "Functional", RootNode: false,
            Prefix: prj.Prefix, ProjectID: prj.ID, ForTestCase: false,
            ParentsID: 12,
        },
        &models.Section{Seq: 1, Title: "Non-Functional", RootNode: false,
            Prefix: prj.Prefix, ProjectID: prj.ID, ForTestCase: false,
            ParentsID: 12,
        },
    }

    for _, section := range sections {
        Database.NewRecord(section)
        Database.Create(&section)
    }

    Database.AutoMigrate(&models.Category{})
    cate := []*models.Category{
        &models.Category{Name: "Funtionality"},
        &models.Category{Name: "Performance"},
        &models.Category{Name: "Usability"},
        &models.Category{Name: "Regression"},
        &models.Category{Name: "Automated"},
        &models.Category{Name: "Security"},
        &models.Category{Name: "Compatibility"},
        &models.Category{Name: "Accessability"},
    }

    for _, ct := range cate {
        Database.NewRecord(ct)
        Database.Create(&ct)
    }

    Database.AutoMigrate(&models.Requirement{})

    reqs := []*models.Requirement{
        &models.Requirement{Title: "Hello, world", SectionID: 13,
            Description: "hello", ReqTypeID: 1,
            Status: models.ReqStatusDraft, Priority: models.PriorityHigh, ProjectID: prj.ID,
        },
        &models.Requirement{Title: "Hello, stranger", SectionID: 14,
            Description: "blahblah", ReqTypeID: 2,
            Status: models.ReqStatusDraft, Priority: models.PriorityMedium, ProjectID: prj.ID,
            RelatedTestCases: []models.TestCase{*testcases[1], *testcases[4]},
        },
        &models.Requirement{Title: "Good bye", SectionID: 14,
            Description: "aaaa", ReqTypeID: 3,
            Status: models.ReqStatusDraft, Priority: models.PriorityLow, ProjectID: prj.ID,
            RelatedTestCases: []models.TestCase{*testcases[1], *testcases[2]},
        },
    }

    for _, sp := range reqs {
        Database.NewRecord(sp)
        Database.Create(&sp)
    }

    var tmpReqs []models.Requirement
    Database.Find(&tmpReqs)

    timeArrayReq := [3]time.Time{n4, n3, n2}

    for i := 0; i < len(tmpReqs); i++ {
        k := tmpReqs[i]
        n := timeArrayReq[i]
        Database.Model(&k).Update("created_at", n)
    }

    // for creating dummy for Activity
    Database.AutoMigrate(&models.Activity{})

    activities := []*models.Activity{
        &models.Activity{UserID: demoUser.ID, Content: "Rey finished Test Execution #1"},
        &models.Activity{UserID: demoUser.ID, Content: "Rey created Test Plan #1"},
        &models.Activity{UserID: demoUser.ID, Content: "Rey modified TC-5"},
    }

    for _, ac := range activities {
        Database.NewRecord(ac)
        Database.Create(&ac)
    }

    // for creating dummy for History
    Database.AutoMigrate(&models.History{})

    Database.AutoMigrate(&models.Milestone{})
    oneMonthFromNow := time.Hour * 24 * 30

    next := now.Add(oneMonthFromNow)
    next1 := next.Add(oneMonthFromNow)
    Milestones := []*models.Milestone{
        &models.Milestone{Name: "Milestone#1", ProjectID: prj.ID, Status: models.MilestoneStatusActive, DueDate: next},
        &models.Milestone{Name: "Milestone#2", ProjectID: prj.ID, Status: models.MilestoneStatusActive, DueDate: next1},
    }

    for _, ms := range Milestones {
        Database.NewRecord(ms)
        Database.Create(&ms)
    }

    // for testcase-requirement relationship
    Database.AutoMigrate(&models.TcReqRelationHistory{})

    relations := []*models.TcReqRelationHistory{
        &models.TcReqRelationHistory{
            RequirementID: 1, TestCaseID: 2,
            Kind:      models.TcReqRelationHistoryLink,
            ProjectID: prj.ID,
        },
        &models.TcReqRelationHistory{
            RequirementID: 2, TestCaseID: 2,
            Kind:      models.TcReqRelationHistoryLink,
            ProjectID: prj.ID,
        },
        &models.TcReqRelationHistory{
            RequirementID: 2, TestCaseID: 3,
            Kind:      models.TcReqRelationHistoryUnlink,
            ProjectID: prj.ID,
        },
        &models.TcReqRelationHistory{
            RequirementID: 3, TestCaseID: 4,
            Kind:      models.TcReqRelationHistoryLink,
            ProjectID: prj.ID,
        },
    }

    for _, ac := range relations {
        Database.NewRecord(ac)
        Database.Create(&ac)
    }

    var tempRelation []models.TcReqRelationHistory
    Database.Find(&tempRelation)

    tmpTimeArray := []time.Time{n4, n3, n3, n2}
    for i := 0; i < len(tempRelation); i++ {
        k := tempRelation[i]
        n := tmpTimeArray[i]
        Database.Model(&k).Update("created_at", n)
    }

    Database.AutoMigrate(&models.ReqType{})

    reqtypes := []*models.ReqType{
        &models.ReqType{Name: "Use Case"},
        &models.ReqType{Name: "Information"},
        &models.ReqType{Name: "Feature"},
        &models.ReqType{Name: "User Interface"},
        &models.ReqType{Name: "Non Functional"},
        &models.ReqType{Name: "Constraint"},
        &models.ReqType{Name: "System Function"},
    }

    for _, t := range reqtypes {
        Database.NewRecord(t)
        Database.Create(&t)
    }
}