<commit_before>package lib

import (
	"encoding/json"
	marathon "github.com/gambol99/go-marathon"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/mock"
	"testing"
)

type MockMarathonClient struct {
	mock.Mock
}

func (c *MockMarathonClient) ListApplications() ([]string, error) {
	var thing []string
	return thing, nil
}

func (c *MockMarathonClient) Tasks(string) (*marathon.Tasks, error) {
	jsonTasks := `{
    "tasks": [
        {
            "appId":"/infrastructure/docker-registry",
            "id":"infrastructure_docker-registry.872a3060-dfae-11e4-bdf0-3624e0a93f16",
            "host":"ip-10-120-100-25.us-west-2.compute.internal",
            "ports":[5000],
            "startedAt":"2015-04-10T18:22:52.829Z",
            "stagedAt":"2015-04-10T18:22:21.295Z",
            "version":"2015-04-09T23:40:51.805Z"
        }
    ]
}`
	var expected marathon.Tasks
	json.Unmarshal([]byte(jsonTasks), &expected)
	return &expected, nil
}

func (c *MockMarathonClient) Applications() (*marathon.Applications, error) {
	jsonContainers := `{
    "apps": [
        {
            "args": null,
            "backoffFactor": 1.15,
            "backoffSeconds": 1,
            "cmd": "python3 -m http.server 8080",
            "constraints": [],
            "container": {
                "docker": {
                    "image": "python:3",
                    "network": "BRIDGE",
                    "portMappings": [
                        {
                            "containerPort": 8080,
                            "hostPort": 0,
                            "servicePort": 9000,
                            "protocol": "tcp"
                        },
                        {
                            "containerPort": 161,
                            "hostPort": 0,
                            "protocol": "udp"
                        }
                    ]
                },
                "type": "DOCKER",
                "volumes": []
            },
            "cpus": 0.5,
            "dependencies": [],
            "deployments": [],
            "disk": 0.0,
            "env": {},
            "executor": "",
            "healthChecks": [
                {
                    "command": null,
                    "gracePeriodSeconds": 5,
                    "intervalSeconds": 20,
                    "maxConsecutiveFailures": 3,
                    "path": "/",
                    "portIndex": 0,
                    "protocol": "HTTP",
                    "timeoutSeconds": 20
                }
            ],
            "id": "/fake_app",
            "instances": 2,
            "mem": 64.0,
            "ports": [
                10000,
                10001
            ],
            "requirePorts": false,
            "storeUrls": [],
            "tasksRunning": 2,
            "tasksStaged": 0,
            "upgradeStrategy": {
                "minimumHealthCapacity": 1.0
            },
            "uris": [],
            "user": null,
            "version": "2014-09-25T02:26:59.256Z"
        },
        {
            "args": null,
            "backoffFactor": 1.15,
            "backoffSeconds": 1,
            "cmd": "python3 -m http.server 8080",
            "constraints": [],
            "container": {
                "docker": {
                    "image": "python:3",
                    "network": "BRIDGE",
                    "portMappings": [
                        {
                            "containerPort": 8080,
                            "hostPort": 0,
                            "servicePort": 9000,
                            "protocol": "tcp"
                        },
                        {
                            "containerPort": 161,
                            "hostPort": 0,
                            "protocol": "udp"
                        }
                    ]
                },
                "type": "DOCKER",
                "volumes": []
            },
            "cpus": 1.5,
            "dependencies": [],
            "deployments": [],
            "disk": 0.0,
            "env": {},
            "executor": "",
            "healthChecks": [
                {
                    "command": null,
                    "gracePeriodSeconds": 5,
                    "intervalSeconds": 20,
                    "maxConsecutiveFailures": 3,
                    "path": "/",
                    "portIndex": 0,
                    "protocol": "HTTP",
                    "timeoutSeconds": 20
                }
            ],
            "id": "/fake_app_broken",
            "instances": 2,
            "mem": 64.0,
            "ports": [
                10000,
                10001
            ],
            "requirePorts": false,
            "storeUrls": [],
            "tasksRunning": 2,
            "tasksStaged": 0,
            "upgradeStrategy": {
                "minimumHealthCapacity": 1.0
            },
            "uris": [],
            "user": null,
            "version": "2014-09-25T02:26:59.256Z"
        }
    ]
}`
	var expected marathon.Applications
	json.Unmarshal([]byte(jsonContainers), &expected)
	return &expected, nil
}

func expApplications() *marathon.Applications {
	return &marathon.Applications{
		Apps: []marathon.Application{
			marathon.Application{
				ID:   "/fake_app",
				CPUs: float32(0.5),
				Mem:  float32(64),
				Disk: float32(0),
			},
			marathon.Application{
				ID:   "/fake_app_broken",
				CPUs: float32(1.5),
				Mem:  float32(64),
				Disk: float32(0),
			},
		},
	}
}

func expMarathonApps() *MarathonApps {
	return &MarathonApps{
		Apps: []*MarathonApp{
			expFakeApp(),
		},
	}
}

func expFakeApp() *MarathonApp {
	return &MarathonApp{
		Id: "/fake_app",
		Tasks: []*MarathonTask{
			&MarathonTask{
				Id:        "fake-app-task",
				Container: "fake-app-container",
				SlaveId:   "slave1",
				SlaveHost: "slave1-host",
			},
		},
	}
}

func TestLoadApps(t *testing.T) {
	m := &Marathon{}
	mockClient := new(MockMarathonClient)
	err := m.LoadApps(mockClient)
	exp := expApplications()
	assert.Nil(t, err)
	assert.Equal(t, len(m.Apps), len(exp.Apps), "The expected number of apps should be returned")
	for i, app := range exp.Apps {
		assert.Equal(t, m.Apps[i].ID, app.ID, "App should be returned")
	}
}

func TestGetAppById(t *testing.T) {
	apps := expMarathonApps()
	app := apps.GetAppById("/fake_app")
	assert.Equal(t, app.Id, "/fake_app")
}

func TestGetAppByIdNotExist(t *testing.T) {
	apps := expMarathonApps()
	app := apps.GetAppById("/no_app")
	assert.Nil(t, app)
}

func TestGetTaskById(t *testing.T) {
	app := expFakeApp()
	task := app.GetTaskById("fake-app-task")
	assert.Equal(t, task.Id, "fake-app-task")
}

func TestAddTaskExistingApp(t *testing.T) {
	apps := expMarathonApps()
	apps.AddTask("new-fake-app-task", "/fake_app", "slave2", "slave2-host", true, false, false)
	assert.Equal(t, apps.Apps[0].Tasks[0].Id, "fake-app-task", "Original task should still exist")
	assert.Equal(t, apps.Apps[0].Tasks[1].Id, "new-fake-app-task", "New Task ID should exist")
}

func TestAddTaskNotExistingApp(t *testing.T) {
	apps := expMarathonApps()
	apps.AddTask("faker-app-task", "/faker_app", "slave1", "slave1-host", true, false, false)
	assert.Equal(t, apps.Apps[1].Id, "/faker_app", "New app should exist")
	assert.Equal(t, apps.Apps[1].Tasks[0].Id, "faker-app-task", "New app task should exist")
}

func TestAddAppExisting(t *testing.T) {
	apps := expMarathonApps()
	apps.AddApp("/fake_app")
	assert.Equal(t, len(apps.Apps), 1, "No new app should be added")
	assert.Equal(t, apps.Apps[0].Id, "/fake_app", "Original app should still exist")
}

func TestAddAppNotExisting(t *testing.T) {
	apps := expMarathonApps()
	apps.AddApp("/faker_app")
	assert.Equal(t, len(apps.Apps), 2, "An additional app should exist")
	assert.Equal(t, apps.Apps[0].Id, "/fake_app", "Original app should still exist")
	assert.Equal(t, apps.Apps[1].Id, "/faker_app", "New app should exist")
}
<commit_msg>fix test types to match upstream repo changes...<commit_after>package lib

import (
	"encoding/json"
	marathon "github.com/gambol99/go-marathon"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/mock"
	"testing"
)

type MockMarathonClient struct {
	mock.Mock
}

func (c *MockMarathonClient) ListApplications() ([]string, error) {
	var thing []string
	return thing, nil
}

func (c *MockMarathonClient) Tasks(string) (*marathon.Tasks, error) {
	jsonTasks := `{
    "tasks": [
        {
            "appId":"/infrastructure/docker-registry",
            "id":"infrastructure_docker-registry.872a3060-dfae-11e4-bdf0-3624e0a93f16",
            "host":"ip-10-120-100-25.us-west-2.compute.internal",
            "ports":[5000],
            "startedAt":"2015-04-10T18:22:52.829Z",
            "stagedAt":"2015-04-10T18:22:21.295Z",
            "version":"2015-04-09T23:40:51.805Z"
        }
    ]
}`
	var expected marathon.Tasks
	json.Unmarshal([]byte(jsonTasks), &expected)
	return &expected, nil
}

func (c *MockMarathonClient) Applications() (*marathon.Applications, error) {
	jsonContainers := `{
    "apps": [
        {
            "args": null,
            "backoffFactor": 1.15,
            "backoffSeconds": 1,
            "cmd": "python3 -m http.server 8080",
            "constraints": [],
            "container": {
                "docker": {
                    "image": "python:3",
                    "network": "BRIDGE",
                    "portMappings": [
                        {
                            "containerPort": 8080,
                            "hostPort": 0,
                            "servicePort": 9000,
                            "protocol": "tcp"
                        },
                        {
                            "containerPort": 161,
                            "hostPort": 0,
                            "protocol": "udp"
                        }
                    ]
                },
                "type": "DOCKER",
                "volumes": []
            },
            "cpus": 0.5,
            "dependencies": [],
            "deployments": [],
            "disk": 0.0,
            "env": {},
            "executor": "",
            "healthChecks": [
                {
                    "command": null,
                    "gracePeriodSeconds": 5,
                    "intervalSeconds": 20,
                    "maxConsecutiveFailures": 3,
                    "path": "/",
                    "portIndex": 0,
                    "protocol": "HTTP",
                    "timeoutSeconds": 20
                }
            ],
            "id": "/fake_app",
            "instances": 2,
            "mem": 64.0,
            "ports": [
                10000,
                10001
            ],
            "requirePorts": false,
            "storeUrls": [],
            "tasksRunning": 2,
            "tasksStaged": 0,
            "upgradeStrategy": {
                "minimumHealthCapacity": 1.0
            },
            "uris": [],
            "user": null,
            "version": "2014-09-25T02:26:59.256Z"
        },
        {
            "args": null,
            "backoffFactor": 1.15,
            "backoffSeconds": 1,
            "cmd": "python3 -m http.server 8080",
            "constraints": [],
            "container": {
                "docker": {
                    "image": "python:3",
                    "network": "BRIDGE",
                    "portMappings": [
                        {
                            "containerPort": 8080,
                            "hostPort": 0,
                            "servicePort": 9000,
                            "protocol": "tcp"
                        },
                        {
                            "containerPort": 161,
                            "hostPort": 0,
                            "protocol": "udp"
                        }
                    ]
                },
                "type": "DOCKER",
                "volumes": []
            },
            "cpus": 1.5,
            "dependencies": [],
            "deployments": [],
            "disk": 0.0,
            "env": {},
            "executor": "",
            "healthChecks": [
                {
                    "command": null,
                    "gracePeriodSeconds": 5,
                    "intervalSeconds": 20,
                    "maxConsecutiveFailures": 3,
                    "path": "/",
                    "portIndex": 0,
                    "protocol": "HTTP",
                    "timeoutSeconds": 20
                }
            ],
            "id": "/fake_app_broken",
            "instances": 2,
            "mem": 64.0,
            "ports": [
                10000,
                10001
            ],
            "requirePorts": false,
            "storeUrls": [],
            "tasksRunning": 2,
            "tasksStaged": 0,
            "upgradeStrategy": {
                "minimumHealthCapacity": 1.0
            },
            "uris": [],
            "user": null,
            "version": "2014-09-25T02:26:59.256Z"
        }
    ]
}`
	var expected marathon.Applications
	json.Unmarshal([]byte(jsonContainers), &expected)
	return &expected, nil
}

func expApplications() *marathon.Applications {
	return &marathon.Applications{
		Apps: []marathon.Application{
			marathon.Application{
				ID:   "/fake_app",
				CPUs: float64(0.5),
				Mem:  float64(64),
				Disk: float64(0),
			},
			marathon.Application{
				ID:   "/fake_app_broken",
				CPUs: float64(1.5),
				Mem:  float64(64),
				Disk: float64(0),
			},
		},
	}
}

