<commit_before>// Copyright 2018 by caixw, All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.

package context

import (
	"bytes"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"

	"github.com/issue9/assert"
	"golang.org/x/text/encoding/simplifiedchinese"
	"golang.org/x/text/transform"

	"github.com/issue9/web/encoding"
	"github.com/issue9/web/encoding/encodingtest"
	"github.com/issue9/web/encoding/gob"
)

var (
	gbkstr1            = "中文1,11"
	gbkstr2            = "中文2,22"
	gbkdata1, gbkdata2 []byte
)

func TestMain(m *testing.M) {
	if err := encoding.AddCharset("gbk", simplifiedchinese.GBK); err != nil {
		panic(err)
	}

	if err := encoding.AddMarshal(encoding.DefaultMimeType, gob.Marshal); err != nil {
		panic(err)
	}

	if err := encoding.AddUnmarshal(encoding.DefaultMimeType, gob.Unmarshal); err != nil {
		panic(err)
	}

	reader := transform.NewReader(strings.NewReader(gbkstr1), simplifiedchinese.GBK.NewEncoder())
	gbkdata, err := ioutil.ReadAll(reader)
	if err != nil {
		panic(err)
	}
	gbkdata1 = gbkdata

	reader = transform.NewReader(strings.NewReader(gbkstr2), simplifiedchinese.GBK.NewEncoder())
	gbkdata, err = ioutil.ReadAll(reader)
	if err != nil {
		panic(err)
	}
	gbkdata2 = gbkdata

	m.Run()
}

func BenchmarkContext_Marshal(b *testing.B) {
	a := assert.New(b)

	for i := 0; i < b.N; i++ {
		w := httptest.NewRecorder()
		r := httptest.NewRequest(http.MethodGet, "/path", nil)
		r.Header.Set("Accept", encoding.DefaultMimeType)
		ctx := New(w, r, nil)

		obj := &encodingtest.TextObject{Age: 16, Name: "response"}
		a.NotError(ctx.Marshal(http.StatusCreated, obj, nil))
		a.Equal(w.Body.String(), "response,16")
	}
}

func BenchmarkContext_MarshalWithCharset(b *testing.B) {
	a := assert.New(b)

	for i := 0; i < b.N; i++ {
		w := httptest.NewRecorder()
		r := httptest.NewRequest(http.MethodGet, "/path", nil)
		r.Header.Set("Content-type", encoding.BuildContentType(encoding.DefaultMimeType, "gbk"))
		r.Header.Set("Accept", encoding.DefaultMimeType)
		r.Header.Set("Accept-Charset", "gbk;q=1,gb18080;q=0.1")
		ctx := New(w, r, nil)

		obj := &encodingtest.TextObject{Age: 22, Name: "中文2"}
		a.NotError(ctx.Marshal(http.StatusCreated, obj, nil))
		a.Equal(w.Body.Bytes(), gbkdata2)
	}
}

func BenchmarkContext_Unmarshal(b *testing.B) {
	a := assert.New(b)

	for i := 0; i < b.N; i++ {
		w := httptest.NewRecorder()
		r := httptest.NewRequest(http.MethodPost, "/path", bytes.NewBufferString("request,15"))
		r.Header.Set("Accept", encoding.DefaultMimeType)
		ctx := New(w, r, nil)

		obj := &encodingtest.TextObject{}
		a.NotError(ctx.Unmarshal(obj))
		a.Equal(obj.Age, 15).Equal(obj.Name, "request")
	}
}

func BenchmarkContext_UnmarshalWithCharset(b *testing.B) {
	a := assert.New(b)

	for i := 0; i < b.N; i++ {
		w := httptest.NewRecorder()
		r := httptest.NewRequest(http.MethodGet, "/path", bytes.NewBuffer(gbkdata1))
		r.Header.Set("Content-type", encoding.BuildContentType(encoding.DefaultMimeType, "gbk"))
		r.Header.Set("Accept", encoding.DefaultMimeType)
		r.Header.Set("Accept-Charset", "gbk;q=1,gb18080;q=0.1")
		ctx := New(w, r, nil)

		obj := &encodingtest.TextObject{}
		a.NotError(ctx.Unmarshal(obj))
		a.Equal(obj.Age, 11).Equal(obj.Name, "中文1")
	}
}

// 一次普通的 POST 请求过程
func BenchmarkPost(b *testing.B) {
	a := assert.New(b)

	for i := 0; i < b.N; i++ {
		w := httptest.NewRecorder()
		r := httptest.NewRequest(http.MethodPost, "/path", bytes.NewBufferString("request,15"))
		r.Header.Set("Accept", encoding.DefaultMimeType)
		ctx := New(w, r, nil)

		obj := &encodingtest.TextObject{}
		a.NotError(ctx.Unmarshal(obj))
		a.Equal(obj.Age, 15).Equal(obj.Name, "request")

		obj.Age++
		obj.Name = "response"
		ctx.Render(http.StatusCreated, obj, nil)
		a.Equal(w.Body.String(), "response,16")
	}
}

func BenchmarkPostWithCharset(b *testing.B) {
	a := assert.New(b)

	for i := 0; i < b.N; i++ {
		w := httptest.NewRecorder()
		r := httptest.NewRequest(http.MethodPost, "/path", bytes.NewBuffer(gbkdata1))
		r.Header.Set("Content-type", encoding.BuildContentType(encoding.DefaultMimeType, "gbk"))
		r.Header.Set("Accept", encoding.DefaultMimeType)
		r.Header.Set("Accept-Charset", "gbk;q=1,gb18080;q=0.1")
		ctx := New(w, r, nil)

		obj := &encodingtest.TextObject{}
		a.NotError(ctx.Unmarshal(obj))
		a.Equal(obj.Age, 11).Equal(obj.Name, "中文1")

		obj.Age = 22
		obj.Name = "中文2"
		a.NotError(ctx.Marshal(http.StatusCreated, obj, nil))
		a.Equal(w.Body.Bytes(), gbkdata2)
	}
}
<commit_msg>修正性能测试错误<commit_after>// Copyright 2018 by caixw, All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.

package context

import (
	"bytes"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"

	"github.com/issue9/assert"
	"golang.org/x/text/encoding/simplifiedchinese"
	"golang.org/x/text/transform"

	"github.com/issue9/web/encoding"
	"github.com/issue9/web/encoding/encodingtest"
)

var (
	gbkstr1            = "中文1,11"
	gbkstr2            = "中文2,22"
	gbkdata1, gbkdata2 []byte
)

func TestMain(m *testing.M) {
	if err := encoding.AddCharset("gbk", simplifiedchinese.GBK); err != nil {
		panic(err)
	}

	if err := encoding.AddMarshal(encoding.DefaultMimeType, encodingtest.TextMarshal); err != nil {
		panic(err)
	}

	if err := encoding.AddUnmarshal(encoding.DefaultMimeType, encodingtest.TextUnmarshal); err != nil {
		panic(err)
	}

	reader := transform.NewReader(strings.NewReader(gbkstr1), simplifiedchinese.GBK.NewEncoder())
	gbkdata, err := ioutil.ReadAll(reader)
	if err != nil {
		panic(err)
	}
	gbkdata1 = gbkdata

	reader = transform.NewReader(strings.NewReader(gbkstr2), simplifiedchinese.GBK.NewEncoder())
	gbkdata, err = ioutil.ReadAll(reader)
	if err != nil {
		panic(err)
	}
	gbkdata2 = gbkdata

	m.Run()
}

func BenchmarkContext_Marshal(b *testing.B) {
	a := assert.New(b)

	for i := 0; i < b.N; i++ {
		w := httptest.NewRecorder()
		r := httptest.NewRequest(http.MethodGet, "/path", nil)
		r.Header.Set("Accept", encoding.DefaultMimeType)
		ctx := New(w, r, nil)

		obj := &encodingtest.TextObject{Age: 16, Name: "response"}
		a.NotError(ctx.Marshal(http.StatusCreated, obj, nil))
		a.Equal(w.Body.String(), "response,16")
	}
}

func BenchmarkContext_MarshalWithCharset(b *testing.B) {
	a := assert.New(b)

	for i := 0; i < b.N; i++ {
		w := httptest.NewRecorder()
		r := httptest.NewRequest(http.MethodGet, "/path", nil)
		r.Header.Set("Content-type", encoding.BuildContentType(encoding.DefaultMimeType, "gbk"))
		r.Header.Set("Accept", encoding.DefaultMimeType)
		r.Header.Set("Accept-Charset", "gbk;q=1,gb18080;q=0.1")
		ctx := New(w, r, nil)

		obj := &encodingtest.TextObject{Age: 22, Name: "中文2"}
		a.NotError(ctx.Marshal(http.StatusCreated, obj, nil))
		a.Equal(w.Body.Bytes(), gbkdata2)
	}
}

func BenchmarkContext_Unmarshal(b *testing.B) {
	a := assert.New(b)

	for i := 0; i < b.N; i++ {
		w := httptest.NewRecorder()
		r := httptest.NewRequest(http.MethodPost, "/path", bytes.NewBufferString("request,15"))
		r.Header.Set("Accept", encoding.DefaultMimeType)
		ctx := New(w, r, nil)

		obj := &encodingtest.TextObject{}
		a.NotError(ctx.Unmarshal(obj))
		a.Equal(obj.Age, 15).Equal(obj.Name, "request")
	}
}

func BenchmarkContext_UnmarshalWithCharset(b *testing.B) {
	a := assert.New(b)

	for i := 0; i < b.N; i++ {
		w := httptest.NewRecorder()
		r := httptest.NewRequest(http.MethodGet, "/path", bytes.NewBuffer(gbkdata1))
		r.Header.Set("Content-type", encoding.BuildContentType(encoding.DefaultMimeType, "gbk"))
		r.Header.Set("Accept", encoding.DefaultMimeType)
		r.Header.Set("Accept-Charset", "gbk;q=1,gb18080;q=0.1")
		ctx := New(w, r, nil)

		obj := &encodingtest.TextObject{}
		a.NotError(ctx.Unmarshal(obj))
		a.Equal(obj.Age, 11).Equal(obj.Name, "中文1")
	}
}

// 一次普通的 POST 请求过程
func BenchmarkPost(b *testing.B) {
	a := assert.New(b)

	for i := 0; i < b.N; i++ {
		w := httptest.NewRecorder()
		r := httptest.NewRequest(http.MethodPost, "/path", bytes.NewBufferString("request,15"))
		r.Header.Set("Accept", encoding.DefaultMimeType)
		ctx := New(w, r, nil)

		obj := &encodingtest.TextObject{}
		a.NotError(ctx.Unmarshal(obj))
		a.Equal(obj.Age, 15).Equal(obj.Name, "request")

		obj.Age++
		obj.Name = "response"
		ctx.Render(http.StatusCreated, obj, nil)
		a.Equal(w.Body.String(), "response,16")
	}
}

func BenchmarkPostWithCharset(b *testing.B) {
	a := assert.New(b)

	for i := 0; i < b.N; i++ {
		w := httptest.NewRecorder()
		r := httptest.NewRequest(http.MethodPost, "/path", bytes.NewBuffer(gbkdata1))
		r.Header.Set("Content-type", encoding.BuildContentType(encoding.DefaultMimeType, "gbk"))
		r.Header.Set("Accept", encoding.DefaultMimeType)
		r.Header.Set("Accept-Charset", "gbk;q=1,gb18080;q=0.1")
		ctx := New(w, r, nil)

		obj := &encodingtest.TextObject{}
		a.NotError(ctx.Unmarshal(obj))
		a.Equal(obj.Age, 11).Equal(obj.Name, "中文1")

		obj.Age = 22
		obj.Name = "中文2"
		a.NotError(ctx.Marshal(http.StatusCreated, obj, nil))
		a.Equal(w.Body.Bytes(), gbkdata2)
	}
}
<|endoftext|>


<commit_before>// Copyright 2017 Xiaomi, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package funcs

import (
	"fmt"
	"github.com/open-falcon/falcon-plus/common/model"
	"github.com/toolkits/nux"
	"log"
	"strings"
	"sync"
)

var (
	diskStatsMap = make(map[string][2]*nux.DiskStats)
	dsLock       = new(sync.RWMutex)
)

func UpdateDiskStats() error {
	dsList, err := nux.ListDiskStats()
	if err != nil {
		return err
	}

	dsLock.Lock()
	defer dsLock.Unlock()
	for i := 0; i < len(dsList); i++ {
		device := dsList[i].Device
		diskStatsMap[device] = [2]*nux.DiskStats{dsList[i], diskStatsMap[device][0]}
	}
	return nil
}

func IOReadRequests(arr [2]*nux.DiskStats) uint64 {
	return arr[0].ReadRequests - arr[1].ReadRequests
}

func IOReadMerged(arr [2]*nux.DiskStats) uint64 {
	return arr[0].ReadMerged - arr[1].ReadMerged
}

func IOReadSectors(arr [2]*nux.DiskStats) uint64 {
	return arr[0].ReadSectors - arr[1].ReadSectors
}

func IOMsecRead(arr [2]*nux.DiskStats) uint64 {
	return arr[0].MsecRead - arr[1].MsecRead
}

func IOWriteRequests(arr [2]*nux.DiskStats) uint64 {
	return arr[0].WriteRequests - arr[1].WriteRequests
}

func IOWriteMerged(arr [2]*nux.DiskStats) uint64 {
	return arr[0].WriteMerged - arr[1].WriteMerged
}

func IOWriteSectors(arr [2]*nux.DiskStats) uint64 {
	return arr[0].WriteSectors - arr[1].WriteSectors
}

func IOMsecWrite(arr [2]*nux.DiskStats) uint64 {
	return arr[0].MsecWrite - arr[1].MsecWrite
}

