<commit_before>package scenarios

import (
	"os"
	"testing"
	"time"

	"v2ray.com/core"
	"v2ray.com/core/app/proxyman"
	"v2ray.com/core/common/net"
	"v2ray.com/core/common/protocol"
	"v2ray.com/core/common/serial"
	"v2ray.com/core/common/uuid"
	"v2ray.com/core/proxy/dokodemo"
	"v2ray.com/core/proxy/freedom"
	"v2ray.com/core/proxy/vmess"
	"v2ray.com/core/proxy/vmess/inbound"
	"v2ray.com/core/proxy/vmess/outbound"
	"v2ray.com/core/testing/servers/tcp"
	"v2ray.com/core/transport/internet"
	"v2ray.com/core/transport/internet/domainsocket"
	"v2ray.com/core/transport/internet/headers/http"
	tcptransport "v2ray.com/core/transport/internet/tcp"
	. "v2ray.com/ext/assert"
)

func TestHttpConnectionHeader(t *testing.T) {
	assert := With(t)

	tcpServer := tcp.Server{
		MsgProcessor: xor,
	}
	dest, err := tcpServer.Start()
	assert(err, IsNil)
	defer tcpServer.Close()

	userID := protocol.NewID(uuid.New())
	serverPort := tcp.PickPort()
	serverConfig := &core.Config{
		Inbound: []*core.InboundHandlerConfig{
			{
				ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
					PortRange: net.SinglePortRange(serverPort),
					Listen:    net.NewIPOrDomain(net.LocalHostIP),
					StreamSettings: &internet.StreamConfig{
						TransportSettings: []*internet.TransportConfig{
							{
								Protocol: internet.TransportProtocol_TCP,
								Settings: serial.ToTypedMessage(&tcptransport.Config{
									HeaderSettings: serial.ToTypedMessage(&http.Config{}),
								}),
							},
						},
					},
				}),
				ProxySettings: serial.ToTypedMessage(&inbound.Config{
					User: []*protocol.User{
						{
							Account: serial.ToTypedMessage(&vmess.Account{
								Id: userID.String(),
							}),
						},
					},
				}),
			},
		},
		Outbound: []*core.OutboundHandlerConfig{
			{
				ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
			},
		},
	}

	clientPort := tcp.PickPort()
	clientConfig := &core.Config{
		Inbound: []*core.InboundHandlerConfig{
			{
				ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
					PortRange: net.SinglePortRange(clientPort),
					Listen:    net.NewIPOrDomain(net.LocalHostIP),
				}),
				ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
					Address: net.NewIPOrDomain(dest.Address),
					Port:    uint32(dest.Port),
					NetworkList: &net.NetworkList{
						Network: []net.Network{net.Network_TCP},
					},
				}),
			},
		},
		Outbound: []*core.OutboundHandlerConfig{
			{
				ProxySettings: serial.ToTypedMessage(&outbound.Config{
					Receiver: []*protocol.ServerEndpoint{
						{
							Address: net.NewIPOrDomain(net.LocalHostIP),
							Port:    uint32(serverPort),
							User: []*protocol.User{
								{
									Account: serial.ToTypedMessage(&vmess.Account{
										Id: userID.String(),
									}),
								},
							},
						},
					},
				}),
				SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{
					StreamSettings: &internet.StreamConfig{
						TransportSettings: []*internet.TransportConfig{
							{
								Protocol: internet.TransportProtocol_TCP,
								Settings: serial.ToTypedMessage(&tcptransport.Config{
									HeaderSettings: serial.ToTypedMessage(&http.Config{}),
								}),
							},
						},
					},
				}),
			},
		},
	}

	servers, err := InitializeServerConfigs(serverConfig, clientConfig)
	assert(err, IsNil)

	conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{
		IP:   []byte{127, 0, 0, 1},
		Port: int(clientPort),
	})
	assert(err, IsNil)

	payload := "dokodemo request."
	nBytes, err := conn.Write([]byte(payload))
	assert(err, IsNil)
	assert(nBytes, Equals, len(payload))

	response := readFrom(conn, time.Second*2, len(payload))
	assert(response, Equals, xor([]byte(payload)))
	assert(conn.Close(), IsNil)

	CloseAllServers(servers)
}

func TestDomainSocket(t *testing.T) {
	assert := With(t)

	tcpServer := tcp.Server{
		MsgProcessor: xor,
	}
	dest, err := tcpServer.Start()
	assert(err, IsNil)
	defer tcpServer.Close()

	const dsPath = "/tmp/ds_scenario"
	os.Remove(dsPath)

	userID := protocol.NewID(uuid.New())
	serverPort := tcp.PickPort()
	serverConfig := &core.Config{
		Inbound: []*core.InboundHandlerConfig{
			{
				ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
					PortRange: net.SinglePortRange(serverPort),
					Listen:    net.NewIPOrDomain(net.LocalHostIP),
					StreamSettings: &internet.StreamConfig{
						Protocol: internet.TransportProtocol_DomainSocket,
						TransportSettings: []*internet.TransportConfig{
							{
								Protocol: internet.TransportProtocol_DomainSocket,
								Settings: serial.ToTypedMessage(&domainsocket.Config{
									Path: dsPath,
								}),
							},
						},
					},
				}),
				ProxySettings: serial.ToTypedMessage(&inbound.Config{
					User: []*protocol.User{
						{
							Account: serial.ToTypedMessage(&vmess.Account{
								Id: userID.String(),
							}),
						},
					},
				}),
			},
		},
		Outbound: []*core.OutboundHandlerConfig{
			{
				ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
			},
		},
	}

	clientPort := tcp.PickPort()
	clientConfig := &core.Config{
		Inbound: []*core.InboundHandlerConfig{
			{
				ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
					PortRange: net.SinglePortRange(clientPort),
					Listen:    net.NewIPOrDomain(net.LocalHostIP),
				}),
				ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
					Address: net.NewIPOrDomain(dest.Address),
					Port:    uint32(dest.Port),
					NetworkList: &net.NetworkList{
						Network: []net.Network{net.Network_TCP},
					},
				}),
			},
		},
		Outbound: []*core.OutboundHandlerConfig{
			{
				ProxySettings: serial.ToTypedMessage(&outbound.Config{
					Receiver: []*protocol.ServerEndpoint{
						{
							Address: net.NewIPOrDomain(net.LocalHostIP),
							Port:    uint32(serverPort),
							User: []*protocol.User{
								{
									Account: serial.ToTypedMessage(&vmess.Account{
										Id: userID.String(),
									}),
								},
							},
						},
					},
				}),
				SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{
					StreamSettings: &internet.StreamConfig{
						Protocol: internet.TransportProtocol_DomainSocket,
						TransportSettings: []*internet.TransportConfig{
							{
								Protocol: internet.TransportProtocol_DomainSocket,
								Settings: serial.ToTypedMessage(&domainsocket.Config{
									Path: dsPath,
								}),
							},
						},
					},
				}),
			},
		},
	}

	servers, err := InitializeServerConfigs(serverConfig, clientConfig)
	assert(err, IsNil)

	conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{
		IP:   []byte{127, 0, 0, 1},
		Port: int(clientPort),
	})
	assert(err, IsNil)

	payload := "dokodemo request."
	nBytes, err := conn.Write([]byte(payload))
	assert(err, IsNil)
	assert(nBytes, Equals, len(payload))

	response := readFrom(conn, time.Second*2, len(payload))
	assert(response, Equals, xor([]byte(payload)))
	assert(conn.Close(), IsNil)

	CloseAllServers(servers)
}
<commit_msg>skip domain socket test on windows<commit_after>package scenarios

import (
	"os"
	"runtime"
	"testing"
	"time"

	"v2ray.com/core"
	"v2ray.com/core/app/proxyman"
	"v2ray.com/core/common/net"
	"v2ray.com/core/common/protocol"
	"v2ray.com/core/common/serial"
	"v2ray.com/core/common/uuid"
	"v2ray.com/core/proxy/dokodemo"
	"v2ray.com/core/proxy/freedom"
	"v2ray.com/core/proxy/vmess"
	"v2ray.com/core/proxy/vmess/inbound"
	"v2ray.com/core/proxy/vmess/outbound"
	"v2ray.com/core/testing/servers/tcp"
	"v2ray.com/core/transport/internet"
	"v2ray.com/core/transport/internet/domainsocket"
	"v2ray.com/core/transport/internet/headers/http"
	tcptransport "v2ray.com/core/transport/internet/tcp"
	. "v2ray.com/ext/assert"
)

func TestHttpConnectionHeader(t *testing.T) {
	assert := With(t)

	tcpServer := tcp.Server{
		MsgProcessor: xor,
	}
	dest, err := tcpServer.Start()
	assert(err, IsNil)
	defer tcpServer.Close()

	userID := protocol.NewID(uuid.New())
	serverPort := tcp.PickPort()
	serverConfig := &core.Config{
		Inbound: []*core.InboundHandlerConfig{
			{
				ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
					PortRange: net.SinglePortRange(serverPort),
					Listen:    net.NewIPOrDomain(net.LocalHostIP),
					StreamSettings: &internet.StreamConfig{
						TransportSettings: []*internet.TransportConfig{
							{
								Protocol: internet.TransportProtocol_TCP,
								Settings: serial.ToTypedMessage(&tcptransport.Config{
									HeaderSettings: serial.ToTypedMessage(&http.Config{}),
								}),
							},
						},
					},
				}),
				ProxySettings: serial.ToTypedMessage(&inbound.Config{
					User: []*protocol.User{
						{
							Account: serial.ToTypedMessage(&vmess.Account{
								Id: userID.String(),
							}),
						},
					},
				}),
			},
		},
		Outbound: []*core.OutboundHandlerConfig{
			{
				ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
			},
		},
	}

	clientPort := tcp.PickPort()
	clientConfig := &core.Config{
		Inbound: []*core.InboundHandlerConfig{
			{
				ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
					PortRange: net.SinglePortRange(clientPort),
					Listen:    net.NewIPOrDomain(net.LocalHostIP),
				}),
				ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
					Address: net.NewIPOrDomain(dest.Address),
					Port:    uint32(dest.Port),
					NetworkList: &net.NetworkList{
						Network: []net.Network{net.Network_TCP},
					},
				}),
			},
		},
		Outbound: []*core.OutboundHandlerConfig{
			{
				ProxySettings: serial.ToTypedMessage(&outbound.Config{
					Receiver: []*protocol.ServerEndpoint{
						{
							Address: net.NewIPOrDomain(net.LocalHostIP),
							Port:    uint32(serverPort),
							User: []*protocol.User{
								{
									Account: serial.ToTypedMessage(&vmess.Account{
										Id: userID.String(),
									}),
								},
							},
						},
					},
				}),
				SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{
					StreamSettings: &internet.StreamConfig{
						TransportSettings: []*internet.TransportConfig{
							{
								Protocol: internet.TransportProtocol_TCP,
								Settings: serial.ToTypedMessage(&tcptransport.Config{
									HeaderSettings: serial.ToTypedMessage(&http.Config{}),
								}),
							},
						},
					},
				}),
			},
		},
	}

	servers, err := InitializeServerConfigs(serverConfig, clientConfig)
	assert(err, IsNil)

	conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{
		IP:   []byte{127, 0, 0, 1},
		Port: int(clientPort),
	})
	assert(err, IsNil)

	payload := "dokodemo request."
	nBytes, err := conn.Write([]byte(payload))
	assert(err, IsNil)
	assert(nBytes, Equals, len(payload))

	response := readFrom(conn, time.Second*2, len(payload))
	assert(response, Equals, xor([]byte(payload)))
	assert(conn.Close(), IsNil)

	CloseAllServers(servers)
}