func expMarathonApps() *MarathonApps {
	return &MarathonApps{
		Apps: []*MarathonApp{
			expFakeApp(),
		},
	}
}

func expFakeApp() *MarathonApp {
	return &MarathonApp{
		Id: "/fake_app",
		Tasks: []*MarathonTask{
			&MarathonTask{
				Id:        "fake-app-task",
				Container: "fake-app-container",
				SlaveId:   "slave1",
				SlaveHost: "slave1-host",
			},
		},
	}
}

func TestLoadApps(t *testing.T) {
	m := &Marathon{}
	mockClient := new(MockMarathonClient)
	err := m.LoadApps(mockClient)
	exp := expApplications()
	assert.Nil(t, err)
	assert.Equal(t, len(m.Apps), len(exp.Apps), "The expected number of apps should be returned")
	for i, app := range exp.Apps {
		assert.Equal(t, m.Apps[i].ID, app.ID, "App should be returned")
	}
}

func TestGetAppById(t *testing.T) {
	apps := expMarathonApps()
	app := apps.GetAppById("/fake_app")
	assert.Equal(t, app.Id, "/fake_app")
}

func TestGetAppByIdNotExist(t *testing.T) {
	apps := expMarathonApps()
	app := apps.GetAppById("/no_app")
	assert.Nil(t, app)
}

func TestGetTaskById(t *testing.T) {
	app := expFakeApp()
	task := app.GetTaskById("fake-app-task")
	assert.Equal(t, task.Id, "fake-app-task")
}

func TestAddTaskExistingApp(t *testing.T) {
	apps := expMarathonApps()
	apps.AddTask("new-fake-app-task", "/fake_app", "slave2", "slave2-host", true, false, false)
	assert.Equal(t, apps.Apps[0].Tasks[0].Id, "fake-app-task", "Original task should still exist")
	assert.Equal(t, apps.Apps[0].Tasks[1].Id, "new-fake-app-task", "New Task ID should exist")
}

func TestAddTaskNotExistingApp(t *testing.T) {
	apps := expMarathonApps()
	apps.AddTask("faker-app-task", "/faker_app", "slave1", "slave1-host", true, false, false)
	assert.Equal(t, apps.Apps[1].Id, "/faker_app", "New app should exist")
	assert.Equal(t, apps.Apps[1].Tasks[0].Id, "faker-app-task", "New app task should exist")
}

func TestAddAppExisting(t *testing.T) {
	apps := expMarathonApps()
	apps.AddApp("/fake_app")
	assert.Equal(t, len(apps.Apps), 1, "No new app should be added")
	assert.Equal(t, apps.Apps[0].Id, "/fake_app", "Original app should still exist")
}

func TestAddAppNotExisting(t *testing.T) {
	apps := expMarathonApps()
	apps.AddApp("/faker_app")
	assert.Equal(t, len(apps.Apps), 2, "An additional app should exist")
	assert.Equal(t, apps.Apps[0].Id, "/fake_app", "Original app should still exist")
	assert.Equal(t, apps.Apps[1].Id, "/faker_app", "New app should exist")
}
<|endoftext|>


<commit_before>/*******************************************************************************
The MIT License (MIT)

Copyright (c) 2013 Hajime Nakagami

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*******************************************************************************/

package firebirdsql

import (
    "testing"
    "database/sql"
)

func TestConnect(t *testing.T) {
    conn, err := sql.Open("firebirdsql", "sysdba:masterkey@localhost:3050/tmp/go_test.fdb")
    if err != nil {
        t.Fatalf("Error connecting: %v", err)
    }
    var sql string
    var n int

    sql = "SELECT Count(*) FROM rdb$relations where rdb$relation_name='FOO'"
    err = conn.QueryRow(sql).Scan(&n)
    if err != nil {
        t.Fatalf("Error QueryRow: %v", err)
    }
    if n > 0 {
        conn.Exec("DROP TABLE foo")
    }

    sql = `
        CREATE TABLE foo (
            a INTEGER NOT NULL,
            b VARCHAR(30) NOT NULL UNIQUE,
            c VARCHAR(1024),
            d DECIMAL(16,3) DEFAULT -0.123,
            e DATE DEFAULT '1967-08-11',
            f TIMESTAMP DEFAULT '1967-08-11 23:45:01',
            g TIME DEFAULT '23:45:01',
            h BLOB SUB_TYPE 1,
            i DOUBLE PRECISION DEFAULT 0.0,
            j FLOAT DEFAULT 0.0,
            PRIMARY KEY (a),
            CONSTRAINT CHECK_A CHECK (a <> 0)
        )
    `
    conn.Exec(sql)
    // 3 records insert
    conn.Exec("insert into foo(a, b, c,h) values (1, 'a', 'b','This is a memo')")
    conn.Exec("insert into foo(a, b, c, e, g, i, j) values (2, 'A', 'B', '1999-01-25', '00:00:01', 0.1, 0.1)")
    conn.Exec("insert into foo(a, b, c, e, g, i, j) values (3, 'X', 'Y', '2001-07-05', '00:01:02', 0.2, 0.2)")

    err = conn.QueryRow("select count(*) cnt from foo").Scan(&n)
    if err != nil {
        t.Fatalf("Error QueryRow: %v", err)
    }
    if n != 3 {
        t.Fatalf("Error bad record count: %v", n)
    }

    rows, err := conn.Query("select a, b, c, i, j from foo")
    for rows.Next() {
        // TODO:
    }

    defer conn.Close()

}
<commit_msg>Fetch and Scan float32 & float64<commit_after>/*******************************************************************************
The MIT License (MIT)

Copyright (c) 2013 Hajime Nakagami

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*******************************************************************************/

package firebirdsql

import (
    "testing"
    "database/sql"
)

func TestConnect(t *testing.T) {
    conn, err := sql.Open("firebirdsql", "sysdba:masterkey@localhost:3050/tmp/go_test.fdb")
    if err != nil {
        t.Fatalf("Error connecting: %v", err)
    }
    var sql string
    var n int

    sql = "SELECT Count(*) FROM rdb$relations where rdb$relation_name='FOO'"
    err = conn.QueryRow(sql).Scan(&n)
    if err != nil {
        t.Fatalf("Error QueryRow: %v", err)
    }
    if n > 0 {
        conn.Exec("DROP TABLE foo")
    }

    sql = `
        CREATE TABLE foo (
            a INTEGER NOT NULL,
            b VARCHAR(30) NOT NULL UNIQUE,
            c VARCHAR(1024),
            d DECIMAL(16,3) DEFAULT -0.123,
            e DATE DEFAULT '1967-08-11',
            f TIMESTAMP DEFAULT '1967-08-11 23:45:01',
            g TIME DEFAULT '23:45:01',
            h BLOB SUB_TYPE 1,
            i DOUBLE PRECISION DEFAULT 0.0,
            j FLOAT DEFAULT 0.0,
            PRIMARY KEY (a),
            CONSTRAINT CHECK_A CHECK (a <> 0)
        )
    `
    conn.Exec(sql)
    // 3 records insert
    conn.Exec("insert into foo(a, b, c,h) values (1, 'a', 'b','This is a memo')")
    conn.Exec("insert into foo(a, b, c, e, g, i, j) values (2, 'A', 'B', '1999-01-25', '00:00:01', 0.1, 0.1)")
    conn.Exec("insert into foo(a, b, c, e, g, i, j) values (3, 'X', 'Y', '2001-07-05', '00:01:02', 0.2, 0.2)")

    err = conn.QueryRow("select count(*) cnt from foo").Scan(&n)
    if err != nil {
        t.Fatalf("Error QueryRow: %v", err)
    }
    if n != 3 {
        t.Fatalf("Error bad record count: %v", n)
    }

    rows, err := conn.Query("select a, b, c, i, j from foo")
    var a int
    var b, c string
    var i float64
    var j float32
    for rows.Next() {
        rows.Scan(&a, &b, &c, &i, &j)
//        fmt.Println(a, b, i, j)
    }

    defer conn.Close()

}
<|endoftext|>


<commit_before>/*******************************************************************************
The MIT License (MIT)

Copyright (c) 2013-2014 Hajime Nakagami

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*******************************************************************************/

package firebirdsql

import (
	"database/sql"
	"testing"
	"time"
)

func TestBasic(t *testing.T) {
	conn, err := sql.Open("firebirdsql_createdb", "sysdba:masterkey@localhost:3050/tmp/go_test.fdb")
	defer conn.Close()

	if err != nil {
		t.Fatalf("Error connecting: %v", err)
	}
	var sql string
	var n int

	sql = "SELECT Count(*) FROM rdb$relations where rdb$relation_name='FOO'"
	err = conn.QueryRow(sql).Scan(&n)
	if err != nil {
		t.Fatalf("Error QueryRow: %v", err)
	}
	if n > 0 {
		conn.Exec("DROP TABLE foo")
	}

	sql = `
        CREATE TABLE foo (
            a INTEGER NOT NULL,
            b VARCHAR(30) NOT NULL UNIQUE,
            c VARCHAR(1024),
            d DECIMAL(16,3) DEFAULT -0.123,
            e DATE DEFAULT '1967-08-11',
            f TIMESTAMP DEFAULT '1967-08-11 23:45:01',
            g TIME DEFAULT '23:45:01',
            h BLOB SUB_TYPE 1,
            i DOUBLE PRECISION DEFAULT 0.0,
            j FLOAT DEFAULT 0.0,
            PRIMARY KEY (a),
            CONSTRAINT CHECK_A CHECK (a <> 0)
        )
    `
	conn.Exec(sql)
	_, err = conn.Exec("CREATE TABLE foo (a INTEGER)")
	if err == nil {
		t.Fatalf("Need metadata update error")
	}
	if err.Error() != "unsuccessful metadata update\nTable FOO already exists\n" {
		t.Fatalf("Bad message:%v", err.Error())
	}

	// 3 records insert
	conn.Exec("insert into foo(a, b, c,h) values (1, 'a', 'b','This is a memo')")
	conn.Exec("insert into foo(a, b, c, e, g, i, j) values (2, 'A', 'B', '1999-01-25', '00:00:01', 0.1, 0.1)")
	conn.Exec("insert into foo(a, b, c, e, g, i, j) values (3, 'X', 'Y', '2001-07-05', '00:01:02', 0.2, 0.2)")

	err = conn.QueryRow("select count(*) cnt from foo").Scan(&n)
	if err != nil {
		t.Fatalf("Error QueryRow: %v", err)
	}
	if n != 3 {
		t.Fatalf("Error bad record count: %v", n)
	}

	rows, err := conn.Query("select a, b, c, d, e, f, g, i, j from foo")
	var a int
	var b, c string
	var d float64
	var e time.Time
	var f time.Time
	var g time.Time
	var i float64
	var j float32

	for rows.Next() {
		rows.Scan(&a, &b, &c, &d, &e, &f, &g, &i, &j)
	}

	stmt, _ := conn.Prepare("select count(*) from foo where a=? and b=? and d=? and e=? and f=? and g=?")
	ep := time.Date(1967, 8, 11, 0, 0, 0, 0, time.UTC)
	fp := time.Date(1967, 8, 11, 23, 45, 1, 0, time.UTC)
	gp, err := time.Parse("15:04:05", "23:45:01")
	err = stmt.QueryRow(1, "a", -0.123, ep, fp, gp).Scan(&n)
	if err != nil {
		t.Fatalf("Error QueryRow: %v", err)
	}
	if n != 1 {
		t.Fatalf("Error bad record count: %v", n)
	}

}

func TestIssue2(t *testing.T) {
	conn, _ := sql.Open("firebirdsql_createdb", "sysdba:masterkey@localhost:3050/tmp/go_test.fdb")

	conn.Exec(`
        CREATE TABLE test_issue2
         (f1 integer NOT NULL,
          f2 integer,
          f3 integer NOT NULL,
          f4 integer NOT NULL,
          f5 integer NOT NULL,
          f6 integer NOT NULL,
          f7 varchar(255) NOT NULL,
          f8 varchar(255) NOT NULL,
          f9 varchar(255) NOT NULL,
          f10 varchar(255) NOT NULL,
          f11 varchar(255) NOT NULL,
          f12 varchar(255) NOT NULL,
          f13 varchar(255) NOT NULL,
          f14 varchar(255) NOT NULL,
          f15 integer,
          f16 integer,
          f17 integer,
          f18 integer,
          f19 integer,
          f20 integer,
          f21 integer,
          f22 varchar(1),
          f23 varchar(255),
          f24 integer,
          f25 varchar(64),
          f26 integer)`)
	defer conn.Close()

	conn.Exec(`
        INSERT INTO test_issue2 VALUES
        (1, 2, 3, 4, 5, 6, '7', '8', '9', '10', '11', '12', '13', '14',
          15, 16, 17, 18, 19, 20, 21, 'A', '23', 24, '25', '26')`)

	rows, err := conn.Query("SELECT * FROM test_issue2")
	if err != nil {
		t.Fatalf("Error Query: %v", err)
	}
	for rows.Next() {
	}
}