func IOMsecTotal(arr [2]*nux.DiskStats) uint64 {
	return arr[0].MsecTotal - arr[1].MsecTotal
}

func IOMsecWeightedTotal(arr [2]*nux.DiskStats) uint64 {
	return arr[0].MsecWeightedTotal - arr[1].MsecWeightedTotal
}

func TS(arr [2]*nux.DiskStats) uint64 {
	return uint64(arr[0].TS.Sub(arr[1].TS).Nanoseconds() / 1000000)
}

func IODelta(device string, f func([2]*nux.DiskStats) uint64) uint64 {
	val, ok := diskStatsMap[device]
	if !ok {
		return 0
	}

	if val[1] == nil {
		return 0
	}
	return f(val)
}

func DiskIOMetrics() (L []*model.MetricValue) {

	dsList, err := nux.ListDiskStats()
	if err != nil {
		log.Println(err)
		return
	}

	for _, ds := range dsList {
		if !ShouldHandleDevice(ds.Device) {
			continue
		}

		device := "device=" + ds.Device

		L = append(L, CounterValue("disk.io.read_requests", ds.ReadRequests, device))
		L = append(L, CounterValue("disk.io.read_merged", ds.ReadMerged, device))
		L = append(L, CounterValue("disk.io.read_sectors", ds.ReadSectors, device))
		L = append(L, CounterValue("disk.io.msec_read", ds.MsecRead, device))
		L = append(L, CounterValue("disk.io.write_requests", ds.WriteRequests, device))
		L = append(L, CounterValue("disk.io.write_merged", ds.WriteMerged, device))
		L = append(L, CounterValue("disk.io.write_sectors", ds.WriteSectors, device))
		L = append(L, CounterValue("disk.io.msec_write", ds.MsecWrite, device))
		L = append(L, CounterValue("disk.io.ios_in_progress", ds.IosInProgress, device))
		L = append(L, CounterValue("disk.io.msec_total", ds.MsecTotal, device))
		L = append(L, CounterValue("disk.io.msec_weighted_total", ds.MsecWeightedTotal, device))
	}
	return
}

func IOStatsMetrics() (L []*model.MetricValue) {
	dsLock.RLock()
	defer dsLock.RUnlock()

	for device := range diskStatsMap {
		if !ShouldHandleDevice(device) {
			continue
		}

		tags := "device=" + device
		rio := IODelta(device, IOReadRequests)
		wio := IODelta(device, IOWriteRequests)
		delta_rsec := IODelta(device, IOReadSectors)
		delta_wsec := IODelta(device, IOWriteSectors)
		ruse := IODelta(device, IOMsecRead)
		wuse := IODelta(device, IOMsecWrite)
		use := IODelta(device, IOMsecTotal)
		n_io := rio + wio
		avgrq_sz := 0.0
		await := 0.0
		svctm := 0.0
		if n_io != 0 {
			avgrq_sz = float64(delta_rsec+delta_wsec) / float64(n_io)
			await = float64(ruse+wuse) / float64(n_io)
			svctm = float64(use) / float64(n_io)
		}

		duration := IODelta(device, TS)

		L = append(L, GaugeValue("disk.io.read_bytes", float64(delta_rsec)*512.0, tags))
		L = append(L, GaugeValue("disk.io.write_bytes", float64(delta_wsec)*512.0, tags))
		L = append(L, GaugeValue("disk.io.avgrq_sz", avgrq_sz, tags))
		L = append(L, GaugeValue("disk.io.avgqu-sz", float64(IODelta(device, IOMsecWeightedTotal))/1000.0, tags))
		L = append(L, GaugeValue("disk.io.await", await, tags))
		L = append(L, GaugeValue("disk.io.svctm", svctm, tags))
		tmp := float64(use) * 100.0 / float64(duration)
		if tmp > 100.0 {
			tmp = 100.0
		}
		L = append(L, GaugeValue("disk.io.util", tmp, tags))
	}

	return
}

func IOStatsForPage() (L [][]string) {
	dsLock.RLock()
	defer dsLock.RUnlock()

	for device := range diskStatsMap {
		if !ShouldHandleDevice(device) {
			continue
		}

		rio := IODelta(device, IOReadRequests)
		wio := IODelta(device, IOWriteRequests)

		delta_rsec := IODelta(device, IOReadSectors)
		delta_wsec := IODelta(device, IOWriteSectors)

		ruse := IODelta(device, IOMsecRead)
		wuse := IODelta(device, IOMsecWrite)
		use := IODelta(device, IOMsecTotal)
		n_io := rio + wio
		avgrq_sz := 0.0
		await := 0.0
		svctm := 0.0
		if n_io != 0 {
			avgrq_sz = float64(delta_rsec+delta_wsec) / float64(n_io)
			await = float64(ruse+wuse) / float64(n_io)
			svctm = float64(use) / float64(n_io)
		}

		item := []string{
			device,
			fmt.Sprintf("%d", IODelta(device, IOReadMerged)),
			fmt.Sprintf("%d", IODelta(device, IOWriteMerged)),
			fmt.Sprintf("%d", rio),
			fmt.Sprintf("%d", wio),
			fmt.Sprintf("%.2f", float64(delta_rsec)/2.0),
			fmt.Sprintf("%.2f", float64(delta_wsec)/2.0),
			fmt.Sprintf("%.2f", avgrq_sz),                                             // avgrq-sz: delta(rsect+wsect)/delta(rio+wio)
			fmt.Sprintf("%.2f", float64(IODelta(device, IOMsecWeightedTotal))/1000.0), // avgqu-sz: delta(aveq)/s/1000
			fmt.Sprintf("%.2f", await),                                                // await: delta(ruse+wuse)/delta(rio+wio)
			fmt.Sprintf("%.2f", svctm),                                                // svctm: delta(use)/delta(rio+wio)
			fmt.Sprintf("%.2f%%", float64(use)/10.0),                                  // %util: delta(use)/s/1000 * 100%
		}
		L = append(L, item)
	}

	return
}

