jkawamoto/roadie

View on GitHub
command/config_test.go

Summary

Maintainability
F
5 days
Test Coverage
//
// command/config_test.go
//
// Copyright (c) 2016-2017 Junpei Kawamoto
//
// This file is part of Roadie.
//
// Roadie 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.
//
// Roadie 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 Roadie.  If not, see <http://www.gnu.org/licenses/>.
//

package command

import (
    "bytes"
    "context"
    "fmt"
    "io/ioutil"
    "os"
    "strings"
    "testing"

    "github.com/jkawamoto/roadie/cloud"
    "github.com/jkawamoto/roadie/cloud/mock"
)

var (
    testMachineTypes = []cloud.MachineType{
        {Name: "type A", Description: "sample machine type"},
        {Name: "type B", Description: "another machine type"},
    }
    testRegions = []cloud.Region{
        {Name: "region A", Status: "up"},
        {Name: "region B", Status: "down"},
    }
)

func TestCmdConfigProjectSet(t *testing.T) {

    var err error
    var output bytes.Buffer
    p := mock.NewProvider()
    m := testMetadata(&output, p)

    resource, err := p.ResourceManager(m.Context)
    if err != nil {
        t.Fatalf("ResourceManager returns an error: %v", err)
    }

    f, err := ioutil.TempFile("", "")
    if err != nil {
        t.Fatalf("cannot create a temp file: %v", err)
    }
    f.Close()
    m.Config.FileName = f.Name()
    defer os.Remove(f.Name())

    cases := []struct {
        input  string
        expect string
        output string
    }{
        {"sample1", "sample1", "sample1"},
        {"sample2", "sample2", "sample1 -> sample2"},
        {"sample-3", "sample-3", "sample2 -> sample-3"},
        {"sample 4", "sample_4", "sample-3 -> sample_4"},
    }

    for _, c := range cases {

        t.Run(c.input, func(t *testing.T) {
            defer output.Reset()

            err = cmdConfigProjectSet(m, c.input)
            if err != nil {
                t.Fatalf("cmdConfigProjectSet returns an error: %v", err)
            }
            if id := resource.GetProjectID(); id != c.expect {
                t.Errorf("updated project name is %q, want %q", id, c.expect)
            }
            lines := strings.Split(strings.TrimRight(output.String(), "\n"), "\n")
            if len(lines) < 2 {
                t.Errorf("output message is too short: %v", lines)
            }
            if output := strings.TrimSpace(lines[len(lines)-1]); output != c.output {
                t.Errorf("output message is %q, want %q", output, c.output)
            }
        })

    }

    t.Run("wrong file name", func(t *testing.T) {
        m.Config.FileName = ""
        err = cmdConfigProjectSet(m, "sample 1")
        if err == nil {
            t.Error("a wrong config file path is used but no errors are returned")
        }
    })

}

func TestCmdConfigProjectShow(t *testing.T) {

    var err error
    var output bytes.Buffer
    p := mock.NewProvider()
    m := testMetadata(&output, p)

    resource, err := m.ResourceManager()
    if err != nil {
        t.Fatalf("ResourceManager returns an error: %v", err)
    }

    cases := []struct {
        set    string
        expect string
    }{
        {"", MsgNotSet},
        {"test-id", "test-id"},
    }

    for _, c := range cases {

        t.Run(fmt.Sprintf("ID=%q", c.set), func(t *testing.T) {
            defer output.Reset()

            resource.SetProjectID(c.set)
            err = cmdConfigProjectShow(m)
            if err != nil {
                t.Fatalf("cmdConfigProjectShow returns an error: %v", err)
            }
            if res := strings.TrimSpace(output.String()); res != c.expect {
                t.Errorf("printed %q, want %q", res, c.expect)
            }
        })

    }

}