func TestIssue3(t *testing.T) {
	conn, _ := sql.Open("firebirdsql_createdb", "sysdba:masterkey@localhost:3050/tmp/go_test.fdb")
	too_many := 401

	conn.Exec("CREATE TABLE test_issue3 (f1 integer NOT NULL)")
	defer conn.Close()
	stmt, _ := conn.Prepare("INSERT INTO test_issue3 values (?)")
	for i := 0; i < too_many; i++ {
		stmt.Exec(i + 1)
	}

	rows, _ := conn.Query("SELECT * FROM test_issue3 ORDER BY f1")
	i := 0
	var n int
	for rows.Next() {
		rows.Scan(&n)
		i++
		if i != n {
			t.Fatalf("Error %v != %v", n, i)
		}
	}
	if i != too_many {
		t.Fatalf("Can't get all %v records. only %v", too_many, i)
	}
}

func TestError(t *testing.T) {
	conn, err := sql.Open("firebirdsql_createdb", "sysdba:masterkey@localhost:3050/tmp/go_test.fdb")
	if err != nil {
		t.Fatalf("Error connecting: %v", err)
	}
	_, err = conn.Exec("incorrect sql statement")
	if err == nil || err.Error() != "Dynamic SQL Error\nSQL error code = -104\nToken unknown - line 1, column 1\nincorrect\n" {
		t.Fatalf("Incorrect error")
	}
}

/*
func TestFB3(t *testing.T) {
	conn, err := sql.Open("firebirdsql_createdb", "sysdba:masterkey@localhost:3050/tmp/go_test.fdb")
	if err != nil {
		t.Fatalf("Error connecting: %v", err)
	}
	var sql string
	var n int

	sql = "SELECT Count(*) FROM rdb$relations where rdb$relation_name='TEST_FB3'"
	err = conn.QueryRow(sql).Scan(&n)
	if err != nil {
		t.Fatalf("Error QueryRow: %v", err)
	}
	if n > 0 {
		conn.Exec("DROP TABLE test_fb3")
	}

	sql = `
        CREATE TABLE test_fb3 (
            b BOOLEAN
        )
    `
	conn.Exec(sql)
	conn.Exec("insert into test_fb3(b) values (true)")
	conn.Exec("insert into test_fb3(b) values (false)")
    var b bool
	err = conn.QueryRow("select * from test_fb3 where b is true").Scan(&b)
	if err != nil {
		t.Fatalf("Error QueryRow: %v", err)
	}
	if b != true{
		conn.Exec("Invalid boolean value")
	}
	err = conn.QueryRow("select * from test_fb3 where b is false").Scan(&b)
	if err != nil {
		t.Fatalf("Error QueryRow: %v", err)
	}
	if b != false{
		conn.Exec("Invalid boolean value")
	}

	stmt, _ := conn.Prepare("select * from test_fb3 where b=?")
	err = stmt.QueryRow(true).Scan(&b)
	if err != nil {
		t.Fatalf("Error QueryRow: %v", err)
	}
	if b != false{
		conn.Exec("Invalid boolean value")
	}

	defer conn.Close()
}
*/
<commit_msg>add test for 'insert ... returning ...'<commit_after>/*******************************************************************************
The MIT License (MIT)

Copyright (c) 2013-2014 Hajime Nakagami

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*******************************************************************************/

package firebirdsql

import (
	"database/sql"
	"testing"
	"time"
)

func TestBasic(t *testing.T) {
	conn, err := sql.Open("firebirdsql_createdb", "sysdba:masterkey@localhost:3050/tmp/go_test.fdb")
	defer conn.Close()

	if err != nil {
		t.Fatalf("Error connecting: %v", err)
	}
	var sql string
	var n int

	sql = "SELECT Count(*) FROM rdb$relations where rdb$relation_name='FOO'"
	err = conn.QueryRow(sql).Scan(&n)
	if err != nil {
		t.Fatalf("Error QueryRow: %v", err)
	}
	if n > 0 {
		conn.Exec("DROP TABLE foo")
	}

	sql = `
        CREATE TABLE foo (
            a INTEGER NOT NULL,
            b VARCHAR(30) NOT NULL UNIQUE,
            c VARCHAR(1024) DEFAULT 'abc',
            d DECIMAL(16,3) DEFAULT -0.123,
            e DATE DEFAULT '1967-08-11',
            f TIMESTAMP DEFAULT '1967-08-11 23:45:01',
            g TIME DEFAULT '23:45:01',
            h BLOB SUB_TYPE 1,
            i DOUBLE PRECISION DEFAULT 0.0,
            j FLOAT DEFAULT 0.0,
            PRIMARY KEY (a),
            CONSTRAINT CHECK_A CHECK (a <> 0)
        )
    `
	conn.Exec(sql)
	_, err = conn.Exec("CREATE TABLE foo (a INTEGER)")
	if err == nil {
		t.Fatalf("Need metadata update error")
	}
	if err.Error() != "unsuccessful metadata update\nTable FOO already exists\n" {
		t.Fatalf("Bad message:%v", err.Error())
	}

	// 3 records insert
	conn.Exec("insert into foo(a, b, c,h) values (1, 'a', 'b','This is a memo')")
	conn.Exec("insert into foo(a, b, c, e, g, i, j) values (2, 'A', 'B', '1999-01-25', '00:00:01', 0.1, 0.1)")
	conn.Exec("insert into foo(a, b, c, e, g, i, j) values (3, 'X', 'Y', '2001-07-05', '00:01:02', 0.2, 0.2)")

	err = conn.QueryRow("select count(*) cnt from foo").Scan(&n)
	if err != nil {
		t.Fatalf("Error QueryRow: %v", err)
	}
	if n != 3 {
		t.Fatalf("Error bad record count: %v", n)
	}

	rows, err := conn.Query("select a, b, c, d, e, f, g, i, j from foo")
	var a int
	var b, c string
	var d float64
	var e time.Time
	var f time.Time
	var g time.Time
	var i float64
	var j float32

	for rows.Next() {
		rows.Scan(&a, &b, &c, &d, &e, &f, &g, &i, &j)
	}

	stmt, _ := conn.Prepare("select count(*) from foo where a=? and b=? and d=? and e=? and f=? and g=?")
	ep := time.Date(1967, 8, 11, 0, 0, 0, 0, time.UTC)
	fp := time.Date(1967, 8, 11, 23, 45, 1, 0, time.UTC)
	gp, err := time.Parse("15:04:05", "23:45:01")
	err = stmt.QueryRow(1, "a", -0.123, ep, fp, gp).Scan(&n)
	if err != nil {
		t.Fatalf("Error QueryRow: %v", err)
	}
	if n != 1 {
		t.Fatalf("Error bad record count: %v", n)
	}

	rows, err = conn.Query("insert into foo(a, b) values (4, '4') returning c")
	if err != nil {
		t.Fatalf("Error Insert returning : %v", err)
	}
	rows.Next()
	rows.Scan(&c)
	if c != "abc" {
		t.Fatalf("Error insert returning: %v", c)
	}

}

func TestIssue2(t *testing.T) {
	conn, _ := sql.Open("firebirdsql_createdb", "sysdba:masterkey@localhost:3050/tmp/go_test.fdb")

	conn.Exec(`
        CREATE TABLE test_issue2
         (f1 integer NOT NULL,
          f2 integer,
          f3 integer NOT NULL,
          f4 integer NOT NULL,
          f5 integer NOT NULL,
          f6 integer NOT NULL,
          f7 varchar(255) NOT NULL,
          f8 varchar(255) NOT NULL,
          f9 varchar(255) NOT NULL,
          f10 varchar(255) NOT NULL,
          f11 varchar(255) NOT NULL,
          f12 varchar(255) NOT NULL,
          f13 varchar(255) NOT NULL,
          f14 varchar(255) NOT NULL,
          f15 integer,
          f16 integer,
          f17 integer,
          f18 integer,
          f19 integer,
          f20 integer,
          f21 integer,
          f22 varchar(1),
          f23 varchar(255),
          f24 integer,
          f25 varchar(64),
          f26 integer)`)
	defer conn.Close()

	conn.Exec(`
        INSERT INTO test_issue2 VALUES
        (1, 2, 3, 4, 5, 6, '7', '8', '9', '10', '11', '12', '13', '14',
          15, 16, 17, 18, 19, 20, 21, 'A', '23', 24, '25', '26')`)

	rows, err := conn.Query("SELECT * FROM test_issue2")
	if err != nil {
		t.Fatalf("Error Query: %v", err)
	}
	for rows.Next() {
	}
}

func TestIssue3(t *testing.T) {
	conn, _ := sql.Open("firebirdsql_createdb", "sysdba:masterkey@localhost:3050/tmp/go_test.fdb")
	too_many := 401

	conn.Exec("CREATE TABLE test_issue3 (f1 integer NOT NULL)")
	defer conn.Close()
	stmt, _ := conn.Prepare("INSERT INTO test_issue3 values (?)")
	for i := 0; i < too_many; i++ {
		stmt.Exec(i + 1)
	}

	rows, _ := conn.Query("SELECT * FROM test_issue3 ORDER BY f1")
	i := 0
	var n int
	for rows.Next() {
		rows.Scan(&n)
		i++
		if i != n {
			t.Fatalf("Error %v != %v", n, i)
		}
	}
	if i != too_many {
		t.Fatalf("Can't get all %v records. only %v", too_many, i)
	}
}

func TestError(t *testing.T) {
	conn, err := sql.Open("firebirdsql_createdb", "sysdba:masterkey@localhost:3050/tmp/go_test.fdb")
	if err != nil {
		t.Fatalf("Error connecting: %v", err)
	}
	_, err = conn.Exec("incorrect sql statement")
	if err == nil || err.Error() != "Dynamic SQL Error\nSQL error code = -104\nToken unknown - line 1, column 1\nincorrect\n" {
		t.Fatalf("Incorrect error")
	}
}

/*
func TestFB3(t *testing.T) {
	conn, err := sql.Open("firebirdsql_createdb", "sysdba:masterkey@localhost:3050/tmp/go_test.fdb")
	if err != nil {
		t.Fatalf("Error connecting: %v", err)
	}
	var sql string
	var n int

	sql = "SELECT Count(*) FROM rdb$relations where rdb$relation_name='TEST_FB3'"
	err = conn.QueryRow(sql).Scan(&n)
	if err != nil {
		t.Fatalf("Error QueryRow: %v", err)
	}
	if n > 0 {
		conn.Exec("DROP TABLE test_fb3")
	}

	sql = `
        CREATE TABLE test_fb3 (
            b BOOLEAN
        )
    `
	conn.Exec(sql)
	conn.Exec("insert into test_fb3(b) values (true)")
	conn.Exec("insert into test_fb3(b) values (false)")
    var b bool
	err = conn.QueryRow("select * from test_fb3 where b is true").Scan(&b)
	if err != nil {
		t.Fatalf("Error QueryRow: %v", err)
	}
	if b != true{
		conn.Exec("Invalid boolean value")
	}
	err = conn.QueryRow("select * from test_fb3 where b is false").Scan(&b)
	if err != nil {
		t.Fatalf("Error QueryRow: %v", err)
	}
	if b != false{
		conn.Exec("Invalid boolean value")
	}

	stmt, _ := conn.Prepare("select * from test_fb3 where b=?")
	err = stmt.QueryRow(true).Scan(&b)
	if err != nil {
		t.Fatalf("Error QueryRow: %v", err)
	}
	if b != false{
		conn.Exec("Invalid boolean value")
	}

	defer conn.Close()
}
*/
<|endoftext|>


<commit_before>package models

import (
	"fmt"
	"time"
)