func TestDomainSocket(t *testing.T) {
	if runtime.GOOS == "windows" {
		t.Skip("Not supported on windows")
		return
	}
	assert := With(t)

	tcpServer := tcp.Server{
		MsgProcessor: xor,
	}
	dest, err := tcpServer.Start()
	assert(err, IsNil)
	defer tcpServer.Close()

	const dsPath = "/tmp/ds_scenario"
	os.Remove(dsPath)

	userID := protocol.NewID(uuid.New())
	serverPort := tcp.PickPort()
	serverConfig := &core.Config{
		Inbound: []*core.InboundHandlerConfig{
			{
				ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
					PortRange: net.SinglePortRange(serverPort),
					Listen:    net.NewIPOrDomain(net.LocalHostIP),
					StreamSettings: &internet.StreamConfig{
						Protocol: internet.TransportProtocol_DomainSocket,
						TransportSettings: []*internet.TransportConfig{
							{
								Protocol: internet.TransportProtocol_DomainSocket,
								Settings: serial.ToTypedMessage(&domainsocket.Config{
									Path: dsPath,
								}),
							},
						},
					},
				}),
				ProxySettings: serial.ToTypedMessage(&inbound.Config{
					User: []*protocol.User{
						{
							Account: serial.ToTypedMessage(&vmess.Account{
								Id: userID.String(),
							}),
						},
					},
				}),
			},
		},
		Outbound: []*core.OutboundHandlerConfig{
			{
				ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
			},
		},
	}

	clientPort := tcp.PickPort()
	clientConfig := &core.Config{
		Inbound: []*core.InboundHandlerConfig{
			{
				ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
					PortRange: net.SinglePortRange(clientPort),
					Listen:    net.NewIPOrDomain(net.LocalHostIP),
				}),
				ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
					Address: net.NewIPOrDomain(dest.Address),
					Port:    uint32(dest.Port),
					NetworkList: &net.NetworkList{
						Network: []net.Network{net.Network_TCP},
					},
				}),
			},
		},
		Outbound: []*core.OutboundHandlerConfig{
			{
				ProxySettings: serial.ToTypedMessage(&outbound.Config{
					Receiver: []*protocol.ServerEndpoint{
						{
							Address: net.NewIPOrDomain(net.LocalHostIP),
							Port:    uint32(serverPort),
							User: []*protocol.User{
								{
									Account: serial.ToTypedMessage(&vmess.Account{
										Id: userID.String(),
									}),
								},
							},
						},
					},
				}),
				SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{
					StreamSettings: &internet.StreamConfig{
						Protocol: internet.TransportProtocol_DomainSocket,
						TransportSettings: []*internet.TransportConfig{
							{
								Protocol: internet.TransportProtocol_DomainSocket,
								Settings: serial.ToTypedMessage(&domainsocket.Config{
									Path: dsPath,
								}),
							},
						},
					},
				}),
			},
		},
	}

	servers, err := InitializeServerConfigs(serverConfig, clientConfig)
	assert(err, IsNil)

	conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{
		IP:   []byte{127, 0, 0, 1},
		Port: int(clientPort),
	})
	assert(err, IsNil)

	payload := "dokodemo request."
	nBytes, err := conn.Write([]byte(payload))
	assert(err, IsNil)
	assert(nBytes, Equals, len(payload))

	response := readFrom(conn, time.Second*2, len(payload))
	assert(response, Equals, xor([]byte(payload)))
	assert(conn.Close(), IsNil)

	CloseAllServers(servers)
}
<|endoftext|>


<commit_before>package testblas

import (
	"math"
	"testing"

	"github.com/gonum/blas"
)

// throwPanic will throw unexpected panics if true, or will just report them as errors if false
const throwPanic = true

func dTolEqual(a, b float64) bool {
	m := math.Max(math.Abs(a), math.Abs(b))
	if m > 1 {
		a /= m
		b /= m
	}
	if math.Abs(a-b) < 1e-14 {
		return true
	}
	return false
}

func dSliceTolEqual(a, b []float64) bool {
	if len(a) != len(b) {
		return false
	}
	for i := range a {
		if !dTolEqual(a[i], b[i]) {
			return false
		}
	}
	return true
}

func dStridedSliceTolEqual(n int, a []float64, inca int, b []float64, incb int) bool {
	ia := 0
	ib := 0
	if inca <= 0 {
		ia = -(n - 1) * inca
	}
	if incb <= 0 {
		ib = -(n - 1) * incb
	}
	for i := 0; i < n; i++ {
		if !dTolEqual(a[ia], b[ib]) {
			return false
		}
		ia += inca
		ib += incb
	}
	return true
}

func dSliceEqual(a, b []float64) bool {
	if len(a) != len(b) {
		return false
	}
	for i := range a {
		if !(a[i] == b[i]) {
			return false
		}
	}
	return true
}

func dCopyTwoTmp(x, xTmp, y, yTmp []float64) {
	if len(x) != len(xTmp) {
		panic("x size mismatch")
	}
	if len(y) != len(yTmp) {
		panic("y size mismatch")
	}
	for i, val := range x {
		xTmp[i] = val
	}
	for i, val := range y {
		yTmp[i] = val
	}
}

// returns true if the function panics
func panics(f func()) (b bool) {
	defer func() {
		err := recover()
		if err != nil {
			b = true
		}
	}()
	f()
	return
}

func testpanics(f func(), name string, t *testing.T) {
	b := panics(f)
	if !b {
		t.Errorf("%v should panic and does not", name)
	}
}

func sliceOfSliceCopy(a [][]float64) [][]float64 {
	n := make([][]float64, len(a))
	for i := range a {
		n[i] = make([]float64, len(a[i]))
		copy(n[i], a[i])
	}
	return n
}

func sliceCopy(a []float64) []float64 {
	n := make([]float64, len(a))
	copy(n, a)
	return n
}

func flatten(a [][]float64) []float64 {
	if len(a) == 0 {
		return nil
	}
	m := len(a)
	n := len(a[0])
	s := make([]float64, m*n)
	for i := 0; i < m; i++ {
		for j := 0; j < n; j++ {
			s[i*n+j] = a[i][j]
		}
	}
	return s
}

func unflatten(a []float64, m, n int) [][]float64 {
	s := make([][]float64, m)
	for i := 0; i < m; i++ {
		s[i] = make([]float64, n)
		for j := 0; j < n; j++ {
			s[i][j] = a[i*n+j]
		}
	}
	return s
}

// flattenTriangular turns the upper or lower triangle of a dense slice of slice
// into a single slice with packed storage.
func flattenTriangular(a [][]float64, ul blas.Uplo) []float64 {
	m := len(a)
	n := len(a[0])
	if m != n {
		panic("must be square")
	}
	aFlat := make([]float64, n*(n+1)/2)
	var count int
	if ul == blas.Upper {
		for i := 0; i < m; i++ {
			for j := i; j < n; j++ {
				aFlat[count] = a[i][j]
				count++
			}
		}
		return aFlat
	}
	for i := 0; i < m; i++ {
		for j := 0; j <= i; j++ {
			aFlat[count] = a[i][j]
			count++
		}
	}
	return aFlat
}

// flattenBanded turns a dense banded slice of slice into the compact banded matrix format
func flattenBanded(a [][]float64, ku, kl int) []float64 {
	m := len(a)
	n := len(a[0])
	if ku < 0 || kl < 0 {
		panic("testblas: negative band length")
	}
	nRows := m
	nCols := (ku + kl + 1)
	aflat := make([]float64, nRows*nCols)
	for i := range aflat {
		aflat[i] = math.NaN()
	}
	// loop over the rows, and then the bands
	// elements in the ith row stay in the ith row
	// order in bands is kept
	for i := 0; i < nRows; i++ {
		min := -kl
		if i-kl < 0 {
			min = -i
		}
		max := ku
		if i+ku >= n {
			max = n - i - 1
		}
		for j := min; j <= max; j++ {
			col := kl + j
			aflat[i*nCols+col] = a[i][i+j]
		}
	}
	return aflat
}

// makeIncremented takes a slice with inc == 1 and makes an incremented version
// and adds extra values on the end
func makeIncremented(x []float64, inc int, extra int) []float64 {
	if inc == 0 {
		panic("zero inc")
	}
	absinc := inc
	if absinc < 0 {
		absinc = -inc
	}
	xcopy := make([]float64, len(x))
	if inc > 0 {
		copy(xcopy, x)
	} else {
		for i := 0; i < len(x); i++ {
			xcopy[i] = x[len(x)-i-1]
		}
	}

	// don't use NaN because it makes comparison hard
	// Do use a weird unique value for easier debugging
	counter := 100.0
	var xnew []float64
	for i, v := range xcopy {
		xnew = append(xnew, v)
		if i != len(x)-1 {
			for j := 0; j < absinc-1; j++ {
				xnew = append(xnew, counter)
				counter++
			}
		}
	}
	for i := 0; i < extra; i++ {
		xnew = append(xnew, counter)
		counter++
	}
	return xnew
}
<commit_msg>removed flatten to pull from master<commit_after>package testblas

import (
	"math"
	"testing"
)

// throwPanic will throw unexpected panics if true, or will just report them as errors if false
const throwPanic = true

func dTolEqual(a, b float64) bool {
	m := math.Max(math.Abs(a), math.Abs(b))
	if m > 1 {
		a /= m
		b /= m
	}
	if math.Abs(a-b) < 1e-14 {
		return true
	}
	return false
}

func dSliceTolEqual(a, b []float64) bool {
	if len(a) != len(b) {
		return false
	}
	for i := range a {
		if !dTolEqual(a[i], b[i]) {
			return false
		}
	}
	return true
}

func dStridedSliceTolEqual(n int, a []float64, inca int, b []float64, incb int) bool {
	ia := 0
	ib := 0
	if inca <= 0 {
		ia = -(n - 1) * inca
	}
	if incb <= 0 {
		ib = -(n - 1) * incb
	}
	for i := 0; i < n; i++ {
		if !dTolEqual(a[ia], b[ib]) {
			return false
		}
		ia += inca
		ib += incb
	}
	return true
}

func dSliceEqual(a, b []float64) bool {
	if len(a) != len(b) {
		return false
	}
	for i := range a {
		if !(a[i] == b[i]) {
			return false
		}
	}
	return true
}

func dCopyTwoTmp(x, xTmp, y, yTmp []float64) {
	if len(x) != len(xTmp) {
		panic("x size mismatch")
	}
	if len(y) != len(yTmp) {
		panic("y size mismatch")
	}
	for i, val := range x {
		xTmp[i] = val
	}
	for i, val := range y {
		yTmp[i] = val
	}
}

// returns true if the function panics
func panics(f func()) (b bool) {
	defer func() {
		err := recover()
		if err != nil {
			b = true
		}
	}()
	f()
	return
}

func testpanics(f func(), name string, t *testing.T) {
	b := panics(f)
	if !b {
		t.Errorf("%v should panic and does not", name)
	}
}

func sliceOfSliceCopy(a [][]float64) [][]float64 {
	n := make([][]float64, len(a))
	for i := range a {
		n[i] = make([]float64, len(a[i]))
		copy(n[i], a[i])
	}
	return n
}

func sliceCopy(a []float64) []float64 {
	n := make([]float64, len(a))
	copy(n, a)
	return n
}

func flatten(a [][]float64) []float64 {
	if len(a) == 0 {
		return nil
	}
	m := len(a)
	n := len(a[0])
	s := make([]float64, m*n)
	for i := 0; i < m; i++ {
		for j := 0; j < n; j++ {
			s[i*n+j] = a[i][j]
		}
	}
	return s
}

func unflatten(a []float64, m, n int) [][]float64 {
	s := make([][]float64, m)
	for i := 0; i < m; i++ {
		s[i] = make([]float64, n)
		for j := 0; j < n; j++ {
			s[i][j] = a[i*n+j]
		}
	}
	return s
}

// flattenBanded turns a dense banded slice of slice into the compact banded matrix format
func flattenBanded(a [][]float64, ku, kl int) []float64 {
	m := len(a)
	n := len(a[0])
	if ku < 0 || kl < 0 {
		panic("testblas: negative band length")
	}
	nRows := m
	nCols := (ku + kl + 1)
	aflat := make([]float64, nRows*nCols)
	for i := range aflat {
		aflat[i] = math.NaN()
	}
	// loop over the rows, and then the bands
	// elements in the ith row stay in the ith row
	// order in bands is kept
	for i := 0; i < nRows; i++ {
		min := -kl
		if i-kl < 0 {
			min = -i
		}
		max := ku
		if i+ku >= n {
			max = n - i - 1
		}
		for j := min; j <= max; j++ {
			col := kl + j
			aflat[i*nCols+col] = a[i][i+j]
		}
	}
	return aflat
}

// makeIncremented takes a slice with inc == 1 and makes an incremented version
// and adds extra values on the end
func makeIncremented(x []float64, inc int, extra int) []float64 {
	if inc == 0 {
		panic("zero inc")
	}
	absinc := inc
	if absinc < 0 {
		absinc = -inc
	}
	xcopy := make([]float64, len(x))
	if inc > 0 {
		copy(xcopy, x)
	} else {
		for i := 0; i < len(x); i++ {
			xcopy[i] = x[len(x)-i-1]
		}
	}

	// don't use NaN because it makes comparison hard
	// Do use a weird unique value for easier debugging
	counter := 100.0
	var xnew []float64
	for i, v := range xcopy {
		xnew = append(xnew, v)
		if i != len(x)-1 {
			for j := 0; j < absinc-1; j++ {
				xnew = append(xnew, counter)
				counter++
			}
		}
	}
	for i := 0; i < extra; i++ {
		xnew = append(xnew, counter)
		counter++
	}
	return xnew
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/lxc/lxd"
	"github.com/lxc/lxd/shared/i18n"
)

type fingerCmd struct{}

