<commit_before>// +build all unit

package gocql

import (
	"crypto/tls"
	"crypto/x509"
	"io"
	"io/ioutil"
	"net"
	"strings"
	"sync"
	"sync/atomic"
	"testing"
	"time"
)

func TestJoinHostPort(t *testing.T) {
	tests := map[string]string{
		"127.0.0.1:0":                                 JoinHostPort("127.0.0.1", 0),
		"127.0.0.1:1":                                 JoinHostPort("127.0.0.1:1", 9142),
		"[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:0": JoinHostPort("2001:0db8:85a3:0000:0000:8a2e:0370:7334", 0),
		"[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:1": JoinHostPort("[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:1", 9142),
	}
	for k, v := range tests {
		if k != v {
			t.Fatalf("expected '%v', got '%v'", k, v)
		}
	}
}

type TestServer struct {
	Address  string
	t        *testing.T
	nreq     uint64
	listen   net.Listener
	nKillReq uint64
}

func TestSimple(t *testing.T) {
	srv := NewTestServer(t)
	defer srv.Stop()

	db, err := NewCluster(srv.Address).CreateSession()
	if err != nil {
		t.Errorf("NewCluster: %v", err)
	}

	if err := db.Query("void").Exec(); err != nil {
		t.Error(err)
	}
}

func TestSSLSimple(t *testing.T) {
	srv := NewSSLTestServer(t)
	defer srv.Stop()

	db, err := createTestSslCluster(srv.Address).CreateSession()
	if err != nil {
		t.Errorf("NewCluster: %v", err)
	}

	if err := db.Query("void").Exec(); err != nil {
		t.Error(err)
	}
}

func createTestSslCluster(hosts string) *ClusterConfig {
	cluster := NewCluster(hosts)
	cluster.SslOpts = &SslOptions{
		CertPath:               "testdata/pki/gocql.crt",
		KeyPath:                "testdata/pki/gocql.key",
		CaPath:                 "testdata/pki/ca.crt",
		EnableHostVerification: false,
	}
	return cluster
}

func TestClosed(t *testing.T) {
	t.Skip("Skipping the execution of TestClosed for now to try to concentrate on more important test failures on Travis")
	srv := NewTestServer(t)
	defer srv.Stop()

	session, err := NewCluster(srv.Address).CreateSession()
	if err != nil {
		t.Errorf("NewCluster: %v", err)
	}
	session.Close()

	if err := session.Query("void").Exec(); err != ErrSessionClosed {
		t.Errorf("expected %#v, got %#v", ErrSessionClosed, err)
	}
}

func TestTimeout(t *testing.T) {
	srv := NewTestServer(t)
	defer srv.Stop()

	db, err := NewCluster(srv.Address).CreateSession()
	if err != nil {
		t.Errorf("NewCluster: %v", err)
	}

	go func() {
		<-time.After(2 * time.Second)
		t.Fatal("no timeout")
	}()

	if err := db.Query("kill").Exec(); err == nil {
		t.Fatal("expected error")
	}
}

// TestQueryRetry will test to make sure that gocql will execute
// the exact amount of retry queries designated by the user.
func TestQueryRetry(t *testing.T) {
	srv := NewTestServer(t)
	defer srv.Stop()

	db, err := NewCluster(srv.Address).CreateSession()
	if err != nil {
		t.Errorf("NewCluster: %v", err)
	}

	go func() {
		<-time.After(5 * time.Second)
		t.Fatal("no timeout")
	}()
	rt := &SimpleRetryPolicy{NumRetries: 1}

	qry := db.Query("kill").RetryPolicy(rt)
	if err := qry.Exec(); err == nil {
		t.Fatal("expected error")
	}
	requests := srv.nKillReq
	if requests != uint64(qry.Attempts()) {
		t.Fatalf("expected requests %v to match query attemps %v", requests, qry.Attempts())
	}
	//Minus 1 from the requests variable since there is the initial query attempt
	if requests-1 != uint64(rt.NumRetries) {
		t.Fatalf("failed to retry the query %v time(s). Query executed %v times", rt.NumRetries, requests-1)
	}
}

func TestSlowQuery(t *testing.T) {
	srv := NewTestServer(t)
	defer srv.Stop()

	db, err := NewCluster(srv.Address).CreateSession()
	if err != nil {
		t.Errorf("NewCluster: %v", err)
	}

	if err := db.Query("slow").Exec(); err != nil {
		t.Fatal(err)
	}
}

func TestRoundRobin(t *testing.T) {
	servers := make([]*TestServer, 5)
	addrs := make([]string, len(servers))
	for i := 0; i < len(servers); i++ {
		servers[i] = NewTestServer(t)
		addrs[i] = servers[i].Address
		defer servers[i].Stop()
	}
	cluster := NewCluster(addrs...)
	db, err := cluster.CreateSession()
	time.Sleep(1 * time.Second) //Sleep to allow the Cluster.fillPool to complete

	if err != nil {
		t.Errorf("NewCluster: %v", err)
	}

	var wg sync.WaitGroup
	wg.Add(5)
	for i := 0; i < 5; i++ {
		go func() {
			for j := 0; j < 5; j++ {
				if err := db.Query("void").Exec(); err != nil {
					t.Fatal(err)
				}
			}
			wg.Done()
		}()
	}
	wg.Wait()

	diff := 0
	for i := 1; i < len(servers); i++ {
		d := 0
		if servers[i].nreq > servers[i-1].nreq {
			d = int(servers[i].nreq - servers[i-1].nreq)
		} else {
			d = int(servers[i-1].nreq - servers[i].nreq)
		}
		if d > diff {
			diff = d
		}
	}

	if diff > 0 {
		t.Fatal("diff:", diff)
	}
}

func TestConnClosing(t *testing.T) {
	t.Skip("Skipping until test can be ran reliably")
	srv := NewTestServer(t)
	defer srv.Stop()

	db, err := NewCluster(srv.Address).CreateSession()
	if err != nil {
		t.Errorf("NewCluster: %v", err)
	}
	defer db.Close()

	numConns := db.cfg.NumConns
	count := db.cfg.NumStreams * numConns

	wg := &sync.WaitGroup{}
	wg.Add(count)
	for i := 0; i < count; i++ {
		go func(wg *sync.WaitGroup) {
			wg.Done()
			db.Query("kill").Exec()
		}(wg)
	}

	wg.Wait()

	time.Sleep(1 * time.Second) //Sleep so the fillPool can complete.
	pool := db.Pool.(ConnectionPool)
	conns := pool.Size()

	if conns != numConns {
		t.Fatalf("Expected to have %d connections but have %d", numConns, conns)
	}
}

func NewTestServer(t *testing.T) *TestServer {
	laddr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:0")
	if err != nil {
		t.Fatal(err)
	}
	listen, err := net.ListenTCP("tcp", laddr)
	if err != nil {
		t.Fatal(err)
	}
	srv := &TestServer{Address: listen.Addr().String(), listen: listen, t: t}
	go srv.serve()
	return srv
}

func NewSSLTestServer(t *testing.T) *TestServer {
	pem, err := ioutil.ReadFile("testdata/pki/ca.crt")
	certPool := x509.NewCertPool()
	if !certPool.AppendCertsFromPEM(pem) {
		t.Errorf("Failed parsing or appending certs")
	}
	mycert, err := tls.LoadX509KeyPair("testdata/pki/cassandra.crt", "testdata/pki/cassandra.key")
	if err != nil {
		t.Errorf("could not load cert")
	}
	config := &tls.Config{
		Certificates: []tls.Certificate{mycert},
		RootCAs:      certPool,
	}
	listen, err := tls.Listen("tcp", "127.0.0.1:0", config)
	if err != nil {
		t.Fatal(err)
	}
	srv := &TestServer{Address: listen.Addr().String(), listen: listen, t: t}
	go srv.serve()
	return srv
}

func (srv *TestServer) serve() {
	defer srv.listen.Close()
	for {
		conn, err := srv.listen.Accept()
		if err != nil {
			break
		}
		go func(conn net.Conn) {
			defer conn.Close()
			for {
				frame := srv.readFrame(conn)
				atomic.AddUint64(&srv.nreq, 1)
				srv.process(frame, conn)
			}
		}(conn)
	}
}

func (srv *TestServer) Stop() {
	srv.listen.Close()
}

func (srv *TestServer) process(frame frame, conn net.Conn) {
	switch frame[3] {
	case opStartup:
		frame = frame[:headerSize]
		frame.setHeader(protoResponse, 0, frame[2], opReady)
	case opQuery:
		input := frame
		input.skipHeader()
		query := strings.TrimSpace(input.readLongString())
		frame = frame[:headerSize]
		frame.setHeader(protoResponse, 0, frame[2], opResult)
		first := query
		if n := strings.Index(query, " "); n > 0 {
			first = first[:n]
		}
		switch strings.ToLower(first) {
		case "kill":
			atomic.AddUint64(&srv.nKillReq, 1)
			select {}
		case "slow":
			go func() {
				<-time.After(1 * time.Second)
				frame.writeInt(resultKindVoid)
				frame.setLength(len(frame) - headerSize)
				if _, err := conn.Write(frame); err != nil {
					return
				}
			}()
			return
		case "use":
			frame.writeInt(3)
			frame.writeString(strings.TrimSpace(query[3:]))
		case "void":
			frame.writeInt(resultKindVoid)
		default:
			frame.writeInt(resultKindVoid)
		}
	default:
		frame = frame[:headerSize]
		frame.setHeader(protoResponse, 0, frame[2], opError)
		frame.writeInt(0)
		frame.writeString("not supported")
	}
	frame.setLength(len(frame) - headerSize)
	if _, err := conn.Write(frame); err != nil {
		return
	}
}

func (srv *TestServer) readFrame(conn net.Conn) frame {
	frame := make(frame, headerSize, headerSize+512)
	if _, err := io.ReadFull(conn, frame); err != nil {
		srv.t.Fatal(err)
	}
	if n := frame.Length(); n > 0 {
		frame.grow(n)
		if _, err := io.ReadFull(conn, frame[headerSize:]); err != nil {
			srv.t.Fatal(err)
		}
	}
	return frame
}
<commit_msg>Update tests to support multiple protocol versions<commit_after>// +build all unit

package gocql

import (
	"crypto/tls"
	"crypto/x509"
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"strings"
	"sync"
	"sync/atomic"
	"testing"
	"time"
)

const (
	defaultProto = protoVersion2
)

func TestJoinHostPort(t *testing.T) {
	tests := map[string]string{
		"127.0.0.1:0":                                 JoinHostPort("127.0.0.1", 0),
		"127.0.0.1:1":                                 JoinHostPort("127.0.0.1:1", 9142),
		"[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:0": JoinHostPort("2001:0db8:85a3:0000:0000:8a2e:0370:7334", 0),
		"[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:1": JoinHostPort("[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:1", 9142),
	}
	for k, v := range tests {
		if k != v {
			t.Fatalf("expected '%v', got '%v'", k, v)
		}
	}
}

func TestSimple(t *testing.T) {
	srv := NewTestServer(t, defaultProto)
	defer srv.Stop()

	cluster := NewCluster(srv.Address)
	cluster.ProtoVersion = int(defaultProto)
	db, err := cluster.CreateSession()
	if err != nil {
		t.Errorf("0x%x: NewCluster: %v", defaultProto, err)
		return
	}

	if err := db.Query("void").Exec(); err != nil {
		t.Errorf("0x%x: %v", defaultProto, err)
	}
}

func TestSSLSimple(t *testing.T) {
	srv := NewSSLTestServer(t, defaultProto)
	defer srv.Stop()

	db, err := createTestSslCluster(srv.Address, defaultProto).CreateSession()
	if err != nil {
		t.Fatalf("0x%x: NewCluster: %v", defaultProto, err)
	}

	if err := db.Query("void").Exec(); err != nil {
		t.Fatalf("0x%x: %v", defaultProto, err)
	}
}

func createTestSslCluster(hosts string, proto uint8) *ClusterConfig {
	cluster := NewCluster(hosts)
	cluster.SslOpts = &SslOptions{
		CertPath:               "testdata/pki/gocql.crt",
		KeyPath:                "testdata/pki/gocql.key",
		CaPath:                 "testdata/pki/ca.crt",
		EnableHostVerification: false,
	}
	cluster.ProtoVersion = int(proto)
	return cluster
}

func TestClosed(t *testing.T) {
	t.Skip("Skipping the execution of TestClosed for now to try to concentrate on more important test failures on Travis")

	srv := NewTestServer(t, defaultProto)
	defer srv.Stop()

	cluster := NewCluster(srv.Address)
	cluster.ProtoVersion = int(defaultProto)

	session, err := cluster.CreateSession()
	defer session.Close()
	if err != nil {
		t.Errorf("0x%x: NewCluster: %v", defaultProto, err)
		return
	}

	if err := session.Query("void").Exec(); err != ErrSessionClosed {
		t.Errorf("0x%x: expected %#v, got %#v", defaultProto, ErrSessionClosed, err)
		return
	}
}

func newTestSession(addr string, proto uint8) (*Session, error) {
	cluster := NewCluster(addr)
	cluster.ProtoVersion = int(proto)
	return cluster.CreateSession()
}

func TestTimeout(t *testing.T) {

	srv := NewTestServer(t, defaultProto)
	defer srv.Stop()

	db, err := newTestSession(srv.Address, defaultProto)
	if err != nil {
		t.Errorf("NewCluster: %v", err)
		return
	}
	defer db.Close()

	go func() {
		<-time.After(2 * time.Second)
		t.Errorf("no timeout")
	}()

	if err := db.Query("kill").Exec(); err == nil {
		t.Errorf("expected error")
	}
}