type MarketHistory struct {
	Date     time.Time `db:"date" json:"date"`
	Low      float64   `db:"low" json:"low"`
	High     float64   `db:"high" json:"high"`
	Open     float64   `db:"open" json:"open"`
	Close    float64   `db:"close" json:"close"`
	Quantity int64     `db:"quantity" json:"quantity"`
}

// [BENCHMARK] 0.407 sec / 0.421 sec [TODO] Optimize
func GetMarketHistory(itemID int64, regionID int32) ([]MarketHistory, error) {
	s := []MarketHistory{}
	if err := database.Select(&s, `
		SELECT H.date, H.low, H.high, H.mean AS close, Y.mean AS open, H.quantity
		FROM evedata.market_history H
		INNER JOIN evedata.market_history Y ON H.date = DATE_SUB(Y.date, INTERVAL 1 DAY)
			AND H.regionID = Y.regionID
			AND H.itemID = Y.itemID
		WHERE H.regionID = ? AND H.itemID = ? AND H.quantity > 10
	`, regionID, itemID); err != nil {
		return nil, err
	}
	return s, nil
}

type ArbitrageCalculatorStations struct {
	StationName string `db:"stationName" json:"stationName" `
	StationID   string `db:"stationID" json:"stationID" `
}

// [BENCHMARK] 0.015 sec / 0.000 sec
func GetArbitrageCalculatorStations() ([]ArbitrageCalculatorStations, error) {
	s := []ArbitrageCalculatorStations{}
	if err := database.Select(&s, `
		SELECT stationID, stationName
			FROM    evedata.marketStations
			WHERE 	Count > 4000
			ORDER BY stationName
	`); err != nil {
		return nil, err
	}
	return s, nil
}

type ArbitrageCalculator struct {
	TypeID   int64  `db:"typeID" json:"typeID" `
	TypeName string `db:"typeName" json:"typeName" `
	Volume   int64  `db:"volume" json:"volume" `
	Buys     int64  `db:"buys" json:"buys" `
	Margin   string `db:"margin" json:"margin" `
}

func GetArbitrageCalculator(stationID int64, minVolume int64, maxPrice int64, brokersFee float64, tax float64, method string) ([]ArbitrageCalculator, error) {
	type buys struct {
		TypeID   int64   `db:"typeID"`
		TypeName string  `db:"typeName"`
		Buys     int64   `db:"buys"`
		Volume   int64   `db:"volume"`
		Price    float64 `db:"price"`
	}
	type sells struct {
		TypeID int64   `db:"typeID"`
		Price  float64 `db:"price"`
	}

	errc := make(chan error)

	b := []buys{}

	go func() {
		// [BENCHMARK] 0.432 sec / 0.016 sec
		err := database.Select(&b, `
		SELECT  market.typeID AS typeID, typeName, count(*) as buys, ROUND(market_vol.quantity / 2) as volume, ROUND(max(price) + (max(price) * ?),2) AS price
		FROM    evedata.market, invTypes, evedata.market_vol
		WHERE   market.typeID = market_vol.itemID AND
		        market.regionID = market_vol.regionID AND
		        market.typeID = invTypes.typeID AND
		        market.stationID = ?
		        AND bid = 1
		        AND market_vol.quantity /2 > ?
		GROUP BY market.typeID
		HAVING price < ?`, brokersFee, stationID, minVolume, maxPrice)

		errc <- err
	}()

	sellOrders := make(map[int64]sells)
	s := []sells{}
	go func() {
		// [BENCHMARK] 0.297 sec / 0.000 sec
		err := database.Select(&s, `
		SELECT  typeID, ROUND(min(price) - (min(price) * ?) - (min(price) * ?),2) AS price
		FROM    evedata.market
		WHERE   market.stationID = ?
		        AND bid = 0
		        AND price < ?
		        GROUP BY typeID`, brokersFee, tax, stationID, maxPrice)

		// Add broker fee to all orders.
		for _, order := range s {
			sellOrders[order.TypeID] = order
		}
		errc <- err
	}()

	margins := []ArbitrageCalculator{}

	// clear the error channel
	for i := 0; i < 2; i++ {
		err := <-errc
		if err != nil {
			return nil, err
		}
	}

	for _, buyOrder := range b {
		sellOrder, ok := sellOrders[buyOrder.TypeID]

		if !ok {
			continue
		}
		if method == "delta" {
			if (sellOrder.Price - buyOrder.Price) > 500000 {
				newOrder := ArbitrageCalculator{}

				newOrder.Buys = buyOrder.Buys
				newOrder.Volume = ((int64)(sellOrder.Price+buyOrder.Price) / 2) * buyOrder.Volume
				newOrder.TypeID = buyOrder.TypeID
				newOrder.TypeName = buyOrder.TypeName
				newOrder.Margin = fmt.Sprintf("%.2f", sellOrder.Price-buyOrder.Price)

				margins = append(margins, newOrder)
			}
		} else if method == "percentage" {
			if (sellOrder.Price / buyOrder.Price) > 1.05 {
				newOrder := ArbitrageCalculator{}

				newOrder.Buys = buyOrder.Buys
				newOrder.Volume = ((int64)(sellOrder.Price+buyOrder.Price) / 2) * buyOrder.Volume
				newOrder.TypeID = buyOrder.TypeID
				newOrder.TypeName = buyOrder.TypeName
				newOrder.Margin = fmt.Sprintf("%.2f", sellOrder.Price/buyOrder.Price)

				margins = append(margins, newOrder)
			}
		}
	}

	return margins, nil
}

type MarketRegion struct {
	RegionID   int32  `db:"regionID"`
	RegionName string `db:"regionName"`
}

// [BENCHMARK] 0.000 sec / 0.000 sec
// Anywhere can now have a public market.
func GetMarketRegions() ([]MarketRegion, error) {
	v := []MarketRegion{}
	err := database.Select(&v, `
		SELECT 	regionID, regionName
		FROM 	mapRegions
		WHERE regionID < 11000000;
	`)
	if err != nil {
		return nil, err
	}
	return v, nil
}

type MarketType struct {
	TypeID   int32  `db:"typeID"`
	TypeName string `db:"typeName"`
}

// [BENCHMARK] 0.000 sec / 0.047 sec
func GetMarketTypes() ([]MarketType, error) {
	v := []MarketType{}
	err := database.Select(&v, `
		SELECT 	typeID, typeName
		FROM 	invTypes
		WHERE 	marketGroupID IS NOT NULL
	`)
	if err != nil {
		return nil, err
	}
	return v, nil
}

type MarketItems struct {
	StationName string `db:"stationName" json:"stationName"`
	StationID   string `db:"stationID"   json:"stationID"   `
	Quantity    string `db:"quantity"    json:"quantity"   `
	Price       string `db:"price"       json:"price"      `
}

const (
	highSec = 1 << iota
	lowSec  = 1 << iota
	nullSec = 1 << iota
)

func MarketRegionItems(regionID int, itemID int, secFlags int, buy bool) ([]MarketItems, error) {
	var (
		secFilter     string
		secFilterPass int
		err           error
	)

	mR := []MarketItems{}

	if secFlags&highSec != 0 {
		secFilterPass++
		secFilter += "round(Sy.security,1) >= 0.5"
	}

	if secFlags&lowSec != 0 {
		secFilterPass++
		if secFilterPass > 1 {
			secFilter += " OR "
		}
		secFilter += "round(Sy.security,1) BETWEEN 0.1 AND 0.4"
	}

	if secFlags&nullSec != 0 {
		secFilterPass++
		if secFilterPass > 1 {
			secFilter += " OR "
		}

		secFilter += "round(Sy.security,1) <= 0 "
	}

	if regionID == 0 {
		err = database.Select(&mR, `
			SELECT  remainingVolume AS quantity, price, stationName, M.stationID
				FROM    evedata.market M
				INNER JOIN staStations S ON S.stationID=M.stationID
				INNER JOIN mapSolarSystems Sy ON Sy.solarSystemID = S.solarSystemID
				WHERE	bid=? AND
						typeID = ? AND (`+secFilter+`);
			`, buy, itemID)
	} else {
		err = database.Select(&mR, `
			SELECT  remainingVolume AS quantity, price, stationName, M.stationID
				FROM    evedata.market M
				INNER JOIN staStations S ON S.stationID=M.stationID
				INNER JOIN mapSolarSystems Sy ON Sy.solarSystemID = S.solarSystemID
				WHERE	bid=? AND
						M.regionID = ? AND
						typeID = ? AND (`+secFilter+`);
			`, buy, regionID, itemID)
	}

	return mR, err
}
<commit_msg>Fix the many many errors we are causing to market history endpoint.<commit_after>package models

import (
	"fmt"
	"time"
)

type MarketHistory struct {
	Date     time.Time `db:"date" json:"date"`
	Low      float64   `db:"low" json:"low"`
	High     float64   `db:"high" json:"high"`
	Open     float64   `db:"open" json:"open"`
	Close    float64   `db:"close" json:"close"`
	Quantity int64     `db:"quantity" json:"quantity"`
}

// [BENCHMARK] 0.407 sec / 0.421 sec [TODO] Optimize
func GetMarketHistory(itemID int64, regionID int32) ([]MarketHistory, error) {
	s := []MarketHistory{}
	if err := database.Select(&s, `
		SELECT H.date, H.low, H.high, H.mean AS close, Y.mean AS open, H.quantity
		FROM evedata.market_history H
		INNER JOIN evedata.market_history Y ON H.date = DATE_SUB(Y.date, INTERVAL 1 DAY)
			AND H.regionID = Y.regionID
			AND H.itemID = Y.itemID
		WHERE H.regionID = ? AND H.itemID = ? AND H.quantity > 10
	`, regionID, itemID); err != nil {
		return nil, err
	}
	return s, nil
}

type ArbitrageCalculatorStations struct {
	StationName string `db:"stationName" json:"stationName" `
	StationID   string `db:"stationID" json:"stationID" `
}

// [BENCHMARK] 0.015 sec / 0.000 sec
func GetArbitrageCalculatorStations() ([]ArbitrageCalculatorStations, error) {
	s := []ArbitrageCalculatorStations{}
	if err := database.Select(&s, `
		SELECT stationID, stationName
			FROM    evedata.marketStations
			WHERE 	Count > 4000
			ORDER BY stationName
	`); err != nil {
		return nil, err
	}
	return s, nil
}

type ArbitrageCalculator struct {
	TypeID   int64  `db:"typeID" json:"typeID" `
	TypeName string `db:"typeName" json:"typeName" `
	Volume   int64  `db:"volume" json:"volume" `
	Buys     int64  `db:"buys" json:"buys" `
	Margin   string `db:"margin" json:"margin" `
}

func GetArbitrageCalculator(stationID int64, minVolume int64, maxPrice int64, brokersFee float64, tax float64, method string) ([]ArbitrageCalculator, error) {
	type buys struct {
		TypeID   int64   `db:"typeID"`
		TypeName string  `db:"typeName"`
		Buys     int64   `db:"buys"`
		Volume   int64   `db:"volume"`
		Price    float64 `db:"price"`
	}
	type sells struct {
		TypeID int64   `db:"typeID"`
		Price  float64 `db:"price"`
	}

	errc := make(chan error)

	b := []buys{}

	go func() {
		// [BENCHMARK] 0.432 sec / 0.016 sec
		err := database.Select(&b, `
		SELECT  market.typeID AS typeID, typeName, count(*) as buys, ROUND(market_vol.quantity / 2) as volume, ROUND(max(price) + (max(price) * ?),2) AS price
		FROM    evedata.market, invTypes, evedata.market_vol
		WHERE   market.typeID = market_vol.itemID AND
		        market.regionID = market_vol.regionID AND
		        market.typeID = invTypes.typeID AND
		        market.stationID = ?
		        AND bid = 1
		        AND market_vol.quantity /2 > ?
		GROUP BY market.typeID
		HAVING price < ?`, brokersFee, stationID, minVolume, maxPrice)

		errc <- err
	}()

	sellOrders := make(map[int64]sells)
	s := []sells{}
	go func() {
		// [BENCHMARK] 0.297 sec / 0.000 sec
		err := database.Select(&s, `
		SELECT  typeID, ROUND(min(price) - (min(price) * ?) - (min(price) * ?),2) AS price
		FROM    evedata.market
		WHERE   market.stationID = ?
		        AND bid = 0
		        AND price < ?
		        GROUP BY typeID`, brokersFee, tax, stationID, maxPrice)

		// Add broker fee to all orders.
		for _, order := range s {
			sellOrders[order.TypeID] = order
		}
		errc <- err
	}()

	margins := []ArbitrageCalculator{}

	// clear the error channel
	for i := 0; i < 2; i++ {
		err := <-errc
		if err != nil {
			return nil, err
		}
	}

	for _, buyOrder := range b {
		sellOrder, ok := sellOrders[buyOrder.TypeID]

		if !ok {
			continue
		}
		if method == "delta" {
			if (sellOrder.Price - buyOrder.Price) > 500000 {
				newOrder := ArbitrageCalculator{}

				newOrder.Buys = buyOrder.Buys
				newOrder.Volume = ((int64)(sellOrder.Price+buyOrder.Price) / 2) * buyOrder.Volume
				newOrder.TypeID = buyOrder.TypeID
				newOrder.TypeName = buyOrder.TypeName
				newOrder.Margin = fmt.Sprintf("%.2f", sellOrder.Price-buyOrder.Price)

				margins = append(margins, newOrder)
			}
		} else if method == "percentage" {
			if (sellOrder.Price / buyOrder.Price) > 1.05 {
				newOrder := ArbitrageCalculator{}

				newOrder.Buys = buyOrder.Buys
				newOrder.Volume = ((int64)(sellOrder.Price+buyOrder.Price) / 2) * buyOrder.Volume
				newOrder.TypeID = buyOrder.TypeID
				newOrder.TypeName = buyOrder.TypeName
				newOrder.Margin = fmt.Sprintf("%.2f", sellOrder.Price/buyOrder.Price)

				margins = append(margins, newOrder)
			}
		}
	}

	return margins, nil
}