func TestConfigMachineTypeSet(t *testing.T) {

    var err error
    var output bytes.Buffer
    p := mock.NewProvider()
    m := testMetadata(&output, p)
    p.MockResourceManager.AvailableMachineTypes = testMachineTypes

    f, err := ioutil.TempFile("", "")
    if err != nil {
        t.Fatalf("cannot create a temp file: %v", err)
    }
    f.Close()
    m.Config.FileName = f.Name()
    defer os.Remove(f.Name())

    cases := []struct {
        input  string
        expect string
    }{
        {"type A", "type A"},
        {"type B", "type A -> type B"},
    }

    for _, c := range cases {
        t.Run(c.input, func(t *testing.T) {
            defer output.Reset()

            err = cmdConfigMachineTypeSet(m, c.input)
            if err != nil {
                t.Fatalf("cmdConfigMachineTypeSet with %q returns an error: %v", c.input, err)
            }
            lines := strings.Split(strings.TrimRight(output.String(), "\n"), "\n")
            if len(lines) < 2 {
                t.Errorf("output message is too short: %v", lines)
            }
            if res := strings.TrimSpace(lines[len(lines)-1]); res != c.expect {
                t.Errorf("output message is %q, want %q", res, c.expect)
            }
        })
    }

    t.Run("wrong machine type", func(t *testing.T) {
        err = cmdConfigMachineTypeSet(m, "type C")
        if err == nil {
            t.Fatal("set a wrong machine type but no errors are returned")
        }
    })

    t.Run("out-of-service resource manager", func(t *testing.T) {
        p.MockResourceManager.Failure = true
        defer func() { p.MockResourceManager.Failure = false }()

        err = cmdConfigMachineTypeSet(m, "type A")
        if err == nil {
            t.Error("failure is true but no errors are returned")
        }
    })

    t.Run("wrong file name", func(t *testing.T) {
        m.Config.FileName = ""
        err = cmdConfigMachineTypeSet(m, "type A")
        if err == nil {
            t.Error("a wrong config file path is used but no errors are returned")
        }
    })

}

func TestCmdConfigMachineTypeList(t *testing.T) {

    var err error
    var output bytes.Buffer
    p := mock.NewProvider()
    m := testMetadata(&output, p)
    p.MockResourceManager.AvailableMachineTypes = testMachineTypes
    p.MockResourceManager.SetMachineType("type A")

    t.Run("type A", func(t *testing.T) {
        defer output.Reset()

        err = cmdConfigMachineTypeList(m)
        if err != nil {
            t.Fatalf("cmdConfigMachineTypeList returns an error: %v", err)
        }

        lines := strings.Split(output.String(), "\n")
        if !strings.Contains(lines[0], "MACHINE TYPE") || !strings.Contains(lines[0], "DESCRIPTION") {
            t.Errorf("a wrong table header: %v", lines[0])
        }
        if len(lines) < 2 {
            t.Fatalf("output message is too short: %v", lines)
        }
        for _, row := range lines[1:] {
            if row == "" {
                continue
            }
            kv := strings.Split(row, "\t")
            if len(kv) < 2 {
                t.Fatalf("table row doesn't have enough information: %v", kv)
            }
            if name := strings.TrimSpace(kv[0]); name != "type A*" && name != "type B" {
                t.Errorf("machine type name is incorrect: %q", name)
            }
            if desc := strings.TrimSpace(kv[1]); desc != "sample machine type" && desc != "another machine type" {
                t.Errorf("machine description is incorrect: %q", desc)
            }
        }

    })

    t.Run("out-of-service resource manager", func(t *testing.T) {
        p.MockResourceManager.Failure = true
        defer func() { p.MockResourceManager.Failure = false }()
        err = cmdConfigMachineTypeList(m)
        if err == nil {
            t.Error("resource manager is out-of-service but no errors are returned")
        }
    })

    t.Run("canceled", func(t *testing.T) {
        var cancel context.CancelFunc
        m.Context, cancel = context.WithCancel(context.Background())
        cancel()
        if cmdConfigMachineTypeList(m) == nil {
            t.Error("context is canceled but no errors are returned")
        }
    })

}

func TestCmdConfigMachineTypeShow(t *testing.T) {

    var err error
    var output bytes.Buffer
    p := mock.NewProvider()
    m := testMetadata(&output, p)

    resource, err := m.ResourceManager()
    if err != nil {
        t.Fatalf("ResourceManager returns an error: %v", err)
    }

    cases := []struct {
        set    string
        expect string
    }{
        {"", MsgNotSet},
        {"test-type", "test-type"},
    }

    for _, c := range cases {

        t.Run(fmt.Sprintf("type=%q", c.set), func(t *testing.T) {
            defer output.Reset()

            resource.SetMachineType(c.set)
            err = cmdConfigMachineTypeShow(m)
            if err != nil {
                t.Fatalf("cmdConfigMachineTypeShow returns an error: %v", err)
            }
            if res := strings.TrimSpace(output.String()); res != c.expect {
                t.Errorf("printed %q, want %q", res, MsgNotSet)
            }
        })

    }

}