// TestQueryRetry will test to make sure that gocql will execute
// the exact amount of retry queries designated by the user.
func TestQueryRetry(t *testing.T) {
	srv := NewTestServer(t, defaultProto)
	defer srv.Stop()

	db, err := newTestSession(srv.Address, defaultProto)
	if err != nil {
		t.Fatalf("NewCluster: %v", err)
	}
	defer db.Close()

	go func() {
		<-time.After(5 * time.Second)
		t.Fatalf("no timeout")
	}()
	rt := &SimpleRetryPolicy{NumRetries: 1}

	qry := db.Query("kill").RetryPolicy(rt)
	if err := qry.Exec(); err == nil {
		t.Fatalf("expected error")
	}

	requests := atomic.LoadInt64(&srv.nKillReq)
	attempts := qry.Attempts()
	if requests != int64(attempts) {
		t.Fatalf("expected requests %v to match query attemps %v", requests, attempts)
	}

	//Minus 1 from the requests variable since there is the initial query attempt
	if requests-1 != int64(rt.NumRetries) {
		t.Fatalf("failed to retry the query %v time(s). Query executed %v times", rt.NumRetries, requests-1)
	}
}

func TestSlowQuery(t *testing.T) {
	srv := NewTestServer(t, defaultProto)
	defer srv.Stop()

	db, err := newTestSession(srv.Address, defaultProto)
	if err != nil {
		t.Errorf("NewCluster: %v", err)
		return
	}

	if err := db.Query("slow").Exec(); err != nil {
		t.Fatal(err)
	}
}

func TestRoundRobin(t *testing.T) {
	servers := make([]*TestServer, 5)
	addrs := make([]string, len(servers))
	for n := 0; n < len(servers); n++ {
		servers[n] = NewTestServer(t, defaultProto)
		addrs[n] = servers[n].Address
		defer servers[n].Stop()
	}
	cluster := NewCluster(addrs...)
	cluster.ProtoVersion = defaultProto

	db, err := cluster.CreateSession()
	time.Sleep(1 * time.Second) // Sleep to allow the Cluster.fillPool to complete

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

	var wg sync.WaitGroup
	wg.Add(5)
	for n := 0; n < 5; n++ {
		go func() {
			for j := 0; j < 5; j++ {
				if err := db.Query("void").Exec(); err != nil {
					t.Fatal(err)
				}
			}
			wg.Done()
		}()
	}
	wg.Wait()

	diff := 0
	for n := 1; n < len(servers); n++ {
		d := 0
		if servers[n].nreq > servers[n-1].nreq {
			d = int(servers[n].nreq - servers[n-1].nreq)
		} else {
			d = int(servers[n-1].nreq - servers[n].nreq)
		}
		if d > diff {
			diff = d
		}
	}

	if diff > 0 {
		t.Fatal("diff:", diff)
	}
}

func TestConnClosing(t *testing.T) {
	t.Skip("Skipping until test can be ran reliably")

	srv := NewTestServer(t, protoVersion2)
	defer srv.Stop()

	db, err := NewCluster(srv.Address).CreateSession()
	if err != nil {
		t.Errorf("NewCluster: %v", err)
	}
	defer db.Close()

	numConns := db.cfg.NumConns
	count := db.cfg.NumStreams * numConns

	wg := &sync.WaitGroup{}
	wg.Add(count)
	for i := 0; i < count; i++ {
		go func(wg *sync.WaitGroup) {
			wg.Done()
			db.Query("kill").Exec()
		}(wg)
	}

	wg.Wait()

	time.Sleep(1 * time.Second) //Sleep so the fillPool can complete.
	pool := db.Pool.(ConnectionPool)
	conns := pool.Size()

	if conns != numConns {
		t.Fatalf("Expected to have %d connections but have %d", numConns, conns)
	}
}

func TestStreams_Protocol1(t *testing.T) {
	srv := NewTestServer(t, protoVersion1)
	defer srv.Stop()

	// TODO: these are more like session tests and should instead operate
	// on a single Conn
	cluster := NewCluster(srv.Address)
	cluster.NumConns = 1
	cluster.ProtoVersion = 1

	db, err := cluster.CreateSession()
	if err != nil {
		t.Fatal(err)
	}
	defer db.Close()

	var wg sync.WaitGroup
	for i := 0; i < db.cfg.NumStreams; i++ {
		// here were just validating that if we send NumStream request we get
		// a response for every stream and the lengths for the queries are set
		// correctly.
		wg.Add(1)
		go func() {
			defer wg.Done()
			if err := db.Query("void").Exec(); err != nil {
				t.Error(err)
			}
		}()
	}
	wg.Wait()
}

func TestStreams_Protocol2(t *testing.T) {
	srv := NewTestServer(t, protoVersion2)
	defer srv.Stop()

	// TODO: these are more like session tests and should instead operate
	// on a single Conn
	cluster := NewCluster(srv.Address)
	cluster.NumConns = 1
	cluster.ProtoVersion = 2

	db, err := cluster.CreateSession()
	if err != nil {
		t.Fatal(err)
	}
	defer db.Close()

	for i := 0; i < db.cfg.NumStreams; i++ {
		// the test server processes each conn synchronously
		// here were just validating that if we send NumStream request we get
		// a response for every stream and the lengths for the queries are set
		// correctly.
		if err = db.Query("void").Exec(); err != nil {
			t.Fatal(err)
		}
	}
}

func TestStreams_Protocol3(t *testing.T) {
	srv := NewTestServer(t, protoVersion3)
	defer srv.Stop()

	// TODO: these are more like session tests and should instead operate
	// on a single Conn
	cluster := NewCluster(srv.Address)
	cluster.NumConns = 1
	cluster.ProtoVersion = 3

	db, err := cluster.CreateSession()
	if err != nil {
		t.Fatal(err)
	}
	defer db.Close()

	for i := 0; i < db.cfg.NumStreams; i++ {
		// the test server processes each conn synchronously
		// here were just validating that if we send NumStream request we get
		// a response for every stream and the lengths for the queries are set
		// correctly.
		if err = db.Query("void").Exec(); err != nil {
			t.Fatal(err)
		}
	}
}

func BenchmarkProtocolV3(b *testing.B) {
	srv := NewTestServer(b, protoVersion3)
	defer srv.Stop()

	// TODO: these are more like session tests and should instead operate
	// on a single Conn
	cluster := NewCluster(srv.Address)
	cluster.NumConns = 1
	cluster.ProtoVersion = 3

	db, err := cluster.CreateSession()
	if err != nil {
		b.Fatal(err)
	}
	defer db.Close()

	b.ResetTimer()
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		if err = db.Query("void").Exec(); err != nil {
			b.Fatal(err)
		}
	}
}

func NewTestServer(t testing.TB, protocol uint8) *TestServer {
	laddr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:0")
	if err != nil {
		t.Fatal(err)
	}

	listen, err := net.ListenTCP("tcp", laddr)
	if err != nil {
		t.Fatal(err)
	}

	headerSize := 8
	if protocol > protoVersion2 {
		headerSize = 9
	}

	srv := &TestServer{
		Address:    listen.Addr().String(),
		listen:     listen,
		t:          t,
		protocol:   protocol,
		headerSize: headerSize,
	}

	go srv.serve()

	return srv
}

func NewSSLTestServer(t testing.TB, protocol uint8) *TestServer {
	pem, err := ioutil.ReadFile("testdata/pki/ca.crt")
	certPool := x509.NewCertPool()
	if !certPool.AppendCertsFromPEM(pem) {
		t.Errorf("Failed parsing or appending certs")
	}
	mycert, err := tls.LoadX509KeyPair("testdata/pki/cassandra.crt", "testdata/pki/cassandra.key")
	if err != nil {
		t.Errorf("could not load cert")
	}
	config := &tls.Config{
		Certificates: []tls.Certificate{mycert},
		RootCAs:      certPool,
	}
	listen, err := tls.Listen("tcp", "127.0.0.1:0", config)
	if err != nil {
		t.Fatal(err)
	}

	headerSize := 8
	if protocol > protoVersion2 {
		headerSize = 9
	}

	srv := &TestServer{
		Address:    listen.Addr().String(),
		listen:     listen,
		t:          t,
		protocol:   protocol,
		headerSize: headerSize,
	}
	go srv.serve()
	return srv
}

type TestServer struct {
	Address  string
	t        testing.TB
	nreq     uint64
	listen   net.Listener
	nKillReq int64

	protocol   uint8
	headerSize int
}

func (srv *TestServer) serve() {
	defer srv.listen.Close()
	for {
		conn, err := srv.listen.Accept()
		if err != nil {
			break
		}
		go func(conn net.Conn) {
			defer conn.Close()
			for {
				frame := srv.readFrame(conn)
				atomic.AddUint64(&srv.nreq, 1)
				srv.process(frame, conn)
			}
		}(conn)
	}
}

func (srv *TestServer) Stop() {
	srv.listen.Close()
}

func (srv *TestServer) process(f frame, conn net.Conn) {
	headerSize := headerProtoSize[srv.protocol]
	stream := f.Stream(srv.protocol)

	switch f.Op(srv.protocol) {
	case opStartup:
		f = f[:headerSize]
		f.setHeader(protoDirectionMask|srv.protocol, 0, stream, opReady)
	case opOptions:
		f = f[:headerSize]
		f.setHeader(protoDirectionMask|srv.protocol, 0, stream, opSupported)
		f.writeShort(0)
	case opQuery:
		input := f
		input.skipHeader(srv.protocol)
		query := strings.TrimSpace(input.readLongString())
		f = f[:headerSize]
		f.setHeader(protoDirectionMask|srv.protocol, 0, stream, opResult)
		first := query
		if n := strings.Index(query, " "); n > 0 {
			first = first[:n]
		}
		switch strings.ToLower(first) {
		case "kill":
			atomic.AddInt64(&srv.nKillReq, 1)
			f = f[:headerSize]
			f.setHeader(protoDirectionMask|srv.protocol, 0, stream, opError)
			f.writeInt(0x1001)
			f.writeString("query killed")
		case "slow":
			go func() {
				<-time.After(1 * time.Second)
				f.writeInt(resultKindVoid)
				f.setLength(len(f)-headerSize, srv.protocol)
				if _, err := conn.Write(f); err != nil {
					return
				}
			}()
			return
		case "use":
			f.writeInt(3)
			f.writeString(strings.TrimSpace(query[3:]))
		case "void":
			f.writeInt(resultKindVoid)
		default:
			f.writeInt(resultKindVoid)
		}
	default:
		f = f[:headerSize]
		f.setHeader(protoDirectionMask|srv.protocol, 0, stream, opError)
		f.writeInt(0)
		f.writeString("not supported")
	}

	f.setLength(len(f)-headerSize, srv.protocol)
	if _, err := conn.Write(f); err != nil {
		srv.t.Log(err)
		return
	}
}