func ShouldHandleDevice(device string) bool {
	normal := len(device) == 3 && (strings.HasPrefix(device, "sd") || strings.HasPrefix(device, "vd"))
	aws := len(device) >= 4 && strings.HasPrefix(device, "xvd")
	flash := len(device) >= 4 && (strings.HasPrefix(device, "fio") || strings.HasPrefix(device, "nvme"))
	nbd := len(device) >= 4 && strings.HasPrefix(device, "nbd")
	return normal || aws || flash || nbd
}
<commit_msg>more robust to parse /proc/diskstats (#945)<commit_after>// Copyright 2017 Xiaomi, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package funcs

import (
	"fmt"
	"log"
	"strings"
	"sync"

	"github.com/open-falcon/falcon-plus/common/model"
	"github.com/toolkits/nux"
)

var (
	diskStatsMap = make(map[string][2]*nux.DiskStats)
	dsLock       = new(sync.RWMutex)
)

func UpdateDiskStats() error {
	dsList, err := nux.ListDiskStats()
	if err != nil {
		return err
	}

	dsLock.Lock()
	defer dsLock.Unlock()
	for i := 0; i < len(dsList); i++ {
		device := dsList[i].Device
		diskStatsMap[device] = [2]*nux.DiskStats{dsList[i], diskStatsMap[device][0]}
	}
	return nil
}

func IOReadRequests(arr [2]*nux.DiskStats) uint64 {
	return arr[0].ReadRequests - arr[1].ReadRequests
}

func IOReadMerged(arr [2]*nux.DiskStats) uint64 {
	return arr[0].ReadMerged - arr[1].ReadMerged
}

func IOReadSectors(arr [2]*nux.DiskStats) uint64 {
	return arr[0].ReadSectors - arr[1].ReadSectors
}

func IOMsecRead(arr [2]*nux.DiskStats) uint64 {
	return arr[0].MsecRead - arr[1].MsecRead
}

func IOWriteRequests(arr [2]*nux.DiskStats) uint64 {
	return arr[0].WriteRequests - arr[1].WriteRequests
}

func IOWriteMerged(arr [2]*nux.DiskStats) uint64 {
	return arr[0].WriteMerged - arr[1].WriteMerged
}

func IOWriteSectors(arr [2]*nux.DiskStats) uint64 {
	return arr[0].WriteSectors - arr[1].WriteSectors
}

func IOMsecWrite(arr [2]*nux.DiskStats) uint64 {
	return arr[0].MsecWrite - arr[1].MsecWrite
}

func IOMsecTotal(arr [2]*nux.DiskStats) uint64 {
	return arr[0].MsecTotal - arr[1].MsecTotal
}

func IOMsecWeightedTotal(arr [2]*nux.DiskStats) uint64 {
	return arr[0].MsecWeightedTotal - arr[1].MsecWeightedTotal
}

func TS(arr [2]*nux.DiskStats) uint64 {
	return uint64(arr[0].TS.Sub(arr[1].TS).Nanoseconds() / 1000000)
}

func IODelta(device string, f func([2]*nux.DiskStats) uint64) uint64 {
	val, ok := diskStatsMap[device]
	if !ok {
		return 0
	}

	if val[1] == nil {
		return 0
	}
	return f(val)
}

func DiskIOMetrics() (L []*model.MetricValue) {

	dsList, err := nux.ListDiskStats()
	if err != nil {
		log.Println(err)
		return
	}

	for _, ds := range dsList {
		if !ShouldHandleDevice(ds.Device) {
			continue
		}

		device := "device=" + ds.Device

		L = append(L, CounterValue("disk.io.read_requests", ds.ReadRequests, device))
		L = append(L, CounterValue("disk.io.read_merged", ds.ReadMerged, device))
		L = append(L, CounterValue("disk.io.read_sectors", ds.ReadSectors, device))
		L = append(L, CounterValue("disk.io.msec_read", ds.MsecRead, device))
		L = append(L, CounterValue("disk.io.write_requests", ds.WriteRequests, device))
		L = append(L, CounterValue("disk.io.write_merged", ds.WriteMerged, device))
		L = append(L, CounterValue("disk.io.write_sectors", ds.WriteSectors, device))
		L = append(L, CounterValue("disk.io.msec_write", ds.MsecWrite, device))
		L = append(L, CounterValue("disk.io.ios_in_progress", ds.IosInProgress, device))
		L = append(L, CounterValue("disk.io.msec_total", ds.MsecTotal, device))
		L = append(L, CounterValue("disk.io.msec_weighted_total", ds.MsecWeightedTotal, device))
	}
	return
}

func IOStatsMetrics() (L []*model.MetricValue) {
	dsLock.RLock()
	defer dsLock.RUnlock()

	for device := range diskStatsMap {
		if !ShouldHandleDevice(device) {
			continue
		}

		tags := "device=" + device
		rio := IODelta(device, IOReadRequests)
		wio := IODelta(device, IOWriteRequests)
		delta_rsec := IODelta(device, IOReadSectors)
		delta_wsec := IODelta(device, IOWriteSectors)
		ruse := IODelta(device, IOMsecRead)
		wuse := IODelta(device, IOMsecWrite)
		use := IODelta(device, IOMsecTotal)
		n_io := rio + wio
		avgrq_sz := 0.0
		await := 0.0
		svctm := 0.0
		if n_io != 0 {
			avgrq_sz = float64(delta_rsec+delta_wsec) / float64(n_io)
			await = float64(ruse+wuse) / float64(n_io)
			svctm = float64(use) / float64(n_io)
		}

		duration := IODelta(device, TS)

		L = append(L, GaugeValue("disk.io.read_bytes", float64(delta_rsec)*512.0, tags))
		L = append(L, GaugeValue("disk.io.write_bytes", float64(delta_wsec)*512.0, tags))
		L = append(L, GaugeValue("disk.io.avgrq_sz", avgrq_sz, tags))
		L = append(L, GaugeValue("disk.io.avgqu-sz", float64(IODelta(device, IOMsecWeightedTotal))/1000.0, tags))
		L = append(L, GaugeValue("disk.io.await", await, tags))
		L = append(L, GaugeValue("disk.io.svctm", svctm, tags))
		tmp := float64(use) * 100.0 / float64(duration)
		if tmp > 100.0 {
			tmp = 100.0
		}
		L = append(L, GaugeValue("disk.io.util", tmp, tags))
	}

	return
}

func IOStatsForPage() (L [][]string) {
	dsLock.RLock()
	defer dsLock.RUnlock()

	for device := range diskStatsMap {
		if !ShouldHandleDevice(device) {
			continue
		}

		rio := IODelta(device, IOReadRequests)
		wio := IODelta(device, IOWriteRequests)

		delta_rsec := IODelta(device, IOReadSectors)
		delta_wsec := IODelta(device, IOWriteSectors)

		ruse := IODelta(device, IOMsecRead)
		wuse := IODelta(device, IOMsecWrite)
		use := IODelta(device, IOMsecTotal)
		n_io := rio + wio
		avgrq_sz := 0.0
		await := 0.0
		svctm := 0.0
		if n_io != 0 {
			avgrq_sz = float64(delta_rsec+delta_wsec) / float64(n_io)
			await = float64(ruse+wuse) / float64(n_io)
			svctm = float64(use) / float64(n_io)
		}

		item := []string{
			device,
			fmt.Sprintf("%d", IODelta(device, IOReadMerged)),
			fmt.Sprintf("%d", IODelta(device, IOWriteMerged)),
			fmt.Sprintf("%d", rio),
			fmt.Sprintf("%d", wio),
			fmt.Sprintf("%.2f", float64(delta_rsec)/2.0),
			fmt.Sprintf("%.2f", float64(delta_wsec)/2.0),
			fmt.Sprintf("%.2f", avgrq_sz),                                             // avgrq-sz: delta(rsect+wsect)/delta(rio+wio)
			fmt.Sprintf("%.2f", float64(IODelta(device, IOMsecWeightedTotal))/1000.0), // avgqu-sz: delta(aveq)/s/1000
			fmt.Sprintf("%.2f", await),                                                // await: delta(ruse+wuse)/delta(rio+wio)
			fmt.Sprintf("%.2f", svctm),                                                // svctm: delta(use)/delta(rio+wio)
			fmt.Sprintf("%.2f%%", float64(use)/10.0),                                  // %util: delta(use)/s/1000 * 100%
		}
		L = append(L, item)
	}

	return
}

func ShouldHandleDevice(device string) bool {
	normal := len(device) <= 4 && (strings.HasPrefix(device, "sd") || strings.HasPrefix(device, "vd")) && !strings.ContainsAny(device, "1234")
	aws := len(device) >= 4 && strings.HasPrefix(device, "xvd")
	flash := len(device) >= 4 && (strings.HasPrefix(device, "fio") || strings.HasPrefix(device, "nvme"))
	nbd := len(device) >= 4 && strings.HasPrefix(device, "nbd")
	return normal || aws || flash || nbd
}
<|endoftext|>


<commit_before>package teles

import (
	"testing"
)

var (
	serverHost    = "192.168.36.129"
	serverPort    = "2856"
	serverAddress = serverHost + ":" + serverPort
	dummySpace    = Space{Name: "asdf"}
	validSpace    = Space{
		Name: "thing",
		Conn: &Connection{Server: serverAddress},
	}
	anotherSpace = Space{
		Name: "another",
		Conn: &Connection{Server: serverAddress},
	}
)

func failIfError(t *testing.T, err error) {
	if err != nil {
		t.Error(err.Error())
	}
}
<commit_msg>Needs to be localhost for travis<commit_after>package teles

import (
	"testing"
)

var (
	serverHost    = "127.0.0.1"
	serverPort    = "2856"
	serverAddress = serverHost + ":" + serverPort
	dummySpace    = Space{Name: "asdf"}
	validSpace    = Space{
		Name: "thing",
		Conn: &Connection{Server: serverAddress},
	}
	anotherSpace = Space{
		Name: "another",
		Conn: &Connection{Server: serverAddress},
	}
)

func failIfError(t *testing.T, err error) {
	if err != nil {
		t.Error(err.Error())
	}
}
<|endoftext|>


<commit_before>// Copyright 2016 The nvim-go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package pathutil

import (
	"go/build"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"sync"

	"github.com/neovim/go-client/nvim"
)

var pkgPathutil = "pathutil"

// Chdir changes the vim current working directory.
// The returned function restores working directory to `getcwd()` result path
// and unlocks the mutex.
func Chdir(v *nvim.Nvim, dir string) func() {
	var (
		m   sync.Mutex
		cwd interface{}
	)
	m.Lock()
	v.Eval("getcwd()", &cwd)
	v.SetCurrentDirectory(dir)
	return func() {
		v.SetCurrentDirectory(cwd.(string))
		m.Unlock()
	}
}

// TrimGoPath trims the GOPATH and {bin,pkg,src}, basically for the converts
// the package ID
func TrimGoPath(p string) string {
	// Separate trim work for p equal GOPATH
	p = strings.TrimPrefix(p, build.Default.GOPATH)
	p = strings.TrimPrefix(p, string(filepath.Separator))

	if len(p) >= 4 {
		switch p[:3] {
		case "bin", "pkg", "src":
			return filepath.Clean(p[4:])
		}
	}

	return p
}

// JoinGoPath joins the $GOPATH + "src" to p
func JoinGoPath(p string) string {
	return filepath.Join(build.Default.GOPATH, "src", p)
}

// ShortFilePath return the simply trim cwd into p.
func ShortFilePath(p, cwd string) string {
	return strings.Replace(p, cwd, ".", 1)
}

// Rel wrapper of filepath.Rel function that return only one variable.
func Rel(cwd, f string) string {
	rel, err := filepath.Rel(cwd, f)
	if err != nil {
		return f
	}
	return rel
}

// ExpandGoRoot expands the "$GOROOT" include from p.
func ExpandGoRoot(p string) string {
	if strings.Index(p, "$GOROOT") != -1 {
		return strings.Replace(p, "$GOROOT", runtime.GOROOT(), 1)
	}

	return p // Not hit
}

// IsDir returns whether the filename is directory.
func IsDir(filename string) bool {
	fi, err := os.Stat(filename)
	return err == nil && fi.IsDir()
}

// IsExist returns whether the filename is exists.
func IsExist(filename string) bool {
	_, err := os.Stat(filename)
	return !os.IsNotExist(err) || err == nil
}

// IsNotExist returns whether the filename is exists.
func IsNotExist(filename string) bool {
	_, err := os.Stat(filename)
	return os.IsNotExist(err)
}

// IsGoFile returns whether the filename is exists.
func IsGoFile(filename string) bool {
	f, err := os.Stat(filename)
	return err == nil && filepath.Ext(f.Name()) == ".go"
}

// ToWildcard returns the path with wildcard(...) suffix.
func ToWildcard(path string) string {
	return path + string(filepath.Separator) + "..."
}
<commit_msg>internal/pathutil: add Create, Mkdir and IsDirExist functions<commit_after>// Copyright 2016 The nvim-go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package pathutil

import (
	"go/build"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"sync"

	"github.com/neovim/go-client/nvim"
)

var pkgPathutil = "pathutil"

// Chdir changes the vim current working directory.
// The returned function restores working directory to `getcwd()` result path
// and unlocks the mutex.
func Chdir(v *nvim.Nvim, dir string) func() {
	var (
		m   sync.Mutex
		cwd interface{}
	)
	m.Lock()
	v.Eval("getcwd()", &cwd)
	v.SetCurrentDirectory(dir)
	return func() {
		v.SetCurrentDirectory(cwd.(string))
		m.Unlock()
	}
}

// TrimGoPath trims the GOPATH and {bin,pkg,src}, basically for the converts
// the package ID
func TrimGoPath(p string) string {
	// Separate trim work for p equal GOPATH
	p = strings.TrimPrefix(p, build.Default.GOPATH)
	p = strings.TrimPrefix(p, string(filepath.Separator))

	if len(p) >= 4 {
		switch p[:3] {
		case "bin", "pkg", "src":
			return filepath.Clean(p[4:])
		}
	}

	return p
}

// JoinGoPath joins the $GOPATH + "src" to p
func JoinGoPath(p string) string {
	return filepath.Join(build.Default.GOPATH, "src", p)
}

// ShortFilePath return the simply trim cwd into p.
func ShortFilePath(p, cwd string) string {
	return strings.Replace(p, cwd, ".", 1)
}

// Rel wrapper of filepath.Rel function that return only one variable.
func Rel(cwd, f string) string {
	rel, err := filepath.Rel(cwd, f)
	if err != nil {
		return f
	}
	return rel
}

// ExpandGoRoot expands the "$GOROOT" include from p.
func ExpandGoRoot(p string) string {
	if strings.Index(p, "$GOROOT") != -1 {
		return strings.Replace(p, "$GOROOT", runtime.GOROOT(), 1)
	}

	return p // Not hit
}

func Create(filename string) error {
	if IsNotExist(filename) {
		if _, err := os.Create(filename); err != nil {
			return err
		}
	}
	return nil
}

func Mkdir(dir string, perm os.FileMode) error {
	if !IsDirExist(dir) {
		if err := os.MkdirAll(dir, perm); err != nil {
			return err
		}
	}
	return nil
}

// IsDir returns whether the filename is directory.
func IsDir(filename string) bool {
	fi, err := os.Stat(filename)
	return err == nil && fi.IsDir()
}

// IsExist returns whether the filename is exists.
func IsExist(filename string) bool {
	_, err := os.Stat(filename)
	return !os.IsNotExist(err) || err == nil
}

// IsNotExist returns whether the filename is exists.
func IsNotExist(filename string) bool {
	_, err := os.Stat(filename)
	return os.IsNotExist(err)
}

// IsDirExist reports whether dir exists and which is directory.
func IsDirExist(dir string) bool {
	fi, err := os.Stat(dir)
	return err == nil && fi.IsDir()
}

// IsGoFile returns whether the filename is exists.
func IsGoFile(filename string) bool {
	f, err := os.Stat(filename)
	return err == nil && filepath.Ext(f.Name()) == ".go"
}

// ToWildcard returns the path with wildcard(...) suffix.
func ToWildcard(path string) string {
	return path + string(filepath.Separator) + "..."
}
<|endoftext|>


<commit_before>package asciidocgo

import (
	"os"
	"testing"
	. "github.com/smartystreets/goconvey/convey"
)

func TestPathResolver(t *testing.T) {

	Convey("A pathResolver can be initialized", t, func() {

		Convey("By default, a pathResolver can be created", func() {
			So(NewPathResolver(0, ""), ShouldNotBeNil)
		})
		Convey("By default, a pathResolver has a system path separator", func() {
			So(NewPathResolver(0, "").FileSeparator(), ShouldEqual, os.PathSeparator)
			So(NewPathResolver('/', "").FileSeparator(), ShouldNotEqual, os.PathSeparator)
			So(NewPathResolver('/', "").FileSeparator(), ShouldEqual, '/')
		})

		Convey("By default, a pathResolver has a current working path", func() {
			pwd, err := os.Getwd()
			if err != nil {
				panic(err)
			}
			So(NewPathResolver(0, "").WorkingDir(), ShouldEqual, pwd)
			So(NewPathResolver(0, "C:\\").WorkingDir(), ShouldEqual, "C:\\")
			So(NewPathResolver(0, "test").WorkingDir(), ShouldEqual, pwd+string(os.PathSeparator)+"test")
			//So(NewPathResolver(0, "panicnoroot").WorkingDir(), ShouldEqual, pwd)

		})
		Convey("A pathResolver should not panic on getting pwd", func() {
			recovered := false
			defer func() {
				recover()
				recovered = true
				So(recovered, ShouldBeTrue)
			}()
			_ = NewPathResolver(0, "panic on os.Getwd")
		})
		Convey("A pathResolver should not panic on filepath.Abs", func() {
			recovered := false
			defer func() {
				recover()
				recovered = true
				So(recovered, ShouldBeTrue)
			}()
			_ = NewPathResolver(0, "panic on filepath.Abs")
		})
	})

	Convey("A pathResolver can test for a web path", t, func() {
		So(IsWebRoot(""), ShouldBeFalse)
		So(IsWebRoot("a"), ShouldBeFalse)
		So(IsWebRoot("\\a\\b/c"), ShouldBeFalse)
		So(IsWebRoot("/a/b/c"), ShouldBeTrue)
	})

	Convey("A pathResolver can replace backslash by slash", t, func() {
		So(Posixfy(""), ShouldEqual, "")
		So(Posixfy("a/b/c"), ShouldEqual, "a/b/c")
		So(Posixfy("a\\b\\c"), ShouldEqual, "a/b/c")
	})

	Convey("A pathResolver can test for root", t, func() {
		Convey("A Path starting with C:/ is root", func() {
			So(IsRoot(""), ShouldBeFalse)
			So(IsRoot("C:\\"), ShouldBeTrue)
			So(IsRoot("C:/"), ShouldBeTrue)
			So(IsRoot("C:\\a/b/"), ShouldBeTrue)
			So(IsRoot("c:/a/b/../c"), ShouldBeTrue)
			So(IsRoot("c:\\a/b/../c"), ShouldBeTrue)
		})
	})

	Convey("A pathResolver can test for web root", t, func() {
		Convey("A Path starting with / is web root", func() {
			So(IsWebRoot(""), ShouldBeFalse)
			So(IsWebRoot("C:\\"), ShouldBeFalse)
			So(IsWebRoot("\\"), ShouldBeFalse)
			So(IsWebRoot("/"), ShouldBeTrue)
			So(IsWebRoot("/a/b/"), ShouldBeTrue)
			So(IsWebRoot("/a\\b/./c"), ShouldBeTrue)
			So(IsWebRoot("/a/b/./c"), ShouldBeTrue)
		})
	})

	Convey("A pathResolver can expand a path", t, func() {
		Convey("empty path returns an empty string", func() {
			So(ExpandPath(""), ShouldEqual, "")
		})
		Convey("non-empty path returns an posix path", func() {
			So(ExpandPath("c:\\a/.\\b/../c"), ShouldEqual, "c:/a/b/../c")
		})
	})

	Convey("A pathResolver can partition a path", t, func() {
		pathSegments, root, posixPath := PartitionPath("", false)
		So(len(pathSegments), ShouldEqual, 0)
		So(root, ShouldEqual, "")
		So(posixPath, ShouldEqual, "")

		Convey("A Path starting with dot has a dot root", func() {
			pathSegments, root, posixPath := PartitionPath(".", false)
			So(len(pathSegments), ShouldEqual, 0)
			So(root, ShouldEqual, ".")
			So(posixPath, ShouldEqual, ".")

			pathSegments, root, posixPath = PartitionPath(".\\a/b", false)
			So(len(pathSegments), ShouldEqual, 2)
			So(root, ShouldEqual, ".")
			So(posixPath, ShouldEqual, "./a/b")

		})
		Convey("A Partition removes self-reference path", func() {
			pathSegments, root, posixPath := PartitionPath("a\\b/./c", false)
			So(len(pathSegments), ShouldEqual, 3)
			So(root, ShouldEqual, "")
			So(posixPath, ShouldEqual, "a/b/./c")

			pathSegments, root, posixPath = PartitionPath("C:/a\\b/./c", false)
			So(len(pathSegments), ShouldEqual, 3)
			So(root, ShouldEqual, "C:")
			So(posixPath, ShouldEqual, "C:/a/b/./c")

			pathSegments, root, posixPath = PartitionPath("/a\\b/./c", true)
			So(len(pathSegments), ShouldEqual, 2)
			So(root, ShouldEqual, "/a")
			So(posixPath, ShouldEqual, "/a/b/./c")
		})
		Convey("A Partition keep '..' paths", func() {
			pathSegments, root, posixPath = PartitionPath("a\\b/../c", true)
			So(len(pathSegments), ShouldEqual, 4)
			So(root, ShouldEqual, "")
			So(posixPath, ShouldEqual, "a/b/../c")

			pathSegments, root, posixPath = PartitionPath("\\a\\b/../c", true)
			So(len(pathSegments), ShouldEqual, 3)
			So(root, ShouldEqual, "/a")
			So(posixPath, ShouldEqual, "/a/b/../c")

			pathSegments, root, posixPath = PartitionPath("c:\\a\\b/../c", false)
			So(len(pathSegments), ShouldEqual, 4)
			So(root, ShouldEqual, "c:")
			So(posixPath, ShouldEqual, "c:/a/b/../c")
		})
	})

	Convey("A pathResolver can join a path", t, func() {
		Convey("No segment and empty root returns an empty string", func() {
			So(JoinPath(nil, ""), ShouldEqual, "")
		})
		Convey("Segments with no root returns an slash-separated segments", func() {
			So(JoinPath([]string{"a"}, ""), ShouldEqual, "a")
			So(JoinPath([]string{"a", "b"}, ""), ShouldEqual, "a/b")
			So(JoinPath([]string{"a", "b", "c"}, ""), ShouldEqual, "a/b/c")
		})
		Convey("Segments with root returns an root plus slash-separated segments", func() {
			So(JoinPath([]string{"a"}, "c:"), ShouldEqual, "c:/a")
			So(JoinPath([]string{"a", "b"}, "d:"), ShouldEqual, "d:/a/b")
			So(JoinPath([]string{"a", "b", "c"}, "e:"), ShouldEqual, "e:/a/b/c")
		})
	})

	Convey("A Partition can resolve a system path from the target and start paths", t, func() {
		pr := NewPathResolver(0, "C:/a/working/dir")
		Convey("A Non-absolute jail path should panic", func() {
			recovered := false
			defer func() {
				r := recover()
				recovered = true
				So(recovered, ShouldBeTrue)
				So(r, ShouldEqual, "Jail is not an absolute path: c")
			}()
			_ = pr.SystemPath("a", "b", "c", false, "")
		})
		Convey("A system path with no start resolves from the root", func() {
			So(pr.SystemPath("images", "", "", false, ""), ShouldEqual, "")
			So(pr.SystemPath("../images", "", "", false, ""), ShouldEqual, "")
			So(pr.SystemPath("/etc/images", "", "", false, ""), ShouldEqual, "")
		})
		Convey("Empty target segment and empty start and empty jail means working dir", func() {
			So(pr.SystemPath("", "", "", false, ""), ShouldEqual, "C:/a/working/dir")
		})
		Convey("Empty target segment, non-empty root start and empty jail means expanded start path", func() {
			So(pr.SystemPath("", "C:\\start/../b", "", false, ""), ShouldEqual, "C:/start/../b")
		})
		Convey("Empty target segment, non-empty non-root start means susyem path start", func() {
			recovered := false
			defer func() {
				r := recover()
				recovered = true
				So(recovered, ShouldBeTrue)
				So(r, ShouldEqual, "should not happen yet")
			}()
			SkipSo(pr.SystemPath("", "start/../b", "", false, ""), ShouldEqual, "start/../b")
			SkipSo(pr.SystemPath("", "start/../b", "C:\\", false, ""), ShouldEqual, "start/../b")
		})
		Convey("Non-Empty target segments starting with jail (or empty jail) returns target", func() {
			So(pr.SystemPath("C:/start/b", "", "", false, ""), ShouldEqual, "C:/start/b")
			So(pr.SystemPath("C:/start/b", "C:\\start", "", false, ""), ShouldEqual, "C:/start/b")
			So(pr.SystemPath("C:/start/b", "C:\\start/", "", false, ""), ShouldEqual, "C:/start/b")
		})

		/*
			resolver.system_path('images')
			    => '/path/to/docs/images'

			    resolver.system_path('../images')
			    => '/path/to/images'

			    resolver.system_path('/etc/images')
			    => '/etc/images'

			    resolver.system_path('images', '/etc')
			    => '/etc/images'

			    resolver.system_path('', '/etc/images')
			    => '/etc/images'

			    resolver.system_path(nil, nil, '/path/to/docs')
			    => '/path/to/docs'

			    resolver.system_path('..', nil, '/path/to/docs')
			    => '/path/to/docs'

			    resolver.system_path('../../../css', nil, '/path/to/docs')
			    => '/path/to/docs/css'

			    resolver.system_path('../../../css', '../../..', '/path/to/docs')
			    => '/path/to/docs/css'

			    resolver.system_path('..', 'C:\\data\\docs\\assets', 'C:\\data\\docs')
			    => 'C:/data/docs'

			    resolver.system_path('..\\..\\css', 'C:\\data\\docs\\assets', 'C:\\data\\docs')
			    => 'C:/data/docs/css'

			    begin
			      resolver.system_path('../../../css', '../../..', '/path/to/docs', :recover => false)
			    rescue SecurityError => e
			      puts e.message
			    end
			    => 'path ../../../../../../css refers to location outside jail: /path/to/docs (disallowed in safe mode)'

			    resolver.system_path('/path/to/docs/images', nil, '/path/to/docs')
			    => '/path/to/docs/images'

			    begin
			      resolver.system_path('images', '/etc', '/path/to/docs')
			    rescue SecurityError => e
			      puts e.message
			    end
			    => Start path /etc is outside of jail: /path/to/docs'
		*/
	})
}
<commit_msg>comment initial test cases for PathResolver.SystemPath()<commit_after>package asciidocgo

import (
	"os"
	"testing"
	. "github.com/smartystreets/goconvey/convey"
)

func TestPathResolver(t *testing.T) {

	Convey("A pathResolver can be initialized", t, func() {

		Convey("By default, a pathResolver can be created", func() {
			So(NewPathResolver(0, ""), ShouldNotBeNil)
		})
		Convey("By default, a pathResolver has a system path separator", func() {
			So(NewPathResolver(0, "").FileSeparator(), ShouldEqual, os.PathSeparator)
			So(NewPathResolver('/', "").FileSeparator(), ShouldNotEqual, os.PathSeparator)
			So(NewPathResolver('/', "").FileSeparator(), ShouldEqual, '/')
		})

		Convey("By default, a pathResolver has a current working path", func() {
			pwd, err := os.Getwd()
			if err != nil {
				panic(err)
			}
			So(NewPathResolver(0, "").WorkingDir(), ShouldEqual, pwd)
			So(NewPathResolver(0, "C:\\").WorkingDir(), ShouldEqual, "C:\\")
			So(NewPathResolver(0, "test").WorkingDir(), ShouldEqual, pwd+string(os.PathSeparator)+"test")
			//So(NewPathResolver(0, "panicnoroot").WorkingDir(), ShouldEqual, pwd)

		})
		Convey("A pathResolver should not panic on getting pwd", func() {
			recovered := false
			defer func() {
				recover()
				recovered = true
				So(recovered, ShouldBeTrue)
			}()
			_ = NewPathResolver(0, "panic on os.Getwd")
		})
		Convey("A pathResolver should not panic on filepath.Abs", func() {
			recovered := false
			defer func() {
				recover()
				recovered = true
				So(recovered, ShouldBeTrue)
			}()
			_ = NewPathResolver(0, "panic on filepath.Abs")
		})
	})

	Convey("A pathResolver can test for a web path", t, func() {
		So(IsWebRoot(""), ShouldBeFalse)
		So(IsWebRoot("a"), ShouldBeFalse)
		So(IsWebRoot("\\a\\b/c"), ShouldBeFalse)
		So(IsWebRoot("/a/b/c"), ShouldBeTrue)
	})

	Convey("A pathResolver can replace backslash by slash", t, func() {
		So(Posixfy(""), ShouldEqual, "")
		So(Posixfy("a/b/c"), ShouldEqual, "a/b/c")
		So(Posixfy("a\\b\\c"), ShouldEqual, "a/b/c")
	})

	Convey("A pathResolver can test for root", t, func() {
		Convey("A Path starting with C:/ is root", func() {
			So(IsRoot(""), ShouldBeFalse)
			So(IsRoot("C:\\"), ShouldBeTrue)
			So(IsRoot("C:/"), ShouldBeTrue)
			So(IsRoot("C:\\a/b/"), ShouldBeTrue)
			So(IsRoot("c:/a/b/../c"), ShouldBeTrue)
			So(IsRoot("c:\\a/b/../c"), ShouldBeTrue)
		})
	})

	Convey("A pathResolver can test for web root", t, func() {
		Convey("A Path starting with / is web root", func() {
			So(IsWebRoot(""), ShouldBeFalse)
			So(IsWebRoot("C:\\"), ShouldBeFalse)
			So(IsWebRoot("\\"), ShouldBeFalse)
			So(IsWebRoot("/"), ShouldBeTrue)
			So(IsWebRoot("/a/b/"), ShouldBeTrue)
			So(IsWebRoot("/a\\b/./c"), ShouldBeTrue)
			So(IsWebRoot("/a/b/./c"), ShouldBeTrue)
		})
	})

	Convey("A pathResolver can expand a path", t, func() {
		Convey("empty path returns an empty string", func() {
			So(ExpandPath(""), ShouldEqual, "")
		})
		Convey("non-empty path returns an posix path", func() {
			So(ExpandPath("c:\\a/.\\b/../c"), ShouldEqual, "c:/a/b/../c")
		})
	})

	Convey("A pathResolver can partition a path", t, func() {
		pathSegments, root, posixPath := PartitionPath("", false)
		So(len(pathSegments), ShouldEqual, 0)
		So(root, ShouldEqual, "")
		So(posixPath, ShouldEqual, "")

		Convey("A Path starting with dot has a dot root", func() {
			pathSegments, root, posixPath := PartitionPath(".", false)
			So(len(pathSegments), ShouldEqual, 0)
			So(root, ShouldEqual, ".")
			So(posixPath, ShouldEqual, ".")

			pathSegments, root, posixPath = PartitionPath(".\\a/b", false)
			So(len(pathSegments), ShouldEqual, 2)
			So(root, ShouldEqual, ".")
			So(posixPath, ShouldEqual, "./a/b")

		})
		Convey("A Partition removes self-reference path", func() {
			pathSegments, root, posixPath := PartitionPath("a\\b/./c", false)
			So(len(pathSegments), ShouldEqual, 3)
			So(root, ShouldEqual, "")
			So(posixPath, ShouldEqual, "a/b/./c")

			pathSegments, root, posixPath = PartitionPath("C:/a\\b/./c", false)
			So(len(pathSegments), ShouldEqual, 3)
			So(root, ShouldEqual, "C:")
			So(posixPath, ShouldEqual, "C:/a/b/./c")

			pathSegments, root, posixPath = PartitionPath("/a\\b/./c", true)
			So(len(pathSegments), ShouldEqual, 2)
			So(root, ShouldEqual, "/a")
			So(posixPath, ShouldEqual, "/a/b/./c")
		})
		Convey("A Partition keep '..' paths", func() {
			pathSegments, root, posixPath = PartitionPath("a\\b/../c", true)
			So(len(pathSegments), ShouldEqual, 4)
			So(root, ShouldEqual, "")
			So(posixPath, ShouldEqual, "a/b/../c")

			pathSegments, root, posixPath = PartitionPath("\\a\\b/../c", true)
			So(len(pathSegments), ShouldEqual, 3)
			So(root, ShouldEqual, "/a")
			So(posixPath, ShouldEqual, "/a/b/../c")

			pathSegments, root, posixPath = PartitionPath("c:\\a\\b/../c", false)
			So(len(pathSegments), ShouldEqual, 4)
			So(root, ShouldEqual, "c:")
			So(posixPath, ShouldEqual, "c:/a/b/../c")
		})
	})

	Convey("A pathResolver can join a path", t, func() {
		Convey("No segment and empty root returns an empty string", func() {
			So(JoinPath(nil, ""), ShouldEqual, "")
		})
		Convey("Segments with no root returns an slash-separated segments", func() {
			So(JoinPath([]string{"a"}, ""), ShouldEqual, "a")
			So(JoinPath([]string{"a", "b"}, ""), ShouldEqual, "a/b")
			So(JoinPath([]string{"a", "b", "c"}, ""), ShouldEqual, "a/b/c")
		})
		Convey("Segments with root returns an root plus slash-separated segments", func() {
			So(JoinPath([]string{"a"}, "c:"), ShouldEqual, "c:/a")
			So(JoinPath([]string{"a", "b"}, "d:"), ShouldEqual, "d:/a/b")
			So(JoinPath([]string{"a", "b", "c"}, "e:"), ShouldEqual, "e:/a/b/c")
		})
	})

	Convey("A Partition can resolve a system path from the target and start paths", t, func() {
		pr := NewPathResolver(0, "C:/a/working/dir")
		Convey("A Non-absolute jail path should panic", func() {
			recovered := false
			defer func() {
				r := recover()
				recovered = true
				So(recovered, ShouldBeTrue)
				So(r, ShouldEqual, "Jail is not an absolute path: c")
			}()
			_ = pr.SystemPath("a", "b", "c", false, "")
		})
		/*
			Convey("A system path with no start resolves from the root", func() {
				So(pr.SystemPath("images", "", "", false, ""), ShouldEqual, "")
				So(pr.SystemPath("../images", "", "", false, ""), ShouldEqual, "")
				So(pr.SystemPath("/etc/images", "", "", false, ""), ShouldEqual, "")
			})*/
		Convey("Empty target segment and empty start and empty jail means working dir", func() {
			So(pr.SystemPath("", "", "", false, ""), ShouldEqual, "C:/a/working/dir")
		})
		Convey("Empty target segment, non-empty root start and empty jail means expanded start path", func() {
			So(pr.SystemPath("", "C:\\start/../b", "", false, ""), ShouldEqual, "C:/start/../b")
		})
		Convey("Empty target segment, non-empty non-root start means susyem path start", func() {
			recovered := false
			defer func() {
				r := recover()
				recovered = true
				So(recovered, ShouldBeTrue)
				So(r, ShouldEqual, "should not happen yet")
			}()
			SkipSo(pr.SystemPath("", "start/../b", "", false, ""), ShouldEqual, "start/../b")
			SkipSo(pr.SystemPath("", "start/../b", "C:\\", false, ""), ShouldEqual, "start/../b")
		})
		Convey("Non-Empty target segments starting with jail (or empty jail) returns target", func() {
			So(pr.SystemPath("C:/start/b", "", "", false, ""), ShouldEqual, "C:/start/b")
			So(pr.SystemPath("C:/start/b", "C:\\start", "", false, ""), ShouldEqual, "C:/start/b")
			So(pr.SystemPath("C:/start/b", "C:\\start/", "", false, ""), ShouldEqual, "C:/start/b")
		})

		/*
			resolver.system_path('images')
			    => '/path/to/docs/images'

			    resolver.system_path('../images')
			    => '/path/to/images'

			    resolver.system_path('/etc/images')
			    => '/etc/images'

			    resolver.system_path('images', '/etc')
			    => '/etc/images'

			    resolver.system_path('', '/etc/images')
			    => '/etc/images'

			    resolver.system_path(nil, nil, '/path/to/docs')
			    => '/path/to/docs'

			    resolver.system_path('..', nil, '/path/to/docs')
			    => '/path/to/docs'

			    resolver.system_path('../../../css', nil, '/path/to/docs')
			    => '/path/to/docs/css'

			    resolver.system_path('../../../css', '../../..', '/path/to/docs')
			    => '/path/to/docs/css'

			    resolver.system_path('..', 'C:\\data\\docs\\assets', 'C:\\data\\docs')
			    => 'C:/data/docs'

			    resolver.system_path('..\\..\\css', 'C:\\data\\docs\\assets', 'C:\\data\\docs')
			    => 'C:/data/docs/css'

			    begin
			      resolver.system_path('../../../css', '../../..', '/path/to/docs', :recover => false)
			    rescue SecurityError => e
			      puts e.message
			    end
			    => 'path ../../../../../../css refers to location outside jail: /path/to/docs (disallowed in safe mode)'

			    resolver.system_path('/path/to/docs/images', nil, '/path/to/docs')
			    => '/path/to/docs/images'

			    begin
			      resolver.system_path('images', '/etc', '/path/to/docs')
			    rescue SecurityError => e
			      puts e.message
			    end
			    => Start path /etc is outside of jail: /path/to/docs'
		*/
	})
}
<|endoftext|>


<commit_before>package model

import (
	"database/sql/driver"
	"encoding/xml"
	"fmt"
	"strconv"
	"strings"
	"time"
)

type Properties struct {
	properties []Property `xml:"property"`
}

type SanitizedInt int

type SanitizedDate time.Time

func (si *SanitizedInt) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	// Read tag content into value
	d.DecodeElement(&value, &start)
	if value == "" {
		*si = (SanitizedInt)(0)
		return nil
	}

	i, err := strconv.ParseInt(strings.Replace(value, `""`, "", -1), 0, 64)
	if err != nil {
		return err
	}
	// Cast int64 to SanitizedInt
	*si = (SanitizedInt)(i)
	return nil
}