func (c *fingerCmd) showByDefault() bool {
	return false
}

func (c *fingerCmd) usage() string {
	return i18n.G(
		`Check if the LXD instance is up.

lxc finger [<remote>:]`)
}

func (c *fingerCmd) flags() {}

func (c *fingerCmd) run(config *lxd.Config, args []string) error {
	if len(args) > 1 {
		return errArgs
	}

	var remote string
	if len(args) == 1 {
		remote = config.ParseRemote(args[0])
	} else {
		remote = config.DefaultRemote
	}

	// New client may or may not need to connect to the remote host, but
	// client.ServerStatus will at least request the basic information from
	// the server.
	client, err := lxd.NewClient(config, remote)
	if err != nil {
		return err
	}
	_, err = client.ServerStatus()
	return err
}
<commit_msg>lxc/finger: Rework usage to be parsable by help2man<commit_after>package main

import (
	"github.com/lxc/lxd"
	"github.com/lxc/lxd/shared/i18n"
)

type fingerCmd struct{}

func (c *fingerCmd) showByDefault() bool {
	return false
}

func (c *fingerCmd) usage() string {
	return i18n.G(
		`Usage: lxc finger [<remote>:]

Check if the LXD server is alive.`)
}

func (c *fingerCmd) flags() {}

func (c *fingerCmd) run(config *lxd.Config, args []string) error {
	if len(args) > 1 {
		return errArgs
	}

	var remote string
	if len(args) == 1 {
		remote = config.ParseRemote(args[0])
	} else {
		remote = config.DefaultRemote
	}

	// New client may or may not need to connect to the remote host, but
	// client.ServerStatus will at least request the basic information from
	// the server.
	client, err := lxd.NewClient(config, remote)
	if err != nil {
		return err
	}
	_, err = client.ServerStatus()
	return err
}
<|endoftext|>


<commit_before>package client

import (
	"fmt"
	//"github.com/gopherjs/gopherjs/js"
	"github.com/gopherjs/jquery"
	//"honnef.co/go/js/console"
	//"reflect"
	"strings"
)

type ViewImpl struct {
	tag      string
	id       string
	classes  []string
	style    string
	children []*ViewImpl
	text     string
	builders []builder
	event    []*eventHandler
}

type option func(*ViewImpl) *ViewImpl

func Event(name EventName, fn EventFunc) option {
	return func(self *ViewImpl) *ViewImpl {
		self.event = append(self.event, &eventHandler{
			name: name,
			fn:   fn,
		})
		return self
	}
}

func Style(s string) option {
	return func(self *ViewImpl) *ViewImpl {
		self.style = self.style + s
		return self
	}
}

func Class(cl CssClass) option {
	return func(self *ViewImpl) *ViewImpl {
		self.classes = append(self.classes, cl.ClassName())
		return self
	}
}

func Text(str string) option {
	return func(self *ViewImpl) *ViewImpl {
		self.text = str
		return self
	}
}

func IdConstant(id string) option {
	return func(self *ViewImpl) *ViewImpl {
		if id == "" {
			panic("should not be calling IdConstant() with an empty id")
		}
		self.id = id
		return self
	}
}

func Id(id HtmlId) option {
	return func(self *ViewImpl) *ViewImpl {
		if id == nil {
			panic("should not be calling Id() on a nil HtmlId")
		}
		self.id = id.Id()
		return self
	}
}

func ModelId(m ModelName) option {
	return func(self *ViewImpl) *ViewImpl {
		id := fmt.Sprintf("%s-%s", strings.ToLower(self.tag), m.Id())
		self.id = newHtmlIdNoCheck(self.tag, id).Id()
		return self
	}
}

func addBuilder(b builder) option {
	return func(self *ViewImpl) *ViewImpl {
		self.builders = append(self.builders, b)
		return self
	}
}

func CssExistence(c CssClass, b BooleanAttribute) option {
	return addBuilder(cssExistenceBuilder(c, b))
}

func PropEqual(n propName, b BooleanAttribute) option {
	return addBuilder(propBuilder(n, b, nil))
}

func HtmlAttrEqual(h htmlAttrName, attr Attribute) option {
	return addBuilder(htmlAttrBuilder(h, attr, nil))
}

func HtmlAttrConstant(h htmlAttrName, str string) option {
	attr := NewStringSimple(str)
	return addBuilder(htmlAttrBuilder(h, attr, nil))
}

func TextEqual(attr Attribute) option {
	return addBuilder(textAttrBuilder(attr, nil))
}

//BindEqual constrains the attribute provided to be the same as the value of
//the tag this is located in.  Typically, this is an INPUT tag.  Data flows
//_from_ the input text that the user types to the attribute, not the other
//way around. There is a strange, but useful, edge case
//in the initialization of the INPUT tag: ff the attr provided returns a string
//value, that value is used to initialize INPUT field.
func BindEqual(attr Attribute) option {
	return addBuilder(valueAttrBuilder(attr, nil))
}

//Bind constrains the attribute provided to be a function of the value of
//the tag this call is located in.  Typically, this is an INPUT tag.  Data flows
//_from_ the input text that the user types to the attribute via this constraint
//given, not the other way around.  There is a strange, but useful, edge case
//in the initialization of the INPUT tag: ff the attr provided returns a string
//value, that value is used to initialize INPUT field.
func Bind(attr Attribute, cons Constraint) option {
	return addBuilder(valueAttrBuilder(attr, cons))
}

//HtmlIdFromModel returns an HtmlId object from the given modelname and
//tagname.  Resulting id is unique to the modelname and tag, but not
//between tags with the same name.
func HtmlIdFromModel(tag string, m ModelName) HtmlId {
	id := fmt.Sprintf("%s-%s", strings.ToLower(tag), m.Id())
	return NewHtmlId(tag, id)
}

//ParseHtml returns a NarrowDom that points at the fragment
//of HTML provided in t.  No attempt is made to validate that
//the HTML is sensible, much less syntatically correct.
func ParseHtml(t string) NarrowDom {
	parsed := jquery.ParseHTML(t)
	var nDom NarrowDom
	if TestMode {
		nDom = newTestOps()
	} else {
		nDom = wrap(jquery.NewJQuery(parsed[0]))
	}
	return nDom
}

func (p *ViewImpl) Build() NarrowDom {
	id := ""
	classes := ""
	styles := ""
	if p.id != "" {
		id = fmt.Sprintf(" id='%s'", p.id)
	}

	if p.classes != nil {
		classes = fmt.Sprintf(" class='%s'", strings.Join(p.classes, " "))
	}
	if p.style != "" {
		styles = fmt.Sprintf(" style='%s'", p.style)
	}

	var t string
	if p.text == "" {
		t = fmt.Sprintf("<%s%s%s%s/>", p.tag, id, classes, styles)
	} else {
		t = fmt.Sprintf("<%s%s%s%s>%s</%s>", p.tag, id, classes, styles, p.text, p.tag)
	}
	nDom := ParseHtml(t)
	for _, child := range p.children {
		built := child.Build()
		nDom.Append(built)
	}

	if p.builders != nil {
		for _, b := range p.builders {
			if b == nil {
				panic("found a nil builder in tree construction!")
			}
			b.build(nDom)
		}
	}

	if p.event != nil {
		for _, h := range p.event {
			//we have the object now, assign to j
			h.t = nDom
			h.register()
		}
	}
	return nDom
}

func IMG(obj ...interface{}) *ViewImpl {
	return tag("img", obj...)
}

func FORM(obj ...interface{}) *ViewImpl {
	return tag("form", obj...)
}

func DIV(obj ...interface{}) *ViewImpl {
	return tag("div", obj...)
}

func INPUT(obj ...interface{}) *ViewImpl {
	return tag("input", obj...)
}

func TEXTAREA(obj ...interface{}) *ViewImpl {
	return tag("textarea", obj...)
}

func LABEL(obj ...interface{}) *ViewImpl {
	return tag("label", obj...)
}

func A(obj ...interface{}) *ViewImpl {
	return tag("a", obj...)
}

func SPAN(obj ...interface{}) *ViewImpl {
	return tag("span", obj...)
}

func STRONG(obj ...interface{}) *ViewImpl {
	return tag("strong", obj...)
}
func P(obj ...interface{}) *ViewImpl {
	return tag("p", obj...)
}

func EM(obj ...interface{}) *ViewImpl {
	return tag("em", obj...)
}

func H1(obj ...interface{}) *ViewImpl {
	return tag("h1", obj...)
}

func H2(obj ...interface{}) *ViewImpl {
	return tag("h2", obj...)
}

func H3(obj ...interface{}) *ViewImpl {
	return tag("h3", obj...)
}

func H4(obj ...interface{}) *ViewImpl {
	return tag("h4", obj...)
}

func H5(obj ...interface{}) *ViewImpl {
	return tag("h5", obj...)
}

func H6(obj ...interface{}) *ViewImpl {
	return tag("h6", obj...)
}

func HR(obj ...interface{}) *ViewImpl {
	return tag("hr", obj...)
}

func LI(obj ...interface{}) *ViewImpl {
	return tag("li", obj...)
}

func UL(obj ...interface{}) *ViewImpl {
	return tag("ul", obj...)
}
func OL(obj ...interface{}) *ViewImpl {
	return tag("ol", obj...)
}
func BUTTON(obj ...interface{}) *ViewImpl {
	return tag("button", obj...)
}
func PRE(obj ...interface{}) *ViewImpl {
	return tag("pre", obj...)
}

func tag(tagName string, obj ...interface{}) *ViewImpl {
	p := &ViewImpl{tag: tagName}

	for i := 0; i < len(obj); i++ {
		if obj[i] == nil {
			panic("nil value in view construction")
		}
		opt, ok := obj[i].(option)
		if ok {
			opt(p)
			continue
		}
		v, ok := obj[i].(*ViewImpl)
		if v == nil && ok {
			continue
		}
		if ok {
			p.children = append(p.children, v)
			continue
		}
		varr, isArray := obj[i].([]*ViewImpl)
		if isArray {
			for _, v := range varr {
				if v != nil {
					p.children = append(p.children, v)
				}
			}
			continue
		}
		panic(fmt.Sprintf("unable to understand type of parameter: %v (%T %d) to %s", obj[i], obj[i], i, tagName))
	}
	return p
}
<commit_msg>safety<commit_after>package client

import (
	"fmt"
	//"github.com/gopherjs/gopherjs/js"
	"github.com/gopherjs/jquery"
	//"honnef.co/go/js/console"
	//"reflect"
	"strings"
)

type ViewImpl struct {
	tag      string
	id       string
	classes  []string
	style    string
	children []*ViewImpl
	text     string
	builders []builder
	event    []*eventHandler
}

type option func(*ViewImpl) *ViewImpl

func Event(name EventName, fn EventFunc) option {
	return func(self *ViewImpl) *ViewImpl {
		self.event = append(self.event, &eventHandler{
			name: name,
			fn:   fn,
		})
		return self
	}
}

func Style(s string) option {
	return func(self *ViewImpl) *ViewImpl {
		self.style = self.style + s
		return self
	}
}

func Class(cl CssClass) option {
	return func(self *ViewImpl) *ViewImpl {
		self.classes = append(self.classes, cl.ClassName())
		return self
	}
}

func Text(str string) option {
	return func(self *ViewImpl) *ViewImpl {
		self.text = str
		return self
	}
}

func IdConstant(id string) option {
	return func(self *ViewImpl) *ViewImpl {
		if id == "" {
			panic("should not be calling IdConstant() with an empty id")
		}
		self.id = id
		return self
	}
}

func Id(id HtmlId) option {
	return func(self *ViewImpl) *ViewImpl {
		if id == nil {
			panic("should not be calling Id() on a nil HtmlId")
		}
		self.id = id.Id()
		return self
	}
}

func ModelId(m ModelName) option {
	return func(self *ViewImpl) *ViewImpl {
		id := fmt.Sprintf("%s-%s", strings.ToLower(self.tag), m.Id())
		self.id = newHtmlIdNoCheck(self.tag, id).Id()
		return self
	}
}

func addBuilder(b builder) option {
	return func(self *ViewImpl) *ViewImpl {
		self.builders = append(self.builders, b)
		return self
	}
}

func CssExistence(c CssClass, b BooleanAttribute) option {
	return addBuilder(cssExistenceBuilder(c, b))
}

func PropEqual(n propName, b BooleanAttribute) option {
	return addBuilder(propBuilder(n, b, nil))
}

func HtmlAttrEqual(h htmlAttrName, attr Attribute) option {
	return addBuilder(htmlAttrBuilder(h, attr, nil))
}

func HtmlAttrConstant(h htmlAttrName, str string) option {
	attr := NewStringSimple(str)
	return addBuilder(htmlAttrBuilder(h, attr, nil))
}