func (srv *TestServer) readFrame(conn net.Conn) frame {
	frame := make(frame, headerSize, headerSize+512)
	if _, err := io.ReadFull(conn, frame); err != nil {
		srv.t.Fatal(err)
	}
	if n := frame.Length(); n > 0 {
		frame.grow(n)
		if _, err := io.ReadFull(conn, frame[headerSize:]); err != nil {
			srv.t.Fatal(err)
		}
	}
	return frame
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Uber Technologies, 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 jaeger

import (
	"fmt"

	"github.com/opentracing/opentracing-go"
)

const (
	// JaegerClientVersion is the version of the client library reported as Span tag.
	JaegerClientVersion = "Go-2.29.1"

	// JaegerClientVersionTagKey is the name of the tag used to report client version.
	JaegerClientVersionTagKey = "jaeger.version"

	// JaegerDebugHeader is the name of HTTP header or a TextMap carrier key which,
	// if found in the carrier, forces the trace to be sampled as "debug" trace.
	// The value of the header is recorded as the tag on the root span, so that the
	// trace can be found in the UI using this value as a correlation ID.
	JaegerDebugHeader = "jaeger-debug-id"

	// JaegerBaggageHeader is the name of the HTTP header that is used to submit baggage.
	// It differs from TraceBaggageHeaderPrefix in that it can be used only in cases where
	// a root span does not exist.
	JaegerBaggageHeader = "jaeger-baggage"

	// TracerHostnameTagKey used to report host name of the process.
	TracerHostnameTagKey = "hostname"

	// TracerIPTagKey used to report ip of the process.
	TracerIPTagKey = "ip"

	// TracerUUIDTagKey used to report UUID of the client process.
	TracerUUIDTagKey = "client-uuid"

	// SamplerTypeTagKey reports which sampler was used on the root span.
	SamplerTypeTagKey = "sampler.type"

	// SamplerParamTagKey reports the parameter of the sampler, like sampling probability.
	SamplerParamTagKey = "sampler.param"

	// TraceContextHeaderName is the http header name used to propagate tracing context.
	// This must be in lower-case to avoid mismatches when decoding incoming headers.
	TraceContextHeaderName = "uber-trace-id"

	// TracerStateHeaderName is deprecated.
	// Deprecated: use TraceContextHeaderName
	TracerStateHeaderName = TraceContextHeaderName

	// TraceBaggageHeaderPrefix is the prefix for http headers used to propagate baggage.
	// This must be in lower-case to avoid mismatches when decoding incoming headers.
	TraceBaggageHeaderPrefix = "uberctx-"

	// SamplerTypeConst is the type of sampler that always makes the same decision.
	SamplerTypeConst = "const"

	// SamplerTypeRemote is the type of sampler that polls Jaeger agent for sampling strategy.
	SamplerTypeRemote = "remote"

	// SamplerTypeProbabilistic is the type of sampler that samples traces
	// with a certain fixed probability.
	SamplerTypeProbabilistic = "probabilistic"

	// SamplerTypeRateLimiting is the type of sampler that samples
	// only up to a fixed number of traces per second.
	SamplerTypeRateLimiting = "ratelimiting"

	// SamplerTypeLowerBound is the type of sampler that samples
	// at least a fixed number of traces per second.
	SamplerTypeLowerBound = "lowerbound"

	// DefaultUDPSpanServerHost is the default host to send the spans to, via UDP
	DefaultUDPSpanServerHost = "localhost"

	// DefaultUDPSpanServerPort is the default port to send the spans to, via UDP
	DefaultUDPSpanServerPort = 6831

	// DefaultSamplingServerPort is the default port to fetch sampling config from, via http
	DefaultSamplingServerPort = 5778

	// DefaultMaxTagValueLength is the default max length of byte array or string allowed in the tag value.
	DefaultMaxTagValueLength = 256

	// SelfRefType is a jaeger specific reference type that supports creating a span
	// with an already defined context.
	selfRefType opentracing.SpanReferenceType = 99
)

var (
	// DefaultSamplingServerURL is the default url to fetch sampling config from, via http
	DefaultSamplingServerURL = fmt.Sprintf("http://127.0.0.1:%d/sampling", DefaultSamplingServerPort)
)
<commit_msg>Back to development<commit_after>// Copyright (c) 2017 Uber Technologies, 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 jaeger

import (
	"fmt"

	"github.com/opentracing/opentracing-go"
)

const (
	// JaegerClientVersion is the version of the client library reported as Span tag.
	JaegerClientVersion = "Go-2.29.2-dev"

	// JaegerClientVersionTagKey is the name of the tag used to report client version.
	JaegerClientVersionTagKey = "jaeger.version"

	// JaegerDebugHeader is the name of HTTP header or a TextMap carrier key which,
	// if found in the carrier, forces the trace to be sampled as "debug" trace.
	// The value of the header is recorded as the tag on the root span, so that the
	// trace can be found in the UI using this value as a correlation ID.
	JaegerDebugHeader = "jaeger-debug-id"

	// JaegerBaggageHeader is the name of the HTTP header that is used to submit baggage.
	// It differs from TraceBaggageHeaderPrefix in that it can be used only in cases where
	// a root span does not exist.
	JaegerBaggageHeader = "jaeger-baggage"

	// TracerHostnameTagKey used to report host name of the process.
	TracerHostnameTagKey = "hostname"

	// TracerIPTagKey used to report ip of the process.
	TracerIPTagKey = "ip"

	// TracerUUIDTagKey used to report UUID of the client process.
	TracerUUIDTagKey = "client-uuid"

	// SamplerTypeTagKey reports which sampler was used on the root span.
	SamplerTypeTagKey = "sampler.type"

	// SamplerParamTagKey reports the parameter of the sampler, like sampling probability.
	SamplerParamTagKey = "sampler.param"

	// TraceContextHeaderName is the http header name used to propagate tracing context.
	// This must be in lower-case to avoid mismatches when decoding incoming headers.
	TraceContextHeaderName = "uber-trace-id"

	// TracerStateHeaderName is deprecated.
	// Deprecated: use TraceContextHeaderName
	TracerStateHeaderName = TraceContextHeaderName

	// TraceBaggageHeaderPrefix is the prefix for http headers used to propagate baggage.
	// This must be in lower-case to avoid mismatches when decoding incoming headers.
	TraceBaggageHeaderPrefix = "uberctx-"

	// SamplerTypeConst is the type of sampler that always makes the same decision.
	SamplerTypeConst = "const"

	// SamplerTypeRemote is the type of sampler that polls Jaeger agent for sampling strategy.
	SamplerTypeRemote = "remote"

	// SamplerTypeProbabilistic is the type of sampler that samples traces
	// with a certain fixed probability.
	SamplerTypeProbabilistic = "probabilistic"

	// SamplerTypeRateLimiting is the type of sampler that samples
	// only up to a fixed number of traces per second.
	SamplerTypeRateLimiting = "ratelimiting"

	// SamplerTypeLowerBound is the type of sampler that samples
	// at least a fixed number of traces per second.
	SamplerTypeLowerBound = "lowerbound"

	// DefaultUDPSpanServerHost is the default host to send the spans to, via UDP
	DefaultUDPSpanServerHost = "localhost"

	// DefaultUDPSpanServerPort is the default port to send the spans to, via UDP
	DefaultUDPSpanServerPort = 6831

	// DefaultSamplingServerPort is the default port to fetch sampling config from, via http
	DefaultSamplingServerPort = 5778

	// DefaultMaxTagValueLength is the default max length of byte array or string allowed in the tag value.
	DefaultMaxTagValueLength = 256

	// SelfRefType is a jaeger specific reference type that supports creating a span
	// with an already defined context.
	selfRefType opentracing.SpanReferenceType = 99
)

var (
	// DefaultSamplingServerURL is the default url to fetch sampling config from, via http
	DefaultSamplingServerURL = fmt.Sprintf("http://127.0.0.1:%d/sampling", DefaultSamplingServerPort)
)
<|endoftext|>


<commit_before>// Copyright 2014-2015 The DevMine authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// srctool is a command line tool to manage source code parsers. It is able to
// download parsers from a web server, install them and run them. In short, it is a
// manager for source code parsers.
package main

import (
	"fmt"
	"os"

	"github.com/codegangsta/cli"

	"github.com/DevMine/srctool/cmd"
	"github.com/DevMine/srctool/log"
)

func main() {
	app := cli.NewApp()
	app.Name = "srctool"
	app.Usage = "tool for parsing source code"
	app.Version = "1.0.0"
	app.Author = "The DevMine authors"
	app.Email = "contact@devmine.ch"
	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:  "d",
			Usage: "enable debug mode",
		},
	}
	app.Commands = []cli.Command{
		{
			Name:      "install",
			ShortName: "i",
			Usage:     "install one or all language parser(s)",
			Action: func(c *cli.Context) {
				log.SetDebugMode(c.GlobalBool("d"))
				cmd.Install(c)
			},
		},
		{
			Name:      "delete",
			ShortName: "d",
			Usage:     "delete one or all language parser(s)",
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "dry",
					Usage: "dry mode",
				},
			},
			Action: func(c *cli.Context) {
				log.SetDebugMode(c.GlobalBool("d"))
				cmd.Delete(c)
			},
		},
		{
			Name:      "update",
			ShortName: "u",
			Usage:     "update one or all language parser(s)",
			Action: func(c *cli.Context) {
				log.SetDebugMode(c.GlobalBool("d"))
				cmd.Update(c)
			},
		},
		{
			Name:      "list",
			ShortName: "l",
			Usage:     "list all installed parsers",
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "r",
					Usage: "list remote available parsers",
				},
			},
			Action: func(c *cli.Context) {
				log.SetDebugMode(c.GlobalBool("d"))
				cmd.List(c)
			},
		},
		{
			Name:      "parse",
			ShortName: "p",
			Usage:     "parse a project",
			Action: func(c *cli.Context) {
				log.SetDebugMode(c.GlobalBool("d"))
				cmd.Parse(c)
			},
		},
		{
			Name:      "config",
			ShortName: "c",
			Usage:     "create config file",
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "server-url",
					Usage: "get/set the download server URL",
				},
			},
			Action: func(c *cli.Context) {
				log.SetDebugMode(c.GlobalBool("d"))
				cmd.Config(c)
			},
		},
		{
			Name:      "version",
			ShortName: "v",
			Usage:     "print program version",
			Action: func(c *cli.Context) {
				fmt.Printf("%s - v%s\n", app.Name, app.Version)
			},
		},
	}

	app.Run(os.Args)
}
<commit_msg>cmd/list: fix doc string<commit_after>// Copyright 2014-2015 The DevMine authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// srctool is a command line tool to manage source code parsers. It is able to
// download parsers from a web server, install them and run them. In short, it is a
// manager for source code parsers.
package main

import (
	"fmt"
	"os"

	"github.com/codegangsta/cli"

	"github.com/DevMine/srctool/cmd"
	"github.com/DevMine/srctool/log"
)

func main() {
	app := cli.NewApp()
	app.Name = "srctool"
	app.Usage = "tool for parsing source code"
	app.Version = "1.0.0"
	app.Author = "The DevMine authors"
	app.Email = "contact@devmine.ch"
	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:  "d",
			Usage: "enable debug mode",
		},
	}
	app.Commands = []cli.Command{
		{
			Name:      "install",
			ShortName: "i",
			Usage:     "install one or all language parser(s)",
			Action: func(c *cli.Context) {
				log.SetDebugMode(c.GlobalBool("d"))
				cmd.Install(c)
			},
		},
		{
			Name:      "delete",
			ShortName: "d",
			Usage:     "delete one or all language parser(s)",
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "dry",
					Usage: "dry mode",
				},
			},
			Action: func(c *cli.Context) {
				log.SetDebugMode(c.GlobalBool("d"))
				cmd.Delete(c)
			},
		},
		{
			Name:      "update",
			ShortName: "u",
			Usage:     "update one or all language parser(s)",
			Action: func(c *cli.Context) {
				log.SetDebugMode(c.GlobalBool("d"))
				cmd.Update(c)
			},
		},
		{
			Name:      "list",
			ShortName: "l",
			Usage:     "list installed or available parsers",
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "r",
					Usage: "list remote parsers",
				},
			},
			Action: func(c *cli.Context) {
				log.SetDebugMode(c.GlobalBool("d"))
				cmd.List(c)
			},
		},
		{
			Name:      "parse",
			ShortName: "p",
			Usage:     "parse a project",
			Action: func(c *cli.Context) {
				log.SetDebugMode(c.GlobalBool("d"))
				cmd.Parse(c)
			},
		},
		{
			Name:      "config",
			ShortName: "c",
			Usage:     "create config file",
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "server-url",
					Usage: "get/set the download server URL",
				},
			},
			Action: func(c *cli.Context) {
				log.SetDebugMode(c.GlobalBool("d"))
				cmd.Config(c)
			},
		},
		{
			Name:      "version",
			ShortName: "v",
			Usage:     "print program version",
			Action: func(c *cli.Context) {
				fmt.Printf("%s - v%s\n", app.Name, app.Version)
			},
		},
	}

	app.Run(os.Args)
}
<|endoftext|>


<commit_before>package ssh

import (
	"fmt"
	"regexp"
	"strings"
	"time"

	"github.com/blacknon/lssh/conf"
	"github.com/shavac/gexpect"
)

// OS ssh command Rapper
func ConnectSsh(connectServer string, confList conf.Config) {
	// Get ssh config value
	connectUser := confList.Server[connectServer].User
	connectAddr := confList.Server[connectServer].Addr
	var connectPort string
	if confList.Server[connectServer].Port == "" {
		connectPort = "22"
	} else {
		connectPort = confList.Server[connectServer].Port
	}
	connectPass := confList.Server[connectServer].Pass
	connectKey := confList.Server[connectServer].Key
	connectHost := connectUser + "@" + connectAddr

	// ssh command Args
	connectArgStr := ""
	if connectKey != "" {
		connectArgStr = "-i " + connectKey + " " + connectHost + " -p " + connectPort
	} else {
		connectArgStr = connectHost + " -p " + connectPort
	}
	connectArgMap := strings.Split(connectArgStr, " ")

	// exec ssh command
	child, _ := gexpect.NewSubProcess("/usr/bin/ssh", connectArgMap...)
	if err := child.Start(); err != nil {
		fmt.Println(err)
	}
	defer child.Close()

	// Password Input
	if connectPass != "" {
		if idx, _ := child.ExpectTimeout(20*time.Second, regexp.MustCompile("word:")); idx >= 0 {
			child.SendLine(connectPass)
		}
	}

	// timeout
	child.InteractTimeout(86400 * time.Second)
}
<commit_msg>script command test<commit_after>package ssh

import (
	"fmt"
	"regexp"
	"time"

	"github.com/blacknon/lssh/conf"
	"github.com/shavac/gexpect"
)

// OS ssh command Rapper
func ConnectSsh(connectServer string, confList conf.Config) {
	// Get ssh config value
	connectUser := confList.Server[connectServer].User
	connectAddr := confList.Server[connectServer].Addr
	var connectPort string
	if confList.Server[connectServer].Port == "" {
		connectPort = "22"
	} else {
		connectPort = confList.Server[connectServer].Port
	}
	connectPass := confList.Server[connectServer].Pass
	connectKey := confList.Server[connectServer].Key
	connectHost := connectUser + "@" + connectAddr

	// ssh command Args
	connectCmd := ""
	//connectArgStr := ""
	if connectKey != "" {
		//connectArgStr = "/usr/bin/ssh" + "-i " + connectKey + " " + connectHost + " -p " + connectPort
		connectCmd = "/usr/bin/ssh -i " + connectKey + " " + connectHost + " -p " + connectPort
	} else {
		//connectArgStr = "/usr/bin/ssh" + connectHost + " -p " + connectPort
		connectCmd = "/usr/bin/ssh " + connectHost + " -p " + connectPort
	}
	fmt.Println(connectCmd)
	//connectArgMap := strings.Split(connectArgStr, " ")

	// exec ssh command
	//child, _ := gexpect.NewSubProcess("/usr/bin/ssh", connectArgMap...)
	//child, _ := gexpect.NewSubProcess("/bin/bash", "-c", connectCmd)
	child, _ := gexpect.NewSubProcess("/usr/bin/script", "-c", connectCmd)

	if err := child.Start(); err != nil {
		fmt.Println(err)
	}
	defer child.Close()

	// Password Input
	if connectPass != "" {
		if idx, _ := child.ExpectTimeout(20*time.Second, regexp.MustCompile("word:")); idx >= 0 {
			child.SendLine(connectPass)
		}
	}

	// timeout
	child.InteractTimeout(86400 * time.Second)
}
<|endoftext|>


<commit_before>/**
 * Copyright 2015 @ z3q.net.
 * name : types.go
 * author : jarryliu
 * date : -- :
 * description :
 * history :
 */
package core

import (
	"encoding/gob"
	"github.com/jsix/goex/report"
	"github.com/jsix/gof/db"
	"go2o/core/dao/model"
	"go2o/core/domain/interface/ad"
	"go2o/core/domain/interface/after-sales"
	"go2o/core/domain/interface/cart"
	"go2o/core/domain/interface/content"
	"go2o/core/domain/interface/delivery"
	"go2o/core/domain/interface/express"
	"go2o/core/domain/interface/item"
	"go2o/core/domain/interface/member"
	"go2o/core/domain/interface/merchant"
	"go2o/core/domain/interface/merchant/shop"
	"go2o/core/domain/interface/merchant/user"
	"go2o/core/domain/interface/merchant/wholesaler"
	"go2o/core/domain/interface/mss"
	"go2o/core/domain/interface/order"
	"go2o/core/domain/interface/payment"
	"go2o/core/domain/interface/personfinance"
	"go2o/core/domain/interface/pro_model"
	"go2o/core/domain/interface/product"
	"go2o/core/domain/interface/promotion"
	"go2o/core/domain/interface/shipment"
	"go2o/core/domain/interface/valueobject"
	"go2o/core/domain/interface/wallet"
	"go2o/core/dto"
	"go2o/core/variable"
	"go2o/gen-code/thrift/define"
	"strings"
)