type SanitizedBool bool

func (u SanitizedInt) Value() (driver.Value, error)  { return int64(u), nil }
func (u SanitizedDate) Value() (driver.Value, error) { return time.Time(u), nil }
func (u SanitizedBool) Value() (driver.Value, error) { return bool(u), nil }

func (u *SanitizedInt) Scan(value interface{}) error {
	switch value.(type) {
	case []uint8:
		s := value.([]uint8)
		val, err := strconv.Atoi(string(s))

		if err != nil {
			return fmt.Errorf("Error converting to sanitized int: %s", err)
		}

		*u = SanitizedInt(val)
	case int64:
		*u = SanitizedInt(value.(int64))
	}
	return nil
}

func (u *SanitizedDate) Scan(value interface{}) error {
	switch value.(type) {
	case time.Time:
		*u = SanitizedDate(value.(time.Time))
		return nil
	case []uint8:
		layout := "2006-01-02 15:04:05"
		str := string(value.([]uint8))
		t, err := time.Parse(layout, str)

		if err != nil {
			fmt.Errorf("Error scanning SanitizedDate: %s", err)
		}
		*u = SanitizedDate(t)
		return nil
	default:
		fmt.Errorf("Error: cant handle type %T in SanitizedDate.Scan", value)
		return nil
	}
}