func TestConfigRegionSet(t *testing.T) {

    var err error
    var output bytes.Buffer
    p := mock.NewProvider()
    m := testMetadata(&output, p)
    p.MockResourceManager.AvailableRegions = testRegions

    f, err := ioutil.TempFile("", "")
    if err != nil {
        t.Fatalf("cannot create a temp file: %v", err)
    }
    f.Close()
    m.Config.FileName = f.Name()
    defer os.Remove(f.Name())

    cases := []struct {
        input  string
        expect string
    }{
        {"region A", "region A"},
        {"region B", "region A -> region B"},
    }

    for _, c := range cases {

        t.Run(c.input, func(t *testing.T) {
            defer output.Reset()

            err = cmdConfigRegionSet(m, c.input)
            if err != nil {
                t.Fatalf("cmdConfigRegionSet with %q returns an error: %v", c.input, err)
            }
            lines := strings.Split(strings.TrimRight(output.String(), "\n"), "\n")
            if len(lines) < 2 {
                t.Errorf("output message is too short: %v", lines)
            }
            if res := strings.TrimSpace(lines[len(lines)-1]); res != c.expect {
                t.Errorf("output message is %q, want %q", res, c.expect)
            }
        })

    }

    t.Run("wrong machine type", func(t *testing.T) {
        err = cmdConfigRegionSet(m, "region C")
        if err == nil {
            t.Fatal("set a wrong machine type but no errors are returned")
        }
    })

    t.Run("out-of-service resource manager", func(t *testing.T) {
        p.MockResourceManager.Failure = true
        defer func() { p.MockResourceManager.Failure = false }()
        err = cmdConfigRegionSet(m, "region A")
        if err == nil {
            t.Error("failure is true but no errors are returned")
        }
    })

    t.Run("wrong file name", func(t *testing.T) {
        m.Config.FileName = ""
        err = cmdConfigRegionSet(m, "region A")
        if err == nil {
            t.Error("a wrong config file path is used but no errors are returned")
        }
    })

}

func TestCmdConfigRegionList(t *testing.T) {

    var err error
    var output bytes.Buffer
    p := mock.NewProvider()
    m := testMetadata(&output, p)
    p.MockResourceManager.AvailableRegions = testRegions
    p.MockResourceManager.SetRegion("region A")

    t.Run(fmt.Sprintf("region=%q", "region A"), func(t *testing.T) {
        defer output.Reset()

        err = cmdConfigRegionList(m)
        if err != nil {
            t.Fatalf("cmdConfigRegionList returns an error: %v", err)
        }

        lines := strings.Split(output.String(), "\n")
        if !strings.Contains(lines[0], "REGION") || !strings.Contains(lines[0], "STATUS") {
            t.Errorf("a wrong table header: %v", lines[0])
        }
        if len(lines) < 2 {
            t.Fatalf("output message is too short: %v", lines)
        }
        for _, row := range lines[1:] {
            if row == "" {
                continue
            }
            kv := strings.Split(row, "\t")
            if len(kv) < 2 {
                t.Fatalf("table row doesn't have enough information: %v", kv)
            }
            if name := strings.TrimSpace(kv[0]); name != "region A*" && name != "region B" {
                t.Errorf("region name is incorrect: %q", name)
            }
            if desc := strings.TrimSpace(kv[1]); desc != "up" && desc != "down" {
                t.Errorf("region status is incorrect: %q", desc)
            }
        }

    })

    t.Run("out-of-service resource manager", func(t *testing.T) {
        p.MockResourceManager.Failure = true
        defer func() { p.MockResourceManager.Failure = false }()
        err = cmdConfigRegionList(m)
        if err == nil {
            t.Error("resource manager is out-of-service but no errors are returned")
        }
    })

    t.Run("canceled", func(t *testing.T) {
        var cancel context.CancelFunc
        m.Context, cancel = context.WithCancel(context.Background())
        cancel()
        if cmdConfigRegionList(m) == nil {
            t.Error("context is canceled but no errors are returned")
        }
    })

}

func TestCmdConfigRegionShow(t *testing.T) {

    var err error
    var output bytes.Buffer
    p := mock.NewProvider()
    m := testMetadata(&output, p)

    resource, err := m.ResourceManager()
    if err != nil {
        t.Fatalf("ResourceManager returns an error: %v", err)
    }

    cases := []struct {
        set    string
        expect string
    }{
        {"", MsgNotSet},
        {"test-region", "test-region"},
    }

    for _, c := range cases {

        t.Run(fmt.Sprintf("region=%q", c.set), func(t *testing.T) {
            defer output.Reset()

            resource.SetRegion(c.set)
            err = cmdConfigRegionShow(m)
            if err != nil {
                t.Fatalf("cmdConfigRegionShow returns an error: %v", err)
            }
            if res := strings.TrimSpace(output.String()); res != c.expect {
                t.Errorf("printed %q, want %q", res, MsgNotSet)
            }
        })

    }

}