func init() {
	registerTypes()
}

// 注册序列类型
func registerTypes() {
	gob.Register(&member.Member{})
	gob.Register(&merchant.Merchant{})
	gob.Register(&merchant.ApiInfo{})
	gob.Register(&shop.OnlineShop{})
	gob.Register(&shop.OfflineShop{})
	gob.Register(&shop.ComplexShop{})
	gob.Register(&member.Account{})
	gob.Register(&payment.PaymentOrder{})
	gob.Register(&member.Relation{})
	gob.Register(&dto.ListOnlineShop{})
	gob.Register([]*dto.ListOnlineShop{})
	gob.Register(&define.Member{})
	gob.Register(&define.Profile{})
}

func Init(a *AppImpl, debug, trace bool) bool {
	a._debugMode = debug
	if trace {
		a.Db().GetOrm().SetTrace(a._debugMode)
	}
	if debug {
		report.WATCH_CONF_FILE = true
	}
	OrmMapping(a.Db())
	// 初始化变量
	variable.Domain = a._config.GetString(variable.ServerDomain)
	confPath := strings.TrimSpace(a._config.GetString("conf_path"))
	if len(confPath) > 0 {
		variable.ConfPath = confPath
	}
	a.Loaded = true
	return true
}

func OrmMapping(conn db.Connector) {
	//table mapping
	orm := conn.GetOrm()
	orm.Mapping(valueobject.Area{}, "china_area")
	/* ad */
	orm.Mapping(ad.Ad{}, "ad_list")
	orm.Mapping(ad.Image{}, "ad_image")
	orm.Mapping(ad.HyperLink{}, "ad_hyperlink")
	orm.Mapping(ad.AdGroup{}, "ad_group")
	orm.Mapping(ad.AdPosition{}, "ad_position")
	orm.Mapping(ad.AdUserSet{}, "ad_userset")

	/* MSS */
	orm.Mapping(mss.Message{}, "msg_list")
	orm.Mapping(mss.To{}, "msg_to")
	orm.Mapping(mss.Content{}, "msg_content")
	orm.Mapping(mss.Replay{}, "msg_replay")

	/* 内容 */
	orm.Mapping(content.Page{}, "ex_page")
	orm.Mapping(content.Article{}, "article_list")
	orm.Mapping(content.ArticleCategory{}, "article_category")

	/** new **/
	orm.Mapping(member.Level{}, "mm_level")
	orm.Mapping(member.Member{}, "mm_member")
	orm.Mapping(member.Profile{}, "mm_profile")
	orm.Mapping(member.IntegralLog{}, "mm_integral_log")
	orm.Mapping(member.BalanceLog{}, "mm_balance_log")
	orm.Mapping(member.MWalletLog{}, "mm_wallet_log")
	orm.Mapping(member.Account{}, "mm_account")
	orm.Mapping(member.Address{}, "mm_deliver_addr")
	orm.Mapping(member.Relation{}, "mm_relation")
	orm.Mapping(member.BalanceInfo{}, "mm_balance_info")
	orm.Mapping(member.TrustedInfo{}, "mm_trusted_info")
	orm.Mapping(member.Favorite{}, "mm_favorite")
	orm.Mapping(member.BankInfo{}, "mm_bank")
	orm.Mapping(member.LevelUpLog{}, "mm_levelup")
	orm.Mapping(member.BuyerGroup{}, "mm_buyer_group")

	//** ORDER **//

	orm.Mapping(order.NormalOrder{}, "sale_order")
	orm.Mapping(order.NormalSubOrder{}, "sale_sub_order")

	orm.Mapping(order.SubOrderItem{}, "sale_order_item")
	orm.Mapping(order.OrderCoupon{}, "pt_order_coupon")
	orm.Mapping(order.OrderPromotionBind{}, "pt_order_pb")
	orm.Mapping(order.OrderLog{}, "sale_order_log")
	orm.Mapping(cart.RetailCart{}, "sale_cart")
	orm.Mapping(cart.RetailCartItem{}, "sale_cart_item")
	orm.Mapping(order.Order{}, "order_list")
	orm.Mapping(order.WholesaleOrder{}, "order_wholesale_order")
	orm.Mapping(order.WholesaleItem{}, "order_wholesale_item")
	orm.Mapping(order.TradeOrder{}, "order_trade_order")

	//** After Sales **/
	orm.Mapping(afterSales.AfterSalesOrder{}, "sale_after_order")
	orm.Mapping(afterSales.ReturnOrder{}, "sale_return")
	orm.Mapping(afterSales.ExchangeOrder{}, "sale_exchange")
	orm.Mapping(afterSales.RefundOrder{}, "sale_refund")

	//** Express **//
	orm.Mapping(express.ExpressProvider{}, "express_provider")
	orm.Mapping(express.ExpressTemplate{}, "express_template")
	orm.Mapping(express.ExpressAreaTemplate{}, "express_area_set")

	//** Shipment **/
	orm.Mapping(shipment.ShipmentOrder{}, "ship_order")
	orm.Mapping(shipment.Item{}, "ship_item")

	/** 产品 **/
	orm.Mapping(product.Product{}, "pro_product")
	orm.Mapping(item.GoodsItem{}, "item_info")
	orm.Mapping(item.Sku{}, "item_sku")
	orm.Mapping(product.Category{}, "pro_category")
	orm.Mapping(promodel.ProModel{}, "pro_model")
	orm.Mapping(promodel.ProModelBrand{}, "pro_model_brand")
	orm.Mapping(promodel.ProBrand{}, "pro_brand")
	orm.Mapping(promodel.Attr{}, "pro_attr")
	orm.Mapping(promodel.AttrItem{}, "pro_attr_item")
	orm.Mapping(promodel.Spec{}, "pro_spec")
	orm.Mapping(promodel.SpecItem{}, "pro_spec_item")
	orm.Mapping(product.Attr{}, "pro_attr_info")
	orm.Mapping(item.Snapshot{}, "item_snapshot")
	orm.Mapping(item.TradeSnapshot{}, "item_trade_snapshot")
	orm.Mapping(item.Label{}, "gs_sale_label")
	orm.Mapping(item.MemberPrice{}, "gs_member_price")

	/** 商户 **/
	orm.Mapping(merchant.Merchant{}, "mch_merchant")
	orm.Mapping(merchant.EnterpriseInfo{}, "mch_enterprise_info")
	orm.Mapping(merchant.ApiInfo{}, "mch_api_info")
	orm.Mapping(shop.Shop{}, "mch_shop")
	orm.Mapping(shop.OnlineShop{}, "mch_online_shop")
	orm.Mapping(shop.OfflineShop{}, "mch_offline_shop")
	orm.Mapping(merchant.SaleConf{}, "mch_sale_conf")
	orm.Mapping(merchant.TradeConf{}, "mch_trade_conf")
	orm.Mapping(merchant.MemberLevel{}, "pt_member_level")
	orm.Mapping(merchant.Account{}, "mch_account")
	orm.Mapping(merchant.BalanceLog{}, "mch_balance_log")
	orm.Mapping(merchant.MchDayChart{}, "mch_day_chart")
	orm.Mapping(merchant.MchSignUp{}, "mch_sign_up")
	orm.Mapping(merchant.MchBuyerGroup{}, "mch_buyer_group")
	orm.Mapping(mss.MailTemplate{}, "pt_mail_template")
	orm.Mapping(mss.MailTask{}, "pt_mail_queue")

	/* 批发 */
	orm.Mapping(wholesaler.WsWholesaler{}, "ws_wholesaler")
	orm.Mapping(wholesaler.WsRebateRate{}, "ws_rebate_rate")
	orm.Mapping(item.WsItem{}, "ws_item")
	orm.Mapping(item.WsItemDiscount{}, "ws_item_discount")
	orm.Mapping(item.WsSkuPrice{}, "ws_sku_price")
	orm.Mapping(cart.WsCart{}, "ws_cart")
	orm.Mapping(cart.WsCartItem{}, "ws_cart_item")

	orm.Mapping(payment.PaymentOrder{}, "pay_order")

	/** 促销 **/
	orm.Mapping(promotion.ValueCoupon{}, "pm_coupon")
	orm.Mapping(promotion.ValueCouponBind{}, "pm_coupon_bind")
	orm.Mapping(promotion.ValueCouponTake{}, "pm_coupon_take")
	orm.Mapping(promotion.PromotionInfo{}, "pm_info")
	orm.Mapping(promotion.ValueCashBack{}, "pm_cash_back")

	/** 配送 **/
	orm.Mapping(delivery.AreaValue{}, "dlv_area")
	orm.Mapping(delivery.CoverageValue{}, "dlv_coverage")
	orm.Mapping(delivery.MerchantDeliverBind{}, "dlv_merchant_bind")

	// 用户
	orm.Mapping(user.RoleValue{}, "usr_role")
	orm.Mapping(user.PersonValue{}, "usr_person")
	orm.Mapping(user.CredentialValue{}, "usr_credential")

	orm.Mapping(personfinance.RiseInfoValue{}, "pf_riseinfo")
	orm.Mapping(personfinance.RiseDayInfo{}, "pf_riseday")
	orm.Mapping(personfinance.RiseLog{}, "pf_riselog")

	// 通用模块
	orm.Mapping(model.CommQrTemplate{}, "comm_qr_template")
	orm.Mapping(model.PortalNav{}, "portal_nav")
	orm.Mapping(model.PortalNavType{}, "portal_nav_type")
	orm.Mapping(model.PortalFloorAd{}, "portal_floor_ad")
	orm.Mapping(model.PortalFloorLink{}, "portal_floor_link")
	orm.Mapping(valueobject.Goods{}, "")

	// 钱包
	orm.Mapping(wallet.Wallet{}, "wal_wallet")
	orm.Mapping(wallet.WalletLog{}, "wal_wallet_log")
	// KV
	orm.Mapping(valueobject.SysKeyValue{}, "sys_kv")
}
<commit_msg>init.go<commit_after>/**
 * Copyright 2015 @ z3q.net.
 * name : types.go
 * author : jarryliu
 * date : -- :
 * description :
 * history :
 */
package core

import (
	"encoding/gob"
	"github.com/jsix/gof/db"
	"go2o/core/dao/model"
	"go2o/core/domain/interface/ad"
	"go2o/core/domain/interface/after-sales"
	"go2o/core/domain/interface/cart"
	"go2o/core/domain/interface/content"
	"go2o/core/domain/interface/delivery"
	"go2o/core/domain/interface/express"
	"go2o/core/domain/interface/item"
	"go2o/core/domain/interface/member"
	"go2o/core/domain/interface/merchant"
	"go2o/core/domain/interface/merchant/shop"
	"go2o/core/domain/interface/merchant/user"
	"go2o/core/domain/interface/merchant/wholesaler"
	"go2o/core/domain/interface/mss"
	"go2o/core/domain/interface/order"
	"go2o/core/domain/interface/payment"
	"go2o/core/domain/interface/personfinance"
	"go2o/core/domain/interface/pro_model"
	"go2o/core/domain/interface/product"
	"go2o/core/domain/interface/promotion"
	"go2o/core/domain/interface/shipment"
	"go2o/core/domain/interface/valueobject"
	"go2o/core/domain/interface/wallet"
	"go2o/core/dto"
	"go2o/core/variable"
	"go2o/gen-code/thrift/define"
	"strings"
)

func init() {
	registerTypes()
}

// 注册序列类型
func registerTypes() {
	gob.Register(&member.Member{})
	gob.Register(&merchant.Merchant{})
	gob.Register(&merchant.ApiInfo{})
	gob.Register(&shop.OnlineShop{})
	gob.Register(&shop.OfflineShop{})
	gob.Register(&shop.ComplexShop{})
	gob.Register(&member.Account{})
	gob.Register(&payment.PaymentOrder{})
	gob.Register(&member.Relation{})
	gob.Register(&dto.ListOnlineShop{})
	gob.Register([]*dto.ListOnlineShop{})
	gob.Register(&define.Member{})
	gob.Register(&define.Profile{})
}

func Init(a *AppImpl, debug, trace bool) bool {
	a._debugMode = debug
	if trace {
		a.Db().GetOrm().SetTrace(a._debugMode)
	}
	OrmMapping(a.Db())
	// 初始化变量
	variable.Domain = a._config.GetString(variable.ServerDomain)
	confPath := strings.TrimSpace(a._config.GetString("conf_path"))
	if len(confPath) > 0 {
		variable.ConfPath = confPath
	}
	a.Loaded = true
	return true
}