func (u *SanitizedBool) Scan(value interface{}) error {
	s := value.([]uint8)
	val, err := strconv.Atoi(string(s))

	if err != nil {
		return fmt.Errorf("Error converting to sanitized int: %s", err)
	}
	if val == 1 {
		*u = SanitizedBool(true)
		return nil
	}

	*u = SanitizedBool(false)
	return nil
}

func (si *SanitizedBool) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	// Read tag content into value
	d.DecodeElement(&value, &start)
	if value == "" {
		*si = (SanitizedBool)(false)
		return nil
	}

	i, err := strconv.ParseBool(value)
	if err != nil {
		return err
	}
	// Cast int64 to SanitizedInt
	*si = (SanitizedBool)(i)
	return nil
}

func (si *SanitizedDate) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err error) {
	var value string
	var tmpTime time.Time
	d.DecodeElement(&value, &start)

	if value == "" {
		*si = (SanitizedDate)(time.Now())
		return nil
	}

	if len(value) == len("2006-01-02T15:04:05") {
		if tmpTime, err = time.Parse(`2006-01-02T15:04:05`, value); err == nil {
			*si = (SanitizedDate)(tmpTime)
		}
	}

	if strings.Contains(value, "/") {
		if tmpTime, err = time.Parse(`02/01/2006`, value); err == nil {
			*si = (SanitizedDate)(tmpTime)
		}
	}

	if strings.Contains(value, "-") && len(value) != len("2006-01-02T15:04:05") {
		if tmpTime, err = time.Parse(`2006-01-02`, value); err == nil {
			*si = (SanitizedDate)(tmpTime)
		}
	}

	if time.Time(*si).Before(time.Now().Add(-(time.Duration(time.Now().Unix()) * time.Second))) {
		*si = (SanitizedDate)(time.Now())
		return nil
	}

	*si = (SanitizedDate)(time.Now())
	return nil
}

type Property struct {
	ID                  int                 `xml:"id,attr"`
	PropertyID          int                 `xml:"propertyid,attr"`
	System              string              `xml:"system,attr"`
	Firmid              string              `xml:"firmid,attr"`
	Branchid            string              `xml:"branchid,attr"`
	Database            string              `xml:"database,attr"`
	Featured            string              `xml:"featured,attr"`
	AgentReference      Reference           `xml:"reference"` // to implement
	Address             Address             `xml:"address"`
	Price               Price               `xml:"price"`
	RentalFees          string              `xml:"rentalfees"`
	LettingsFee         string              `xml:"lettingsfee"`
	RmQualifier         SanitizedInt        `xml:"rm_qualifier"`
	Available           string              `xml:"available"`
	Uploaded            SanitizedDate       `xml:"uploaded" gorm:"type:datetime"`
	Longitude           float32             `xml:"longitude"`
	Latitude            float32             `xml:"latitude"`
	Easting             SanitizedInt        `xml:"easting"`
	Northing            SanitizedInt        `xml:"northing"`
	StreetView          StreetView          `xml:"streetview"`
	WebStatus           SanitizedInt        `xml:"web_status"`
	CustomStatus        string              `xml:"custom_status"`
	CommRent            string              `xml:"comm_rent"`
	Premium             string              `xml:"premium"`
	ServiceCharge       string              `xml:"service_charge"`
	RateableValue       string              `xml:"rateable_value"`
	Type                string              `xml:"type"`
	Furnished           string              `xml:"furnished"`
	RmType              SanitizedInt        `xml:"rm_type"`
	LetBond             SanitizedInt        `xml:"let_bond"`
	RmLetTypeID         SanitizedInt        `xml:"rm_let_type_id"`
	Bedrooms            SanitizedInt        `xml:"bedrooms"`
	Receptions          SanitizedInt        `xml:"receptions"`
	Bathrooms           SanitizedInt        `xml:"bathrooms"`
	UserField1          string              `xml:"userfield1"`
	UserField2          SanitizedInt        `xml:"userfield2"`
	SoldDate            SanitizedDate       `xml:"solddate" gorm:"type:datetime"`
	LeaseEnd            SanitizedDate       `xml:"leaseend" gorm:"type:datetime"`
	Instructed          SanitizedDate       `xml:"instructed" gorm:"type:datetime"`
	SoldPrice           SanitizedInt        `xml:"soldprice"`
	Garden              SanitizedBool       `xml:"garden"`
	Parking             SanitizedBool       `xml:"parking"`
	NewBuild            SanitizedBool       `xml:"newbuild"`
	GroundRent          string              `xml:"groundrent"`
	Commission          string              `xml:"commission"`
	Area                Area                `xml:"area"`
	LandArea            LandArea            `xml:"landarea"`
	Description         string              `xml:"description" gorm:"type:varchar(2056)"`
	EnergyEfficiency    EnergyEfficiency    `xml:"hip>energy_performance>energy_efficiency"`
	EnvironmentalImpact EnvironmentalImpact `xml:"hip>energy_performance>environmental_impact"`
	Paragraphs          []Paragraph         `xml:"paragraphs>paragraph"`
	Bullets             []Bullet            `xml:"bullets>bullet"`
	Files               []File              `xml:"files>file"`
	QueriedAt           SanitizedDate       `xml:"queriedat" gorm:"type:datetime"` // To implement - date-time retreived.
	LocalFiles          []File              // Path used for local storage
}
<commit_msg>Fixed SanitizedBool to convert bool to int<commit_after>package model

import (
	"database/sql/driver"
	"encoding/xml"
	"fmt"
	"strconv"
	"strings"
	"time"
)

type Properties struct {
	properties []Property `xml:"property"`
}

type SanitizedInt int

type SanitizedDate time.Time

func (si *SanitizedInt) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	// Read tag content into value
	d.DecodeElement(&value, &start)
	if value == "" {
		*si = (SanitizedInt)(0)
		return nil
	}

	i, err := strconv.ParseInt(strings.Replace(value, `""`, "", -1), 0, 64)
	if err != nil {
		return err
	}
	// Cast int64 to SanitizedInt
	*si = (SanitizedInt)(i)
	return nil
}

type SanitizedBool bool

func (u SanitizedInt) Value() (driver.Value, error)  { return int64(u), nil }
func (u SanitizedDate) Value() (driver.Value, error) { return time.Time(u), nil }
func (u SanitizedBool) Value() (driver.Value, error) {
	if bool(u) {
		return int64(1), nil
	}
	return int64(0), nil
}

func (u *SanitizedInt) Scan(value interface{}) error {
	switch value.(type) {
	case []uint8:
		s := value.([]uint8)
		val, err := strconv.Atoi(string(s))

		if err != nil {
			return fmt.Errorf("Error converting to sanitized int: %s", err)
		}

		*u = SanitizedInt(val)
	case int64:
		*u = SanitizedInt(value.(int64))
	}
	return nil
}

func (u *SanitizedDate) Scan(value interface{}) error {
	switch value.(type) {
	case time.Time:
		*u = SanitizedDate(value.(time.Time))
		return nil
	case []uint8:
		layout := "2006-01-02 15:04:05"
		str := string(value.([]uint8))
		t, err := time.Parse(layout, str)

		if err != nil {
			fmt.Errorf("Error scanning SanitizedDate: %s", err)
		}
		*u = SanitizedDate(t)
		return nil
	default:
		fmt.Errorf("Error: cant handle type %T in SanitizedDate.Scan", value)
		return nil
	}
}

func (u *SanitizedBool) Scan(value interface{}) error {
	s := value.([]uint8)
	val, err := strconv.Atoi(string(s))

	if err != nil {
		return fmt.Errorf("Error converting to sanitized int: %s", err)
	}
	if val == 1 {
		*u = SanitizedBool(true)
		return nil
	}

	*u = SanitizedBool(false)
	return nil
}

func (si *SanitizedBool) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	// Read tag content into value
	d.DecodeElement(&value, &start)
	if value == "" {
		*si = (SanitizedBool)(false)
		return nil
	}

	i, err := strconv.ParseBool(value)
	if err != nil {
		return err
	}
	// Cast int64 to SanitizedInt
	*si = (SanitizedBool)(i)
	return nil
}