type MarketRegion struct {
	RegionID   int32  `db:"regionID"`
	RegionName string `db:"regionName"`
}

// [BENCHMARK] 0.000 sec / 0.000 sec
// Anywhere can now have a public market.
func GetMarketRegions() ([]MarketRegion, error) {
	v := []MarketRegion{}
	err := database.Select(&v, `
		SELECT 	regionID, regionName
		FROM 	mapRegions
		WHERE regionID < 11000000;
	`)
	if err != nil {
		return nil, err
	}
	return v, nil
}

type MarketType struct {
	TypeID   int32  `db:"typeID"`
	TypeName string `db:"typeName"`
}

// [BENCHMARK] 0.000 sec / 0.047 sec
func GetMarketTypes() ([]MarketType, error) {
	v := []MarketType{}
	err := database.Select(&v, `
		SELECT 	typeID, typeName
		FROM 	invTypes
		WHERE 	marketGroupID IS NOT NULL
		AND published = 1
	`)
	if err != nil {
		return nil, err
	}
	return v, nil
}

type MarketItems struct {
	StationName string `db:"stationName" json:"stationName"`
	StationID   string `db:"stationID"   json:"stationID"   `
	Quantity    string `db:"quantity"    json:"quantity"   `
	Price       string `db:"price"       json:"price"      `
}

const (
	highSec = 1 << iota
	lowSec  = 1 << iota
	nullSec = 1 << iota
)

func MarketRegionItems(regionID int, itemID int, secFlags int, buy bool) ([]MarketItems, error) {
	var (
		secFilter     string
		secFilterPass int
		err           error
	)

	mR := []MarketItems{}

	if secFlags&highSec != 0 {
		secFilterPass++
		secFilter += "round(Sy.security,1) >= 0.5"
	}

	if secFlags&lowSec != 0 {
		secFilterPass++
		if secFilterPass > 1 {
			secFilter += " OR "
		}
		secFilter += "round(Sy.security,1) BETWEEN 0.1 AND 0.4"
	}

	if secFlags&nullSec != 0 {
		secFilterPass++
		if secFilterPass > 1 {
			secFilter += " OR "
		}

		secFilter += "round(Sy.security,1) <= 0 "
	}

	if regionID == 0 {
		err = database.Select(&mR, `
			SELECT  remainingVolume AS quantity, price, stationName, M.stationID
				FROM    evedata.market M
				INNER JOIN staStations S ON S.stationID=M.stationID
				INNER JOIN mapSolarSystems Sy ON Sy.solarSystemID = S.solarSystemID
				WHERE	bid=? AND
						typeID = ? AND (`+secFilter+`);
			`, buy, itemID)
	} else {
		err = database.Select(&mR, `
			SELECT  remainingVolume AS quantity, price, stationName, M.stationID
				FROM    evedata.market M
				INNER JOIN staStations S ON S.stationID=M.stationID
				INNER JOIN mapSolarSystems Sy ON Sy.solarSystemID = S.solarSystemID
				WHERE	bid=? AND
						M.regionID = ? AND
						typeID = ? AND (`+secFilter+`);
			`, buy, regionID, itemID)
	}

	return mR, err
}
<|endoftext|>


<commit_before>package command

import (
	"bytes"
	"context"
	"fmt"
	"path/filepath"
	"sync"
	"testing"

	"golang.org/x/sync/errgroup"

	"github.com/hashicorp/packer/builder/file"
	"github.com/hashicorp/packer/packer"
	"github.com/hashicorp/packer/provisioner/sleep"
)

// NewParallelTestBuilder will return a New ParallelTestBuilder that will
// unlock after `runs` builds
func NewParallelTestBuilder(runs int) *ParallelTestBuilder {
	pb := &ParallelTestBuilder{}
	pb.wg.Add(runs)
	return pb
}

// The ParallelTestBuilder's first run will lock
type ParallelTestBuilder struct {
	wg sync.WaitGroup
}

func (b *ParallelTestBuilder) Prepare(raws ...interface{}) ([]string, error) { return nil, nil }

func (b *ParallelTestBuilder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) {
	ui.Say("building")
	b.wg.Done()
	return nil, nil
}

// LockedBuilder wont run until unlock is called
type LockedBuilder struct{ unlock chan interface{} }

func (b *LockedBuilder) Prepare(raws ...interface{}) ([]string, error) { return nil, nil }

func (b *LockedBuilder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) {
	ui.Say("locking build")
	select {
	case <-b.unlock:
	case <-ctx.Done():
		return nil, ctx.Err()
	}
	return nil, nil
}

// testMetaFile creates a Meta object that includes a file builder
func testMetaParallel(t *testing.T, builder *ParallelTestBuilder, locked *LockedBuilder) Meta {
	var out, err bytes.Buffer
	return Meta{
		CoreConfig: &packer.CoreConfig{
			Components: packer.ComponentFinder{
				Builder: func(n string) (packer.Builder, error) {
					switch n {
					case "parallel-test":
						return builder, nil
					case "file":
						return &file.Builder{}, nil
					case "lock":
						return locked, nil
					default:
						panic(n)
					}
				},
				Provisioner: func(n string) (packer.Provisioner, error) {
					switch n {
					case "sleep":
						return &sleep.Provisioner{}, nil
					default:
						panic(n)
					}
				},
			},
		},
		Ui: &packer.BasicUi{
			Writer:      &out,
			ErrorWriter: &err,
		},
	}
}

func TestBuildParallel_1(t *testing.T) {
	// testfile has 6 builds, with first one locks 'forever', other builds
	// should go through.
	b := NewParallelTestBuilder(5)
	locked := &LockedBuilder{unlock: make(chan interface{})}

	c := &BuildCommand{
		Meta: testMetaParallel(t, b, locked),
	}

	args := []string{
		fmt.Sprintf("-parallel=true"),
		filepath.Join(testFixture("parallel"), "1lock-5wg.json"),
	}

	wg := errgroup.Group{}

	wg.Go(func() error {
		if code := c.Run(args); code != 0 {
			fatalCommand(t, c.Meta)
		}
		return nil
	})

	b.wg.Wait()          // ran 5 times
	close(locked.unlock) // unlock locking one
	wg.Wait()            // wait for termination
}

func TestBuildParallel_2(t *testing.T) {
	// testfile has 6 builds, 2 of them lock 'forever', other builds
	// should go through.
	b := NewParallelTestBuilder(4)
	locked := &LockedBuilder{unlock: make(chan interface{})}

	c := &BuildCommand{
		Meta: testMetaParallel(t, b, locked),
	}

	args := []string{
		fmt.Sprintf("-parallel-builds=3"),
		filepath.Join(testFixture("parallel"), "2lock-4wg"),
	}

	wg := errgroup.Group{}

	wg.Go(func() error {
		if code := c.Run(args); code != 0 {
			fatalCommand(t, c.Meta)
		}
		return nil
	})

	b.wg.Wait()          // ran 4 times
	close(locked.unlock) // unlock locking one
	wg.Wait()            // wait for termination
}

func TestBuildParallel_Timeout(t *testing.T) {
	// testfile has 6 builds, 1 of them locks 'forever', one locks and times
	// out other builds should go through.
	b := NewParallelTestBuilder(4)
	locked := &LockedBuilder{unlock: make(chan interface{})}

	c := &BuildCommand{
		Meta: testMetaParallel(t, b, locked),
	}

	args := []string{
		fmt.Sprintf("-parallel-builds=3"),
		filepath.Join(testFixture("parallel"), "2lock-timeout.json"),
	}

	wg := errgroup.Group{}

	wg.Go(func() error {
		if code := c.Run(args); code == 0 {
			fatalCommand(t, c.Meta)
		}
		return nil
	})

	b.wg.Wait()          // ran 4 times
	close(locked.unlock) // unlock locking one
	wg.Wait()            // wait for termination
}
<commit_msg>fix testfile call<commit_after>package command

import (
	"bytes"
	"context"
	"fmt"
	"path/filepath"
	"sync"
	"testing"

	"golang.org/x/sync/errgroup"

	"github.com/hashicorp/packer/builder/file"
	"github.com/hashicorp/packer/packer"
	"github.com/hashicorp/packer/provisioner/sleep"
)

// NewParallelTestBuilder will return a New ParallelTestBuilder that will
// unlock after `runs` builds
func NewParallelTestBuilder(runs int) *ParallelTestBuilder {
	pb := &ParallelTestBuilder{}
	pb.wg.Add(runs)
	return pb
}

// The ParallelTestBuilder's first run will lock
type ParallelTestBuilder struct {
	wg sync.WaitGroup
}

func (b *ParallelTestBuilder) Prepare(raws ...interface{}) ([]string, error) { return nil, nil }

func (b *ParallelTestBuilder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) {
	ui.Say("building")
	b.wg.Done()
	return nil, nil
}

// LockedBuilder wont run until unlock is called
type LockedBuilder struct{ unlock chan interface{} }

func (b *LockedBuilder) Prepare(raws ...interface{}) ([]string, error) { return nil, nil }

func (b *LockedBuilder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) {
	ui.Say("locking build")
	select {
	case <-b.unlock:
	case <-ctx.Done():
		return nil, ctx.Err()
	}
	return nil, nil
}

// testMetaFile creates a Meta object that includes a file builder
func testMetaParallel(t *testing.T, builder *ParallelTestBuilder, locked *LockedBuilder) Meta {
	var out, err bytes.Buffer
	return Meta{
		CoreConfig: &packer.CoreConfig{
			Components: packer.ComponentFinder{
				Builder: func(n string) (packer.Builder, error) {
					switch n {
					case "parallel-test":
						return builder, nil
					case "file":
						return &file.Builder{}, nil
					case "lock":
						return locked, nil
					default:
						panic(n)
					}
				},
				Provisioner: func(n string) (packer.Provisioner, error) {
					switch n {
					case "sleep":
						return &sleep.Provisioner{}, nil
					default:
						panic(n)
					}
				},
			},
		},
		Ui: &packer.BasicUi{
			Writer:      &out,
			ErrorWriter: &err,
		},
	}
}

func TestBuildParallel_1(t *testing.T) {
	// testfile has 6 builds, with first one locks 'forever', other builds
	// should go through.
	b := NewParallelTestBuilder(5)
	locked := &LockedBuilder{unlock: make(chan interface{})}

	c := &BuildCommand{
		Meta: testMetaParallel(t, b, locked),
	}

	args := []string{
		fmt.Sprintf("-parallel=true"),
		filepath.Join(testFixture("parallel"), "1lock-5wg.json"),
	}

	wg := errgroup.Group{}

	wg.Go(func() error {
		if code := c.Run(args); code != 0 {
			fatalCommand(t, c.Meta)
		}
		return nil
	})

	b.wg.Wait()          // ran 5 times
	close(locked.unlock) // unlock locking one
	wg.Wait()            // wait for termination
}