func TextEqual(attr Attribute) option {
	return addBuilder(textAttrBuilder(attr, nil))
}

//BindEqual constrains the attribute provided to be the same as the value of
//the tag this is located in.  Typically, this is an INPUT tag.  Data flows
//_from_ the input text that the user types to the attribute, not the other
//way around. There is a strange, but useful, edge case
//in the initialization of the INPUT tag: ff the attr provided returns a string
//value, that value is used to initialize INPUT field.
func BindEqual(attr Attribute) option {
	return addBuilder(valueAttrBuilder(attr, nil))
}

//Bind constrains the attribute provided to be a function of the value of
//the tag this call is located in.  Typically, this is an INPUT tag.  Data flows
//_from_ the input text that the user types to the attribute via this constraint
//given, not the other way around.  There is a strange, but useful, edge case
//in the initialization of the INPUT tag: ff the attr provided returns a string
//value, that value is used to initialize INPUT field.
func Bind(attr Attribute, cons Constraint) option {
	return addBuilder(valueAttrBuilder(attr, cons))
}

//HtmlIdFromModel returns an HtmlId object from the given modelname and
//tagname.  Resulting id is unique to the modelname and tag, but not
//between tags with the same name.
func HtmlIdFromModel(tag string, m ModelName) HtmlId {
	id := fmt.Sprintf("%s-%s", strings.ToLower(tag), m.Id())
	return NewHtmlId(tag, id)
}

//ParseHtml returns a NarrowDom that points at the fragment
//of HTML provided in t.  No attempt is made to validate that
//the HTML is sensible, much less syntatically correct.
func ParseHtml(t string) NarrowDom {
	parsed := jquery.ParseHTML(t)
	var nDom NarrowDom
	if TestMode {
		nDom = newTestOps()
	} else {
		nDom = wrap(jquery.NewJQuery(parsed[0]))
	}
	return nDom
}

func (p *ViewImpl) Build() NarrowDom {
	id := ""
	classes := ""
	styles := ""
	if p.id != "" {
		id = fmt.Sprintf(" id='%s'", p.id)
	}

	if p.classes != nil {
		classes = fmt.Sprintf(" class='%s'", strings.Join(p.classes, " "))
	}
	if p.style != "" {
		styles = fmt.Sprintf(" style='%s'", p.style)
	}

	var t string
	if p.text == "" {
		t = fmt.Sprintf("<%s%s%s%s/>", p.tag, id, classes, styles)
	} else {
		t = fmt.Sprintf("<%s%s%s%s>%s</%s>", p.tag, id, classes, styles, p.text, p.tag)
	}
	nDom := ParseHtml(t)
	for _, child := range p.children {
		built := child.Build()
		nDom.Append(built)
	}

	if p.builders != nil {
		for _, b := range p.builders {
			if b == nil {
				panic("found a nil builder in tree construction!")
			}
			b.build(nDom)
		}
	}

	if p.event != nil {
		for _, h := range p.event {
			//we have the object now, assign to j
			h.t = nDom
			h.register()
		}
	}
	return nDom
}

func IMG(obj ...interface{}) *ViewImpl {
	return tag("img", obj...)
}

func FORM(obj ...interface{}) *ViewImpl {
	return tag("form", obj...)
}

func DIV(obj ...interface{}) *ViewImpl {
	return tag("div", obj...)
}

func INPUT(obj ...interface{}) *ViewImpl {
	return tag("input", obj...)
}

func TEXTAREA(obj ...interface{}) *ViewImpl {
	return tag("textarea", obj...)
}

func LABEL(obj ...interface{}) *ViewImpl {
	return tag("label", obj...)
}

func A(obj ...interface{}) *ViewImpl {
	return tag("a", obj...)
}

func SPAN(obj ...interface{}) *ViewImpl {
	return tag("span", obj...)
}

func STRONG(obj ...interface{}) *ViewImpl {
	return tag("strong", obj...)
}
func P(obj ...interface{}) *ViewImpl {
	return tag("p", obj...)
}

func EM(obj ...interface{}) *ViewImpl {
	return tag("em", obj...)
}

func H1(obj ...interface{}) *ViewImpl {
	return tag("h1", obj...)
}

func H2(obj ...interface{}) *ViewImpl {
	return tag("h2", obj...)
}

func H3(obj ...interface{}) *ViewImpl {
	return tag("h3", obj...)
}

func H4(obj ...interface{}) *ViewImpl {
	return tag("h4", obj...)
}

func H5(obj ...interface{}) *ViewImpl {
	return tag("h5", obj...)
}

func H6(obj ...interface{}) *ViewImpl {
	return tag("h6", obj...)
}

func HR(obj ...interface{}) *ViewImpl {
	return tag("hr", obj...)
}

func LI(obj ...interface{}) *ViewImpl {
	return tag("li", obj...)
}

func UL(obj ...interface{}) *ViewImpl {
	return tag("ul", obj...)
}
func OL(obj ...interface{}) *ViewImpl {
	return tag("ol", obj...)
}
func BUTTON(obj ...interface{}) *ViewImpl {
	return tag("button", obj...)
}
func PRE(obj ...interface{}) *ViewImpl {
	return tag("pre", obj...)
}
func OPTION(obj ...interface{}) *ViewImpl {
	return tag("option", obj...)
}

func tag(tagName string, obj ...interface{}) *ViewImpl {
	p := &ViewImpl{tag: tagName}

	for i := 0; i < len(obj); i++ {
		if obj[i] == nil {
			panic("nil value in view construction")
		}
		opt, ok := obj[i].(option)
		if ok {
			opt(p)
			continue
		}
		v, ok := obj[i].(*ViewImpl)
		if v == nil && ok {
			continue
		}
		if ok {
			p.children = append(p.children, v)
			continue
		}
		varr, isArray := obj[i].([]*ViewImpl)
		if isArray {
			for _, v := range varr {
				if v != nil {
					p.children = append(p.children, v)
				}
			}
			continue
		}
		panic(fmt.Sprintf("unable to understand type of parameter: %v (%T %d) to %s", obj[i], obj[i], i, tagName))
	}
	return p
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/binary"
	"encoding/hex"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"runtime"

	"github.com/BurntSushi/toml"
	blake2b "github.com/minio/blake2b-simd"
	"github.com/mitchellh/go-homedir"
)

const (
	// Version - Piknik version
	Version = "0.5"
	// DomainStr - BLAKE2 domain (personalization)
	DomainStr = "PK"
	// DefaultListen - Default value for the Listen parameter
	DefaultListen = "0.0.0.0:8075"
	// DefaultConnect - Default value for the Connect parameter
	DefaultConnect = "127.0.0.1:8075"
)

type tomlConfig struct {
	Connect     string
	Listen      string
	EncryptSk   string
	EncryptSkID uint64
	Psk         string
	SignPk      string
	SignSk      string
}

// Conf - Shared config
type Conf struct {
	Connect     string
	Listen      string
	MaxClients  uint64
	MaxLen      uint64
	EncryptSk   []byte
	EncryptSkID []byte
	Psk         []byte
	SignPk      []byte
	SignSk      []byte
}

func expandConfigFile(path string) string {
	file, err := homedir.Expand(path)
	if err != nil {
		log.Fatal(err)
	}
	return file
}

func version() {
	fmt.Printf("\nPiknik v%v (protocol version: %v)\n",
		Version, DefaultClientVersion)
}

func main() {
	log.SetFlags(0)

	isCopy := flag.Bool("copy", false, "store content (copy)")
	_ = flag.Bool("paste", false, "retrieve the content (paste) - this is the default action")
	isMove := flag.Bool("move", false, "retrieve and delete the clipboard content")
	isServer := flag.Bool("server", false, "start a server")
	isGenKeys := flag.Bool("genkeys", false, "generate keys")
	isDeterministic := flag.Bool("password", false, "derive the keys from a password (default=random keys)")
	maxClients := flag.Uint64("maxclients", 10, "maximum number of simultaneous client connections")
	maxLenMb := flag.Uint64("maxlen", 0, "maximum content length to accept in Mb (0=unlimited)")
	isVersion := flag.Bool("version", false, "display package version")

	defaultConfigFile := "~/.piknik.toml"
	if runtime.GOOS == "windows" {
		defaultConfigFile = "~/piknik.toml"
	}
	configFile := flag.String("config", defaultConfigFile, "configuration file")
	flag.Parse()
	if *isVersion {
		version()
		return
	}
	tomlData, err := ioutil.ReadFile(expandConfigFile(*configFile))
	if err != nil && *isGenKeys == false {
		log.Fatal(err)
	}
	var tomlConf tomlConfig
	if _, err = toml.Decode(string(tomlData), &tomlConf); err != nil {
		log.Fatal(err)
	}
	var conf Conf
	if tomlConf.Listen == "" {
		conf.Listen = DefaultListen
	} else {
		conf.Listen = tomlConf.Listen
	}
	if tomlConf.Connect == "" {
		conf.Connect = DefaultConnect
	} else {
		conf.Connect = tomlConf.Connect
	}
	if *isGenKeys {
		leKey := ""
		if *isDeterministic {
			leKey = getPassword("Password> ")
		}
		genKeys(conf, *configFile, leKey)
		return
	}
	pskHex := tomlConf.Psk
	psk, err := hex.DecodeString(pskHex)
	if err != nil {
		log.Fatal(err)
	}
	conf.Psk = psk
	if encryptSkHex := tomlConf.EncryptSk; encryptSkHex != "" {
		encryptSk, err := hex.DecodeString(encryptSkHex)
		if err != nil {
			log.Fatal(err)
		}
		conf.EncryptSk = encryptSk
	}
	if signPkHex := tomlConf.SignPk; signPkHex != "" {
		signPk, err := hex.DecodeString(signPkHex)
		if err != nil {
			log.Fatal(err)
		}
		conf.SignPk = signPk
	}
	if encryptSkID := tomlConf.EncryptSkID; encryptSkID > 0 {
		conf.EncryptSkID = make([]byte, 8)
		binary.LittleEndian.PutUint64(conf.EncryptSkID, encryptSkID)
	} else if len(conf.EncryptSk) > 0 {
		hf, _ := blake2b.New(&blake2b.Config{
			Person: []byte(DomainStr),
			Size:   8,
		})
		hf.Write(conf.EncryptSk)
		encryptSkID := hf.Sum(nil)
		encryptSkID[7] &= 0x7f
		conf.EncryptSkID = encryptSkID
	}
	if signSkHex := tomlConf.SignSk; signSkHex != "" {
		signSk, err := hex.DecodeString(signSkHex)
		if err != nil {
			log.Fatal(err)
		}
		switch len(signSk) {
		case 32:
			if len(conf.SignPk) != 32 {
				log.Fatal("Public signing key required")
			}
			signSk = append(signSk, conf.SignPk...)
		case 64:
		default:
			log.Fatal("Unsupported length for the secret signing key")
		}
		conf.SignSk = signSk
	}
	conf.MaxClients = *maxClients
	conf.MaxLen = *maxLenMb * 1024 * 1024
	if *isServer {
		RunServer(conf)
	} else {
		RunClient(conf, *isCopy, *isMove)
	}
}
<commit_msg>Forbid usage as a client without secret keys<commit_after>package main

import (
	"encoding/binary"
	"encoding/hex"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"runtime"

	"github.com/BurntSushi/toml"
	blake2b "github.com/minio/blake2b-simd"
	"github.com/mitchellh/go-homedir"
)

const (
	// Version - Piknik version
	Version = "0.5"
	// DomainStr - BLAKE2 domain (personalization)
	DomainStr = "PK"
	// DefaultListen - Default value for the Listen parameter
	DefaultListen = "0.0.0.0:8075"
	// DefaultConnect - Default value for the Connect parameter
	DefaultConnect = "127.0.0.1:8075"
)

type tomlConfig struct {
	Connect     string
	Listen      string
	EncryptSk   string
	EncryptSkID uint64
	Psk         string
	SignPk      string
	SignSk      string
}

// Conf - Shared config
type Conf struct {
	Connect     string
	Listen      string
	MaxClients  uint64
	MaxLen      uint64
	EncryptSk   []byte
	EncryptSkID []byte
	Psk         []byte
	SignPk      []byte
	SignSk      []byte
}

func expandConfigFile(path string) string {
	file, err := homedir.Expand(path)
	if err != nil {
		log.Fatal(err)
	}
	return file
}

func version() {
	fmt.Printf("\nPiknik v%v (protocol version: %v)\n",
		Version, DefaultClientVersion)
}