func OrmMapping(conn db.Connector) {
	//table mapping
	orm := conn.GetOrm()
	orm.Mapping(valueobject.Area{}, "china_area")
	/* ad */
	orm.Mapping(ad.Ad{}, "ad_list")
	orm.Mapping(ad.Image{}, "ad_image")
	orm.Mapping(ad.HyperLink{}, "ad_hyperlink")
	orm.Mapping(ad.AdGroup{}, "ad_group")
	orm.Mapping(ad.AdPosition{}, "ad_position")
	orm.Mapping(ad.AdUserSet{}, "ad_userset")

	/* MSS */
	orm.Mapping(mss.Message{}, "msg_list")
	orm.Mapping(mss.To{}, "msg_to")
	orm.Mapping(mss.Content{}, "msg_content")
	orm.Mapping(mss.Replay{}, "msg_replay")

	/* 内容 */
	orm.Mapping(content.Page{}, "ex_page")
	orm.Mapping(content.Article{}, "article_list")
	orm.Mapping(content.ArticleCategory{}, "article_category")

	/** new **/
	orm.Mapping(member.Level{}, "mm_level")
	orm.Mapping(member.Member{}, "mm_member")
	orm.Mapping(member.Profile{}, "mm_profile")
	orm.Mapping(member.IntegralLog{}, "mm_integral_log")
	orm.Mapping(member.BalanceLog{}, "mm_balance_log")
	orm.Mapping(member.MWalletLog{}, "mm_wallet_log")
	orm.Mapping(member.Account{}, "mm_account")
	orm.Mapping(member.Address{}, "mm_deliver_addr")
	orm.Mapping(member.Relation{}, "mm_relation")
	orm.Mapping(member.BalanceInfo{}, "mm_balance_info")
	orm.Mapping(member.TrustedInfo{}, "mm_trusted_info")
	orm.Mapping(member.Favorite{}, "mm_favorite")
	orm.Mapping(member.BankInfo{}, "mm_bank")
	orm.Mapping(member.LevelUpLog{}, "mm_levelup")
	orm.Mapping(member.BuyerGroup{}, "mm_buyer_group")

	//** ORDER **//

	orm.Mapping(order.NormalOrder{}, "sale_order")
	orm.Mapping(order.NormalSubOrder{}, "sale_sub_order")

	orm.Mapping(order.SubOrderItem{}, "sale_order_item")
	orm.Mapping(order.OrderCoupon{}, "pt_order_coupon")
	orm.Mapping(order.OrderPromotionBind{}, "pt_order_pb")
	orm.Mapping(order.OrderLog{}, "sale_order_log")
	orm.Mapping(cart.RetailCart{}, "sale_cart")
	orm.Mapping(cart.RetailCartItem{}, "sale_cart_item")
	orm.Mapping(order.Order{}, "order_list")
	orm.Mapping(order.WholesaleOrder{}, "order_wholesale_order")
	orm.Mapping(order.WholesaleItem{}, "order_wholesale_item")
	orm.Mapping(order.TradeOrder{}, "order_trade_order")

	//** After Sales **/
	orm.Mapping(afterSales.AfterSalesOrder{}, "sale_after_order")
	orm.Mapping(afterSales.ReturnOrder{}, "sale_return")
	orm.Mapping(afterSales.ExchangeOrder{}, "sale_exchange")
	orm.Mapping(afterSales.RefundOrder{}, "sale_refund")

	//** Express **//
	orm.Mapping(express.ExpressProvider{}, "express_provider")
	orm.Mapping(express.ExpressTemplate{}, "express_template")
	orm.Mapping(express.ExpressAreaTemplate{}, "express_area_set")

	//** Shipment **/
	orm.Mapping(shipment.ShipmentOrder{}, "ship_order")
	orm.Mapping(shipment.Item{}, "ship_item")

	/** 产品 **/
	orm.Mapping(product.Product{}, "pro_product")
	orm.Mapping(item.GoodsItem{}, "item_info")
	orm.Mapping(item.Sku{}, "item_sku")
	orm.Mapping(product.Category{}, "pro_category")
	orm.Mapping(promodel.ProModel{}, "pro_model")
	orm.Mapping(promodel.ProModelBrand{}, "pro_model_brand")
	orm.Mapping(promodel.ProBrand{}, "pro_brand")
	orm.Mapping(promodel.Attr{}, "pro_attr")
	orm.Mapping(promodel.AttrItem{}, "pro_attr_item")
	orm.Mapping(promodel.Spec{}, "pro_spec")
	orm.Mapping(promodel.SpecItem{}, "pro_spec_item")
	orm.Mapping(product.Attr{}, "pro_attr_info")
	orm.Mapping(item.Snapshot{}, "item_snapshot")
	orm.Mapping(item.TradeSnapshot{}, "item_trade_snapshot")
	orm.Mapping(item.Label{}, "gs_sale_label")
	orm.Mapping(item.MemberPrice{}, "gs_member_price")

	/** 商户 **/
	orm.Mapping(merchant.Merchant{}, "mch_merchant")
	orm.Mapping(merchant.EnterpriseInfo{}, "mch_enterprise_info")
	orm.Mapping(merchant.ApiInfo{}, "mch_api_info")
	orm.Mapping(shop.Shop{}, "mch_shop")
	orm.Mapping(shop.OnlineShop{}, "mch_online_shop")
	orm.Mapping(shop.OfflineShop{}, "mch_offline_shop")
	orm.Mapping(merchant.SaleConf{}, "mch_sale_conf")
	orm.Mapping(merchant.TradeConf{}, "mch_trade_conf")
	orm.Mapping(merchant.MemberLevel{}, "pt_member_level")
	orm.Mapping(merchant.Account{}, "mch_account")
	orm.Mapping(merchant.BalanceLog{}, "mch_balance_log")
	orm.Mapping(merchant.MchDayChart{}, "mch_day_chart")
	orm.Mapping(merchant.MchSignUp{}, "mch_sign_up")
	orm.Mapping(merchant.MchBuyerGroup{}, "mch_buyer_group")
	orm.Mapping(mss.MailTemplate{}, "pt_mail_template")
	orm.Mapping(mss.MailTask{}, "pt_mail_queue")

	/* 批发 */
	orm.Mapping(wholesaler.WsWholesaler{}, "ws_wholesaler")
	orm.Mapping(wholesaler.WsRebateRate{}, "ws_rebate_rate")
	orm.Mapping(item.WsItem{}, "ws_item")
	orm.Mapping(item.WsItemDiscount{}, "ws_item_discount")
	orm.Mapping(item.WsSkuPrice{}, "ws_sku_price")
	orm.Mapping(cart.WsCart{}, "ws_cart")
	orm.Mapping(cart.WsCartItem{}, "ws_cart_item")

	orm.Mapping(payment.PaymentOrder{}, "pay_order")

	/** 促销 **/
	orm.Mapping(promotion.ValueCoupon{}, "pm_coupon")
	orm.Mapping(promotion.ValueCouponBind{}, "pm_coupon_bind")
	orm.Mapping(promotion.ValueCouponTake{}, "pm_coupon_take")
	orm.Mapping(promotion.PromotionInfo{}, "pm_info")
	orm.Mapping(promotion.ValueCashBack{}, "pm_cash_back")

	/** 配送 **/
	orm.Mapping(delivery.AreaValue{}, "dlv_area")
	orm.Mapping(delivery.CoverageValue{}, "dlv_coverage")
	orm.Mapping(delivery.MerchantDeliverBind{}, "dlv_merchant_bind")

	// 用户
	orm.Mapping(user.RoleValue{}, "usr_role")
	orm.Mapping(user.PersonValue{}, "usr_person")
	orm.Mapping(user.CredentialValue{}, "usr_credential")

	orm.Mapping(personfinance.RiseInfoValue{}, "pf_riseinfo")
	orm.Mapping(personfinance.RiseDayInfo{}, "pf_riseday")
	orm.Mapping(personfinance.RiseLog{}, "pf_riselog")

	// 通用模块
	orm.Mapping(model.CommQrTemplate{}, "comm_qr_template")
	orm.Mapping(model.PortalNav{}, "portal_nav")
	orm.Mapping(model.PortalNavType{}, "portal_nav_type")
	orm.Mapping(model.PortalFloorAd{}, "portal_floor_ad")
	orm.Mapping(model.PortalFloorLink{}, "portal_floor_link")
	orm.Mapping(valueobject.Goods{}, "")

	// 钱包
	orm.Mapping(wallet.Wallet{}, "wal_wallet")
	orm.Mapping(wallet.WalletLog{}, "wal_wallet_log")
	// KV
	orm.Mapping(valueobject.SysKeyValue{}, "sys_kv")
}
<|endoftext|>


<commit_before>package core

import (
	"log"
	"testing"
)

func TestFunct(t *testing.T) {
	res := TestFunc()
	log.Println(res)
	t.Errorf("bang")
}<commit_msg>fixed test<commit_after>package core

import (
	"log"
	"testing"
)

func TestFunct(t *testing.T) {
	res := TestFunc()
	log.Println(res)
	//t.Errorf("bang")
}<|endoftext|>


<commit_before>// Copyright 2016 CoreOS, 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 docker

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"time"

	"github.com/coreos/go-semver/semver"
	"github.com/coreos/pkg/capnslog"
	"golang.org/x/crypto/ssh"
	"golang.org/x/net/context"

	"github.com/coreos/mantle/kola/cluster"
	"github.com/coreos/mantle/kola/register"
	"github.com/coreos/mantle/kola/skip"
	"github.com/coreos/mantle/lang/worker"
	"github.com/coreos/mantle/system/exec"
	"github.com/coreos/mantle/system/targen"
)

var (
	plog = capnslog.NewPackageLogger("github.com/coreos/mantle", "kola/tests/docker")
)

func init() {
	register.Register(&register.Test{
		Run:         dockerResources,
		ClusterSize: 1,
		NativeFuncs: map[string]func() error{
			"sleepcontainer": func() error {
				return genDockerContainer("sleep", []string{"sleep"})
			},
		},
		Name:     "docker.resources",
		UserData: `#cloud-config`,
		// began shipping docker 1.10 in 949, which has all of the
		// tested resource options.
		MinVersion: semver.Version{Major: 949},
	})
	register.Register(&register.Test{
		Run:         dockerNetwork,
		ClusterSize: 2,
		NativeFuncs: map[string]func() error{
			"ncatcontainer": func() error {
				return genDockerContainer("ncat", []string{"ncat"})
			},
		},
		Name:     "docker.network",
		UserData: `#cloud-config`,

		MinVersion: semver.Version{Major: 1192},
	})
	register.Register(&register.Test{
		Run:         dockerOldClient,
		ClusterSize: 1,
		NativeFuncs: map[string]func() error{
			"echocontainer": func() error {
				return genDockerContainer("echo", []string{"echo"})
			},
		},
		Name:       "docker.oldclient",
		UserData:   `#cloud-config`,
		MinVersion: semver.Version{Major: 1192},
	})
}

// executed on the target vm to make a docker container out of binaries on the host
func genDockerContainer(name string, binnames []string) error {
	tg := targen.New()

	for _, bin := range binnames {
		binpath, err := exec.LookPath(bin)
		if err != nil {
			return fmt.Errorf("failed to find %q binary: %v", bin, err)
		}

		tg.AddBinary(binpath)
	}

	pr, pw := io.Pipe()
	dimport := exec.Command("docker", "import", "-", name)
	dimport.Stdin = pr

	if err := dimport.Start(); err != nil {
		return fmt.Errorf("starting docker import failed %v", err)
	}

	if err := tg.Generate(pw); err != nil {
		return fmt.Errorf("failed to generate tarball: %v", err)
	}

	// err is always nil.
	_ = pw.Close()

	if err := dimport.Wait(); err != nil {
		return fmt.Errorf("waiting for docker import failed %v", err)
	}

	return nil
}

// using a simple container, exercise various docker options that set resource
// limits. also acts as a regression test for
// https://github.com/coreos/bugs/issues/1246.
func dockerResources(c cluster.TestCluster) error {
	m := c.Machines()[0]

	plog.Debug("creating sleep container")

	if err := c.RunNative("sleepcontainer", m); err != nil {
		return fmt.Errorf("failed to create sleep container: %v", err)
	}

	dockerFmt := "docker run --rm %s sleep sleep 0.2"

	dCmd := func(arg string) string {
		return fmt.Sprintf(dockerFmt, arg)
	}

	ctx := context.Background()
	wg := worker.NewWorkerGroup(ctx, 10)

	// ref https://docs.docker.com/engine/reference/run/#runtime-constraints-on-resources
	for _, dockerCmd := range []string{
		// must set memory when setting memory-swap
		dCmd("--memory=10m --memory-swap=10m"),
		dCmd("--memory-reservation=10m"),
		dCmd("--kernel-memory=10m"),
		dCmd("--cpu-shares=100"),
		dCmd("--cpu-period=1000"),
		dCmd("--cpuset-cpus=0"),
		dCmd("--cpuset-mems=0"),
		dCmd("--cpu-quota=1000"),
		dCmd("--blkio-weight=10"),
		// none of these work in QEMU due to apparent lack of cfq for
		// blkio in virtual block devices.
		//dCmd("--blkio-weight-device=/dev/vda:10"),
		//dCmd("--device-read-bps=/dev/vda:1kb"),
		//dCmd("--device-write-bps=/dev/vda:1kb"),
		//dCmd("--device-read-iops=/dev/vda:10"),
		//dCmd("--device-write-iops=/dev/vda:10"),
		dCmd("--memory=10m --oom-kill-disable=true"),
		dCmd("--memory-swappiness=50"),
		dCmd("--shm-size=1m"),
	} {
		plog.Debugf("Executing %q", dockerCmd)

		// lol closures
		cmd := dockerCmd

		worker := func(c context.Context) error {
			// TODO: pass context thru to SSH
			output, err := m.SSH(cmd)
			if err != nil {
				return fmt.Errorf("failed to run %q: output: %q status: %q", dockerCmd, output, err)
			}
			return nil
		}

		if err := wg.Start(worker); err != nil {
			return wg.WaitError(err)
		}
	}

	return wg.Wait()
}

// Ensure that docker containers can make network connections outside of the host
func dockerNetwork(c cluster.TestCluster) error {
	machines := c.Machines()
	src, dest := machines[0], machines[1]

	plog.Debug("creating ncat containers")

	if err := c.RunNative("ncatcontainer", src); err != nil {
		return fmt.Errorf("failed to create ncat container on src: %v", err)
	}

	if err := c.RunNative("ncatcontainer", dest); err != nil {
		return fmt.Errorf("failed to create ncat container on dest: %v", err)
	}

	listener := func(c context.Context) error {
		// Will block until a message is recieved
		out, err := dest.SSH(
			`echo "HELLO FROM SERVER" | docker run -i -p 9988:9988 ncat ncat --idle-timeout 20 --listen 0.0.0.0 9988`,
		)
		if err != nil {
			return err
		}

		if !bytes.Equal(out, []byte("HELLO FROM CLIENT")) {
			return fmt.Errorf("unexpected result from listener: %q", out)
		}

		return nil
	}

	talker := func(c context.Context) error {
		// Wait until listener is ready before trying anything
		for {
			_, err := dest.SSH("sudo lsof -i TCP:9988 -s TCP:LISTEN | grep 9988 -q")
			if err == nil {
				break // socket is ready
			}

			exit, ok := err.(*ssh.ExitError)
			if !ok || exit.Waitmsg.ExitStatus() != 1 { // 1 is the expected exit of grep -q
				return err
			}

			plog.Debug("waiting for server to be ready")
			select {
			case <-c.Done():
				return fmt.Errorf("timeout waiting for server")
			default:
				time.Sleep(100 * time.Millisecond)
			}
		}

		srcCmd := fmt.Sprintf(`echo "HELLO FROM CLIENT" | docker run -i ncat ncat %s 9988`, dest.IP())
		out, err := src.SSH(srcCmd)
		if err != nil {
			return err
		}

		if !bytes.Equal(out, []byte("HELLO FROM SERVER")) {
			return fmt.Errorf(`unexpected result from listener: "%v"`, out)
		}

		return nil
	}

	ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
	defer cancel()

	return worker.Parallel(ctx, listener, talker)
}