func (si *SanitizedDate) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err error) {
	var value string
	var tmpTime time.Time
	d.DecodeElement(&value, &start)

	if value == "" {
		*si = (SanitizedDate)(time.Now())
		return nil
	}

	if len(value) == len("2006-01-02T15:04:05") {
		if tmpTime, err = time.Parse(`2006-01-02T15:04:05`, value); err == nil {
			*si = (SanitizedDate)(tmpTime)
		}
	}

	if strings.Contains(value, "/") {
		if tmpTime, err = time.Parse(`02/01/2006`, value); err == nil {
			*si = (SanitizedDate)(tmpTime)
		}
	}

	if strings.Contains(value, "-") && len(value) != len("2006-01-02T15:04:05") {
		if tmpTime, err = time.Parse(`2006-01-02`, value); err == nil {
			*si = (SanitizedDate)(tmpTime)
		}
	}

	if time.Time(*si).Before(time.Now().Add(-(time.Duration(time.Now().Unix()) * time.Second))) {
		*si = (SanitizedDate)(time.Now())
		return nil
	}

	*si = (SanitizedDate)(time.Now())
	return nil
}

type Property struct {
	ID                  int                 `xml:"id,attr"`
	PropertyID          int                 `xml:"propertyid,attr"`
	System              string              `xml:"system,attr"`
	Firmid              string              `xml:"firmid,attr"`
	Branchid            string              `xml:"branchid,attr"`
	Database            string              `xml:"database,attr"`
	Featured            string              `xml:"featured,attr"`
	AgentReference      Reference           `xml:"reference"` // to implement
	Address             Address             `xml:"address"`
	Price               Price               `xml:"price"`
	RentalFees          string              `xml:"rentalfees"`
	LettingsFee         string              `xml:"lettingsfee"`
	RmQualifier         SanitizedInt        `xml:"rm_qualifier"`
	Available           string              `xml:"available"`
	Uploaded            SanitizedDate       `xml:"uploaded" gorm:"type:datetime"`
	Longitude           float32             `xml:"longitude"`
	Latitude            float32             `xml:"latitude"`
	Easting             SanitizedInt        `xml:"easting"`
	Northing            SanitizedInt        `xml:"northing"`
	StreetView          StreetView          `xml:"streetview"`
	WebStatus           SanitizedInt        `xml:"web_status"`
	CustomStatus        string              `xml:"custom_status"`
	CommRent            string              `xml:"comm_rent"`
	Premium             string              `xml:"premium"`
	ServiceCharge       string              `xml:"service_charge"`
	RateableValue       string              `xml:"rateable_value"`
	Type                string              `xml:"type"`
	Furnished           string              `xml:"furnished"`
	RmType              SanitizedInt        `xml:"rm_type"`
	LetBond             SanitizedInt        `xml:"let_bond"`
	RmLetTypeID         SanitizedInt        `xml:"rm_let_type_id"`
	Bedrooms            SanitizedInt        `xml:"bedrooms"`
	Receptions          SanitizedInt        `xml:"receptions"`
	Bathrooms           SanitizedInt        `xml:"bathrooms"`
	UserField1          string              `xml:"userfield1"`
	UserField2          SanitizedInt        `xml:"userfield2"`
	SoldDate            SanitizedDate       `xml:"solddate" gorm:"type:datetime"`
	LeaseEnd            SanitizedDate       `xml:"leaseend" gorm:"type:datetime"`
	Instructed          SanitizedDate       `xml:"instructed" gorm:"type:datetime"`
	SoldPrice           SanitizedInt        `xml:"soldprice"`
	Garden              SanitizedBool       `xml:"garden"`
	Parking             SanitizedBool       `xml:"parking"`
	NewBuild            SanitizedBool       `xml:"newbuild"`
	GroundRent          string              `xml:"groundrent"`
	Commission          string              `xml:"commission"`
	Area                Area                `xml:"area"`
	LandArea            LandArea            `xml:"landarea"`
	Description         string              `xml:"description" gorm:"type:varchar(2056)"`
	EnergyEfficiency    EnergyEfficiency    `xml:"hip>energy_performance>energy_efficiency"`
	EnvironmentalImpact EnvironmentalImpact `xml:"hip>energy_performance>environmental_impact"`
	Paragraphs          []Paragraph         `xml:"paragraphs>paragraph"`
	Bullets             []Bullet            `xml:"bullets>bullet"`
	Files               []File              `xml:"files>file"`
	QueriedAt           SanitizedDate       `xml:"queriedat" gorm:"type:datetime"` // To implement - date-time retreived.
	LocalFiles          []File              // Path used for local storage
}
<|endoftext|>


<commit_before>package net_test

import (
	"fmt"
	"os"
	"testing"
	"text/tabwriter"

	netutil "github.com/mistifyio/util/net"
	"github.com/stretchr/testify/assert"
)

func ExampleSplit() {
	examples := []string{
		"localhost",
		"localhost:1234",
		"[localhost]",
		"[localhost]:1234",
		"2001:db8:85a3:8d3:1319:8a2e:370:7348",
		"[2001:db8:85a3:8d3:1319:8a2e:370:7348]",
		"[2001:db8:85a3:8d3:1319:8a2e:370:7348]:443",
		"2001:db8:85a3:8d3:1319:8a2e:370:7348:443",
		":1234",
		"",
		":::",
		"foo:1234:bar",
		"[2001:db8:85a3:8d3:1319:8a2e:370:7348",
		"[localhost",
		"2001:db8:85a3:8d3:1319:8a2e:370:7348]",
		"localhost]",
		"[loca[lhost]:1234",
		"[loca]lhost]:1234",
		"[localhost]:1234]",
	}

	w := new(tabwriter.Writer)
	w.Init(os.Stdout, 0, 8, 0, '\t', 0)
	fmt.Fprintln(w, "HOSTPORT\tHOST\tPORT\tERR")
	fmt.Fprintln(w, "========\t====\t====\t===")

	for _, hp := range examples {
		host, port, err := netutil.SplitHostPort(hp)

		fmt.Fprintf(w, "%s\t%s\t%s\t%v\n", hp, host, port, err)
	}
	w.Flush()

	// Output:
	// HOSTPORT					HOST					PORT	ERR
	// ========					====					====	===
	// localhost					localhost					<nil>
	// localhost:1234					localhost				1234	<nil>
	// [localhost]					localhost					<nil>
	// [localhost]:1234				localhost				1234	<nil>
	// 2001:db8:85a3:8d3:1319:8a2e:370:7348		2001:db8:85a3:8d3:1319:8a2e:370		7348	<nil>
	// [2001:db8:85a3:8d3:1319:8a2e:370:7348]		2001:db8:85a3:8d3:1319:8a2e:370:7348		<nil>
	// [2001:db8:85a3:8d3:1319:8a2e:370:7348]:443	2001:db8:85a3:8d3:1319:8a2e:370:7348	443	<nil>
	// 2001:db8:85a3:8d3:1319:8a2e:370:7348:443	2001:db8:85a3:8d3:1319:8a2e:370:7348	443	<nil>
	// :1234											1234	<nil>
	// 												<nil>
	// :::						::						<nil>
	// foo:1234:bar					foo:1234				bar	<nil>
	// [2001:db8:85a3:8d3:1319:8a2e:370:7348								missing ']'
	// [localhost											missing ']'
	// 2001:db8:85a3:8d3:1319:8a2e:370:7348]								missing '['
	// localhost]											missing '['
	// [loca[lhost]:1234										too many '['
	// [loca]lhost]:1234										too many ']'
	// [localhost]:1234]										too many ']'
}

func TestLookupSRVPort(t *testing.T) {
	port, err := netutil.LookupSRVPort("_xmpp-server._tcp.google.com")
	assert.NoError(t, err)
	assert.EqualValues(t, 5269, port)

	port, err = netutil.LookupSRVPort("_xmpp-server._tcp.asduhaisudbfa.invalid")
	assert.Error(t, err)
	assert.Empty(t, 0, port)
}

func TestHostWithPort(t *testing.T) {
	hostport, err := netutil.HostWithPort(":8080")
	assert.NoError(t, err)
	assert.EqualValues(t, ":8080", hostport)

	hostport, err = netutil.HostWithPort("localhost:8080")
	assert.NoError(t, err)
	assert.EqualValues(t, "localhost:8080", hostport)

	hostport, err = netutil.HostWithPort("_xmpp-server._tcp.google.com")
	assert.NoError(t, err)
	assert.EqualValues(t, "_xmpp-server._tcp.google.com:5269", hostport)

	hostport, err = netutil.HostWithPort("localhost")
	assert.Error(t, err)
}
<commit_msg>Log flush error in test<commit_after>package net_test

import (
	"fmt"
	"os"
	"testing"
	"text/tabwriter"

	logx "github.com/mistifyio/mistify-logrus-ext"
	netutil "github.com/mistifyio/util/net"
	"github.com/stretchr/testify/assert"
)

func ExampleSplit() {
	examples := []string{
		"localhost",
		"localhost:1234",
		"[localhost]",
		"[localhost]:1234",
		"2001:db8:85a3:8d3:1319:8a2e:370:7348",
		"[2001:db8:85a3:8d3:1319:8a2e:370:7348]",
		"[2001:db8:85a3:8d3:1319:8a2e:370:7348]:443",
		"2001:db8:85a3:8d3:1319:8a2e:370:7348:443",
		":1234",
		"",
		":::",
		"foo:1234:bar",
		"[2001:db8:85a3:8d3:1319:8a2e:370:7348",
		"[localhost",
		"2001:db8:85a3:8d3:1319:8a2e:370:7348]",
		"localhost]",
		"[loca[lhost]:1234",
		"[loca]lhost]:1234",
		"[localhost]:1234]",
	}

	w := new(tabwriter.Writer)
	w.Init(os.Stdout, 0, 8, 0, '\t', 0)
	fmt.Fprintln(w, "HOSTPORT\tHOST\tPORT\tERR")
	fmt.Fprintln(w, "========\t====\t====\t===")

	for _, hp := range examples {
		host, port, err := netutil.SplitHostPort(hp)

		fmt.Fprintf(w, "%s\t%s\t%s\t%v\n", hp, host, port, err)
	}
	logx.LogReturnedErr(w.Flush, "failed to flush tabwriter")

	// Output:
	// HOSTPORT					HOST					PORT	ERR
	// ========					====					====	===
	// localhost					localhost					<nil>
	// localhost:1234					localhost				1234	<nil>
	// [localhost]					localhost					<nil>
	// [localhost]:1234				localhost				1234	<nil>
	// 2001:db8:85a3:8d3:1319:8a2e:370:7348		2001:db8:85a3:8d3:1319:8a2e:370		7348	<nil>
	// [2001:db8:85a3:8d3:1319:8a2e:370:7348]		2001:db8:85a3:8d3:1319:8a2e:370:7348		<nil>
	// [2001:db8:85a3:8d3:1319:8a2e:370:7348]:443	2001:db8:85a3:8d3:1319:8a2e:370:7348	443	<nil>
	// 2001:db8:85a3:8d3:1319:8a2e:370:7348:443	2001:db8:85a3:8d3:1319:8a2e:370:7348	443	<nil>
	// :1234											1234	<nil>
	// 												<nil>
	// :::						::						<nil>
	// foo:1234:bar					foo:1234				bar	<nil>
	// [2001:db8:85a3:8d3:1319:8a2e:370:7348								missing ']'
	// [localhost											missing ']'
	// 2001:db8:85a3:8d3:1319:8a2e:370:7348]								missing '['
	// localhost]											missing '['
	// [loca[lhost]:1234										too many '['
	// [loca]lhost]:1234										too many ']'
	// [localhost]:1234]										too many ']'
}

func TestLookupSRVPort(t *testing.T) {
	port, err := netutil.LookupSRVPort("_xmpp-server._tcp.google.com")
	assert.NoError(t, err)
	assert.EqualValues(t, 5269, port)

	port, err = netutil.LookupSRVPort("_xmpp-server._tcp.asduhaisudbfa.invalid")
	assert.Error(t, err)
	assert.Empty(t, 0, port)
}

func TestHostWithPort(t *testing.T) {
	hostport, err := netutil.HostWithPort(":8080")
	assert.NoError(t, err)
	assert.EqualValues(t, ":8080", hostport)

	hostport, err = netutil.HostWithPort("localhost:8080")
	assert.NoError(t, err)
	assert.EqualValues(t, "localhost:8080", hostport)

	hostport, err = netutil.HostWithPort("_xmpp-server._tcp.google.com")
	assert.NoError(t, err)
	assert.EqualValues(t, "_xmpp-server._tcp.google.com:5269", hostport)

	hostport, err = netutil.HostWithPort("localhost")
	assert.Error(t, err)
}
<|endoftext|>


<commit_before>package discovery_test

import (
	"log"
	"os"
	"testing"

	"github.com/Clever/discovery-go"
)

func insertPairs(pairs map[string]string) {
	for name, val := range pairs {
		err := os.Setenv(name, val)
		if err != nil {
			log.Fatalf("Failed to set env variable, %s", err)
		}
	}
}

func TestMain(m *testing.M) {
	insertPairs(map[string]string{
		"SERVICE_REDIS_TCP_PROTO": "tcp",
		"SERVICE_REDIS_TCP_HOST":  "redis.com",
		"SERVICE_REDIS_TCP_PORT":  "6379",

		"SERVICE_GOOGLE_API_PROTO": "https",
		"SERVICE_GOOGLE_API_HOST":  "api.google.com",
		"SERVICE_GOOGLE_API_PORT":  "80",

		"SERVICE_BREAK_API_HOST": "missing.proto",
		"SERVICE_BREAK_API_PORT": "5000",

		"SERVICE_LONG_APP_NAME_API_HOST": "arbitrary",
	})

	os.Exit(m.Run())
}

func TestTCPDiscovery(t *testing.T) {
	expected := "tcp://redis.com:6379"

	url, err := discovery.URL("redis", "tcp")
	if err != nil {
		t.Fatalf("Unexpected error, %s", err)
	} else if url != expected {
		t.Fatalf("Unexpected result, expected: %s, received: %s", expected, url)
	}
}