func main() {
	log.SetFlags(0)

	isCopy := flag.Bool("copy", false, "store content (copy)")
	_ = flag.Bool("paste", false, "retrieve the content (paste) - this is the default action")
	isMove := flag.Bool("move", false, "retrieve and delete the clipboard content")
	isServer := flag.Bool("server", false, "start a server")
	isGenKeys := flag.Bool("genkeys", false, "generate keys")
	isDeterministic := flag.Bool("password", false, "derive the keys from a password (default=random keys)")
	maxClients := flag.Uint64("maxclients", 10, "maximum number of simultaneous client connections")
	maxLenMb := flag.Uint64("maxlen", 0, "maximum content length to accept in Mb (0=unlimited)")
	isVersion := flag.Bool("version", false, "display package version")

	defaultConfigFile := "~/.piknik.toml"
	if runtime.GOOS == "windows" {
		defaultConfigFile = "~/piknik.toml"
	}
	configFile := flag.String("config", defaultConfigFile, "configuration file")
	flag.Parse()
	if *isVersion {
		version()
		return
	}
	tomlData, err := ioutil.ReadFile(expandConfigFile(*configFile))
	if err != nil && *isGenKeys == false {
		log.Fatal(err)
	}
	var tomlConf tomlConfig
	if _, err = toml.Decode(string(tomlData), &tomlConf); err != nil {
		log.Fatal(err)
	}
	var conf Conf
	if tomlConf.Listen == "" {
		conf.Listen = DefaultListen
	} else {
		conf.Listen = tomlConf.Listen
	}
	if tomlConf.Connect == "" {
		conf.Connect = DefaultConnect
	} else {
		conf.Connect = tomlConf.Connect
	}
	if *isGenKeys {
		leKey := ""
		if *isDeterministic {
			leKey = getPassword("Password> ")
		}
		genKeys(conf, *configFile, leKey)
		return
	}
	pskHex := tomlConf.Psk
	psk, err := hex.DecodeString(pskHex)
	if err != nil {
		log.Fatal(err)
	}
	conf.Psk = psk
	if encryptSkHex := tomlConf.EncryptSk; encryptSkHex != "" {
		encryptSk, err := hex.DecodeString(encryptSkHex)
		if err != nil {
			log.Fatal(err)
		}
		conf.EncryptSk = encryptSk
	}
	if signPkHex := tomlConf.SignPk; signPkHex != "" {
		signPk, err := hex.DecodeString(signPkHex)
		if err != nil {
			log.Fatal(err)
		}
		conf.SignPk = signPk
	}
	if encryptSkID := tomlConf.EncryptSkID; encryptSkID > 0 {
		conf.EncryptSkID = make([]byte, 8)
		binary.LittleEndian.PutUint64(conf.EncryptSkID, encryptSkID)
	} else if len(conf.EncryptSk) > 0 {
		hf, _ := blake2b.New(&blake2b.Config{
			Person: []byte(DomainStr),
			Size:   8,
		})
		hf.Write(conf.EncryptSk)
		encryptSkID := hf.Sum(nil)
		encryptSkID[7] &= 0x7f
		conf.EncryptSkID = encryptSkID
	}
	if signSkHex := tomlConf.SignSk; signSkHex != "" {
		signSk, err := hex.DecodeString(signSkHex)
		if err != nil {
			log.Fatal(err)
		}
		switch len(signSk) {
		case 32:
			if len(conf.SignPk) != 32 {
				log.Fatal("Public signing key required")
			}
			signSk = append(signSk, conf.SignPk...)
		case 64:
		default:
			log.Fatal("Unsupported length for the secret signing key")
		}
		conf.SignSk = signSk
	}
	conf.MaxClients = *maxClients
	conf.MaxLen = *maxLenMb * 1024 * 1024
	if *isServer {
		RunServer(conf)
	} else {
		if len(conf.EncryptSk) != 32 || len(conf.SignSk) != 64 {
			log.Fatal("The EncryptSk and SignSk properties must be present in the configuration file\n" +
				"in order to use this command in client mode")
		}
		RunClient(conf, *isCopy, *isMove)
	}
}
<|endoftext|>


<commit_before>// Copyright 2012 Samuel Stauffer. All rights reserved.
// Use of this source code is governed by a 3-clause BSD
// license that can be found in the LICENSE file.

package thrift

import (
	"errors"
	"fmt"
	"log"
	"net"
	"net/rpc"
	"runtime"
	"sync"
	"testing"
)

var (
	serverAddr, newServerAddr string
	once, newOnce             sync.Once
)

type TestRequest struct {
	Value int32 `thrift:"1,required"`
}

type TestResponse struct {
	Value int32 `thrift:"0,required"`
}

type TestService int

func (s *TestService) Success(req *TestRequest, res *TestResponse) error {
	res.Value = req.Value
	return nil
}

func (s *TestService) Fail(req *TestRequest, res *TestResponse) error {
	res.Value = req.Value
	return errors.New("fail")
}

func listenTCP() (net.Listener, string) {
	l, e := net.Listen("tcp", "127.0.0.1:0") // any available address
	if e != nil {
		log.Fatalf("net.Listen tcp :0: %v", e)
	}
	return l, l.Addr().String()
}

func startServer() {
	rpc.RegisterName("Thrift", new(TestService))

	var l net.Listener
	l, serverAddr = listenTCP()
	log.Println("Test RPC server listening on", serverAddr)
	go func() {
		for {
			conn, err := l.Accept()
			if err != nil {
				panic(err)
				continue
			}
			go rpc.ServeCodec(NewServerCodec(NewFramedReadWriteCloser(conn, 0), NewBinaryProtocol(true, false)))
		}
	}()
}

func TestRPCClientSuccess(t *testing.T) {
	once.Do(startServer)

	c, err := Dial("tcp", serverAddr, true, NewBinaryProtocol(true, false))
	if err != nil {
		t.Fatalf("NewClient returned error: %+v", err)
	}
	req := &TestRequest{123}
	res := &TestResponse{789}
	if err := c.Call("Success", req, res); err != nil {
		t.Fatalf("Client.Call returned error: %+v", err)
	}
	if res.Value != req.Value {
		t.Fatalf("Response value wrong: %d != %d", res.Value, req.Value)
	}
}

func TestRPCClientFail(t *testing.T) {
	once.Do(startServer)

	c, err := Dial("tcp", serverAddr, true, NewBinaryProtocol(true, false))
	if err != nil {
		t.Fatalf("NewClient returned error: %+v", err)
	}
	req := &TestRequest{123}
	res := &TestResponse{789}
	if err := c.Call("Fail", req, res); err == nil {
		t.Fatalf("Client.Call didn't return an error as it should")
	} else if err.Error() != "Internal Error: fail" {
		t.Fatalf("Expected 'fail' error but got '%s'", err)
	}

	// Make sure an exception doesn't cause future requests to fail

	if err := c.Call("Success", req, res); err != nil {
		t.Fatalf("Client.Call returned error: %+v", err)
	}
	if res.Value != req.Value {
		t.Fatalf("Response value wrong: %d != %d", res.Value, req.Value)
	}
}

func TestRPCMallocCount(t *testing.T) {
	once.Do(startServer)

	c, err := Dial("tcp", serverAddr, true, NewBinaryProtocol(true, false))
	if err != nil {
		t.Fatalf("NewClient returned error: %+v", err)
	}
	req := &TestRequest{123}
	res := &TestResponse{789}
	const count = 100
	memstats := new(runtime.MemStats)
	runtime.ReadMemStats(memstats)
	mallocs := 0 - memstats.Mallocs
	for i := 0; i < count; i++ {
		if err := c.Call("Success", req, res); err != nil {
			t.Fatalf("Client.Call returned error: %+v", err)
		}
	}
	runtime.ReadMemStats(memstats)
	mallocs += memstats.Mallocs
	fmt.Printf("mallocs per thrift.rpc round trip: %d\n", mallocs/count)
}
<commit_msg>Fix client tests<commit_after>// Copyright 2012 Samuel Stauffer. All rights reserved.
// Use of this source code is governed by a 3-clause BSD
// license that can be found in the LICENSE file.

package thrift

import (
	"errors"
	"fmt"
	"log"
	"net"
	"net/rpc"
	"runtime"
	"sync"
	"testing"
)

var (
	serverAddr, newServerAddr string
	once, newOnce             sync.Once
)

type TestRequest struct {
	Value int32 `thrift:"1,required"`
}

type TestResponse struct {
	Value int32 `thrift:"0,required"`
}

type TestService int

func (s *TestService) Success(req *TestRequest, res *TestResponse) error {
	res.Value = req.Value
	return nil
}

func (s *TestService) Fail(req *TestRequest, res *TestResponse) error {
	res.Value = req.Value
	return errors.New("fail")
}

func listenTCP() (net.Listener, string) {
	l, e := net.Listen("tcp", "127.0.0.1:0") // any available address
	if e != nil {
		log.Fatalf("net.Listen tcp :0: %v", e)
	}
	return l, l.Addr().String()
}

func startServer() {
	rpc.RegisterName("Thrift", new(TestService))

	var l net.Listener
	l, serverAddr = listenTCP()
	log.Println("Test RPC server listening on", serverAddr)
	go func() {
		for {
			conn, err := l.Accept()
			if err != nil {
				panic(err)
				continue
			}
			go rpc.ServeCodec(NewServerCodec(NewFramedReadWriteCloser(conn, 0), NewBinaryProtocol(true, false)))
		}
	}()
}

func TestRPCClientSuccess(t *testing.T) {
	once.Do(startServer)

	c, err := Dial("tcp", serverAddr, true, NewBinaryProtocol(true, false), false)
	if err != nil {
		t.Fatalf("NewClient returned error: %+v", err)
	}
	req := &TestRequest{123}
	res := &TestResponse{789}
	if err := c.Call("Success", req, res); err != nil {
		t.Fatalf("Client.Call returned error: %+v", err)
	}
	if res.Value != req.Value {
		t.Fatalf("Response value wrong: %d != %d", res.Value, req.Value)
	}
}

func TestRPCClientFail(t *testing.T) {
	once.Do(startServer)

	c, err := Dial("tcp", serverAddr, true, NewBinaryProtocol(true, false), false)
	if err != nil {
		t.Fatalf("NewClient returned error: %+v", err)
	}
	req := &TestRequest{123}
	res := &TestResponse{789}
	if err := c.Call("Fail", req, res); err == nil {
		t.Fatalf("Client.Call didn't return an error as it should")
	} else if err.Error() != "Internal Error: fail" {
		t.Fatalf("Expected 'fail' error but got '%s'", err)
	}

	// Make sure an exception doesn't cause future requests to fail

	if err := c.Call("Success", req, res); err != nil {
		t.Fatalf("Client.Call returned error: %+v", err)
	}
	if res.Value != req.Value {
		t.Fatalf("Response value wrong: %d != %d", res.Value, req.Value)
	}
}

func TestRPCMallocCount(t *testing.T) {
	once.Do(startServer)

	c, err := Dial("tcp", serverAddr, true, NewBinaryProtocol(true, false), false)
	if err != nil {
		t.Fatalf("NewClient returned error: %+v", err)
	}
	req := &TestRequest{123}
	res := &TestResponse{789}
	const count = 100
	memstats := new(runtime.MemStats)
	runtime.ReadMemStats(memstats)
	mallocs := 0 - memstats.Mallocs
	for i := 0; i < count; i++ {
		if err := c.Call("Success", req, res); err != nil {
			t.Fatalf("Client.Call returned error: %+v", err)
		}
	}
	runtime.ReadMemStats(memstats)
	mallocs += memstats.Mallocs
	fmt.Printf("mallocs per thrift.rpc round trip: %d\n", mallocs/count)
}
<|endoftext|>