func TestBuildParallel_2(t *testing.T) {
	// testfile has 6 builds, 2 of them lock 'forever', other builds
	// should go through.
	b := NewParallelTestBuilder(4)
	locked := &LockedBuilder{unlock: make(chan interface{})}

	c := &BuildCommand{
		Meta: testMetaParallel(t, b, locked),
	}

	args := []string{
		fmt.Sprintf("-parallel-builds=3"),
		filepath.Join(testFixture("parallel"), "2lock-4wg.json"),
	}

	wg := errgroup.Group{}

	wg.Go(func() error {
		if code := c.Run(args); code != 0 {
			fatalCommand(t, c.Meta)
		}
		return nil
	})

	b.wg.Wait()          // ran 4 times
	close(locked.unlock) // unlock locking one
	wg.Wait()            // wait for termination
}

func TestBuildParallel_Timeout(t *testing.T) {
	// testfile has 6 builds, 1 of them locks 'forever', one locks and times
	// out other builds should go through.
	b := NewParallelTestBuilder(4)
	locked := &LockedBuilder{unlock: make(chan interface{})}

	c := &BuildCommand{
		Meta: testMetaParallel(t, b, locked),
	}

	args := []string{
		fmt.Sprintf("-parallel-builds=3"),
		filepath.Join(testFixture("parallel"), "2lock-timeout.json"),
	}

	wg := errgroup.Group{}

	wg.Go(func() error {
		if code := c.Run(args); code == 0 {
			fatalCommand(t, c.Meta)
		}
		return nil
	})

	b.wg.Wait()          // ran 4 times
	close(locked.unlock) // unlock locking one
	wg.Wait()            // wait for termination
}
<|endoftext|>


<commit_before>package command

import (
	"encoding/base64"
	"encoding/hex"
	"os"
	"strings"
	"testing"

	"github.com/hashicorp/go-uuid"
	"github.com/hashicorp/vault/helper/pgpkeys"
	"github.com/hashicorp/vault/helper/xor"
	"github.com/hashicorp/vault/http"
	"github.com/hashicorp/vault/logical"
	"github.com/hashicorp/vault/meta"
	"github.com/hashicorp/vault/vault"
	"github.com/mitchellh/cli"
)

func TestGenerateRoot_Cancel(t *testing.T) {
	core, _, _ := vault.TestCoreUnsealed(t)
	ln, addr := http.TestServer(t, core)
	defer ln.Close()

	ui := new(cli.MockUi)
	c := &GenerateRootCommand{
		Meta: meta.Meta{
			Ui: ui,
		},
	}

	otpBytes, err := vault.GenerateRandBytes(16)
	if err != nil {
		t.Fatal(err)
	}
	otp := base64.StdEncoding.EncodeToString(otpBytes)

	args := []string{"-address", addr, "-init", "-otp", otp}
	if code := c.Run(args); code != 0 {
		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
	}

	args = []string{"-address", addr, "-cancel"}
	if code := c.Run(args); code != 0 {
		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
	}

	config, err := core.GenerateRootConfiguration()
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	if config != nil {
		t.Fatal("should not have a config for root generation")
	}
}

func TestGenerateRoot_status(t *testing.T) {
	core, _, _ := vault.TestCoreUnsealed(t)
	ln, addr := http.TestServer(t, core)
	defer ln.Close()

	ui := new(cli.MockUi)
	c := &GenerateRootCommand{
		Meta: meta.Meta{
			Ui: ui,
		},
	}

	otpBytes, err := vault.GenerateRandBytes(16)
	if err != nil {
		t.Fatal(err)
	}
	otp := base64.StdEncoding.EncodeToString(otpBytes)

	args := []string{"-address", addr, "-init", "-otp", otp}
	if code := c.Run(args); code != 0 {
		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
	}

	args = []string{"-address", addr, "-status"}
	if code := c.Run(args); code != 0 {
		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
	}

	if !strings.Contains(string(ui.OutputWriter.Bytes()), "Started: true") {
		t.Fatalf("bad: %s", ui.OutputWriter.String())
	}
}

func TestGenerateRoot_OTP(t *testing.T) {
	core, ts, keys, _ := vault.TestCoreWithTokenStore(t)
	ln, addr := http.TestServer(t, core)
	defer ln.Close()

	ui := new(cli.MockUi)
	c := &GenerateRootCommand{
		Meta: meta.Meta{
			Ui: ui,
		},
	}

	// Generate an OTP
	otpBytes, err := vault.GenerateRandBytes(16)
	if err != nil {
		t.Fatal(err)
	}
	otp := base64.StdEncoding.EncodeToString(otpBytes)

	// Init the attempt
	args := []string{
		"-address", addr,
		"-init",
		"-otp", otp,
	}
	if code := c.Run(args); code != 0 {
		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
	}

	config, err := core.GenerateRootConfiguration()
	if err != nil {
		t.Fatalf("err: %v", err)
	}

	for _, key := range keys {
		ui = new(cli.MockUi)
		c = &GenerateRootCommand{
			Key: hex.EncodeToString(key),
			Meta: meta.Meta{
				Ui: ui,
			},
		}

		c.Nonce = config.Nonce

		// Provide the key
		args = []string{
			"-address", addr,
		}
		if code := c.Run(args); code != 0 {
			t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
		}
	}

	beforeNAfter := strings.Split(ui.OutputWriter.String(), "Encoded root token: ")
	if len(beforeNAfter) != 2 {
		t.Fatalf("did not find encoded root token in %s", ui.OutputWriter.String())
	}
	encodedToken := strings.TrimSpace(beforeNAfter[1])

	decodedToken, err := xor.XORBase64(encodedToken, otp)
	if err != nil {
		t.Fatal(err)
	}

	token, err := uuid.FormatUUID(decodedToken)
	if err != nil {
		t.Fatal(err)
	}

	req := logical.TestRequest(t, logical.ReadOperation, "lookup-self")
	req.ClientToken = token

	resp, err := ts.HandleRequest(req)
	if err != nil {
		t.Fatalf("error running token lookup-self: %v", err)
	}
	if resp == nil {
		t.Fatalf("got nil resp with token lookup-self")
	}
	if resp.Data == nil {
		t.Fatalf("got nil resp.Data with token lookup-self")
	}

	if resp.Data["orphan"].(bool) != true ||
		resp.Data["ttl"].(int64) != 0 ||
		resp.Data["num_uses"].(int) != 0 ||
		resp.Data["meta"].(map[string]string) != nil ||
		len(resp.Data["policies"].([]string)) != 1 ||
		resp.Data["policies"].([]string)[0] != "root" {
		t.Fatalf("bad: %#v", resp.Data)
	}

	// Clear the output and run a decode to verify we get the same result
	ui.OutputWriter.Reset()
	args = []string{
		"-address", addr,
		"-decode", encodedToken,
		"-otp", otp,
	}
	if code := c.Run(args); code != 0 {
		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
	}
	beforeNAfter = strings.Split(ui.OutputWriter.String(), "Root token: ")
	if len(beforeNAfter) != 2 {
		t.Fatalf("did not find decoded root token in %s", ui.OutputWriter.String())
	}

	outToken := strings.TrimSpace(beforeNAfter[1])
	if outToken != token {
		t.Fatalf("tokens do not match:\n%s\n%s", token, outToken)
	}
}

func TestGenerateRoot_PGP(t *testing.T) {
	core, ts, keys, _ := vault.TestCoreWithTokenStore(t)
	ln, addr := http.TestServer(t, core)
	defer ln.Close()

	ui := new(cli.MockUi)
	c := &GenerateRootCommand{
		Meta: meta.Meta{
			Ui: ui,
		},
	}

	tempDir, pubFiles, err := getPubKeyFiles(t)
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tempDir)

	// Init the attempt
	args := []string{
		"-address", addr,
		"-init",
		"-pgp-key", pubFiles[0],
	}
	if code := c.Run(args); code != 0 {
		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
	}

	config, err := core.GenerateRootConfiguration()
	if err != nil {
		t.Fatalf("err: %v", err)
	}

	for _, key := range keys {
		c = &GenerateRootCommand{
			Key: hex.EncodeToString(key),
			Meta: meta.Meta{
				Ui: ui,
			},
		}

		c.Nonce = config.Nonce

		// Provide the key
		args = []string{
			"-address", addr,
		}
		if code := c.Run(args); code != 0 {
			t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
		}
	}

	beforeNAfter := strings.Split(ui.OutputWriter.String(), "Encoded root token: ")
	if len(beforeNAfter) != 2 {
		t.Fatalf("did not find encoded root token in %s", ui.OutputWriter.String())
	}
	encodedToken := strings.TrimSpace(beforeNAfter[1])

	ptBuf, err := pgpkeys.DecryptBytes(encodedToken, pgpkeys.TestPrivKey1)
	if err != nil {
		t.Fatal(err)
	}
	if ptBuf == nil {
		t.Fatal("returned plain text buffer is nil")
	}

	token := ptBuf.String()

	req := logical.TestRequest(t, logical.ReadOperation, "lookup-self")
	req.ClientToken = token

	resp, err := ts.HandleRequest(req)
	if err != nil {
		t.Fatalf("error running token lookup-self: %v", err)
	}
	if resp == nil {
		t.Fatalf("got nil resp with token lookup-self")
	}
	if resp.Data == nil {
		t.Fatalf("got nil resp.Data with token lookup-self")
	}

	if resp.Data["orphan"].(bool) != true ||
		resp.Data["ttl"].(int64) != 0 ||
		resp.Data["num_uses"].(int) != 0 ||
		resp.Data["meta"].(map[string]string) != nil ||
		len(resp.Data["policies"].([]string)) != 1 ||
		resp.Data["policies"].([]string)[0] != "root" {
		t.Fatalf("bad: %#v", resp.Data)
	}
}
<commit_msg>fixed tests for command/generate_share.go<commit_after>package command

import (
	"encoding/hex"
	"os"
	"strings"
	"testing"

	"github.com/hashicorp/vault/helper/pgpkeys"
	"github.com/hashicorp/vault/http"
	"github.com/hashicorp/vault/logical"
	"github.com/hashicorp/vault/meta"
	"github.com/hashicorp/vault/vault"
	"github.com/mitchellh/cli"
)

func TestGenerateShare_Cancel(t *testing.T) {
	core, _, _ := vault.TestCoreUnsealed(t)
	ln, addr := http.TestServer(t, core)
	defer ln.Close()

	ui := new(cli.MockUi)
	c := &GenerateShareCommand{
		Meta: meta.Meta{
			Ui: ui,
		},
	}

	tempDir, pubFiles, err := getPubKeyFiles(t)
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tempDir)

	// Init the attempt
	args := []string{
		"-address", addr,
		"-init",
		"-pgp-key", pubFiles[0],
	}
	if code := c.Run(args); code != 0 {
		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
	}

	args = []string{"-address", addr, "-cancel"}
	if code := c.Run(args); code != 0 {
		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
	}

	config, err := core.GenerateRootConfiguration()
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	if config != nil {
		t.Fatal("should not have a config for root generation")
	}
}

func TestGenerateShare_status(t *testing.T) {
	core, _, _ := vault.TestCoreUnsealed(t)
	ln, addr := http.TestServer(t, core)
	defer ln.Close()

	ui := new(cli.MockUi)
	c := &GenerateShareCommand{
		Meta: meta.Meta{
			Ui: ui,
		},
	}

	tempDir, pubFiles, err := getPubKeyFiles(t)
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tempDir)

	// Init the attempt
	args := []string{
		"-address", addr,
		"-init",
		"-pgp-key", pubFiles[0],
	}
	if code := c.Run(args); code != 0 {
		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
	}

	args = []string{"-address", addr, "-status"}
	if code := c.Run(args); code != 0 {
		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
	}

	if !strings.Contains(string(ui.OutputWriter.Bytes()), "Started: true") {
		t.Fatalf("bad: %s", ui.OutputWriter.String())
	}
}