func TestHTTPSDiscovery(t *testing.T) {
	expected := "https://api.google.com:80"

	url, err := discovery.URL("google", "api")
	if err != nil {
		t.Fatalf("Unexpected error, %s", err)
	} else if url != expected {
		t.Fatalf("Unexpected result, expected: %s, received: %s", expected, url)
	}
}

func TestErrorOnFailure(t *testing.T) {
	_, err := discovery.URL("break", "api")
	if err == nil {
		t.Fatalf("Expected error")
	}
}

func TestLongArbitraryNameWithDashes(t *testing.T) {
	_, err := discovery.Host("long-app-name", "api")
	if err != nil {
		t.Fatalf("Unexpected error with app name w/ dashes, %s", err)
	}
}
<commit_msg>add test for basic auth<commit_after>package discovery_test

import (
	"log"
	"os"
	"testing"

	"github.com/Clever/discovery-go"
)

func insertPairs(pairs map[string]string) {
	for name, val := range pairs {
		err := os.Setenv(name, val)
		if err != nil {
			log.Fatalf("Failed to set env variable, %s", err)
		}
	}
}

func TestMain(m *testing.M) {
	insertPairs(map[string]string{
		"SERVICE_REDIS_TCP_PROTO": "tcp",
		"SERVICE_REDIS_TCP_HOST":  "redis.com",
		"SERVICE_REDIS_TCP_PORT":  "6379",

		"SERVICE_GOOGLE_API_PROTO": "https",
		"SERVICE_GOOGLE_API_HOST":  "api.google.com",
		"SERVICE_GOOGLE_API_PORT":  "80",

		"SERVICE_BREAK_API_HOST": "missing.proto",
		"SERVICE_BREAK_API_PORT": "5000",

		"SERVICE_LONG_APP_NAME_API_HOST": "arbitrary",

		"SERVICE_WITH_AUTH_HTTP_PROTO": "https",
		"SERVICE_WITH_AUTH_HTTP_HOST":  "user:pass@api.google.com",
		"SERVICE_WITH_AUTH_HTTP_PORT":  "80",
	})

	os.Exit(m.Run())
}

func TestTCPDiscovery(t *testing.T) {
	expected := "tcp://redis.com:6379"

	url, err := discovery.URL("redis", "tcp")
	if err != nil {
		t.Fatalf("Unexpected error, %s", err)
	} else if url != expected {
		t.Fatalf("Unexpected result, expected: %s, received: %s", expected, url)
	}
}

func TestURLwithBasicAuth(t *testing.T) {
	expected := "https://user:pass@api.google.com:80"

	url, err := discovery.URL("with-auth", "http")
	if err != nil {
		t.Fatalf("Unexpected error, %s", err)
	} else if url != expected {
		t.Fatalf("Unexpected result, expected: %s, received: %s", expected, url)
	}
}

func TestHTTPSDiscovery(t *testing.T) {
	expected := "https://api.google.com:80"

	url, err := discovery.URL("google", "api")
	if err != nil {
		t.Fatalf("Unexpected error, %s", err)
	} else if url != expected {
		t.Fatalf("Unexpected result, expected: %s, received: %s", expected, url)
	}
}

func TestErrorOnFailure(t *testing.T) {
	_, err := discovery.URL("break", "api")
	if err == nil {
		t.Fatalf("Expected error")
	}
}

func TestLongArbitraryNameWithDashes(t *testing.T) {
	_, err := discovery.Host("long-app-name", "api")
	if err != nil {
		t.Fatalf("Unexpected error with app name w/ dashes, %s", err)
	}
}
<|endoftext|>


<commit_before>package bomberman_test

import (
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"time"

	"code.cloudfoundry.org/garden"
	fakes "code.cloudfoundry.org/garden/gardenfakes"
	"code.cloudfoundry.org/garden/server/bomberman"
)

var _ = Describe("Bomberman", func() {
	It("straps a bomb to the given container with the container's grace time as the countdown", func() {
		detonated := make(chan garden.Container)

		backend := new(fakes.FakeBackend)
		backend.GraceTimeReturns(100 * time.Millisecond)

		bomberman := bomberman.New(backend, func(container garden.Container) {
			detonated <- container
		})

		container := new(fakes.FakeContainer)
		container.HandleReturns("doomed")

		bomberman.Strap(container)

		select {
		case <-detonated:
		case <-time.After(backend.GraceTime(container) + 50*time.Millisecond):
			Fail("did not detonate!")
		}
	})

	Context("when the container has a grace time of 0", func() {
		It("never detonates", func() {
			detonated := make(chan garden.Container)

			backend := new(fakes.FakeBackend)
			backend.GraceTimeReturns(0)

			bomberman := bomberman.New(backend, func(container garden.Container) {
				detonated <- container
			})

			container := new(fakes.FakeContainer)
			container.HandleReturns("doomed")

			bomberman.Strap(container)

			select {
			case <-detonated:
				Fail("detonated!")
			case <-time.After(backend.GraceTime(container) + 50*time.Millisecond):
			}
		})
	})

	Describe("pausing a container's timebomb", func() {
		It("prevents it from detonating", func() {
			detonated := make(chan garden.Container)

			backend := new(fakes.FakeBackend)
			backend.GraceTimeReturns(100 * time.Millisecond)

			bomberman := bomberman.New(backend, func(container garden.Container) {
				detonated <- container
			})

			container := new(fakes.FakeContainer)
			container.HandleReturns("doomed")

			bomberman.Strap(container)
			bomberman.Pause("doomed")

			select {
			case <-detonated:
				Fail("detonated!")
			case <-time.After(backend.GraceTime(container) + 50*time.Millisecond):
			}
		})

		Context("when the handle is invalid", func() {
			It("doesn't launch any missiles or anything like that", func() {
				bomberman := bomberman.New(new(fakes.FakeBackend), func(container garden.Container) {
					panic("dont call me")
				})

				bomberman.Pause("BOOM?!")
			})
		})

		Describe("and then unpausing it", func() {
			It("causes it to detonate after the countdown", func() {
				detonated := make(chan garden.Container)

				backend := new(fakes.FakeBackend)
				backend.GraceTimeReturns(100 * time.Millisecond)

				bomberman := bomberman.New(backend, func(container garden.Container) {
					detonated <- container
				})

				container := new(fakes.FakeContainer)
				container.HandleReturns("doomed")

				bomberman.Strap(container)
				bomberman.Pause("doomed")

				before := time.Now()
				bomberman.Unpause("doomed")

				select {
				case <-detonated:
					Ω(time.Since(before)).Should(BeNumerically(">=", 100*time.Millisecond))
				case <-time.After(backend.GraceTime(container) + 50*time.Millisecond):
					Fail("did not detonate!")
				}
			})

			Context("when the handle is invalid", func() {
				It("doesn't launch any missiles or anything like that", func() {
					bomberman := bomberman.New(new(fakes.FakeBackend), func(container garden.Container) {
						panic("dont call me")
					})

					bomberman.Unpause("BOOM?!")
				})
			})
		})
	})

	Describe("defusing a container's timebomb", func() {
		It("prevents it from detonating", func() {
			detonated := make(chan garden.Container)

			backend := new(fakes.FakeBackend)
			backend.GraceTimeReturns(100 * time.Millisecond)

			bomberman := bomberman.New(backend, func(container garden.Container) {
				detonated <- container
			})

			container := new(fakes.FakeContainer)
			container.HandleReturns("doomed")

			bomberman.Strap(container)
			bomberman.Defuse("doomed")

			select {
			case <-detonated:
				Fail("detonated!")
			case <-time.After(backend.GraceTime(container) + 50*time.Millisecond):
			}
		})

		Context("when the handle is invalid", func() {
			It("doesn't launch any missiles or anything like that", func() {
				bomberman := bomberman.New(new(fakes.FakeBackend), func(container garden.Container) {
					panic("dont call me")
				})

				bomberman.Defuse("BOOM?!")
			})
		})
	})
})
<commit_msg>Increase timeout one bomberman test<commit_after>package bomberman_test

import (
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"time"

	"code.cloudfoundry.org/garden"
	fakes "code.cloudfoundry.org/garden/gardenfakes"
	"code.cloudfoundry.org/garden/server/bomberman"
)

var _ = Describe("Bomberman", func() {
	It("straps a bomb to the given container with the container's grace time as the countdown", func() {
		detonated := make(chan garden.Container)

		backend := new(fakes.FakeBackend)
		backend.GraceTimeReturns(100 * time.Millisecond)

		bomberman := bomberman.New(backend, func(container garden.Container) {
			detonated <- container
		})

		container := new(fakes.FakeContainer)
		container.HandleReturns("doomed")

		bomberman.Strap(container)

		select {
		case <-detonated:
		case <-time.After(backend.GraceTime(container) * 2):
			Fail("did not detonate!")
		}
	})

	Context("when the container has a grace time of 0", func() {
		It("never detonates", func() {
			detonated := make(chan garden.Container)

			backend := new(fakes.FakeBackend)
			backend.GraceTimeReturns(0)

			bomberman := bomberman.New(backend, func(container garden.Container) {
				detonated <- container
			})

			container := new(fakes.FakeContainer)
			container.HandleReturns("doomed")

			bomberman.Strap(container)

			select {
			case <-detonated:
				Fail("detonated!")
			case <-time.After(backend.GraceTime(container) + 50*time.Millisecond):
			}
		})
	})

	Describe("pausing a container's timebomb", func() {
		It("prevents it from detonating", func() {
			detonated := make(chan garden.Container)

			backend := new(fakes.FakeBackend)
			backend.GraceTimeReturns(100 * time.Millisecond)

			bomberman := bomberman.New(backend, func(container garden.Container) {
				detonated <- container
			})

			container := new(fakes.FakeContainer)
			container.HandleReturns("doomed")

			bomberman.Strap(container)
			bomberman.Pause("doomed")

			select {
			case <-detonated:
				Fail("detonated!")
			case <-time.After(backend.GraceTime(container) + 50*time.Millisecond):
			}
		})

		Context("when the handle is invalid", func() {
			It("doesn't launch any missiles or anything like that", func() {
				bomberman := bomberman.New(new(fakes.FakeBackend), func(container garden.Container) {
					panic("dont call me")
				})

				bomberman.Pause("BOOM?!")
			})
		})

		Describe("and then unpausing it", func() {
			It("causes it to detonate after the countdown", func() {
				detonated := make(chan garden.Container)

				backend := new(fakes.FakeBackend)
				backend.GraceTimeReturns(100 * time.Millisecond)

				bomberman := bomberman.New(backend, func(container garden.Container) {
					detonated <- container
				})

				container := new(fakes.FakeContainer)
				container.HandleReturns("doomed")

				bomberman.Strap(container)
				bomberman.Pause("doomed")

				before := time.Now()
				bomberman.Unpause("doomed")

				select {
				case <-detonated:
					Ω(time.Since(before)).Should(BeNumerically(">=", 100*time.Millisecond))
				case <-time.After(backend.GraceTime(container) + 50*time.Millisecond):
					Fail("did not detonate!")
				}
			})

			Context("when the handle is invalid", func() {
				It("doesn't launch any missiles or anything like that", func() {
					bomberman := bomberman.New(new(fakes.FakeBackend), func(container garden.Container) {
						panic("dont call me")
					})

					bomberman.Unpause("BOOM?!")
				})
			})
		})
	})

	Describe("defusing a container's timebomb", func() {
		It("prevents it from detonating", func() {
			detonated := make(chan garden.Container)

			backend := new(fakes.FakeBackend)
			backend.GraceTimeReturns(100 * time.Millisecond)

			bomberman := bomberman.New(backend, func(container garden.Container) {
				detonated <- container
			})

			container := new(fakes.FakeContainer)
			container.HandleReturns("doomed")

			bomberman.Strap(container)
			bomberman.Defuse("doomed")

			select {
			case <-detonated:
				Fail("detonated!")
			case <-time.After(backend.GraceTime(container) + 50*time.Millisecond):
			}
		})

		Context("when the handle is invalid", func() {
			It("doesn't launch any missiles or anything like that", func() {
				bomberman := bomberman.New(new(fakes.FakeBackend), func(container garden.Container) {
					panic("dont call me")
				})

				bomberman.Defuse("BOOM?!")
			})
		})
	})
})
<|endoftext|>


<commit_before>package server

import (
    "fmt"
    "runtime"

    "github.com/gin-gonic/gin"
    "github.com/infinitelyio/go-bindata-assetfs"
    "github.com/infinitelyio/go-bindata-templates"
    "github.com/infinitelyio/config"
)

// App struct.
type App struct {
	API         *API
	Conf        *config.Config
	Engine      *gin.Engine
}

func Create(opts ...AppOptions) *App {
    options := AppOptions{}
	for _, i := range opts {
		options = i
		break
	}
	options.init()

	// Parse config yaml string from ./conf.go
	conf, err := config.ParseYaml(confs)
	Must(err)
	// Choise a config section by given string
	conf, err = conf.Get(options.Config)
	Must(err)

	// Parse environ variables for defined
	// in config constants
	conf.Env()

	// Set up gin
    if !options.Verbose {
		gin.SetMode(gin.ReleaseMode)
    }

	// Make an engine
	engine := gin.Default()

	// Initialize the application
	app := &App{
		API:    &API{},
		Conf:   conf,
		Engine: engine,
	}

    // Load embedded templates
    app.Engine.SetHTMLTemplate(
        binhtml.New(options.Asset, options.AssetDir).MustLoadDirectory("templates"),
    )
    // Define routes and middlewares
    app.Engine.StaticFS("/static", &assetfs.AssetFS{
        Asset:    options.Asset,
        AssetDir: options.AssetDir,
        Prefix:   "static",
    })

	// Map app struct to access from request handlers
	// and middlewares
	app.Engine.Use(func(c *gin.Context) {
		c.Set("app", app)
	})

    app.Engine.GET("/favicon.ico", func(c *gin.Context) {
		c.Redirect(301, "/static/images/favicon.ico")
	})

    // Bind api hadling for URL api.prefix
	app.API.Bind(
		app.Engine.Group(
			app.Conf.UString("api.prefix"),
		),
	)

    return app

}