<commit_before>/*
   Copyright The containerd Authors.

   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 containerd

import (
	"bytes"
	"context"
	"flag"
	"fmt"
	"io/ioutil"
	golog "log"
	"os"
	"os/exec"
	"testing"
	"time"

	"google.golang.org/grpc/grpclog"

	"github.com/containerd/containerd/images"
	"github.com/containerd/containerd/log"
	"github.com/containerd/containerd/namespaces"
	"github.com/containerd/containerd/platforms"
	"github.com/containerd/containerd/sys"
	"github.com/containerd/containerd/testutil"
	"github.com/sirupsen/logrus"
)

var (
	address       string
	noDaemon      bool
	noCriu        bool
	supportsCriu  bool
	testNamespace = "testing"

	ctrd = &daemon{}
)

func init() {
	// Discard grpc logs so that they don't mess with our stdio
	grpclog.SetLogger(golog.New(ioutil.Discard, "", golog.LstdFlags))

	flag.StringVar(&address, "address", defaultAddress, "The address to the containerd socket for use in the tests")
	flag.BoolVar(&noDaemon, "no-daemon", false, "Do not start a dedicated daemon for the tests")
	flag.BoolVar(&noCriu, "no-criu", false, "Do not run the checkpoint tests")
	flag.Parse()
}

func testContext() (context.Context, context.CancelFunc) {
	ctx, cancel := context.WithCancel(context.Background())
	ctx = namespaces.WithNamespace(ctx, testNamespace)
	return ctx, cancel
}

func TestMain(m *testing.M) {
	if testing.Short() {
		os.Exit(m.Run())
	}
	testutil.RequiresRootM()
	// check if criu is installed on the system
	_, err := exec.LookPath("criu")
	supportsCriu = err == nil && !noCriu

	var (
		buf         = bytes.NewBuffer(nil)
		ctx, cancel = testContext()
	)
	defer cancel()

	if !noDaemon {
		sys.ForceRemoveAll(defaultRoot)

		err := ctrd.start("containerd", address, []string{
			"--root", defaultRoot,
			"--state", defaultState,
			"--log-level", "debug",
		}, buf, buf)
		if err != nil {
			fmt.Fprintf(os.Stderr, "%s: %s", err, buf.String())
			os.Exit(1)
		}
	}

	waitCtx, waitCancel := context.WithTimeout(ctx, 2*time.Second)
	client, err := ctrd.waitForStart(waitCtx)
	waitCancel()
	if err != nil {
		ctrd.Kill()
		ctrd.Wait()
		fmt.Fprintf(os.Stderr, "%s: %s\n", err, buf.String())
		os.Exit(1)
	}

	// print out the version in information
	version, err := client.Version(ctx)
	if err != nil {
		fmt.Fprintf(os.Stderr, "error getting version: %s\n", err)
		os.Exit(1)
	}

	// allow comparison with containerd under test
	log.G(ctx).WithFields(logrus.Fields{
		"version":  version.Version,
		"revision": version.Revision,
	}).Info("running tests against containerd")

	// pull a seed image
	if _, err = client.Pull(ctx, testImage, WithPullUnpack, WithPlatform(platforms.Default())); err != nil {
		ctrd.Stop()
		ctrd.Wait()
		fmt.Fprintf(os.Stderr, "%s: %s\n", err, buf.String())
		os.Exit(1)
	}

	if err := client.Close(); err != nil {
		fmt.Fprintln(os.Stderr, "failed to close client", err)
	}

	// run the test
	status := m.Run()

	if !noDaemon {
		// tear down the daemon and resources created
		if err := ctrd.Stop(); err != nil {
			if err := ctrd.Kill(); err != nil {
				fmt.Fprintln(os.Stderr, "failed to signal containerd", err)
			}
		}
		if err := ctrd.Wait(); err != nil {
			if _, ok := err.(*exec.ExitError); !ok {
				fmt.Fprintln(os.Stderr, "failed to wait for containerd", err)
			}
		}
		if err := sys.ForceRemoveAll(defaultRoot); err != nil {
			fmt.Fprintln(os.Stderr, "failed to remove test root dir", err)
			os.Exit(1)
		}
		// only print containerd logs if the test failed
		if status != 0 {
			fmt.Fprintln(os.Stderr, buf.String())
		}
	}
	os.Exit(status)
}

func newClient(t testing.TB, address string, opts ...ClientOpt) (*Client, error) {
	if testing.Short() {
		t.Skip()
	}
	// testutil.RequiresRoot(t) is not needed here (already called in TestMain)
	return New(address, opts...)
}

func TestNewClient(t *testing.T) {
	t.Parallel()

	client, err := newClient(t, address)
	if err != nil {
		t.Fatal(err)
	}
	if client == nil {
		t.Fatal("New() returned nil client")
	}
	if err := client.Close(); err != nil {
		t.Errorf("client closed returned errror %v", err)
	}
}

// All the container's tests depends on this, we need it to run first.
func TestImagePull(t *testing.T) {
	client, err := newClient(t, address)
	if err != nil {
		t.Fatal(err)
	}
	defer client.Close()

	ctx, cancel := testContext()
	defer cancel()
	_, err = client.Pull(ctx, testImage, WithPlatform(platforms.Default()))
	if err != nil {
		t.Fatal(err)
	}
}

func TestImagePullAllPlatforms(t *testing.T) {
	client, err := newClient(t, address)
	if err != nil {
		t.Fatal(err)
	}
	defer client.Close()
	ctx, cancel := testContext()
	defer cancel()

	cs := client.ContentStore()
	img, err := client.Pull(ctx, testImage)
	if err != nil {
		t.Fatal(err)
	}
	index := img.Target()
	manifests, err := images.Children(ctx, cs, index)
	if err != nil {
		t.Fatal(err)
	}
	for _, manifest := range manifests {
		children, err := images.Children(ctx, cs, manifest)
		if err != nil {
			t.Fatal("Th")
		}
		// check if childless data type has blob in content store
		for _, desc := range children {
			ra, err := cs.ReaderAt(ctx, desc.Digest)
			if err != nil {
				t.Fatal(err)
			}
			ra.Close()
		}
	}
}

func TestImagePullSomePlatforms(t *testing.T) {
	client, err := newClient(t, address)
	if err != nil {
		t.Fatal(err)
	}
	defer client.Close()
	ctx, cancel := testContext()
	defer cancel()

	cs := client.ContentStore()
	platformList := []string{"linux/arm64/v8", "linux/386"}
	m := make(map[string]platforms.Matcher)
	var opts []RemoteOpt

	for _, platform := range platformList {
		p, err := platforms.Parse(platform)
		if err != nil {
			t.Fatal(err)
		}
		m[platform] = platforms.NewMatcher(p)
		opts = append(opts, WithPlatform(platform))
	}

	img, err := client.Pull(ctx, "docker.io/library/busybox:latest", opts...)
	if err != nil {
		t.Fatal(err)
	}

	index := img.Target()
	manifests, err := images.Children(ctx, cs, index)
	if err != nil {
		t.Fatal(err)
	}

	count := 0
	for _, manifest := range manifests {
		children, err := images.Children(ctx, cs, manifest)
		found := false
		for _, matcher := range m {
			if matcher.Match(*manifest.Platform) {
				count++
				found = true
			}
		}

		if found {
			if len(children) == 0 {
				t.Fatal("manifest should have pulled children content")
			}

			// check if childless data type has blob in content store
			for _, desc := range children {
				ra, err := cs.ReaderAt(ctx, desc.Digest)
				if err != nil {
					t.Fatal(err)
				}
				ra.Close()
			}
		} else if !found && err == nil {
			t.Fatal("manifest should not have pulled children content")
		}
	}

	if count != len(platformList) {
		t.Fatal("expected a different number of pulled manifests")
	}
}

func TestClientReconnect(t *testing.T) {
	t.Parallel()

	ctx, cancel := testContext()
	defer cancel()

	client, err := newClient(t, address)
	if err != nil {
		t.Fatal(err)
	}
	if client == nil {
		t.Fatal("New() returned nil client")
	}
	ok, err := client.IsServing(ctx)
	if err != nil {
		t.Fatal(err)
	}
	if !ok {
		t.Fatal("containerd is not serving")
	}
	if err := client.Reconnect(); err != nil {
		t.Fatal(err)
	}
	if ok, err = client.IsServing(ctx); err != nil {
		t.Fatal(err)
	}
	if !ok {
		t.Fatal("containerd is not serving")
	}
	if err := client.Close(); err != nil {
		t.Errorf("client closed returned errror %v", err)
	}
}
<commit_msg>Update multiplatform pull test<commit_after>/*
   Copyright The containerd Authors.

   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 containerd

import (
	"bytes"
	"context"
	"flag"
	"fmt"
	"io/ioutil"
	golog "log"
	"os"
	"os/exec"
	"testing"
	"time"

	"google.golang.org/grpc/grpclog"

	"github.com/containerd/containerd/images"
	"github.com/containerd/containerd/log"
	"github.com/containerd/containerd/namespaces"
	"github.com/containerd/containerd/platforms"
	"github.com/containerd/containerd/sys"
	"github.com/containerd/containerd/testutil"
	"github.com/sirupsen/logrus"
)

var (
	address       string
	noDaemon      bool
	noCriu        bool
	supportsCriu  bool
	testNamespace = "testing"

	ctrd = &daemon{}
)

func init() {
	// Discard grpc logs so that they don't mess with our stdio
	grpclog.SetLogger(golog.New(ioutil.Discard, "", golog.LstdFlags))

	flag.StringVar(&address, "address", defaultAddress, "The address to the containerd socket for use in the tests")
	flag.BoolVar(&noDaemon, "no-daemon", false, "Do not start a dedicated daemon for the tests")
	flag.BoolVar(&noCriu, "no-criu", false, "Do not run the checkpoint tests")
	flag.Parse()
}

func testContext() (context.Context, context.CancelFunc) {
	ctx, cancel := context.WithCancel(context.Background())
	ctx = namespaces.WithNamespace(ctx, testNamespace)
	return ctx, cancel
}

func TestMain(m *testing.M) {
	if testing.Short() {
		os.Exit(m.Run())
	}
	testutil.RequiresRootM()
	// check if criu is installed on the system
	_, err := exec.LookPath("criu")
	supportsCriu = err == nil && !noCriu

	var (
		buf         = bytes.NewBuffer(nil)
		ctx, cancel = testContext()
	)
	defer cancel()

	if !noDaemon {
		sys.ForceRemoveAll(defaultRoot)

		err := ctrd.start("containerd", address, []string{
			"--root", defaultRoot,
			"--state", defaultState,
			"--log-level", "debug",
		}, buf, buf)
		if err != nil {
			fmt.Fprintf(os.Stderr, "%s: %s", err, buf.String())
			os.Exit(1)
		}
	}

	waitCtx, waitCancel := context.WithTimeout(ctx, 2*time.Second)
	client, err := ctrd.waitForStart(waitCtx)
	waitCancel()
	if err != nil {
		ctrd.Kill()
		ctrd.Wait()
		fmt.Fprintf(os.Stderr, "%s: %s\n", err, buf.String())
		os.Exit(1)
	}

	// print out the version in information
	version, err := client.Version(ctx)
	if err != nil {
		fmt.Fprintf(os.Stderr, "error getting version: %s\n", err)
		os.Exit(1)
	}

	// allow comparison with containerd under test
	log.G(ctx).WithFields(logrus.Fields{
		"version":  version.Version,
		"revision": version.Revision,
	}).Info("running tests against containerd")

	// pull a seed image
	if _, err = client.Pull(ctx, testImage, WithPullUnpack, WithPlatform(platforms.Default())); err != nil {
		ctrd.Stop()
		ctrd.Wait()
		fmt.Fprintf(os.Stderr, "%s: %s\n", err, buf.String())
		os.Exit(1)
	}

	if err := client.Close(); err != nil {
		fmt.Fprintln(os.Stderr, "failed to close client", err)
	}

	// run the test
	status := m.Run()

	if !noDaemon {
		// tear down the daemon and resources created
		if err := ctrd.Stop(); err != nil {
			if err := ctrd.Kill(); err != nil {
				fmt.Fprintln(os.Stderr, "failed to signal containerd", err)
			}
		}
		if err := ctrd.Wait(); err != nil {
			if _, ok := err.(*exec.ExitError); !ok {
				fmt.Fprintln(os.Stderr, "failed to wait for containerd", err)
			}
		}
		if err := sys.ForceRemoveAll(defaultRoot); err != nil {
			fmt.Fprintln(os.Stderr, "failed to remove test root dir", err)
			os.Exit(1)
		}
		// only print containerd logs if the test failed
		if status != 0 {
			fmt.Fprintln(os.Stderr, buf.String())
		}
	}
	os.Exit(status)
}

func newClient(t testing.TB, address string, opts ...ClientOpt) (*Client, error) {
	if testing.Short() {
		t.Skip()
	}
	// testutil.RequiresRoot(t) is not needed here (already called in TestMain)
	return New(address, opts...)
}

func TestNewClient(t *testing.T) {
	t.Parallel()

	client, err := newClient(t, address)
	if err != nil {
		t.Fatal(err)
	}
	if client == nil {
		t.Fatal("New() returned nil client")
	}
	if err := client.Close(); err != nil {
		t.Errorf("client closed returned errror %v", err)
	}
}

// All the container's tests depends on this, we need it to run first.
func TestImagePull(t *testing.T) {
	client, err := newClient(t, address)
	if err != nil {
		t.Fatal(err)
	}
	defer client.Close()

	ctx, cancel := testContext()
	defer cancel()
	_, err = client.Pull(ctx, testImage, WithPlatform(platforms.Default()))
	if err != nil {
		t.Fatal(err)
	}
}

func TestImagePullAllPlatforms(t *testing.T) {
	client, err := newClient(t, address)
	if err != nil {
		t.Fatal(err)
	}
	defer client.Close()
	ctx, cancel := testContext()
	defer cancel()

	cs := client.ContentStore()
	img, err := client.Pull(ctx, testImage)
	if err != nil {
		t.Fatal(err)
	}
	index := img.Target()
	manifests, err := images.Children(ctx, cs, index)
	if err != nil {
		t.Fatal(err)
	}
	for _, manifest := range manifests {
		children, err := images.Children(ctx, cs, manifest)
		if err != nil {
			t.Fatal("Th")
		}
		// check if childless data type has blob in content store
		for _, desc := range children {
			ra, err := cs.ReaderAt(ctx, desc.Digest)
			if err != nil {
				t.Fatal(err)
			}
			ra.Close()
		}
	}
}

func TestImagePullSomePlatforms(t *testing.T) {
	client, err := newClient(t, address)
	if err != nil {
		t.Fatal(err)
	}
	defer client.Close()
	ctx, cancel := testContext()
	defer cancel()

	cs := client.ContentStore()
	platformList := []string{"linux/amd64", "linux/arm64/v8", "linux/s390x"}
	m := make(map[string]platforms.Matcher)
	var opts []RemoteOpt

	for _, platform := range platformList {
		p, err := platforms.Parse(platform)
		if err != nil {
			t.Fatal(err)
		}
		m[platform] = platforms.NewMatcher(p)
		opts = append(opts, WithPlatform(platform))
	}

	img, err := client.Pull(ctx, "docker.io/library/busybox:latest", opts...)
	if err != nil {
		t.Fatal(err)
	}

	index := img.Target()
	manifests, err := images.Children(ctx, cs, index)
	if err != nil {
		t.Fatal(err)
	}

	count := 0
	for _, manifest := range manifests {
		children, err := images.Children(ctx, cs, manifest)
		found := false
		for _, matcher := range m {
			if matcher.Match(*manifest.Platform) {
				count++
				found = true
			}
		}

		if found {
			if len(children) == 0 {
				t.Fatal("manifest should have pulled children content")
			}

			// check if childless data type has blob in content store
			for _, desc := range children {
				ra, err := cs.ReaderAt(ctx, desc.Digest)
				if err != nil {
					t.Fatal(err)
				}
				ra.Close()
			}
		} else if !found && err == nil {
			t.Fatal("manifest should not have pulled children content")
		}
	}

	if count != len(platformList) {
		t.Fatal("expected a different number of pulled manifests")
	}
}

func TestClientReconnect(t *testing.T) {
	t.Parallel()

	ctx, cancel := testContext()
	defer cancel()

	client, err := newClient(t, address)
	if err != nil {
		t.Fatal(err)
	}
	if client == nil {
		t.Fatal("New() returned nil client")
	}
	ok, err := client.IsServing(ctx)
	if err != nil {
		t.Fatal(err)
	}
	if !ok {
		t.Fatal("containerd is not serving")
	}
	if err := client.Reconnect(); err != nil {
		t.Fatal(err)
	}
	if ok, err = client.IsServing(ctx); err != nil {
		t.Fatal(err)
	}
	if !ok {
		t.Fatal("containerd is not serving")
	}
	if err := client.Close(); err != nil {
		t.Errorf("client closed returned errror %v", err)
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2019 The Ceph-CSI Authors.

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 main

import (
	"flag"
	"fmt"
	"os"
	"runtime"
	"time"

	"github.com/ceph/ceph-csi/internal/cephfs"
	"github.com/ceph/ceph-csi/internal/controller"
	"github.com/ceph/ceph-csi/internal/controller/persistentvolume"
	"github.com/ceph/ceph-csi/internal/liveness"
	"github.com/ceph/ceph-csi/internal/rbd"
	"github.com/ceph/ceph-csi/internal/util"

	"k8s.io/klog/v2"
)

const (
	rbdType        = "rbd"
	cephfsType     = "cephfs"
	livenessType   = "liveness"
	controllerType = "controller"

	rbdDefaultName      = "rbd.csi.ceph.com"
	cephfsDefaultName   = "cephfs.csi.ceph.com"
	livenessDefaultName = "liveness.csi.ceph.com"

	pollTime     = 60 // seconds
	probeTimeout = 3  // seconds

	// use default namespace if namespace is not set
	defaultNS = "default"
)

var (
	conf util.Config
)

func init() {
	// common flags
	flag.StringVar(&conf.Vtype, "type", "", "driver type [rbd|cephfs|liveness|controller]")
	flag.StringVar(&conf.Endpoint, "endpoint", "unix://tmp/csi.sock", "CSI endpoint")
	flag.StringVar(&conf.DriverName, "drivername", "", "name of the driver")
	flag.StringVar(&conf.DriverNamespace, "drivernamespace", defaultNS, "namespace in which driver is deployed")
	flag.StringVar(&conf.NodeID, "nodeid", "", "node id")
	flag.StringVar(&conf.InstanceID, "instanceid", "", "Unique ID distinguishing this instance of Ceph CSI among other"+
		" instances, when sharing Ceph clusters across CSI instances for provisioning")
	flag.IntVar(&conf.PidLimit, "pidlimit", 0, "the PID limit to configure through cgroups")
	flag.BoolVar(&conf.IsControllerServer, "controllerserver", false, "start cephcsi controller server")
	flag.BoolVar(&conf.IsNodeServer, "nodeserver", false, "start cephcsi node server")
	flag.StringVar(&conf.DomainLabels, "domainlabels", "", "list of kubernetes node labels, that determines the topology"+
		" domain the node belongs to, separated by ','")

	// cephfs related flags
	flag.BoolVar(&conf.ForceKernelCephFS, "forcecephkernelclient", false, "enable Ceph Kernel clients on kernel < 4.17 which support quotas")

	// liveness/grpc metrics related flags
	flag.IntVar(&conf.MetricsPort, "metricsport", 8080, "TCP port for liveness/grpc metrics requests")
	flag.StringVar(&conf.MetricsPath, "metricspath", "/metrics", "path of prometheus endpoint where metrics will be available")
	flag.DurationVar(&conf.PollTime, "polltime", time.Second*pollTime, "time interval in seconds between each poll")
	flag.DurationVar(&conf.PoolTimeout, "timeout", time.Second*probeTimeout, "probe timeout in seconds")

	flag.BoolVar(&conf.EnableGRPCMetrics, "enablegrpcmetrics", false, "[DEPRECATED] enable grpc metrics")
	flag.StringVar(&conf.HistogramOption, "histogramoption", "0.5,2,6",
		"[DEPRECATED] Histogram option for grpc metrics, should be comma separated value, ex:= 0.5,2,6 where start=0.5 factor=2, count=6")

	flag.UintVar(&conf.RbdHardMaxCloneDepth, "rbdhardmaxclonedepth", 8, "Hard limit for maximum number of nested volume clones that are taken before a flatten occurs")
	flag.UintVar(&conf.RbdSoftMaxCloneDepth, "rbdsoftmaxclonedepth", 4, "Soft limit for maximum number of nested volume clones that are taken before a flatten occurs")
	flag.UintVar(&conf.MaxSnapshotsOnImage, "maxsnapshotsonimage", 450, "Maximum number of snapshots allowed on rbd image without flattening")
	flag.UintVar(&conf.MinSnapshotsOnImage, "minsnapshotsonimage", 250, "Minimum number of snapshots required on rbd image to start flattening")
	flag.BoolVar(&conf.SkipForceFlatten, "skipforceflatten", false,
		"skip image flattening if kernel support mapping of rbd images which has the deep-flatten feature")

	flag.BoolVar(&conf.Version, "version", false, "Print cephcsi version information")

	klog.InitFlags(nil)
	if err := flag.Set("logtostderr", "true"); err != nil {
		klog.Exitf("failed to set logtostderr flag: %v", err)
	}
	flag.Parse()
}

func getDriverName() string {
	// was explicitly passed a driver name
	if conf.DriverName != "" {
		return conf.DriverName
	}
	// select driver name based on volume type
	switch conf.Vtype {
	case rbdType:
		return rbdDefaultName
	case cephfsType:
		return cephfsDefaultName
	case livenessType:
		return livenessDefaultName
	default:
		return ""
	}
}

func main() {
	if conf.Version {
		fmt.Println("Cephcsi Version:", util.DriverVersion)
		fmt.Println("Git Commit:", util.GitCommit)
		fmt.Println("Go Version:", runtime.Version())
		fmt.Println("Compiler:", runtime.Compiler)
		fmt.Printf("Platform: %s/%s\n", runtime.GOOS, runtime.GOARCH)
		if kv, err := util.GetKernelVersion(); err == nil {
			fmt.Println("Kernel:", kv)
		}
		os.Exit(0)
	}
	util.DefaultLog("Driver version: %s and Git version: %s", util.DriverVersion, util.GitCommit)

	if conf.Vtype == "" {
		logAndExit("driver type not specified")
	}

	dname := getDriverName()
	err := util.ValidateDriverName(dname)
	if err != nil {
		logAndExit(err.Error())
	}

	// the driver may need a higher PID limit for handling all concurrent requests
	if conf.PidLimit != 0 {
		currentLimit, pidErr := util.GetPIDLimit()
		if pidErr != nil {
			klog.Errorf("Failed to get the PID limit, can not reconfigure: %v", pidErr)
		} else {
			util.DefaultLog("Initial PID limit is set to %d", currentLimit)
			err = util.SetPIDLimit(conf.PidLimit)
			if err != nil {
				klog.Errorf("Failed to set new PID limit to %d: %v", conf.PidLimit, err)
			} else {
				s := ""
				if conf.PidLimit == -1 {
					s = " (max)"
				}
				util.DefaultLog("Reconfigured PID limit to %d%s", conf.PidLimit, s)
			}
		}
	}

	if conf.EnableGRPCMetrics || conf.Vtype == livenessType {
		// validate metrics endpoint
		conf.MetricsIP = os.Getenv("POD_IP")

		if conf.MetricsIP == "" {
			klog.Warning("missing POD_IP env var defaulting to 0.0.0.0")
			conf.MetricsIP = "0.0.0.0"
		}
		err = util.ValidateURL(&conf)
		if err != nil {
			logAndExit(err.Error())
		}
	}

	util.DefaultLog("Starting driver type: %v with name: %v", conf.Vtype, dname)
	switch conf.Vtype {
	case rbdType:
		validateCloneDepthFlag(&conf)
		validateMaxSnaphostFlag(&conf)
		driver := rbd.NewDriver()
		driver.Run(&conf)

	case cephfsType:
		driver := cephfs.NewDriver()
		driver.Run(&conf)

	case livenessType:
		liveness.Run(&conf)

	case controllerType:
		cfg := controller.Config{
			DriverName: dname,
			Namespace:  conf.DriverNamespace,
		}
		// initialize all controllers before starting.
		initControllers()
		err = controller.Start(cfg)
		if err != nil {
			logAndExit(err.Error())
		}
	}

	os.Exit(0)
}

// initControllers will initialize all the controllers.
func initControllers() {
	// Add list of controller here.
	persistentvolume.Init()
}

func validateCloneDepthFlag(conf *util.Config) {
	// keeping hardlimit to 14 as max to avoid max image depth
	if conf.RbdHardMaxCloneDepth == 0 || conf.RbdHardMaxCloneDepth > 14 {
		logAndExit("rbdhardmaxclonedepth flag value should be between 1 and 14")
	}

	if conf.RbdSoftMaxCloneDepth > conf.RbdHardMaxCloneDepth {
		logAndExit("rbdsoftmaxclonedepth flag value should not be greater than rbdhardmaxclonedepth")
	}
}

func validateMaxSnaphostFlag(conf *util.Config) {
	// maximum number of snapshots on an image are 510 [1] and 16 images in
	// a parent/child chain [2],keeping snapshot limit to 500 to avoid issues.
	// [1] https://github.com/torvalds/linux/blob/master/drivers/block/rbd.c#L98
	// [2] https://github.com/torvalds/linux/blob/master/drivers/block/rbd.c#L92
	if conf.MaxSnapshotsOnImage == 0 || conf.MaxSnapshotsOnImage > 500 {
		logAndExit("maxsnapshotsonimage flag value should be between 1 and 500")
	}

	if conf.MinSnapshotsOnImage > conf.MaxSnapshotsOnImage {
		logAndExit("minsnapshotsonimage flag value should be less than maxsnapshotsonimage")
	}
}

func logAndExit(msg string) {
	klog.Errorln(msg)
	os.Exit(1)
}
<commit_msg>cleanup: refactor deeply nested if statement in cephcsi.go<commit_after>/*
Copyright 2019 The Ceph-CSI Authors.

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 main

import (
	"flag"
	"fmt"
	"os"
	"runtime"
	"time"

	"github.com/ceph/ceph-csi/internal/cephfs"
	"github.com/ceph/ceph-csi/internal/controller"
	"github.com/ceph/ceph-csi/internal/controller/persistentvolume"
	"github.com/ceph/ceph-csi/internal/liveness"
	"github.com/ceph/ceph-csi/internal/rbd"
	"github.com/ceph/ceph-csi/internal/util"

	"k8s.io/klog/v2"
)

const (
	rbdType        = "rbd"
	cephfsType     = "cephfs"
	livenessType   = "liveness"
	controllerType = "controller"

	rbdDefaultName      = "rbd.csi.ceph.com"
	cephfsDefaultName   = "cephfs.csi.ceph.com"
	livenessDefaultName = "liveness.csi.ceph.com"

	pollTime     = 60 // seconds
	probeTimeout = 3  // seconds

	// use default namespace if namespace is not set
	defaultNS = "default"
)

var (
	conf util.Config
)

func init() {
	// common flags
	flag.StringVar(&conf.Vtype, "type", "", "driver type [rbd|cephfs|liveness|controller]")
	flag.StringVar(&conf.Endpoint, "endpoint", "unix://tmp/csi.sock", "CSI endpoint")
	flag.StringVar(&conf.DriverName, "drivername", "", "name of the driver")
	flag.StringVar(&conf.DriverNamespace, "drivernamespace", defaultNS, "namespace in which driver is deployed")
	flag.StringVar(&conf.NodeID, "nodeid", "", "node id")
	flag.StringVar(&conf.InstanceID, "instanceid", "", "Unique ID distinguishing this instance of Ceph CSI among other"+
		" instances, when sharing Ceph clusters across CSI instances for provisioning")
	flag.IntVar(&conf.PidLimit, "pidlimit", 0, "the PID limit to configure through cgroups")
	flag.BoolVar(&conf.IsControllerServer, "controllerserver", false, "start cephcsi controller server")
	flag.BoolVar(&conf.IsNodeServer, "nodeserver", false, "start cephcsi node server")
	flag.StringVar(&conf.DomainLabels, "domainlabels", "", "list of kubernetes node labels, that determines the topology"+
		" domain the node belongs to, separated by ','")

	// cephfs related flags
	flag.BoolVar(&conf.ForceKernelCephFS, "forcecephkernelclient", false, "enable Ceph Kernel clients on kernel < 4.17 which support quotas")

	// liveness/grpc metrics related flags
	flag.IntVar(&conf.MetricsPort, "metricsport", 8080, "TCP port for liveness/grpc metrics requests")
	flag.StringVar(&conf.MetricsPath, "metricspath", "/metrics", "path of prometheus endpoint where metrics will be available")
	flag.DurationVar(&conf.PollTime, "polltime", time.Second*pollTime, "time interval in seconds between each poll")
	flag.DurationVar(&conf.PoolTimeout, "timeout", time.Second*probeTimeout, "probe timeout in seconds")

	flag.BoolVar(&conf.EnableGRPCMetrics, "enablegrpcmetrics", false, "[DEPRECATED] enable grpc metrics")
	flag.StringVar(&conf.HistogramOption, "histogramoption", "0.5,2,6",
		"[DEPRECATED] Histogram option for grpc metrics, should be comma separated value, ex:= 0.5,2,6 where start=0.5 factor=2, count=6")

	flag.UintVar(&conf.RbdHardMaxCloneDepth, "rbdhardmaxclonedepth", 8, "Hard limit for maximum number of nested volume clones that are taken before a flatten occurs")
	flag.UintVar(&conf.RbdSoftMaxCloneDepth, "rbdsoftmaxclonedepth", 4, "Soft limit for maximum number of nested volume clones that are taken before a flatten occurs")
	flag.UintVar(&conf.MaxSnapshotsOnImage, "maxsnapshotsonimage", 450, "Maximum number of snapshots allowed on rbd image without flattening")
	flag.UintVar(&conf.MinSnapshotsOnImage, "minsnapshotsonimage", 250, "Minimum number of snapshots required on rbd image to start flattening")
	flag.BoolVar(&conf.SkipForceFlatten, "skipforceflatten", false,
		"skip image flattening if kernel support mapping of rbd images which has the deep-flatten feature")

	flag.BoolVar(&conf.Version, "version", false, "Print cephcsi version information")

	klog.InitFlags(nil)
	if err := flag.Set("logtostderr", "true"); err != nil {
		klog.Exitf("failed to set logtostderr flag: %v", err)
	}
	flag.Parse()
}

func getDriverName() string {
	// was explicitly passed a driver name
	if conf.DriverName != "" {
		return conf.DriverName
	}
	// select driver name based on volume type
	switch conf.Vtype {
	case rbdType:
		return rbdDefaultName
	case cephfsType:
		return cephfsDefaultName
	case livenessType:
		return livenessDefaultName
	default:
		return ""
	}
}

func main() {
	if conf.Version {
		fmt.Println("Cephcsi Version:", util.DriverVersion)
		fmt.Println("Git Commit:", util.GitCommit)
		fmt.Println("Go Version:", runtime.Version())
		fmt.Println("Compiler:", runtime.Compiler)
		fmt.Printf("Platform: %s/%s\n", runtime.GOOS, runtime.GOARCH)
		if kv, err := util.GetKernelVersion(); err == nil {
			fmt.Println("Kernel:", kv)
		}
		os.Exit(0)
	}
	util.DefaultLog("Driver version: %s and Git version: %s", util.DriverVersion, util.GitCommit)

	if conf.Vtype == "" {
		logAndExit("driver type not specified")
	}

	dname := getDriverName()
	err := util.ValidateDriverName(dname)
	if err != nil {
		logAndExit(err.Error())
	}

	// the driver may need a higher PID limit for handling all concurrent requests
	if conf.PidLimit != 0 {
		currentLimit, pidErr := util.GetPIDLimit()
		if pidErr != nil {
			klog.Errorf("Failed to get the PID limit, can not reconfigure: %v", pidErr)
		} else {
			util.DefaultLog("Initial PID limit is set to %d", currentLimit)
			err = util.SetPIDLimit(conf.PidLimit)
			switch {
			case err != nil:
				klog.Errorf("Failed to set new PID limit to %d: %v", conf.PidLimit, err)
			case conf.PidLimit == -1:
				util.DefaultLog("Reconfigured PID limit to %d (max)", conf.PidLimit)
			default:
				util.DefaultLog("Reconfigured PID limit to %d", conf.PidLimit)
			}
		}
	}

	if conf.EnableGRPCMetrics || conf.Vtype == livenessType {
		// validate metrics endpoint
		conf.MetricsIP = os.Getenv("POD_IP")

		if conf.MetricsIP == "" {
			klog.Warning("missing POD_IP env var defaulting to 0.0.0.0")
			conf.MetricsIP = "0.0.0.0"
		}
		err = util.ValidateURL(&conf)
		if err != nil {
			logAndExit(err.Error())
		}
	}

	util.DefaultLog("Starting driver type: %v with name: %v", conf.Vtype, dname)
	switch conf.Vtype {
	case rbdType:
		validateCloneDepthFlag(&conf)
		validateMaxSnaphostFlag(&conf)
		driver := rbd.NewDriver()
		driver.Run(&conf)

	case cephfsType:
		driver := cephfs.NewDriver()
		driver.Run(&conf)

	case livenessType:
		liveness.Run(&conf)

	case controllerType:
		cfg := controller.Config{
			DriverName: dname,
			Namespace:  conf.DriverNamespace,
		}
		// initialize all controllers before starting.
		initControllers()
		err = controller.Start(cfg)
		if err != nil {
			logAndExit(err.Error())
		}
	}

	os.Exit(0)
}

// initControllers will initialize all the controllers.
func initControllers() {
	// Add list of controller here.
	persistentvolume.Init()
}

func validateCloneDepthFlag(conf *util.Config) {
	// keeping hardlimit to 14 as max to avoid max image depth
	if conf.RbdHardMaxCloneDepth == 0 || conf.RbdHardMaxCloneDepth > 14 {
		logAndExit("rbdhardmaxclonedepth flag value should be between 1 and 14")
	}

	if conf.RbdSoftMaxCloneDepth > conf.RbdHardMaxCloneDepth {
		logAndExit("rbdsoftmaxclonedepth flag value should not be greater than rbdhardmaxclonedepth")
	}
}

func validateMaxSnaphostFlag(conf *util.Config) {
	// maximum number of snapshots on an image are 510 [1] and 16 images in
	// a parent/child chain [2],keeping snapshot limit to 500 to avoid issues.
	// [1] https://github.com/torvalds/linux/blob/master/drivers/block/rbd.c#L98
	// [2] https://github.com/torvalds/linux/blob/master/drivers/block/rbd.c#L92
	if conf.MaxSnapshotsOnImage == 0 || conf.MaxSnapshotsOnImage > 500 {
		logAndExit("maxsnapshotsonimage flag value should be between 1 and 500")
	}

	if conf.MinSnapshotsOnImage > conf.MaxSnapshotsOnImage {
		logAndExit("minsnapshotsonimage flag value should be less than maxsnapshotsonimage")
	}
}

func logAndExit(msg string) {
	klog.Errorln(msg)
	os.Exit(1)
}
<|endoftext|>


<commit_before>package main

import (
	"io/ioutil"

	"github.com/spf13/cobra"
	"golang.org/x/crypto/ssh"
)

//

func compare(cmd *cobra.Command, args []string) {
	// read in the parameters

	//compFile := args[0]

	// setup a connection to on of the systems

}

//create a ssh client configuration
func createSSHClient(u string, f string, p string) (*ssh.ClientConfig, error) {

	sshConfig := &ssh.ClientConfig{
		User: u,
		Auth: []ssh.AuthMethod{
			ssh.Password(p),
			publicKeyFile(f),
		},
	}

	return sshConfig, nil
}

// parse the public key file
func publicKeyFile(file string) ssh.AuthMethod {
	buffer, err := ioutil.ReadFile(file)
	if err != nil {
		return nil
	}

	key, err := ssh.ParsePrivateKey(buffer)
	if err != nil {
		return nil
	}
	return ssh.PublicKeys(key)
}
<commit_msg>added function to setup ssh session<commit_after>package main

import (
	"fmt"
	"io/ioutil"

	"github.com/spf13/cobra"
	"golang.org/x/crypto/ssh"
)

//

func compare(cmd *cobra.Command, args []string) {
	// read in the parameters

	//compFile := args[0]

	// setup a connection to on of the systems

}

//create a ssh client configuration
func createSSHClient(u string, f string, p string) (*ssh.ClientConfig, error) {

	sshConfig := &ssh.ClientConfig{
		User: u,
		Auth: []ssh.AuthMethod{
			ssh.Password(p),
			publicKeyFile(f),
		},
	}

	return sshConfig, nil
}

// parse the public key file
func publicKeyFile(file string) ssh.AuthMethod {
	buffer, err := ioutil.ReadFile(file)
	if err != nil {
		return nil
	}

	key, err := ssh.ParsePrivateKey(buffer)
	if err != nil {
		return nil
	}
	return ssh.PublicKeys(key)
}

//get a new ssh connection
func sshSession(h, p string, s *ssh.ClientConfig) (*ssh.Session, error) {

	connection, err := ssh.Dial("tcp", h+":"+p, s)

	if err != nil {
		return nil, fmt.Errorf("Failed to dial: %s", err)
	}

	session, err := connection.NewSession()
	if err != nil {
		return nil, fmt.Errorf("Failed to create session: %s", err)
	}

	return session, nil
}
<|endoftext|>


<commit_before>// Copyright © 2016 Jip J. Dekker <jip@dekker.li>
//
// 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 cmd

import (
	"fmt"

	"github.com/spf13/cobra"
)

// compileCmd represents the compile command
var compileCmd = &cobra.Command{
	Use:   "compile",
	Short: "A brief description of your command",
	Long: `A longer description that spans multiple lines and likely contains examples
and usage of using your command. For example:

Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
	Run: func(cmd *cobra.Command, args []string) {
		// TODO: Work your own magic here
		fmt.Println("compile called")
	},
}

func init() {
	RootCmd.AddCommand(compileCmd)
}
<commit_msg>Adds description to the compile command<commit_after>// Copyright © 2016 Jip J. Dekker <jip@dekker.li>
//
// 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 cmd

import (
	"fmt"

	"github.com/spf13/cobra"
)

// compileCmd represents the compile command
var compileCmd = &cobra.Command{
	Use:   "compile",
	Short: "Compiles all lilypond files in the library",
	Long: `Compile (ponder compile) will walk through and compile all
lilypond files in accordance to ponder settings file.
Files that have already been compiled will be skipped,
unless the lilypond file has been edited.`,
	Run: func(cmd *cobra.Command, args []string) {
		// TODO: Work your own magic here
		fmt.Println("compile called")
	},
}

func init() {
	RootCmd.AddCommand(compileCmd)
}
<|endoftext|>