// Regression test for https://github.com/coreos/bugs/issues/1569 and
// https://github.com/coreos/docker/pull/31
func dockerOldClient(c cluster.TestCluster) error {
	oldclient := "/usr/lib/kola/amd64/docker-1.9.1"
	if _, err := os.Stat(oldclient); err != nil {
		return skip.Skip(fmt.Sprintf("Can't find old docker client to test: %v", err))
	}
	c.DropFile(oldclient)

	m := c.Machines()[0]

	if err := c.RunNative("echocontainer", m); err != nil {
		return fmt.Errorf("failed to create echo container: %v", err)
	}

	output, err := m.SSH("/home/core/docker-1.9.1 run echo echo 'IT WORKED'")
	if err != nil {
		return fmt.Errorf("failed to run old docker client: %q status: %q", output, err)
	}

	if !bytes.Equal(output, []byte("IT WORKED")) {
		return fmt.Errorf("unexpected result from docker client: %q", output)
	}

	return nil
}
<commit_msg>kola/tests/docker: use private ip in docker.network test<commit_after>// Copyright 2016 CoreOS, 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 docker

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"time"

	"github.com/coreos/go-semver/semver"
	"github.com/coreos/pkg/capnslog"
	"golang.org/x/crypto/ssh"
	"golang.org/x/net/context"

	"github.com/coreos/mantle/kola/cluster"
	"github.com/coreos/mantle/kola/register"
	"github.com/coreos/mantle/kola/skip"
	"github.com/coreos/mantle/lang/worker"
	"github.com/coreos/mantle/system/exec"
	"github.com/coreos/mantle/system/targen"
)

var (
	plog = capnslog.NewPackageLogger("github.com/coreos/mantle", "kola/tests/docker")
)

func init() {
	register.Register(&register.Test{
		Run:         dockerResources,
		ClusterSize: 1,
		NativeFuncs: map[string]func() error{
			"sleepcontainer": func() error {
				return genDockerContainer("sleep", []string{"sleep"})
			},
		},
		Name:     "docker.resources",
		UserData: `#cloud-config`,
		// began shipping docker 1.10 in 949, which has all of the
		// tested resource options.
		MinVersion: semver.Version{Major: 949},
	})
	register.Register(&register.Test{
		Run:         dockerNetwork,
		ClusterSize: 2,
		NativeFuncs: map[string]func() error{
			"ncatcontainer": func() error {
				return genDockerContainer("ncat", []string{"ncat"})
			},
		},
		Name:     "docker.network",
		UserData: `#cloud-config`,

		MinVersion: semver.Version{Major: 1192},
	})
	register.Register(&register.Test{
		Run:         dockerOldClient,
		ClusterSize: 1,
		NativeFuncs: map[string]func() error{
			"echocontainer": func() error {
				return genDockerContainer("echo", []string{"echo"})
			},
		},
		Name:       "docker.oldclient",
		UserData:   `#cloud-config`,
		MinVersion: semver.Version{Major: 1192},
	})
}

// executed on the target vm to make a docker container out of binaries on the host
func genDockerContainer(name string, binnames []string) error {
	tg := targen.New()

	for _, bin := range binnames {
		binpath, err := exec.LookPath(bin)
		if err != nil {
			return fmt.Errorf("failed to find %q binary: %v", bin, err)
		}

		tg.AddBinary(binpath)
	}

	pr, pw := io.Pipe()
	dimport := exec.Command("docker", "import", "-", name)
	dimport.Stdin = pr

	if err := dimport.Start(); err != nil {
		return fmt.Errorf("starting docker import failed %v", err)
	}

	if err := tg.Generate(pw); err != nil {
		return fmt.Errorf("failed to generate tarball: %v", err)
	}

	// err is always nil.
	_ = pw.Close()

	if err := dimport.Wait(); err != nil {
		return fmt.Errorf("waiting for docker import failed %v", err)
	}

	return nil
}

// using a simple container, exercise various docker options that set resource
// limits. also acts as a regression test for
// https://github.com/coreos/bugs/issues/1246.
func dockerResources(c cluster.TestCluster) error {
	m := c.Machines()[0]

	plog.Debug("creating sleep container")

	if err := c.RunNative("sleepcontainer", m); err != nil {
		return fmt.Errorf("failed to create sleep container: %v", err)
	}

	dockerFmt := "docker run --rm %s sleep sleep 0.2"

	dCmd := func(arg string) string {
		return fmt.Sprintf(dockerFmt, arg)
	}

	ctx := context.Background()
	wg := worker.NewWorkerGroup(ctx, 10)

	// ref https://docs.docker.com/engine/reference/run/#runtime-constraints-on-resources
	for _, dockerCmd := range []string{
		// must set memory when setting memory-swap
		dCmd("--memory=10m --memory-swap=10m"),
		dCmd("--memory-reservation=10m"),
		dCmd("--kernel-memory=10m"),
		dCmd("--cpu-shares=100"),
		dCmd("--cpu-period=1000"),
		dCmd("--cpuset-cpus=0"),
		dCmd("--cpuset-mems=0"),
		dCmd("--cpu-quota=1000"),
		dCmd("--blkio-weight=10"),
		// none of these work in QEMU due to apparent lack of cfq for
		// blkio in virtual block devices.
		//dCmd("--blkio-weight-device=/dev/vda:10"),
		//dCmd("--device-read-bps=/dev/vda:1kb"),
		//dCmd("--device-write-bps=/dev/vda:1kb"),
		//dCmd("--device-read-iops=/dev/vda:10"),
		//dCmd("--device-write-iops=/dev/vda:10"),
		dCmd("--memory=10m --oom-kill-disable=true"),
		dCmd("--memory-swappiness=50"),
		dCmd("--shm-size=1m"),
	} {
		plog.Debugf("Executing %q", dockerCmd)

		// lol closures
		cmd := dockerCmd

		worker := func(c context.Context) error {
			// TODO: pass context thru to SSH
			output, err := m.SSH(cmd)
			if err != nil {
				return fmt.Errorf("failed to run %q: output: %q status: %q", dockerCmd, output, err)
			}
			return nil
		}

		if err := wg.Start(worker); err != nil {
			return wg.WaitError(err)
		}
	}

	return wg.Wait()
}

// Ensure that docker containers can make network connections outside of the host
func dockerNetwork(c cluster.TestCluster) error {
	machines := c.Machines()
	src, dest := machines[0], machines[1]

	plog.Debug("creating ncat containers")

	if err := c.RunNative("ncatcontainer", src); err != nil {
		return fmt.Errorf("failed to create ncat container on src: %v", err)
	}

	if err := c.RunNative("ncatcontainer", dest); err != nil {
		return fmt.Errorf("failed to create ncat container on dest: %v", err)
	}

	listener := func(c context.Context) error {
		// Will block until a message is recieved
		out, err := dest.SSH(
			`echo "HELLO FROM SERVER" | docker run -i -p 9988:9988 ncat ncat --idle-timeout 20 --listen 0.0.0.0 9988`,
		)
		if err != nil {
			return err
		}

		if !bytes.Equal(out, []byte("HELLO FROM CLIENT")) {
			return fmt.Errorf("unexpected result from listener: %q", out)
		}

		return nil
	}

	talker := func(c context.Context) error {
		// Wait until listener is ready before trying anything
		for {
			_, err := dest.SSH("sudo lsof -i TCP:9988 -s TCP:LISTEN | grep 9988 -q")
			if err == nil {
				break // socket is ready
			}

			exit, ok := err.(*ssh.ExitError)
			if !ok || exit.Waitmsg.ExitStatus() != 1 { // 1 is the expected exit of grep -q
				return err
			}

			plog.Debug("waiting for server to be ready")
			select {
			case <-c.Done():
				return fmt.Errorf("timeout waiting for server")
			default:
				time.Sleep(100 * time.Millisecond)
			}
		}

		srcCmd := fmt.Sprintf(`echo "HELLO FROM CLIENT" | docker run -i ncat ncat %s 9988`, dest.PrivateIP())
		out, err := src.SSH(srcCmd)
		if err != nil {
			return err
		}

		if !bytes.Equal(out, []byte("HELLO FROM SERVER")) {
			return fmt.Errorf(`unexpected result from listener: "%v"`, out)
		}

		return nil
	}

	ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
	defer cancel()

	return worker.Parallel(ctx, listener, talker)
}

// Regression test for https://github.com/coreos/bugs/issues/1569 and
// https://github.com/coreos/docker/pull/31
func dockerOldClient(c cluster.TestCluster) error {
	oldclient := "/usr/lib/kola/amd64/docker-1.9.1"
	if _, err := os.Stat(oldclient); err != nil {
		return skip.Skip(fmt.Sprintf("Can't find old docker client to test: %v", err))
	}
	c.DropFile(oldclient)

	m := c.Machines()[0]

	if err := c.RunNative("echocontainer", m); err != nil {
		return fmt.Errorf("failed to create echo container: %v", err)
	}

	output, err := m.SSH("/home/core/docker-1.9.1 run echo echo 'IT WORKED'")
	if err != nil {
		return fmt.Errorf("failed to run old docker client: %q status: %q", output, err)
	}

	if !bytes.Equal(output, []byte("IT WORKED")) {
		return fmt.Errorf("unexpected result from docker client: %q", output)
	}

	return nil
}
<|endoftext|>


<commit_before>package linear

import (
	"testing"
)

func TestVector(t *testing.T) {
	v := newVector(1000)
	if !v.empty() {
		t.Errorf("empty failed")
	}
	v.setBit(900)
	if v.getBit(100) {
		t.Errorf("bit 100 shouldn't be set")
	}
	if !v.getBit(900) {
		t.Errorf("bit 900 should be set")
	}
	if v.firstBit() != 900 {
		t.Errorf("first bit didn't return 900")
	}
	if v.empty() {
		t.Errorf("empty failed")
	}
	v.setBit(700)
	v.setBit(800)
	if v.firstBit() != 700 {
		t.Errorf("bad first bit")
	}
	v.toggleBit(700)
	if v.getBit(700) {
		t.Errorf("bad toggle")
	}
	v.toggleBit(800)
	v.toggleBit(900)
}
func TestEmptyFirstBit(t *testing.T) {
	v := newVector(500)
	defer func() {
		a := recover()
		if a == nil {
			panic("firstBit of empty vector did not panic")
		}
	}()
	_ = v.firstBit()
}
<commit_msg>Remove unused testing code.<commit_after>package linear

import (
	"testing"
)

func TestVector(t *testing.T) {
	v := newVector(1000)
	if !v.empty() {
		t.Errorf("empty failed")
	}
	v.setBit(900)
	if v.getBit(100) {
		t.Errorf("bit 100 shouldn't be set")
	}
	if !v.getBit(900) {
		t.Errorf("bit 900 should be set")
	}
	if v.firstBit() != 900 {
		t.Errorf("first bit didn't return 900")
	}
	if v.empty() {
		t.Errorf("empty failed")
	}
	v.setBit(700)
	v.setBit(800)
	if v.firstBit() != 700 {
		t.Errorf("bad first bit")
	}
	v.toggleBit(700)
	if v.getBit(700) {
		t.Errorf("bad toggle")
	}
}
func TestEmptyFirstBit(t *testing.T) {
	v := newVector(500)
	defer func() {
		a := recover()
		if a == nil {
			panic("firstBit of empty vector did not panic")
		}
	}()
	_ = v.firstBit()
}
<|endoftext|>


<commit_before>// Package core is the main package contents of the GoCore application collection of packages and utilities
// Also the root contains some debugging/dumping variable functions
package core

import (
	"encoding/hex"
	"encoding/json"
	"fmt"
	"log"
	"os"
	"reflect"
	"runtime"
	"runtime/debug"
	"strings"
	"sync"
	"time"

	"github.com/DanielRenne/GoCore/core/extensions"
	"github.com/DanielRenne/GoCore/core/serverSettings"
	"github.com/davidrenne/reflections"
	"github.com/go-errors/errors"
)

type core_debug struct{}

var core_logger = log.New(os.Stdout, "", 0)

// No one will ever use this, but TransactionLog provides a thread-safe buffer/string if you have debug.EnableTransactionLog set to true you can call something like core.Debug.GetDump in many places and then eventually read the core.TransactionLog value when you need to (note you must manually clear it as it will just increase your memory usage the more logs are sent).  And always remember to use TransactionLogMutex.RLock and unlock when you are trying to read it in a busy system logging lots of stuff
var TransactionLog string

// See TransactionLog documentation
var EnableTransactionLog bool

// Debug is a base struct for all debug functions.
var Debug = core_debug{}

// LogStackTraces will show you where your logs are coming from in the stack.  Alternatively if you are using a GoCore full web app with a webConfig.json you can set CoreDebugStackTrace to true if you dont override this to false or true.  The default is true.
var LogStackTraces bool

// Logger can be overridden with log.New(os.Stdout, "", 0) to log to stdout or some other writer
var Logger = core_logger

// TransactionLogMutex is a mutex for the TransactionLog which should be used on your end to clear the value safely
var TransactionLogMutex *sync.RWMutex

func init() {
	LogStackTraces = true
	TransactionLogMutex = &sync.RWMutex{}
}

