From bc169c266562c2405342cab9e39b98e4bafca44a Mon Sep 17 00:00:00 2001 From: "cvillanueva@equinix.com" Date: Thu, 3 Dec 2020 14:57:48 -0600 Subject: [PATCH] added db unit tests Signed-off-by: cvillanueva@equinix.com --- common_test.go | 187 ++++++++++++++++++++++++++++++++++++ hardware_test.go | 240 +++++++++++++++++++++++++++++++++++++++++++++++ template_test.go | 201 +++++++++++++++++++++++++++++++++++++++ workflow_test.go | 232 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 860 insertions(+) create mode 100644 common_test.go create mode 100644 hardware_test.go create mode 100644 template_test.go create mode 100644 workflow_test.go diff --git a/common_test.go b/common_test.go new file mode 100644 index 000000000..ea9dc0777 --- /dev/null +++ b/common_test.go @@ -0,0 +1,187 @@ +// Package db - common test +// The following file contains all the common functions for testing. +package db + +import ( + "context" + "database/sql" + "fmt" + "testing" + + "github.com/packethost/pkg/log" +) + +var ( + ids = testID{ + instanceID: "da013837-a30c-237a-adfc-2d9ad69d5000", + hardwareID: "ce2e62ed-826f-4485-a39f-a82bb74338e2", + templateID: "da013837-a30c-237a-adfc-2d9ad69d5011", + workflowID: "b356eede-22c1-11eb-8c17-0242ac120004", + } +) + +type hardwarePayload struct { + ID string `json:"id"` + Metadata struct { + Facility struct { + FacilityCode string `json:"facility_code"` + } `json:"facility"` + Instance struct { + IPAddresses []struct { + Address string `json:"address"` + } `json:"ip_addresses"` + } `json:"instance"` + State string `json:"state"` + } `json:"metadata"` + Network struct { + Interfaces []struct { + Dhcp struct { + Arch string `json:"arch"` + IP struct { + Address string `json:"address"` + Gateway string `json:"gateway"` + Netmask string `json:"netmask"` + } `json:"ip"` + Mac string `json:"mac"` + Uefi bool `json:"uefi"` + } `json:"dhcp"` + Netboot struct { + AllowPxe bool `json:"allow_pxe"` + AllowWorkflow bool `json:"allow_workflow"` + } `json:"netboot"` + } `json:"interfaces"` + } `json:"network"` +} + +type testArgs struct { + host string + port int32 + tinkDb *TinkDB + hardwareID string + user string + password string + dbname string + psqlInfo string + logger log.Logger + ctx context.Context + instanceData string + hardwareData string + // templateData - referenced in workflow.Workflow. Formatted as yaml. + templateData string + templateDataUpdated string + workflowData Workflow +} + +type testID struct { + workflowID string + instanceID string + hardwareID string + templateID string +} + +func (a *testArgs) setLogger(t *testing.T) { + var err error + if a.logger, err = log.Init("github.com/tinkerbell/tink"); err != nil { + t.Error(err) + } +} + +func (a *testArgs) setPsqlInfo() { + a.psqlInfo = fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", + a.host, a.port, a.user, a.password, a.dbname) + a.logger.Info(a.psqlInfo) +} + +func newTestParams(t *testing.T, ids testID) *testArgs { + var err error + + hardwareData := `{ + "id": "` + ids.hardwareID + `", + "metadata": { + "facility": { + "facility_code": "onprem" + }, + "instance": { + "ip_addresses": [{ + "address": "" + }] + }, + "state": "" + }, + "network": { + "interfaces": [{ + "dhcp": { + "arch": "x86_64", + "ip": { + "address": "192.168.1.5", + "gateway": "192.168.1.1", + "netmask": "255.255.255.248" + }, + "mac": "08:00:27:00:00:01", + "uefi": false + }, + "netboot": { + "allow_pxe": true, + "allow_workflow": true + } + }] + } + }` + a := &testArgs{ + ctx: context.Background(), + host: "localhost", + port: 5432, + tinkDb: nil, + user: "tinkerbell", + password: "tinkerbell", + dbname: "tinkerbell", + hardwareID: ids.hardwareID, + workflowData: Workflow{ + State: 0, + ID: ids.workflowID, + Hardware: hardwareData, + Template: ids.templateID, + }, + hardwareData: hardwareData, + instanceData: ` { + "id": "` + ids.instanceID + `", + "instance": { + "ip_addresses": [ + { + "address": "192.168.0.1" + } + ] + } + }`, + templateData: ` +version: "0.1" +name: hello_world_workflow +global_timeout: 600 +tasks: +- name: "hello world" + worker: "192.168.0.1" + actions: + - name: "hello_world" + image: hello-world + timeout: 60`, + templateDataUpdated: ` +version: "0.2" +name: hello_world_workflow +global_timeout: 600 +tasks: +- name: "hello world" + worker: "192.168.0.1" + actions: + - name: "hello_world" + image: hello-world + timeout: 60`, + } + //////////////////////////////////////////////////////////////////////////// + a.setLogger(t) + a.setPsqlInfo() + a.tinkDb = Connect(a.logger) + if a.tinkDb.instance, err = sql.Open("postgres", a.psqlInfo); err != nil { + panic(err) + } + return a +} diff --git a/hardware_test.go b/hardware_test.go new file mode 100644 index 000000000..850e57ebe --- /dev/null +++ b/hardware_test.go @@ -0,0 +1,240 @@ +// Package db - hardware tests +// The following tests validate database functionality, using both network and +// instance payloads. A postgres instance with the tink database schema is +// required in order to run the following tests. +package db + +import ( + "encoding/json" + "fmt" + "math/rand" + "sync" + "testing" + + "github.com/google/uuid" + _ "github.com/lib/pq" +) + +// setupInsertIntoDB : inserts a single record in the hardware database. +func setupInsertIntoDB(t *testing.T) { + a := newTestParams(t, ids) + defer a.tinkDb.instance.Close() + + if _, err := a.tinkDb.instance.Exec("delete from hardware;"); err != nil { + t.Fail() + } + if err := a.tinkDb.InsertIntoDB(a.ctx, a.instanceData); err != nil { + t.Logf("%s", a.instanceData) + a.logger.Error(err) + t.Fail() + } + if err := a.tinkDb.InsertIntoDB(a.ctx, a.hardwareData); err != nil { + t.Logf("%s", a.hardwareData) + a.logger.Error(err) + t.Fail() + } +} + +// TestGetByMac : retrieves a single record based on the MAC address provided. +func TestGetByMac(t *testing.T) { + setupInsertIntoDB(t) + var response string + var err error + a := newTestParams(t, ids) + defer a.tinkDb.instance.Close() + + if response, err = a.tinkDb.GetByMAC(a.ctx, "08:00:27:00:00:01"); err != nil { + t.Fail() + } + var expected hardwarePayload + if err = json.Unmarshal([]byte(a.hardwareData), &expected); err != nil { + t.Fail() + } + var received hardwarePayload + if err = json.Unmarshal([]byte(response), &received); err != nil { + t.Fail() + } + if fmt.Sprintf("%+v", received) != fmt.Sprintf("%+v", expected) { + t.Logf("\nRECIEVED: %+v\nEXPECTED: %+v", received, expected) + t.Fail() + } +} + +// TestGetByIP : retrieves a single record based on the IP provided. +func TestGetByIP(t *testing.T) { + setupInsertIntoDB(t) + var response string + var err error + a := newTestParams(t, ids) + defer a.tinkDb.instance.Close() + + if response, err = a.tinkDb.GetByIP(a.ctx, "192.168.1.5"); err != nil { + t.Fail() + } + var expected hardwarePayload + if err = json.Unmarshal([]byte(a.hardwareData), &expected); err != nil { + t.Fail() + } + var received hardwarePayload + if err = json.Unmarshal([]byte(response), &received); err != nil { + t.Fail() + } + if fmt.Sprintf("%+v", received) != fmt.Sprintf("%+v", expected) { + t.Logf("\nRECIEVED: %+v\nEXPECTED: %+v", received, expected) + t.Fail() + } +} + +// TestGetByInstanceIP : retrieves a single hardware instances based on the IP +// provided. +func TestGetByInstanceIP(t *testing.T) { + setupInsertIntoDB(t) + var response string + var err error + a := newTestParams(t, ids) + defer a.tinkDb.instance.Close() + + if response, err = a.tinkDb.GetByIP(a.ctx, "192.168.0.1"); err != nil { + t.Fail() + } + var expected hardwarePayload + if err = json.Unmarshal([]byte(a.instanceData), &expected); err != nil { + t.Fail() + } + var received hardwarePayload + if err = json.Unmarshal([]byte(response), &received); err != nil { + t.Fail() + } + if fmt.Sprintf("%+v", received) != fmt.Sprintf("%+v", expected) { + t.Logf("\nRECIEVED: %+v\nEXPECTED: %+v", received, expected) + t.Logf("%s", response) + t.Fail() + } +} + +// TestConcurrentInsertIntoDb : inserts five records concurrently and validates +// whether or not all five records are actually committed. +func TestConcurrentInsertIntoDb(t *testing.T) { + var err error + count := 10 + a := newTestParams(t, ids) + defer a.tinkDb.instance.Close() + + if _, err := a.tinkDb.instance.Query("delete from hardware;"); err != nil { + t.Fail() + } + var wg sync.WaitGroup + for i := 0; i < count; i++ { + wg.Add(1) + var payload hardwarePayload + mac := fmt.Sprintf("A%v:A%v:A%v:A%v:A%v:A%v", rand.Intn(9), rand.Intn(9), rand.Intn(9), rand.Intn(9), rand.Intn(9), rand.Intn(9)) + if err = json.Unmarshal([]byte(a.hardwareData), &payload); err != nil { + t.Fail() + } + payload.Network.Interfaces[0].Dhcp.Mac = mac + uuid, err := uuid.NewRandom() + if err != nil { + t.Fail() + } + payload.ID = uuid.String() + b, err := json.Marshal(payload) + t.Logf("PUSHING %s", b) + if err != nil { + t.Fail() + } + go func(data string, a *testArgs, wg *sync.WaitGroup) { + defer wg.Done() + if err := a.tinkDb.InsertIntoDB(a.ctx, data); err != nil { + a.logger.Error(err) + t.Fail() + } + }(string(b), a, &wg) + } + wg.Wait() + var resultRole int + if err = a.tinkDb.instance.QueryRow("select count(*) as count from hardware;").Scan(&resultRole); err != nil { + t.Fail() + } + if resultRole != count { + t.Errorf("MACS PUSHED: %v. \n MACS RETURNED: %v", count, resultRole) + } +} + +// TestSerializedInsertIntoDb : inserts five records one at a time and validates +// if all five records are actually committed. +func TestSerializedInsertIntoDb(t *testing.T) { + var err error + count := 10 + a := newTestParams(t, ids) + defer a.tinkDb.instance.Close() + + if _, err := a.tinkDb.instance.Query("delete from hardware;"); err != nil { + t.Fail() + } + for i := 0; i < count; i++ { + var payload hardwarePayload + mac := fmt.Sprintf("A%v:A%v:A%v:A%v:A%v:A%v", rand.Intn(9), rand.Intn(9), rand.Intn(9), rand.Intn(9), rand.Intn(9), rand.Intn(9)) + if err = json.Unmarshal([]byte(a.hardwareData), &payload); err != nil { + t.Fail() + } + payload.Network.Interfaces[0].Dhcp.Mac = mac + uuid, err := uuid.NewRandom() + if err != nil { + t.Fail() + } + payload.ID = uuid.String() + b, err := json.Marshal(payload) + t.Logf("PUSHING %s", b) + if err != nil { + t.Fail() + } + if err := a.tinkDb.InsertIntoDB(a.ctx, string(b)); err != nil { + a.logger.Error(err) + t.Fail() + } + } + var resultRole int + if err = a.tinkDb.instance.QueryRow("select count(*) as count from hardware;").Scan(&resultRole); err != nil { + t.Fail() + } + if resultRole != count { + t.Errorf("MACS PUSHED: %v. \n MACS RETURNED: %v", count, resultRole) + } +} + +// TestGetByID : retrieves a single record based on the UUID provided. +func TestGetByID(t *testing.T) { + setupInsertIntoDB(t) + var response string + var err error + a := newTestParams(t, ids) + defer a.tinkDb.instance.Close() + + if response, err = a.tinkDb.GetByID(a.ctx, ids.hardwareID); err != nil { + t.Fail() + } + var expected hardwarePayload + if err = json.Unmarshal([]byte(a.hardwareData), &expected); err != nil { + t.Fail() + } + var received hardwarePayload + if err = json.Unmarshal([]byte(response), &received); err != nil { + t.Fail() + } + if fmt.Sprintf("%+v", received) != fmt.Sprintf("%+v", expected) { + t.Logf("\nRECIEVED: %+v\nEXPECTED: %+v", received, expected) + t.Fail() + } +} + +// TestDeleteFromDb : deletes a single record based on the UUID provided. +func TestDeleteFromDb(t *testing.T) { + setupInsertIntoDB(t) + var err error + a := newTestParams(t, ids) + defer a.tinkDb.instance.Close() + + if err = a.tinkDb.DeleteFromDB(a.ctx, ids.hardwareID); err != nil { + t.Fail() + } +} diff --git a/template_test.go b/template_test.go new file mode 100644 index 000000000..d27e2b223 --- /dev/null +++ b/template_test.go @@ -0,0 +1,201 @@ +// Package db - template tests +// The following tests validate database functionality, the instance payload. +// A postgres instance with the tink database schema is required in order to run +// the following tests. +package db + +import ( + "database/sql" + "fmt" + "strings" + "sync" + "testing" + + "github.com/google/uuid" + _ "github.com/lib/pq" +) + +// setupCreateTemplate : validates the creation of a new workflow template. +func setupCreateTemplate(t *testing.T) { + a := newTestParams(t, ids) + defer a.tinkDb.instance.Close() + + id, err := uuid.Parse(ids.templateID) + if err != nil { + t.Fail() + } + if _, err := a.tinkDb.instance.Exec("delete from template;"); err != nil { + t.Fail() + } + if err := a.tinkDb.CreateTemplate(a.ctx, "foo", a.templateData, id); err != nil { + a.logger.Error(err) + t.Fail() + } +} + +// TestCreateDuplicateTemplate : creates a duplicate template with the same name. +// This test should fail. It should only work if the original record is marked +// for deletion. +func TestCreateDuplicateTemplate(t *testing.T) { + setupCreateTemplate(t) + var err error + a := newTestParams(t, ids) + defer a.tinkDb.instance.Close() + + id, err := uuid.NewUUID() + if err != nil { + t.Fail() + } + err = a.tinkDb.CreateTemplate(a.ctx, "foo", a.templateData, id) + if err != nil { + a.logger.Error(err) + if !strings.Contains(err.Error(), "exists") { + t.Error("function should return: foo already exists") + } + } else { + t.Error("function should return an error") + } +} + +// TestCreateNewDuplicateTemplate : creates a duplicate template with the same +// name, but the previous template will be marked for deletion. +// This test should pass. +func TestCreateNewDuplicateTemplate(t *testing.T) { + setupInsertIntoDB(t) + var err error + a := newTestParams(t, ids) + defer a.tinkDb.instance.Close() + + if err = a.tinkDb.DeleteTemplate(a.ctx, ids.templateID); err != nil { + a.logger.Error(err) + t.Fail() + } + id, err := uuid.NewUUID() + if err != nil { + t.Fail() + } + if err = a.tinkDb.CreateTemplate(a.ctx, "foo", a.templateData, id); err != nil { + a.logger.Error(err) + t.Fail() + } +} + +// TestUpdatesTemplateOnCreate : updates an existing template if not deleted and +// the uuid is the same. +// This test should pass. +func TestUpdateTemplateOnCreate(t *testing.T) { + setupCreateTemplate(t) + var err error + a := newTestParams(t, ids) + defer a.tinkDb.instance.Close() + + id, err := uuid.Parse(ids.templateID) + if err != nil { + t.Fail() + } + if err = a.tinkDb.CreateTemplate(a.ctx, "bar", a.templateData, id); err != nil { + a.logger.Error(err) + t.Fail() + } +} + +// TestConcurrentCreateTemplate : inserts five records concurrently and validates +// whether or not all five records are actually committed. +func TestConcurrentCreateTemplate(t *testing.T) { + var err error + count := 10 + a := newTestParams(t, ids) + defer a.tinkDb.instance.Close() + + if _, err := a.tinkDb.instance.Query("delete from template;"); err != nil { + t.Fail() + } + var wg sync.WaitGroup + for i := 0; i < count; i++ { + wg.Add(1) + id, err := uuid.NewRandom() + if err != nil { + t.Fail() + } + label := fmt.Sprintf("temp%v", i) + t.Logf("PUSHING %v", i) + if err != nil { + t.Fail() + } + go func(k string, v string, a *testArgs, wg *sync.WaitGroup) { + defer wg.Done() + id, err := uuid.Parse(v) + if err != nil { + t.Fail() + } + if err := a.tinkDb.CreateTemplate(a.ctx, k, a.templateData, id); err != nil { + a.logger.Error(err) + t.Fail() + } + }(label, id.String(), a, &wg) + } + wg.Wait() + var resultRole int + if err = a.tinkDb.instance.QueryRow("select count(*) as count from template;").Scan(&resultRole); err != nil { + t.Fail() + } + if resultRole != count { + t.Error(fmt.Errorf("Tempaltes PUSHED: %v. \n MACS RETURNED: %v", count, resultRole)) + } +} + +// TestGetTemplate : validates retrieving a workflow template. +func TestGetTemplate(t *testing.T) { + setupCreateTemplate(t) + var err error + a := newTestParams(t, ids) + defer a.tinkDb.instance.Close() + + filter := make(map[string]string) + filter["name"] = "foo" + if _, _, _, err = a.tinkDb.GetTemplate(a.ctx, filter); err != nil { + a.logger.Error(err) + t.Fail() + } +} + +// TestDeleteTemplate : validates the deletion of a template. +func TestDeleteTemplate(t *testing.T) { + setupInsertIntoDB(t) + var err error + a := newTestParams(t, ids) + defer a.tinkDb.instance.Close() + + if err = a.tinkDb.DeleteTemplate(a.ctx, ids.templateID); err != nil { + a.logger.Error(err) + t.Fail() + } +} + +// TestUpdateTemplate : validates updating a template. +func TestUpdateTemplate(t *testing.T) { + setupCreateTemplate(t) + var err error + a := newTestParams(t, ids) + defer a.tinkDb.instance.Close() + + id, err := uuid.Parse(ids.templateID) + filter := make(map[string]string) + filter["name"] = "foo" + if a.tinkDb.instance, err = sql.Open("postgres", a.psqlInfo); err != nil { + t.Fail() + } + if err = a.tinkDb.UpdateTemplate(a.ctx, "foo", a.templateDataUpdated, id); err != nil { + a.logger.Error(err) + t.Fail() + } + _, _, received, err := a.tinkDb.GetTemplate(a.ctx, filter) + if err != nil { + a.logger.Error(err) + t.Fail() + } + if received != a.templateDataUpdated { + err = fmt.Errorf("EXPECTED: %s\nRECEIVED: %s", a.templateDataUpdated, received) + t.Error(err) + } +} diff --git a/workflow_test.go b/workflow_test.go new file mode 100644 index 000000000..67ac375eb --- /dev/null +++ b/workflow_test.go @@ -0,0 +1,232 @@ +// Package db - workflow tests +// The following tests validate database functionality, the instance payload. +// A postgres instance with the tink database schema is required in order to run +// the following tests. +package db + +import ( + "database/sql" + "encoding/json" + "fmt" + "testing" + + "github.com/google/uuid" + _ "github.com/lib/pq" + pb "github.com/tinkerbell/tink/protos/workflow" +) + +// setupCreateWorkflow : validates the creation of a new workflow. +func setupCreateWorkflow(t *testing.T) { + setupCreateTemplate(t) + setupInsertIntoDB(t) + var err error + a := newTestParams(t, ids) + defer a.tinkDb.instance.Close() + + id, err := uuid.Parse(ids.templateID) + if err != nil { + t.Fail() + } + if _, err := a.tinkDb.instance.Exec(`delete from workflow;`); err != nil { + t.Fail() + } + if _, err := a.tinkDb.instance.Exec(`delete from workflow_event;`); err != nil { + t.Fail() + } + if _, err := a.tinkDb.instance.Exec(`delete from workflow_state;`); err != nil { + t.Fail() + } + if _, err := a.tinkDb.instance.Exec(`delete from workflow_data;`); err != nil { + t.Fail() + } + if err := a.tinkDb.CreateWorkflow(a.ctx, a.workflowData, a.templateData, id); err != nil { + t.Logf("WORKFLOW: %+v \n", a.workflowData) + a.logger.Error(err) + t.Fail() + } +} + +// TestInsertIntoWfDataTable : validates the insert operation. +func TestInsertIntoWfDataTable(t *testing.T) { + setupCreateWorkflow(t) + var err error + a := newTestParams(t, ids) + defer a.tinkDb.instance.Close() + + data, err := json.Marshal(a.workflowData) + if err != nil { + t.Fail() + } + update := &pb.UpdateWorkflowDataRequest{Metadata: data, Data: data, WorkflowId: ids.templateID} + if a.tinkDb.instance, err = sql.Open("postgres", a.psqlInfo); err != nil { + t.Fail() + } + if err := a.tinkDb.InsertIntoWfDataTable(a.ctx, update); err != nil { + a.logger.Error(err) + t.Fail() + } +} + +// TestGetfromWfDataTable : validates returning workflow data. +func TestGetfromWfDataTable(t *testing.T) { + setupCreateWorkflow(t) + var response []byte + var err error + a := newTestParams(t, ids) + defer a.tinkDb.instance.Close() + + req := &pb.GetWorkflowDataRequest{WorkflowId: ids.templateID} + if a.tinkDb.instance, err = sql.Open("postgres", a.psqlInfo); err != nil { + t.Fail() + } + if response, err = a.tinkDb.GetfromWfDataTable(a.ctx, req); err != nil { + a.logger.Error(err) + t.Error(err) + } + t.Logf("%s", response) +} + +// TestGetWorkflowMetadata : validates retrieving workflow meta data. +func TestGetWorkflowMetadata(t *testing.T) { + setupCreateWorkflow(t) + var response []byte + var err error + a := newTestParams(t, ids) + defer a.tinkDb.instance.Close() + + req := &pb.GetWorkflowDataRequest{WorkflowId: ids.templateID} + if a.tinkDb.instance, err = sql.Open("postgres", a.psqlInfo); err != nil { + t.Fail() + } + if response, err = a.tinkDb.GetWorkflowMetadata(a.ctx, req); err != nil { + a.logger.Error(err) + t.Error(err) + } + t.Logf("%s", response) +} + +// TestGetWorkflowDataVersion : validates getting workflow data version. +func TestGetWorkflowDataVersion(t *testing.T) { + TestInsertIntoWfDataTable(t) + var response int32 + var err error + a := newTestParams(t, ids) + defer a.tinkDb.instance.Close() + + if response, err = a.tinkDb.GetWorkflowDataVersion(a.ctx, ids.templateID); err != nil { + a.logger.Error(err) + t.Error(err) + } + expected := int32(1) + if expected != response { + t.Error(fmt.Errorf("EXPECTED: %v\nRECEIVED: %v", expected, response)) + } +} + +// TestGetWorkflowsForWorker : validates getting workflows for worker. +func TestGetWorkflowsForWorker(t *testing.T) { + setupCreateWorkflow(t) + var response []string + var err error + a := newTestParams(t, ids) + defer a.tinkDb.instance.Close() + + if response, err = a.tinkDb.GetWorkflowsForWorker(ids.workflowID); err != nil { + a.logger.Error(err) + t.Error(err) + } + t.Logf("%+v", response) +} + +// TestGetWorkflow : validates getting workflow. +func TestGetWorkflow(t *testing.T) { + setupCreateWorkflow(t) + var response Workflow + var err error + a := newTestParams(t, ids) + defer a.tinkDb.instance.Close() + + if response, err = a.tinkDb.GetWorkflow(a.ctx, ids.workflowID); err != nil { + a.logger.Error(err) + t.Error(err) + } + if a.workflowData.ID != response.ID { + t.Errorf("EXPECTED: %v\nRECEIVED:%v", a.workflowData.ID, response.ID) + } +} + +// TestDeleteWorkflow : validates deleting workflow. +func TestDeleteWorkflow(t *testing.T) { + setupCreateWorkflow(t) + var err error + a := newTestParams(t, ids) + defer a.tinkDb.instance.Close() + + if a.tinkDb.instance, err = sql.Open("postgres", a.psqlInfo); err != nil { + t.Fail() + } + if err = a.tinkDb.DeleteWorkflow(a.ctx, ids.workflowID, int32(0)); err != nil { + a.logger.Error(err) + t.Error(err) + } +} + +// TestUpdateWorkflow : validates updating a workflow. +func TestUpdateWorkflow(t *testing.T) { + setupCreateWorkflow(t) + var response Workflow + var err error + a := newTestParams(t, ids) + defer a.tinkDb.instance.Close() + + if a.tinkDb.instance, err = sql.Open("postgres", a.psqlInfo); err != nil { + t.Fail() + } + a.workflowData.Hardware = `{"id": "` + ids.hardwareID + `", "network": {"interfaces": [{"dhcp": {"ip": {"address": "192.168.1.6", "gateway": "192.168.1.1", "netmask": "255.255.255.248"}, "mac": "08:00:27:00:00:01", "arch": "x86_64", "uefi": false}, "netboot": {"allow_pxe": true, "allow_workflow": true}}]}, "metadata": {"state": "", "facility": {"facility_code": "onprem"}, "instance": {"ip_addresses": [{"address": ""}]}}}` + if err = a.tinkDb.UpdateWorkflow(a.ctx, a.workflowData, int32(0)); err != nil { + a.logger.Error(err) + t.Error(err) + } + if response, err = a.tinkDb.GetWorkflow(a.ctx, ids.workflowID); err != nil { + a.logger.Error(err) + t.Error(err) + } + if response.Hardware != a.workflowData.Hardware { + t.Error(fmt.Errorf("EXPECTED: %s\nRECEIVED:%s", a.workflowData.Hardware, response.Hardware)) + } +} + +// TestUpdateWorkflowState : validates updating workflow state. +func TestUpdateWorkflowState(t *testing.T) { + setupCreateWorkflow(t) + var err error + a := newTestParams(t, ids) + defer a.tinkDb.instance.Close() + + if a.tinkDb.instance, err = sql.Open("postgres", a.psqlInfo); err != nil { + t.Fail() + } + wfContext := &pb.WorkflowContext{WorkflowId: ids.templateID} + if err = a.tinkDb.UpdateWorkflowState(a.ctx, wfContext); err != nil { + a.logger.Error(err) + t.Error(err) + } +} + +// TestGetWorkflowContexts : validates getting workflow context. +func TestGetWorkflowContexts(t *testing.T) { + setupCreateWorkflow(t) + var response *pb.WorkflowContext + var err error + a := newTestParams(t, ids) + defer a.tinkDb.instance.Close() + + if a.tinkDb.instance, err = sql.Open("postgres", a.psqlInfo); err != nil { + t.Fail() + } + if response, err = a.tinkDb.GetWorkflowContexts(a.ctx, ids.templateID); err != nil { + a.logger.Error(err) + t.Error(err) + } + t.Logf("%s", response) +}