func TestGenerateShare_PGP(t *testing.T) {
	core, ts, keys, _ := vault.TestCoreWithTokenStore(t)
	ln, addr := http.TestServer(t, core)
	defer ln.Close()

	ui := new(cli.MockUi)
	c := &GenerateShareCommand{
		Meta: meta.Meta{
			Ui: ui,
		},
	}

	tempDir, pubFiles, err := getPubKeyFiles(t)
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tempDir)

	// Init the attempt
	args := []string{
		"-address", addr,
		"-init",
		"-pgp-key", pubFiles[0],
	}
	if code := c.Run(args); code != 0 {
		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
	}

	for _, key := range keys {
		c = &GenerateShareCommand{
			Key: hex.EncodeToString(key),
			Meta: meta.Meta{
				Ui: ui,
			},
		}

		// Provide the key
		args = []string{
			"-address", addr,
		}
		if code := c.Run(args); code != 0 {
			t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
		}
	}

	beforeNAfter := strings.Split(ui.OutputWriter.String(), "Share: ")
	if len(beforeNAfter) != 2 {
		t.Fatalf("did not find share in %s", ui.OutputWriter.String())
	}
	encodedShare := strings.TrimSpace(beforeNAfter[1])

	ptBuf, err := pgpkeys.DecryptBytes(encodedShare, pgpkeys.TestPrivKey1)
	if err != nil {
		t.Fatal(err)
	}
	if ptBuf == nil {
		t.Fatal("returned plain text buffer is nil")
	}

	share := ptBuf.String()

	req := logical.TestRequest(t, logical.ReadOperation, "lookup-self")
	req.ClientToken = share

	resp, err := ts.HandleRequest(req)
	if err != nil {
		t.Fatalf("error running share lookup-self: %v", err)
	}
	if resp == nil {
		t.Fatalf("got nil resp with share lookup-self")
	}
	if resp.Data == nil {
		t.Fatalf("got nil resp.Data with share lookup-self")
	}

	if resp.Data["orphan"].(bool) != true ||
		resp.Data["ttl"].(int64) != 0 ||
		resp.Data["num_uses"].(int) != 0 ||
		resp.Data["meta"].(map[string]string) != nil ||
		len(resp.Data["policies"].([]string)) != 1 ||
		resp.Data["policies"].([]string)[0] != "root" {
		t.Fatalf("bad: %#v", resp.Data)
	}
}
<|endoftext|>


<commit_before>package command

import (
	"context"
	"encoding/base64"
	"testing"

	hclog "github.com/hashicorp/go-hclog"
	"github.com/hashicorp/vault/api"
	"github.com/hashicorp/vault/command/server"
	"github.com/hashicorp/vault/helper/logging"
	vaulthttp "github.com/hashicorp/vault/http"
	"github.com/hashicorp/vault/physical"
	physInmem "github.com/hashicorp/vault/physical/inmem"
	"github.com/hashicorp/vault/shamir"
	"github.com/hashicorp/vault/vault"
	"github.com/hashicorp/vault/vault/seal"
)

func TestSealMigration(t *testing.T) {
	logger := logging.NewVaultLogger(hclog.Trace)
	phys, err := physInmem.NewInmem(nil, logger)
	if err != nil {
		t.Fatal(err)
	}
	haPhys, err := physInmem.NewInmemHA(nil, logger)
	if err != nil {
		t.Fatal(err)
	}
	shamirSeal := vault.NewDefaultSeal()
	coreConfig := &vault.CoreConfig{
		Seal:            shamirSeal,
		Physical:        phys,
		HAPhysical:      haPhys.(physical.HABackend),
		DisableSealWrap: true,
	}
	clusterConfig := &vault.TestClusterOptions{
		Logger:      logger,
		HandlerFunc: vaulthttp.Handler,
		SkipInit:    true,
		NumCores:    1,
	}

	var keys []string
	var rootToken string

	// First: start up as normal with shamir seal, init it
	{
		cluster := vault.NewTestCluster(t, coreConfig, clusterConfig)
		cluster.Start()
		defer cluster.Cleanup()

		client := cluster.Cores[0].Client
		coreConfig = cluster.Cores[0].CoreConfig

		// Init
		resp, err := client.Sys().Init(&api.InitRequest{
			SecretShares:    2,
			SecretThreshold: 2,
		})
		if err != nil {
			t.Fatal(err)
		}
		keys = resp.KeysB64
		rootToken = resp.RootToken

		// Now seal
		cluster.Cleanup()
		// This will prevent cleanup from running again on the defer
		cluster.Cores = nil
	}

	// Second: start up as normal with shamir seal and unseal, make sure
	// everything is normal
	{
		cluster := vault.NewTestCluster(t, coreConfig, clusterConfig)
		cluster.Start()
		defer cluster.Cleanup()

		client := cluster.Cores[0].Client
		client.SetToken(rootToken)

		var resp *api.SealStatusResponse
		for _, key := range keys {
			resp, err = client.Sys().Unseal(key)
			if err != nil {
				t.Fatal(err)
			}
			if resp == nil {
				t.Fatal("expected response")
			}
		}
		if resp.Sealed {
			t.Fatal("expected unsealed state")
		}

		cluster.Cleanup()
		cluster.Cores = nil
	}

	var autoSeal vault.Seal

	// Third: create an autoseal and activate migration
	{
		cluster := vault.NewTestCluster(t, coreConfig, clusterConfig)
		cluster.Start()
		defer cluster.Cleanup()

		core := cluster.Cores[0].Core

		newSeal := vault.NewAutoSeal(seal.NeweTestSeal(logger))
		newSeal.SetCore(core)
		autoSeal = newSeal
		if err := adjustCoreForSealMigration(context.Background(), core, coreConfig, newSeal, &server.Config{
			Seal: &server.Seal{
				Type: "test-auto",
			},
		}); err != nil {
			t.Fatal(err)
		}

		client := cluster.Cores[0].Client
		client.SetToken(rootToken)

		var resp *api.SealStatusResponse
		unsealOpts := &api.UnsealOpts{}
		for _, key := range keys {
			unsealOpts.Key = key
			unsealOpts.Migrate = false
			resp, err = client.Sys().UnsealWithOptions(unsealOpts)
			if err == nil {
				t.Fatal("expected error due to lack of migrate parameter")
			}
			unsealOpts.Migrate = true
			resp, err = client.Sys().UnsealWithOptions(unsealOpts)
			if err != nil {
				t.Fatal(err)
			}
			if resp == nil {
				t.Fatal("expected response")
			}
		}
		if resp.Sealed {
			t.Fatalf("expected unsealed state; got %#v", *resp)
		}

		cluster.Cleanup()
		cluster.Cores = nil
	}

	// Fourth: verify autoseal and recovery key usage
	{
		coreConfig.Seal = autoSeal
		cluster := vault.NewTestCluster(t, coreConfig, clusterConfig)
		cluster.Start()
		defer cluster.Cleanup()

		core := cluster.Cores[0].Core
		client := cluster.Cores[0].Client
		client.SetToken(rootToken)

		if err := core.UnsealWithStoredKeys(context.Background()); err != nil {
			t.Fatal(err)
		}
		resp, err := client.Sys().SealStatus()
		if err != nil {
			t.Fatal(err)
		}
		if resp == nil {
			t.Fatal("expected response")
		}
		if resp.Sealed {
			t.Fatalf("expected unsealed state; got %#v", *resp)
		}

		keyParts := [][]byte{}
		for _, key := range keys {
			raw, err := base64.StdEncoding.DecodeString(key)
			if err != nil {
				t.Fatal(err)
			}
			keyParts = append(keyParts, raw)
		}
		recoveredKey, err := shamir.Combine(keyParts)
		if err != nil {
			t.Fatal(err)
		}
		sealAccess := core.SealAccess()
		if err := sealAccess.VerifyRecoveryKey(context.Background(), recoveredKey); err != nil {
			t.Fatal(err)
		}

		cluster.Cleanup()
		cluster.Cores = nil
	}

	// Fifth: create an autoseal and activate migration. Verify it doesn't work
	// if disabled isn't set.
	{
		coreConfig.Seal = autoSeal
		cluster := vault.NewTestCluster(t, coreConfig, clusterConfig)
		cluster.Start()
		defer cluster.Cleanup()

		core := cluster.Cores[0].Core

		serverConf := &server.Config{
			Seal: &server.Seal{
				Type: "test-auto",
			},
		}

		if err := adjustCoreForSealMigration(context.Background(), core, coreConfig, shamirSeal, serverConf); err == nil {
			t.Fatal("expected error since disabled isn't set true")
		}
		serverConf.Seal.Disabled = true
		if err := adjustCoreForSealMigration(context.Background(), core, coreConfig, shamirSeal, serverConf); err != nil {
			t.Fatal(err)
		}

		client := cluster.Cores[0].Client
		client.SetToken(rootToken)

		var resp *api.SealStatusResponse
		unsealOpts := &api.UnsealOpts{}
		for _, key := range keys {
			unsealOpts.Key = key
			unsealOpts.Migrate = false
			resp, err = client.Sys().UnsealWithOptions(unsealOpts)
			if err == nil {
				t.Fatal("expected error due to lack of migrate parameter")
			}
			unsealOpts.Migrate = true
			resp, err = client.Sys().UnsealWithOptions(unsealOpts)
			if err != nil {
				t.Fatal(err)
			}
			if resp == nil {
				t.Fatal("expected response")
			}
		}
		if resp.Sealed {
			t.Fatalf("expected unsealed state; got %#v", *resp)
		}

		cluster.Cleanup()
		cluster.Cores = nil
	}

	// Sixth: verify autoseal is off and the expected key shares work
	{
		coreConfig.Seal = shamirSeal
		cluster := vault.NewTestCluster(t, coreConfig, clusterConfig)
		cluster.Start()
		defer cluster.Cleanup()

		core := cluster.Cores[0].Core
		client := cluster.Cores[0].Client
		client.SetToken(rootToken)

		if err := core.UnsealWithStoredKeys(context.Background()); err != nil {
			t.Fatal(err)
		}
		resp, err := client.Sys().SealStatus()
		if err != nil {
			t.Fatal(err)
		}
		if resp == nil {
			t.Fatal("expected response")
		}
		if !resp.Sealed {
			t.Fatalf("expected sealed state; got %#v", *resp)
		}

		for _, key := range keys {
			resp, err = client.Sys().Unseal(key)
			if err != nil {
				t.Fatal(err)
			}
			if resp == nil {
				t.Fatal("expected response")
			}
		}
		if resp.Sealed {
			t.Fatal("expected unsealed state")
		}

		cluster.Cleanup()
		cluster.Cores = nil
	}
}
<commit_msg>fix typo in test name<commit_after>package command

import (
	"context"
	"encoding/base64"
	"testing"

	hclog "github.com/hashicorp/go-hclog"
	"github.com/hashicorp/vault/api"
	"github.com/hashicorp/vault/command/server"
	"github.com/hashicorp/vault/helper/logging"
	vaulthttp "github.com/hashicorp/vault/http"
	"github.com/hashicorp/vault/physical"
	physInmem "github.com/hashicorp/vault/physical/inmem"
	"github.com/hashicorp/vault/shamir"
	"github.com/hashicorp/vault/vault"
	"github.com/hashicorp/vault/vault/seal"
)