// Nop is a dummy function that can be called in source files where
// other debug functions are constantly added and removed.
// That way import "github.com/ungerik/go-start/debug" won't cause an error when
// no other debug function is currently used.
// Arbitrary objects can be passed as arguments to avoid "declared and not used"
// error messages when commenting code out and in.
// The result is a nil interface{} dummy value.
func (self *core_debug) Nop(dummiesIn ...interface{}) (dummyOut interface{}) {
	return nil
}

// CallStackInfo returns a string with the call stack info.
func (self *core_debug) CallStackInfo(skip int) (info string) {
	pc, file, line, ok := runtime.Caller(skip)
	if ok {
		funcName := runtime.FuncForPC(pc).Name()
		info += fmt.Sprintf("In function %s()", funcName)
	}
	for i := 0; ok; i++ {
		info += fmt.Sprintf("\n%s:%d", file, line)
		_, file, line, ok = runtime.Caller(skip + i)
	}
	return info
}

// PrintCallStack prints the call stack info.
func (self *core_debug) PrintCallStack() {
	debug.PrintStack()
}

// LogCallStack logs the call stack info.
func (self *core_debug) LogCallStack() {
	log.Print(self.Stack())
}

func (self *core_debug) Stack() string {
	return string(debug.Stack())
}

func (self *core_debug) formatValue(value interface{}) string {
	return fmt.Sprintf("\n     Type: %T\n    Value: %v\nGo Syntax: %#v", value, value, value)
}

func (self *core_debug) formatCallstack(skip int) string {
	return fmt.Sprintf("\nCallstack: %s", self.CallStackInfo(skip+1))
}

// FormatSkip formats a value with callstack info.
func (self *core_debug) FormatSkip(skip int, value interface{}) string {
	return self.formatValue(value) + self.formatCallstack(skip+1)
}

// Format formats a value with callstack info.
func (self *core_debug) Format(value interface{}) string {
	return self.FormatSkip(2, value)
}

// IsZeroOfUnderlyingType returns true if the value is the zero value (nil) for its type.
func IsZeroOfUnderlyingType(x interface{}) bool {
	return reflect.DeepEqual(x, reflect.Zero(reflect.TypeOf(x)).Interface())
}

// IsZeroOfUnderlyingType2 returns true if the value is the zero value (nil) for its type.
func IsZeroOfUnderlyingType2(x interface{}) bool {
	return x == reflect.Zero(reflect.TypeOf(x)).Interface()
}

// HandleError is a helper function that will log an error and return it with the callers line and file.
func (self *core_debug) HandleError(err error) (s string) {
	if err != nil {
		// notice that we're using 1, so it will actually log the where
		// the error happened, 0 = this function, we don't want that.
		_, fn, line, _ := runtime.Caller(1)
		fileNameParts := strings.Split(fn, "/")
		return fmt.Sprintf("  Error Info: %s Line %d. ErrorType: %v", fileNameParts[len(fileNameParts)-1], line, err)
	}
	return ""
}

// ErrLineAndFile returns the line and file of the error.
func (self *core_debug) ErrLineAndFile(err error) (s string) {
	if err != nil {
		// notice that we're using 1, so it will actually log the where
		// the error happened, 0 = this function, we don't want that.
		_, fn, line, _ := runtime.Caller(1)
		fileNameParts := strings.Split(fn, "/")
		return fmt.Sprintf("%s Line %d", fileNameParts[len(fileNameParts)-1], line)
	}
	return ""
}

// Dump is a helper function that will log unlimited values to print to stdout or however you have log setup if you overload core/Logger
func (self *core_debug) Dump(valuesOriginal ...interface{}) {
	t := time.Now()
	l := "!!!!!!!!!!!!! DEBUG " + t.Format("2006-01-02 15:04:05.000000") + "!!!!!!!!!!!!!\n\n"
	Logger.Println(l)

	if EnableTransactionLog {
		TransactionLogMutex.Lock()
		TransactionLog += l
		TransactionLogMutex.Unlock()
	}
	for _, value := range valuesOriginal {
		l := self.dumpBase(value)
		Logger.Print(l)
		if EnableTransactionLog {
			TransactionLogMutex.Lock()
			TransactionLog += l
			TransactionLogMutex.Unlock()
		}
	}
	l = self.ThrowAndPrintError()
	Logger.Print(l)

	if EnableTransactionLog {
		TransactionLogMutex.Lock()
		TransactionLog += l
		TransactionLogMutex.Unlock()
	}
	l = "!!!!!!!!!!!!! ENDDEBUG " + t.Format("2006-01-02 15:04:05.000000") + "!!!!!!!!!!!!!"
	Logger.Println(l)
	if EnableTransactionLog {
		TransactionLogMutex.Lock()
		TransactionLog += l
		TransactionLogMutex.Unlock()
	}
}

// GetDump is a helper function that will log unlimited values which will return a string representation of what was logged
func (self *core_debug) GetDump(valuesOriginal ...interface{}) (output string) {
	for _, value := range valuesOriginal {
		output += self.dumpBase(value)
	}
	//output += self.ThrowAndPrintError()
	return output
}

func (self *core_debug) GetDumpWithInfo(valuesOriginal ...interface{}) (output string) {
	t := time.Now()
	return self.GetDumpWithInfoAndTimeString(t.String(), valuesOriginal...)
}

// GetDumpWithInfoAndTimeString is a helper function that will log unlimited values which will return a string representation of what was logged but allows you to pass your own time string in a case of timezone offsets
func (self *core_debug) GetDumpWithInfoAndTimeString(timeStr string, valuesOriginal ...interface{}) (output string) {
	l := "\n!!!!!!!!!!!!! DEBUG " + timeStr + "!!!!!!!!!!!!!\n\n"
	output += l

	if EnableTransactionLog {
		TransactionLogMutex.Lock()
		TransactionLog += l
		TransactionLogMutex.Unlock()
	}

	for _, value := range valuesOriginal {
		output += self.dumpBase(value) + "\n"
	}

	if EnableTransactionLog {
		TransactionLogMutex.Lock()
		TransactionLog += output
		TransactionLogMutex.Unlock()
	}

	l = self.ThrowAndPrintError()
	output += l

	if EnableTransactionLog {
		TransactionLogMutex.Lock()
		TransactionLog += l
		TransactionLogMutex.Unlock()
	}

	l = "!!!!!!!!!!!!! ENDDEBUG " + timeStr + "!!!!!!!!!!!!!\n"
	output += l
	if EnableTransactionLog {
		TransactionLogMutex.Lock()
		TransactionLog += l
		TransactionLogMutex.Unlock()
	}
	return output
}

func (self *core_debug) dumpBase(values ...interface{}) (output string) {
	var jsonString string
	var err error
	var structKeys []string
	if Logger != nil {
		for _, value := range values {
			isAllJSON := true
			var kind string
			kind = strings.TrimSpace(fmt.Sprintf("%T", value))
			kindFormatted := strings.TrimSpace(fmt.Sprintf("%T", value))
			// var pieces = strings.Split(kind, " ")
			// if pieces[0] == "struct" || strings.Index(pieces[0], "model.") != -1 || strings.Index(pieces[0], "viewModel.") != -1 {
			if !IsZeroOfUnderlyingType(value) {
				kind = reflections.ReflectKind(value)
				structKeys, err = reflections.FieldsDeep(value)
				if err == nil {
					for _, field := range structKeys {
						jsonString, err = reflections.GetFieldTag(value, field, "json")
						if err != nil {
							isAllJSON = false
						}
						if jsonString == "" {
							isAllJSON = false
						}
					}
				} else {
					isAllJSON = false
				}
			} else {
				isAllJSON = false
			}

			if kindFormatted != "[]uint8" && (isAllJSON || kind == "map" || kind == "bson.M" || kind == "slice") {
				var rawBytes []byte
				rawBytes, err = json.MarshalIndent(value, "", "\t")
				if err == nil {
					if kind == "slice" || kind[:2] == "[]" {
						valReflected := reflect.ValueOf(value)
						output += fmt.Sprintf("#### %-39s [len:%s]####\n%+v", kindFormatted, extensions.IntToString(valReflected.Len()), string(rawBytes[:]))
					} else {
						output += fmt.Sprintf("#### %-39s ####\n%+v", kindFormatted, string(rawBytes[:]))
					}
				}
			} else {
				if strings.TrimSpace(kind) == "string" {
					var stringVal = fmt.Sprintf("%+v", value)
					position := strings.Index(stringVal, "Desc->")
					if position == -1 {
						if !extensions.IsPrintable(stringVal) {
							kind += " (non printables -> dump hex)"
							stringVal = hex.Dump([]byte(stringVal))
						}
						valReflected := reflect.ValueOf(value)
						output += fmt.Sprintf("#### %-39s [len:%s]####\n%s", kindFormatted, extensions.IntToString(valReflected.Len()), stringVal)
					} else {
						output += stringVal[6:] + " --> "
					}
				} else if kindFormatted == "[]uint8" || kind[:2] == "[]" || strings.TrimSpace(kind) == "array" {
					if kindFormatted == "[]uint8" {
						val, ok := value.([]uint8)
						if ok {
							if !extensions.IsPrintable(string(val)) {
								kind += " (non printables -> dump hex of a []byte)"
								output = hex.Dump(value.([]uint8))
							} else {
								valReflected := reflect.ValueOf(value)
								output += fmt.Sprintf("#### %-39s [len:%s]####\n%s", kindFormatted, extensions.IntToString(valReflected.Len()), string(val))
							}
						}
					} else {
						valReflected := reflect.ValueOf(value)
						output += fmt.Sprintf("#### %-39s [len:%s]####\n%#v", kindFormatted, extensions.IntToString(valReflected.Len()), value)
					}
				} else {
					output += fmt.Sprintf("#### %-39s ####\n%#v", kindFormatted, value)
				}
			}
		}
	}
	return output
}

// ThrowAndPrintError is a helper function that will throw a fake error and get the callstack and return it as a string (you probably shouldnt use this)
func (self *core_debug) ThrowAndPrintError() (output string) {

	serverSettings.WebConfigMutex.RLock()
	ok := serverSettings.WebConfig.Application.CoreDebugStackTrace
	serverSettings.WebConfigMutex.RUnlock()
	if ok || LogStackTraces {
		output += "\n"
		errorInfo := self.ThrowError()
		stack := strings.Split(errorInfo.ErrorStack(), "\n")
		if len(stack) >= 8 {
			output += "\nDump Caller:"
			output += "\n---------------"
			//output += strings.Join(stack, ",")
			output += "\n golines ==> " + strings.TrimSpace(stack[6])
			output += "\n         ==> " + strings.TrimSpace(stack[7])
			output += "\n         ==> " + strings.TrimSpace(stack[8])
			output += "\n         ==> " + strings.TrimSpace(stack[9])
			output += "\n         ==> " + strings.TrimSpace(stack[10])
			if len(stack) >= 12 {
				output += "\n         ==> " + strings.TrimSpace(stack[11])
			}
			if len(stack) >= 13 {
				output += "\n         ==> " + strings.TrimSpace(stack[12])
			}
			if len(stack) >= 14 {
				output += "\n         ==> " + strings.TrimSpace(stack[13])
			}
			if len(stack) >= 15 {
				output += "\n         ==> " + strings.TrimSpace(stack[14])
			}
			if len(stack) >= 16 {
				output += "\n         ==> " + strings.TrimSpace(stack[15])
			}
			output += "\n---------------"
			output += "\n"
			output += "\n"
		}
	}
	return output
}

// ThrowError is a helper function that will throw a fake error and get the callstack and return it as an error (you probably shouldnt use this)
func (self *core_debug) ThrowError() *errors.Error {
	return errors.Errorf("Debug Dump")
}

// GetDump is a helper function that will return a string of the dump of the values passed in
func GetDump(valuesOriginal ...interface{}) string {
	return Debug.GetDump(valuesOriginal...)
}

// Dump is a helper function that will dump the values passed to it
func Dump(valuesOriginal ...interface{}) {
	Debug.Dump(valuesOriginal...)
}
<commit_msg>Log as go structs or slice<commit_after>// Package core is the main package contents of the GoCore application collection of packages and utilities
// Also the root contains some debugging/dumping variable functions
package core

import (
	"encoding/hex"
	"encoding/json"
	"fmt"
	"log"
	"os"
	"reflect"
	"runtime"
	"runtime/debug"
	"strings"
	"sync"
	"time"

	"github.com/DanielRenne/GoCore/core/extensions"
	"github.com/DanielRenne/GoCore/core/serverSettings"
	"github.com/davidrenne/reflections"
	"github.com/go-errors/errors"
)

type core_debug struct{}

var core_logger = log.New(os.Stdout, "", 0)

// No one will ever use this, but TransactionLog provides a thread-safe buffer/string if you have debug.EnableTransactionLog set to true you can call something like core.Debug.GetDump in many places and then eventually read the core.TransactionLog value when you need to (note you must manually clear it as it will just increase your memory usage the more logs are sent).  And always remember to use TransactionLogMutex.RLock and unlock when you are trying to read it in a busy system logging lots of stuff
var TransactionLog string

// See TransactionLog documentation
var EnableTransactionLog bool

// Debug is a base struct for all debug functions.
var Debug = core_debug{}

// LogStackTraces will show you where your logs are coming from in the stack.  Alternatively if you are using a GoCore full web app with a webConfig.json you can set CoreDebugStackTrace to true if you dont override this to false or true.  The default is true.
var LogStackTraces bool

// Logger can be overridden with log.New(os.Stdout, "", 0) to log to stdout or some other writer
var Logger = core_logger

// TransactionLogMutex is a mutex for the TransactionLog which should be used on your end to clear the value safely
var TransactionLogMutex *sync.RWMutex

func init() {
	LogStackTraces = true
	TransactionLogMutex = &sync.RWMutex{}
}

// Nop is a dummy function that can be called in source files where
// other debug functions are constantly added and removed.
// That way import "github.com/ungerik/go-start/debug" won't cause an error when
// no other debug function is currently used.
// Arbitrary objects can be passed as arguments to avoid "declared and not used"
// error messages when commenting code out and in.
// The result is a nil interface{} dummy value.
func (self *core_debug) Nop(dummiesIn ...interface{}) (dummyOut interface{}) {
	return nil
}