func (app *App) init() {
    numCPU := runtime.NumCPU()
    runtime.GOMAXPROCS(numCPU)
    fmt.Printf("Running with %d CPUs\n and PORT %d", numCPU, app.Conf.UString("port"))
}

func (app *App) Run() *App {
	Must(app.Engine.Run(":" + app.Conf.UString("port")))
    return app
}

func (app *App) WebSocket() *App {
    ws := &WebSocket{}
    ws.Bind(app)
    return app
}

func (app *App) AttachRoutes(routes map[string] *Route) *App {
    for _, r := range routes {
        app.AddRoute(r)
    }
    return app
}

func (app *App) AddRoute(route *Route) *App {
    switch {
    case route.Method == "GET":
        app.Engine.GET(route.URI, route.Callback)
    case route.Method == "POST":
        app.Engine.POST(route.URI, route.Callback)
    case route.Method == "PUT":
        app.Engine.PUT(route.URI, route.Callback)
    case route.Method == "PATCH":
        app.Engine.PATCH(route.URI, route.Callback)
    case route.Method == "DELETE":
        app.Engine.DELETE(route.URI, route.Callback)
    case route.Method == "OPTIONS":
        app.Engine.OPTIONS(route.URI, route.Callback)
    }
    fmt.Printf("[Route] %s >> %s\n", route.Method, route.URI)
    return app
}
<commit_msg>allow attaching multiple routes in once<commit_after>package server

import (
    "fmt"
    "runtime"

    "github.com/gin-gonic/gin"
    "github.com/infinitelyio/go-bindata-assetfs"
    "github.com/infinitelyio/go-bindata-templates"
    "github.com/infinitelyio/config"
)

// App struct.
type App struct {
	API         *API
	Conf        *config.Config
	Engine      *gin.Engine
}

func Create(opts ...AppOptions) *App {
    options := AppOptions{}
	for _, i := range opts {
		options = i
		break
	}
	options.init()

	// Parse config yaml string from ./conf.go
	conf, err := config.ParseYaml(confs)
	Must(err)
	// Choise a config section by given string
	conf, err = conf.Get(options.Config)
	Must(err)

	// Parse environ variables for defined
	// in config constants
	conf.Env()

	// Set up gin
    if !options.Verbose {
		gin.SetMode(gin.ReleaseMode)
    }

	// Make an engine
	engine := gin.Default()

	// Initialize the application
	app := &App{
		API:    &API{},
		Conf:   conf,
		Engine: engine,
	}

    // Load embedded templates
    app.Engine.SetHTMLTemplate(
        binhtml.New(options.Asset, options.AssetDir).MustLoadDirectory("templates"),
    )
    // Define routes and middlewares
    app.Engine.StaticFS("/static", &assetfs.AssetFS{
        Asset:    options.Asset,
        AssetDir: options.AssetDir,
        Prefix:   "static",
    })

	// Map app struct to access from request handlers
	// and middlewares
	app.Engine.Use(func(c *gin.Context) {
		c.Set("app", app)
	})

    app.Engine.GET("/favicon.ico", func(c *gin.Context) {
		c.Redirect(301, "/static/images/favicon.ico")
	})

    // Bind api hadling for URL api.prefix
	app.API.Bind(
		app.Engine.Group(
			app.Conf.UString("api.prefix"),
		),
	)

    return app

}

func (app *App) init() {
    numCPU := runtime.NumCPU()
    runtime.GOMAXPROCS(numCPU)
    fmt.Printf("Running with %d CPUs\n and PORT %d", numCPU, app.Conf.UString("port"))
}

func (app *App) Run() *App {
	Must(app.Engine.Run(":" + app.Conf.UString("port")))
    return app
}

func (app *App) WebSocket() *App {
    ws := &WebSocket{}
    ws.Bind(app)
    return app
}

func (app *App) AttachRoutes(args ...map[string]*Route) *App {
    for _, arg := range args {
        for _, r := range arg {
            app.AddRoute(r)
        }
    }
    return app
}

func (app *App) AddRoute(route *Route) *App {
    switch {
    case route.Method == "GET":
        app.Engine.GET(route.URI, route.Callback)
    case route.Method == "POST":
        app.Engine.POST(route.URI, route.Callback)
    case route.Method == "PUT":
        app.Engine.PUT(route.URI, route.Callback)
    case route.Method == "PATCH":
        app.Engine.PATCH(route.URI, route.Callback)
    case route.Method == "DELETE":
        app.Engine.DELETE(route.URI, route.Callback)
    case route.Method == "OPTIONS":
        app.Engine.OPTIONS(route.URI, route.Callback)
    }
    fmt.Printf("[Route] %s >> %s\n", route.Method, route.URI)
    return app
}
<|endoftext|>


<commit_before>package input

import "fmt"
import "os"
import "bufio"
import "strings"
import "strconv"

const IntMax = int(^uint(0) >> 1)
const IntMin = -IntMax - 1

// Line reading closure, to save on bufio.NewReader overhead.
// Prompts with a supplied string.
func GetReader() func(string) (string) {
    in := bufio.NewReader(os.Stdin)
    return func(p string) (string) {
        fmt.Print(p)
        s, _ := in.ReadString('\n')
        s = strings.TrimRight(s, "\n\r")
        return s
    }
}

//Type parser func shorthand...
type Parser func(string, interface{}) error

//Parses a line from stdin with specified func,
//retrying indefinitely on failure
func Read(p string,
          f Parser,
          x interface{}) {
    in := bufio.NewReader(os.Stdin)
    for {
        fmt.Print(p)
        s, e := in.ReadString('\n')
        s = strings.TrimRight(s, "\n\r")
        if e = f(s, x); e == nil {
            break
        }
        fmt.Println(e)
    }
}

//Returns a Parser for ints within specified range
func IntParser(min, max int) Parser {
    return func(s string, x interface{}) error {
        i, e := strconv.Atoi(s)
        if e != nil {
            return fmt.Errorf("Must be an integer")
        }
        if i < min || i > max {
            return fmt.Errorf("Must be in range %d-%d", min, max)
        }
        *x.(*int) = i
        return nil
    }
}

// Prompts with p until a valid int is entered
func ReadInt(p string) (i int) {
    Read(p, GetIntParser(IntMin, IntMax), &i)
    return
}

func ReadRangedInt(p string, min, max int) (i int) {
    Read(p, GetIntParser(min, max), &i)
    return
}
<commit_msg>Axed input.ReadInt() function - input.ReadRangedInt() and the IntMin/IntMax constants are available<commit_after>package input

import "fmt"
import "os"
import "bufio"
import "strings"
import "strconv"

const IntMax = int(^uint(0) >> 1)
const IntMin = -IntMax - 1

// Line reading closure, to save on bufio.NewReader overhead.
// Prompts with a supplied string.
func GetReader() func(string) (string) {
    in := bufio.NewReader(os.Stdin)
    return func(p string) (string) {
        fmt.Print(p)
        s, _ := in.ReadString('\n')
        s = strings.TrimRight(s, "\n\r")
        return s
    }
}

//Type parser func shorthand...
type Parser func(string, interface{}) error

//Parses a line from stdin with specified func,
//retrying indefinitely on failure
func Read(p string,
          f Parser,
          x interface{}) {
    in := bufio.NewReader(os.Stdin)
    for {
        fmt.Print(p)
        s, e := in.ReadString('\n')
        s = strings.TrimRight(s, "\n\r")
        if e = f(s, x); e == nil {
            break
        }
        fmt.Println(e)
    }
}

//Returns a Parser for ints within specified range
func IntParser(min, max int) Parser {
    return func(s string, x interface{}) error {
        i, e := strconv.Atoi(s)
        if e != nil {
            return fmt.Errorf("Must be an integer")
        }
        if i < min || i > max {
            return fmt.Errorf("Must be in range %d-%d", min, max)
        }
        *x.(*int) = i
        return nil
    }
}

func ReadRangedInt(p string, min, max int) (i int) {
    Read(p, GetIntParser(min, max), &i)
    return
}
<|endoftext|>


<commit_before>package telegraf

import (
	"time"
)

// ValueType is an enumeration of metric types that represent a simple value.
type ValueType int

// Possible values for the ValueType enum.
const (
	_ ValueType = iota
	Counter
	Gauge
	Untyped
	Summary
	Histogram
)

type Tag struct {
	Key   string
	Value string
}

type Field struct {
	Key   string
	Value interface{}
}

type Metric interface {
	// Getting data structure functions
	Name() string
	Tags() map[string]string
	TagList() []*Tag
	Fields() map[string]interface{}
	FieldList() []*Field
	Time() time.Time
	Type() ValueType

	// Name functions
	SetName(name string)
	AddPrefix(prefix string)
	AddSuffix(suffix string)

	// Tag functions
	GetTag(key string) (string, bool)
	HasTag(key string) bool
	AddTag(key, value string)
	RemoveTag(key string)

	// Field functions
	GetField(key string) (interface{}, bool)
	HasField(key string) bool
	AddField(key string, value interface{})
	RemoveField(key string)

	SetTime(t time.Time)

	// HashID returns an unique identifier for the series.
	HashID() uint64

	// Copy returns a deep copy of the Metric.
	Copy() Metric

	// Accept marks the metric as processed successfully and written to an
	// output.
	Accept()

	// Reject marks the metric as processed unsuccessfully.
	Reject()

	// Drop marks the metric as processed successfully without being written
	// to any output.
	Drop()

	// Mark Metric as an aggregate
	SetAggregate(bool)
	IsAggregate() bool
}
<commit_msg>Improve documentation for the Metric interface (#7256)<commit_after>package telegraf

import (
	"time"
)

// ValueType is an enumeration of metric types that represent a simple value.
type ValueType int

// Possible values for the ValueType enum.
const (
	_ ValueType = iota
	Counter
	Gauge
	Untyped
	Summary
	Histogram
)

// Tag represents a single tag key and value.
type Tag struct {
	Key   string
	Value string
}

// Field represents a single field key and value.
type Field struct {
	Key   string
	Value interface{}
}

// Metric is the type of data that is processed by Telegraf.  Input plugins,
// and to a lesser degree, Processor and Aggregator plugins create new Metrics
// and Output plugins write them.
type Metric interface {
	// Name is the primary identifier for the Metric and corresponds to the
	// measurement in the InfluxDB data model.
	Name() string

	// Tags returns the tags as a map.  This method is deprecated, use TagList instead.
	Tags() map[string]string

	// TagList returns the tags as a slice ordered by the tag key in lexical
	// bytewise ascending order.  The returned value should not be modified,
	// use the AddTag or RemoveTag methods instead.
	TagList() []*Tag

	// Fields returns the fields as a map.  This method is deprecated, use FieldList instead.
	Fields() map[string]interface{}

	// FieldList returns the fields as a slice in an undefined order.  The
	// returned value should not be modified, use the AddField or RemoveField
	// methods instead.
	FieldList() []*Field

	// Time returns the timestamp of the metric.
	Time() time.Time

	// Type returns a general type for the entire metric that describes how you
	// might interprete, aggregate the values.
	//
	// This method may be removed in the future and its use is discouraged.
	Type() ValueType

	// SetName sets the metric name.
	SetName(name string)

	// AddPrefix adds a string to the front of the metric name.  It is
	// equivalent to m.SetName(prefix + m.Name()).
	//
	// This method is deprecated, use SetName instead.
	AddPrefix(prefix string)

	// AddSuffix appends a string to the back of the metric name.  It is
	// equivalent to m.SetName(m.Name() + suffix).
	//
	// This method is deprecated, use SetName instead.
	AddSuffix(suffix string)

	// GetTag returns the value of a tag and a boolean to indicate if it was set.
	GetTag(key string) (string, bool)

	// HasTag returns true if the tag is set on the Metric.
	HasTag(key string) bool

	// AddTag sets the tag on the Metric.  If the Metric already has the tag
	// set then the current value is replaced.
	AddTag(key, value string)

	// RemoveTag removes the tag if it is set.
	RemoveTag(key string)

	// GetField returns the value of a field and a boolean to indicate if it was set.
	GetField(key string) (interface{}, bool)

	// HasField returns true if the field is set on the Metric.
	HasField(key string) bool

	// AddField sets the field on the Metric.  If the Metric already has the field
	// set then the current value is replaced.
	AddField(key string, value interface{})

	// RemoveField removes the tag if it is set.
	RemoveField(key string)

	// SetTime sets the timestamp of the Metric.
	SetTime(t time.Time)

	// HashID returns an unique identifier for the series.
	HashID() uint64

	// Copy returns a deep copy of the Metric.
	Copy() Metric

	// Accept marks the metric as processed successfully and written to an
	// output.
	Accept()

	// Reject marks the metric as processed unsuccessfully.
	Reject()

	// Drop marks the metric as processed successfully without being written
	// to any output.
	Drop()

	// SetAggregate indicates the metric is an aggregated value.
	//
	// This method may be removed in the future and its use is discouraged.
	SetAggregate(bool)

	// IsAggregate returns true if the Metric is an aggregate.
	//
	// This method may be removed in the future and its use is discouraged.
	IsAggregate() bool
}
<|endoftext|>