func TestSealMigration(t *testing.T) {
	logger := logging.NewVaultLogger(hclog.Trace)
	phys, err := physInmem.NewInmem(nil, logger)
	if err != nil {
		t.Fatal(err)
	}
	haPhys, err := physInmem.NewInmemHA(nil, logger)
	if err != nil {
		t.Fatal(err)
	}
	shamirSeal := vault.NewDefaultSeal()
	coreConfig := &vault.CoreConfig{
		Seal:            shamirSeal,
		Physical:        phys,
		HAPhysical:      haPhys.(physical.HABackend),
		DisableSealWrap: true,
	}
	clusterConfig := &vault.TestClusterOptions{
		Logger:      logger,
		HandlerFunc: vaulthttp.Handler,
		SkipInit:    true,
		NumCores:    1,
	}

	var keys []string
	var rootToken string

	// First: start up as normal with shamir seal, init it
	{
		cluster := vault.NewTestCluster(t, coreConfig, clusterConfig)
		cluster.Start()
		defer cluster.Cleanup()

		client := cluster.Cores[0].Client
		coreConfig = cluster.Cores[0].CoreConfig

		// Init
		resp, err := client.Sys().Init(&api.InitRequest{
			SecretShares:    2,
			SecretThreshold: 2,
		})
		if err != nil {
			t.Fatal(err)
		}
		keys = resp.KeysB64
		rootToken = resp.RootToken

		// Now seal
		cluster.Cleanup()
		// This will prevent cleanup from running again on the defer
		cluster.Cores = nil
	}

	// Second: start up as normal with shamir seal and unseal, make sure
	// everything is normal
	{
		cluster := vault.NewTestCluster(t, coreConfig, clusterConfig)
		cluster.Start()
		defer cluster.Cleanup()

		client := cluster.Cores[0].Client
		client.SetToken(rootToken)

		var resp *api.SealStatusResponse
		for _, key := range keys {
			resp, err = client.Sys().Unseal(key)
			if err != nil {
				t.Fatal(err)
			}
			if resp == nil {
				t.Fatal("expected response")
			}
		}
		if resp.Sealed {
			t.Fatal("expected unsealed state")
		}

		cluster.Cleanup()
		cluster.Cores = nil
	}

	var autoSeal vault.Seal

	// Third: create an autoseal and activate migration
	{
		cluster := vault.NewTestCluster(t, coreConfig, clusterConfig)
		cluster.Start()
		defer cluster.Cleanup()

		core := cluster.Cores[0].Core

		newSeal := vault.NewAutoSeal(seal.NewTestSeal(logger))
		newSeal.SetCore(core)
		autoSeal = newSeal
		if err := adjustCoreForSealMigration(context.Background(), core, coreConfig, newSeal, &server.Config{
			Seal: &server.Seal{
				Type: "test-auto",
			},
		}); err != nil {
			t.Fatal(err)
		}

		client := cluster.Cores[0].Client
		client.SetToken(rootToken)

		var resp *api.SealStatusResponse
		unsealOpts := &api.UnsealOpts{}
		for _, key := range keys {
			unsealOpts.Key = key
			unsealOpts.Migrate = false
			resp, err = client.Sys().UnsealWithOptions(unsealOpts)
			if err == nil {
				t.Fatal("expected error due to lack of migrate parameter")
			}
			unsealOpts.Migrate = true
			resp, err = client.Sys().UnsealWithOptions(unsealOpts)
			if err != nil {
				t.Fatal(err)
			}
			if resp == nil {
				t.Fatal("expected response")
			}
		}
		if resp.Sealed {
			t.Fatalf("expected unsealed state; got %#v", *resp)
		}

		cluster.Cleanup()
		cluster.Cores = nil
	}

	// Fourth: verify autoseal and recovery key usage
	{
		coreConfig.Seal = autoSeal
		cluster := vault.NewTestCluster(t, coreConfig, clusterConfig)
		cluster.Start()
		defer cluster.Cleanup()

		core := cluster.Cores[0].Core
		client := cluster.Cores[0].Client
		client.SetToken(rootToken)

		if err := core.UnsealWithStoredKeys(context.Background()); err != nil {
			t.Fatal(err)
		}
		resp, err := client.Sys().SealStatus()
		if err != nil {
			t.Fatal(err)
		}
		if resp == nil {
			t.Fatal("expected response")
		}
		if resp.Sealed {
			t.Fatalf("expected unsealed state; got %#v", *resp)
		}

		keyParts := [][]byte{}
		for _, key := range keys {
			raw, err := base64.StdEncoding.DecodeString(key)
			if err != nil {
				t.Fatal(err)
			}
			keyParts = append(keyParts, raw)
		}
		recoveredKey, err := shamir.Combine(keyParts)
		if err != nil {
			t.Fatal(err)
		}
		sealAccess := core.SealAccess()
		if err := sealAccess.VerifyRecoveryKey(context.Background(), recoveredKey); err != nil {
			t.Fatal(err)
		}

		cluster.Cleanup()
		cluster.Cores = nil
	}

	// Fifth: create an autoseal and activate migration. Verify it doesn't work
	// if disabled isn't set.
	{
		coreConfig.Seal = autoSeal
		cluster := vault.NewTestCluster(t, coreConfig, clusterConfig)
		cluster.Start()
		defer cluster.Cleanup()

		core := cluster.Cores[0].Core

		serverConf := &server.Config{
			Seal: &server.Seal{
				Type: "test-auto",
			},
		}

		if err := adjustCoreForSealMigration(context.Background(), core, coreConfig, shamirSeal, serverConf); err == nil {
			t.Fatal("expected error since disabled isn't set true")
		}
		serverConf.Seal.Disabled = true
		if err := adjustCoreForSealMigration(context.Background(), core, coreConfig, shamirSeal, serverConf); err != nil {
			t.Fatal(err)
		}

		client := cluster.Cores[0].Client
		client.SetToken(rootToken)

		var resp *api.SealStatusResponse
		unsealOpts := &api.UnsealOpts{}
		for _, key := range keys {
			unsealOpts.Key = key
			unsealOpts.Migrate = false
			resp, err = client.Sys().UnsealWithOptions(unsealOpts)
			if err == nil {
				t.Fatal("expected error due to lack of migrate parameter")
			}
			unsealOpts.Migrate = true
			resp, err = client.Sys().UnsealWithOptions(unsealOpts)
			if err != nil {
				t.Fatal(err)
			}
			if resp == nil {
				t.Fatal("expected response")
			}
		}
		if resp.Sealed {
			t.Fatalf("expected unsealed state; got %#v", *resp)
		}

		cluster.Cleanup()
		cluster.Cores = nil
	}

	// Sixth: verify autoseal is off and the expected key shares work
	{
		coreConfig.Seal = shamirSeal
		cluster := vault.NewTestCluster(t, coreConfig, clusterConfig)
		cluster.Start()
		defer cluster.Cleanup()

		core := cluster.Cores[0].Core
		client := cluster.Cores[0].Client
		client.SetToken(rootToken)

		if err := core.UnsealWithStoredKeys(context.Background()); err != nil {
			t.Fatal(err)
		}
		resp, err := client.Sys().SealStatus()
		if err != nil {
			t.Fatal(err)
		}
		if resp == nil {
			t.Fatal("expected response")
		}
		if !resp.Sealed {
			t.Fatalf("expected sealed state; got %#v", *resp)
		}

		for _, key := range keys {
			resp, err = client.Sys().Unseal(key)
			if err != nil {
				t.Fatal(err)
			}
			if resp == nil {
				t.Fatal("expected response")
			}
		}
		if resp.Sealed {
			t.Fatal("expected unsealed state")
		}

		cluster.Cleanup()
		cluster.Cores = nil
	}
}
<|endoftext|>


<commit_before><commit_msg>return ErrCommandNotFound<commit_after><|endoftext|>


<commit_before>package osutil

import (
	"fmt"
	"io"
	"os"
	"os/exec"
	fp "path/filepath"
	"strings"
	"syscall"

	"github.com/hashicorp/errwrap"
	"github.com/docker/docker/pkg/mount"

	"github.com/yuuki1/droot/log"
)

func ExistsFile(file string) bool {
	f, err := os.Stat(file)
	return err == nil && !f.IsDir()
}

func ExistsDir(dir string) bool {
	if f, err := os.Stat(dir); os.IsNotExist(err) || !f.IsDir() {
		return false
	}
	return true
}

func IsDirEmpty(dir string) (bool, error) {
	f, err := os.Open(dir)
	if err != nil {
		return false, errwrap.Wrapf(fmt.Sprintf("Failed to open %s: {{err}}", dir), err)
	}
	defer f.Close()

	_, err = f.Readdirnames(1)
	if err == io.EOF {
		return true, nil
	}
	return false, nil
}

func RunCmd(name string, arg ...string) error {
	log.Debug("runcmd: ", name, arg)
	out, err := exec.Command(name, arg...).CombinedOutput()
	if len(out) > 0 {
		log.Debug(string(out))
	}
	if err != nil {
		return errwrap.Wrapf(fmt.Sprintf("Failed to exec %s %s: {{err}}", name, arg), err)
	}
	return nil
}

func Cp(from, to string) error {
	if err := RunCmd("cp", "-p", from, to); err != nil {
		return err
	}
	return nil
}

func GetMountsByRoot(rootDir string) ([]*mount.Info, error) {
	mounts, err := mount.GetMounts()
	if err != nil {
		return nil, err
	}

	targets := make([]*mount.Info, 0)
	for _, m := range mounts {
		if strings.HasPrefix(m.Mountpoint, fp.Clean(rootDir)) {
			targets = append(targets, m)
		}
	}

	return targets, nil
}

func UmountRoot(rootDir string) error {
	mounts, err := GetMountsByRoot(rootDir)
	if err != nil {
		return err
	}

	for _, m := range mounts {
		if err := mount.Unmount(m.Mountpoint); err != nil {
			return err
		}
		log.Debug("umount:", m.Mountpoint)
	}

	return nil
}

// Mknod unless path does not exists.
func Mknod(path string, mode uint32, dev int) error {
	if ExistsFile(path) {
		return nil
	}
	if err := syscall.Mknod(path, mode, dev); err != nil {
		return errwrap.Wrapf(fmt.Sprintf("Failed to mknod %s: {{err}}", path), err)
	}
	return nil
}

// Symlink, but ignore already exists file.
func Symlink(oldname, newname string) error {
	if err := os.Symlink(oldname, newname); err != nil {
		// Ignore already created symlink
		if _, ok := err.(*os.LinkError); !ok {
			return errwrap.Wrapf(fmt.Sprintf("Failed to symlink %s %s: {{err}}", oldname, newname), err)
		}
	}
	return nil
}

func Execv(cmd string, args []string, env []string) error {
	name, err := exec.LookPath(cmd)
	if err != nil {
		return errwrap.Wrapf(fmt.Sprintf("Not found %s: {{err}}", cmd), err)
	}

	log.Debug("exec: ", name, args)

	return syscall.Exec(name, args, env)
}
<commit_msg>gofmt<commit_after>package osutil

import (
	"fmt"
	"io"
	"os"
	"os/exec"
	fp "path/filepath"
	"strings"
	"syscall"

	"github.com/docker/docker/pkg/mount"
	"github.com/hashicorp/errwrap"

	"github.com/yuuki1/droot/log"
)

func ExistsFile(file string) bool {
	f, err := os.Stat(file)
	return err == nil && !f.IsDir()
}

func ExistsDir(dir string) bool {
	if f, err := os.Stat(dir); os.IsNotExist(err) || !f.IsDir() {
		return false
	}
	return true
}

func IsDirEmpty(dir string) (bool, error) {
	f, err := os.Open(dir)
	if err != nil {
		return false, errwrap.Wrapf(fmt.Sprintf("Failed to open %s: {{err}}", dir), err)
	}
	defer f.Close()

	_, err = f.Readdirnames(1)
	if err == io.EOF {
		return true, nil
	}
	return false, nil
}

func RunCmd(name string, arg ...string) error {
	log.Debug("runcmd: ", name, arg)
	out, err := exec.Command(name, arg...).CombinedOutput()
	if len(out) > 0 {
		log.Debug(string(out))
	}
	if err != nil {
		return errwrap.Wrapf(fmt.Sprintf("Failed to exec %s %s: {{err}}", name, arg), err)
	}
	return nil
}

func Cp(from, to string) error {
	if err := RunCmd("cp", "-p", from, to); err != nil {
		return err
	}
	return nil
}

func GetMountsByRoot(rootDir string) ([]*mount.Info, error) {
	mounts, err := mount.GetMounts()
	if err != nil {
		return nil, err
	}

	targets := make([]*mount.Info, 0)
	for _, m := range mounts {
		if strings.HasPrefix(m.Mountpoint, fp.Clean(rootDir)) {
			targets = append(targets, m)
		}
	}

	return targets, nil
}

func UmountRoot(rootDir string) error {
	mounts, err := GetMountsByRoot(rootDir)
	if err != nil {
		return err
	}

	for _, m := range mounts {
		if err := mount.Unmount(m.Mountpoint); err != nil {
			return err
		}
		log.Debug("umount:", m.Mountpoint)
	}

	return nil
}

// Mknod unless path does not exists.
func Mknod(path string, mode uint32, dev int) error {
	if ExistsFile(path) {
		return nil
	}
	if err := syscall.Mknod(path, mode, dev); err != nil {
		return errwrap.Wrapf(fmt.Sprintf("Failed to mknod %s: {{err}}", path), err)
	}
	return nil
}

// Symlink, but ignore already exists file.
func Symlink(oldname, newname string) error {
	if err := os.Symlink(oldname, newname); err != nil {
		// Ignore already created symlink
		if _, ok := err.(*os.LinkError); !ok {
			return errwrap.Wrapf(fmt.Sprintf("Failed to symlink %s %s: {{err}}", oldname, newname), err)
		}
	}
	return nil
}

func Execv(cmd string, args []string, env []string) error {
	name, err := exec.LookPath(cmd)
	if err != nil {
		return errwrap.Wrapf(fmt.Sprintf("Not found %s: {{err}}", cmd), err)
	}

	log.Debug("exec: ", name, args)

	return syscall.Exec(name, args, env)
}
<|endoftext|>