// CallStackInfo returns a string with the call stack info.
func (self *core_debug) CallStackInfo(skip int) (info string) {
	pc, file, line, ok := runtime.Caller(skip)
	if ok {
		funcName := runtime.FuncForPC(pc).Name()
		info += fmt.Sprintf("In function %s()", funcName)
	}
	for i := 0; ok; i++ {
		info += fmt.Sprintf("\n%s:%d", file, line)
		_, file, line, ok = runtime.Caller(skip + i)
	}
	return info
}

// PrintCallStack prints the call stack info.
func (self *core_debug) PrintCallStack() {
	debug.PrintStack()
}

// LogCallStack logs the call stack info.
func (self *core_debug) LogCallStack() {
	log.Print(self.Stack())
}

func (self *core_debug) Stack() string {
	return string(debug.Stack())
}

func (self *core_debug) formatValue(value interface{}) string {
	return fmt.Sprintf("\n     Type: %T\n    Value: %v\nGo Syntax: %#v", value, value, value)
}

func (self *core_debug) formatCallstack(skip int) string {
	return fmt.Sprintf("\nCallstack: %s", self.CallStackInfo(skip+1))
}

// FormatSkip formats a value with callstack info.
func (self *core_debug) FormatSkip(skip int, value interface{}) string {
	return self.formatValue(value) + self.formatCallstack(skip+1)
}

// Format formats a value with callstack info.
func (self *core_debug) Format(value interface{}) string {
	return self.FormatSkip(2, value)
}

// IsZeroOfUnderlyingType returns true if the value is the zero value (nil) for its type.
func IsZeroOfUnderlyingType(x interface{}) bool {
	return reflect.DeepEqual(x, reflect.Zero(reflect.TypeOf(x)).Interface())
}

// IsZeroOfUnderlyingType2 returns true if the value is the zero value (nil) for its type.
func IsZeroOfUnderlyingType2(x interface{}) bool {
	return x == reflect.Zero(reflect.TypeOf(x)).Interface()
}

// HandleError is a helper function that will log an error and return it with the callers line and file.
func (self *core_debug) HandleError(err error) (s string) {
	if err != nil {
		// notice that we're using 1, so it will actually log the where
		// the error happened, 0 = this function, we don't want that.
		_, fn, line, _ := runtime.Caller(1)
		fileNameParts := strings.Split(fn, "/")
		return fmt.Sprintf("  Error Info: %s Line %d. ErrorType: %v", fileNameParts[len(fileNameParts)-1], line, err)
	}
	return ""
}

// ErrLineAndFile returns the line and file of the error.
func (self *core_debug) ErrLineAndFile(err error) (s string) {
	if err != nil {
		// notice that we're using 1, so it will actually log the where
		// the error happened, 0 = this function, we don't want that.
		_, fn, line, _ := runtime.Caller(1)
		fileNameParts := strings.Split(fn, "/")
		return fmt.Sprintf("%s Line %d", fileNameParts[len(fileNameParts)-1], line)
	}
	return ""
}

// Dump is a helper function that will log unlimited values to print to stdout or however you have log setup if you overload core/Logger
func (self *core_debug) Dump(valuesOriginal ...interface{}) {
	t := time.Now()
	l := "!!!!!!!!!!!!! DEBUG " + t.Format("2006-01-02 15:04:05.000000") + "!!!!!!!!!!!!!\n\n"
	Logger.Println(l)

	if EnableTransactionLog {
		TransactionLogMutex.Lock()
		TransactionLog += l
		TransactionLogMutex.Unlock()
	}
	for _, value := range valuesOriginal {
		l := self.dumpBase(value)
		Logger.Print(l)
		if EnableTransactionLog {
			TransactionLogMutex.Lock()
			TransactionLog += l
			TransactionLogMutex.Unlock()
		}
	}
	l = self.ThrowAndPrintError()
	Logger.Print(l)

	if EnableTransactionLog {
		TransactionLogMutex.Lock()
		TransactionLog += l
		TransactionLogMutex.Unlock()
	}
	l = "!!!!!!!!!!!!! ENDDEBUG " + t.Format("2006-01-02 15:04:05.000000") + "!!!!!!!!!!!!!"
	Logger.Println(l)
	if EnableTransactionLog {
		TransactionLogMutex.Lock()
		TransactionLog += l
		TransactionLogMutex.Unlock()
	}
}

// GetDump is a helper function that will log unlimited values which will return a string representation of what was logged
func (self *core_debug) GetDump(valuesOriginal ...interface{}) (output string) {
	for _, value := range valuesOriginal {
		output += self.dumpBase(value)
	}
	//output += self.ThrowAndPrintError()
	return output
}

func (self *core_debug) GetDumpWithInfo(valuesOriginal ...interface{}) (output string) {
	t := time.Now()
	return self.GetDumpWithInfoAndTimeString(t.String(), valuesOriginal...)
}

// GetDumpWithInfoAndTimeString is a helper function that will log unlimited values which will return a string representation of what was logged but allows you to pass your own time string in a case of timezone offsets
func (self *core_debug) GetDumpWithInfoAndTimeString(timeStr string, valuesOriginal ...interface{}) (output string) {
	l := "\n!!!!!!!!!!!!! DEBUG " + timeStr + "!!!!!!!!!!!!!\n\n"
	output += l

	if EnableTransactionLog {
		TransactionLogMutex.Lock()
		TransactionLog += l
		TransactionLogMutex.Unlock()
	}

	for _, value := range valuesOriginal {
		output += self.dumpBase(value) + "\n"
	}

	if EnableTransactionLog {
		TransactionLogMutex.Lock()
		TransactionLog += output
		TransactionLogMutex.Unlock()
	}

	l = self.ThrowAndPrintError()
	output += l

	if EnableTransactionLog {
		TransactionLogMutex.Lock()
		TransactionLog += l
		TransactionLogMutex.Unlock()
	}

	l = "!!!!!!!!!!!!! ENDDEBUG " + timeStr + "!!!!!!!!!!!!!\n"
	output += l
	if EnableTransactionLog {
		TransactionLogMutex.Lock()
		TransactionLog += l
		TransactionLogMutex.Unlock()
	}
	return output
}

func (self *core_debug) dumpBase(values ...interface{}) (output string) {
	var jsonString string
	var err error
	var structKeys []string
	if Logger != nil {
		for _, value := range values {
			isAllJSON := true
			var kind string
			kind = strings.TrimSpace(fmt.Sprintf("%T", value))
			kindFormatted := strings.TrimSpace(fmt.Sprintf("%T", value))
			// var pieces = strings.Split(kind, " ")
			// if pieces[0] == "struct" || strings.Index(pieces[0], "model.") != -1 || strings.Index(pieces[0], "viewModel.") != -1 {
			if !IsZeroOfUnderlyingType(value) {
				kind = reflections.ReflectKind(value)
				structKeys, err = reflections.FieldsDeep(value)
				if err == nil {
					for _, field := range structKeys {
						jsonString, err = reflections.GetFieldTag(value, field, "json")
						if err != nil {
							isAllJSON = false
						}
						if jsonString == "" {
							isAllJSON = false
						}
					}
				} else {
					isAllJSON = false
				}
			} else {
				isAllJSON = false
			}

			if kindFormatted != "[]uint8" && (isAllJSON || kind == "map" || kind == "bson.M" || kind == "slice") {
				var rawBytes []byte
				rawBytes, err = json.MarshalIndent(value, "", "\t")
				if err == nil {
					if kind == "slice" || kind[:2] == "[]" {
						valReflected := reflect.ValueOf(value)
						output += fmt.Sprintf("#### %-39s [len:%s]####\n%+v", kindFormatted, extensions.IntToString(valReflected.Len()), string(rawBytes[:]))
						output += "\n\nOr Go Slice Code\n\n" + fmt.Sprintf("%#v", value)
					} else {
						output += fmt.Sprintf("#### %-39s ####\n%+v", kindFormatted, string(rawBytes[:]))
						output += "\n\nOr Go Struct Code\n\n" + fmt.Sprintf("%#v", value)
					}
				}
			} else {
				if strings.TrimSpace(kind) == "string" {
					var stringVal = fmt.Sprintf("%+v", value)
					position := strings.Index(stringVal, "Desc->")
					if position == -1 {
						if !extensions.IsPrintable(stringVal) {
							kind += " (non printables -> dump hex)"
							stringVal = hex.Dump([]byte(stringVal))
						}
						valReflected := reflect.ValueOf(value)
						output += fmt.Sprintf("#### %-39s [len:%s]####\n%s", kindFormatted, extensions.IntToString(valReflected.Len()), stringVal)
					} else {
						output += stringVal[6:] + " --> "
					}
				} else if kindFormatted == "[]uint8" || kind[:2] == "[]" || strings.TrimSpace(kind) == "array" {
					if kindFormatted == "[]uint8" {
						val, ok := value.([]uint8)
						if ok {
							if !extensions.IsPrintable(string(val)) {
								kind += " (non printables -> dump hex of a []byte)"
								output = hex.Dump(value.([]uint8))
							} else {
								valReflected := reflect.ValueOf(value)
								output += fmt.Sprintf("#### %-39s [len:%s]####\n%s", kindFormatted, extensions.IntToString(valReflected.Len()), string(val))
							}
						}
					} else {
						valReflected := reflect.ValueOf(value)
						output += fmt.Sprintf("#### %-39s [len:%s]####\n%#v", kindFormatted, extensions.IntToString(valReflected.Len()), value)
					}
				} else {
					output += fmt.Sprintf("#### %-39s ####\n%#v", kindFormatted, value)
				}
			}
		}
	}
	return output
}

// ThrowAndPrintError is a helper function that will throw a fake error and get the callstack and return it as a string (you probably shouldnt use this)
func (self *core_debug) ThrowAndPrintError() (output string) {

	serverSettings.WebConfigMutex.RLock()
	ok := serverSettings.WebConfig.Application.CoreDebugStackTrace
	serverSettings.WebConfigMutex.RUnlock()
	if ok || LogStackTraces {
		output += "\n"
		errorInfo := self.ThrowError()
		stack := strings.Split(errorInfo.ErrorStack(), "\n")
		if len(stack) >= 8 {
			output += "\nDump Caller:"
			output += "\n---------------"
			//output += strings.Join(stack, ",")
			output += "\n golines ==> " + strings.TrimSpace(stack[6])
			output += "\n         ==> " + strings.TrimSpace(stack[7])
			output += "\n         ==> " + strings.TrimSpace(stack[8])
			output += "\n         ==> " + strings.TrimSpace(stack[9])
			output += "\n         ==> " + strings.TrimSpace(stack[10])
			if len(stack) >= 12 {
				output += "\n         ==> " + strings.TrimSpace(stack[11])
			}
			if len(stack) >= 13 {
				output += "\n         ==> " + strings.TrimSpace(stack[12])
			}
			if len(stack) >= 14 {
				output += "\n         ==> " + strings.TrimSpace(stack[13])
			}
			if len(stack) >= 15 {
				output += "\n         ==> " + strings.TrimSpace(stack[14])
			}
			if len(stack) >= 16 {
				output += "\n         ==> " + strings.TrimSpace(stack[15])
			}
			output += "\n---------------"
			output += "\n"
			output += "\n"
		}
	}
	return output
}

// ThrowError is a helper function that will throw a fake error and get the callstack and return it as an error (you probably shouldnt use this)
func (self *core_debug) ThrowError() *errors.Error {
	return errors.Errorf("Debug Dump")
}

// GetDump is a helper function that will return a string of the dump of the values passed in
func GetDump(valuesOriginal ...interface{}) string {
	return Debug.GetDump(valuesOriginal...)
}

// Dump is a helper function that will dump the values passed to it
func Dump(valuesOriginal ...interface{}) {
	Debug.Dump(valuesOriginal...)
}
<|endoftext|>


<commit_before>// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
// Author: arnej

package startcbinary

import (
	"os"
	"strings"

	"github.com/vespa-engine/vespa/client/go/trace"
	"github.com/vespa-engine/vespa/client/go/util"
	"github.com/vespa-engine/vespa/client/go/vespa"
)

func Run(args []string) int {
	trace.AdjustVerbosity(0)
	if len(args) < 1 {
		trace.Warning("missing program argument")
		return 1
	}
	spec := ProgSpec{
		Program: args[0],
		Args:    args,
	}
	spec.setup()
	vespa.LoadDefaultEnv()
	return startCbinary(spec)
}

func IsCandidate(program string) bool {
	binary := program + "-bin"
	if strings.Contains(binary, "/") {
		return util.IsRegularFile(binary)
	} else {
		path := strings.Split(os.Getenv(ENV_PATH), ":")
		for _, dir := range path {
			fn := dir + "/" + binary
			if util.IsRegularFile(fn) {
				return true
			}
		}
	}
	return false
}
<commit_msg>detect hostname and check for errors<commit_after>// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
// Author: arnej

package startcbinary

import (
	"os"
	"strings"

	"github.com/vespa-engine/vespa/client/go/trace"
	"github.com/vespa-engine/vespa/client/go/util"
	"github.com/vespa-engine/vespa/client/go/vespa"
)

func Run(args []string) int {
	trace.AdjustVerbosity(0)
	if len(args) < 1 {
		trace.Warning("missing program argument")
		return 1
	}
	spec := ProgSpec{
		Program: args[0],
		Args:    args,
	}
	spec.setup()
	err := vespa.LoadDefaultEnv()
	if err != nil {
		panic(err)
	}
	hostname, err := vespa.FindOurHostname()
	if err != nil {
		trace.Warning("could not detect hostname:", err, "; using fallback:", hostname)
	}
	return startCbinary(spec)
}

func IsCandidate(program string) bool {
	binary := program + "-bin"
	if strings.Contains(binary, "/") {
		return util.IsRegularFile(binary)
	} else {
		path := strings.Split(os.Getenv(ENV_PATH), ":")
		for _, dir := range path {
			fn := dir + "/" + binary
			if util.IsRegularFile(fn) {
				return true
			}
		}
	}
	return false
}
<|endoftext|>