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

package source

import (
	"context"
	"go/ast"

	"golang.org/x/tools/go/ast/astutil"
	"golang.org/x/tools/internal/lsp/protocol"
	"golang.org/x/tools/internal/span"
	"golang.org/x/tools/internal/telemetry/trace"
	errors "golang.org/x/xerrors"
)

func Highlight(ctx context.Context, view View, uri span.URI, pos protocol.Position) ([]protocol.Range, error) {
	ctx, done := trace.StartSpan(ctx, "source.Highlight")
	defer done()

	f, err := view.GetFile(ctx, uri)
	if err != nil {
		return nil, err
	}
	fh := view.Snapshot().Handle(ctx, f)
	ph := view.Session().Cache().ParseGoHandle(fh, ParseFull)
	file, m, _, err := ph.Parse(ctx)
	if err != nil {
		return nil, err
	}
	spn, err := m.PointSpan(pos)
	if err != nil {
		return nil, err
	}
	rng, err := spn.Range(m.Converter)
	if err != nil {
		return nil, err
	}
	path, _ := astutil.PathEnclosingInterval(file, rng.Start, rng.Start)
	if len(path) == 0 {
		return nil, errors.Errorf("no enclosing position found for %f:%f", pos.Line, pos.Character)
	}
	id, ok := path[0].(*ast.Ident)
	if !ok {
		return nil, errors.Errorf("%f:%f is not an identifier", pos.Line, pos.Character)
	}
	var result []protocol.Range
	if id.Obj != nil {
		ast.Inspect(path[len(path)-1], func(n ast.Node) bool {
			if n, ok := n.(*ast.Ident); ok && n.Obj == id.Obj {
				rng, err := nodeToProtocolRange(ctx, view, m, n)
				if err == nil {
					result = append(result, rng)
				}
			}
			return true
		})
	}
	return result, nil
}
<commit_msg>internal/lsp: stop cluttering logs with highlight errors<commit_after>// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package source

import (
	"context"
	"go/ast"

	"golang.org/x/tools/go/ast/astutil"
	"golang.org/x/tools/internal/lsp/protocol"
	"golang.org/x/tools/internal/span"
	"golang.org/x/tools/internal/telemetry/trace"
	errors "golang.org/x/xerrors"
)

func Highlight(ctx context.Context, view View, uri span.URI, pos protocol.Position) ([]protocol.Range, error) {
	ctx, done := trace.StartSpan(ctx, "source.Highlight")
	defer done()

	f, err := view.GetFile(ctx, uri)
	if err != nil {
		return nil, err
	}
	fh := view.Snapshot().Handle(ctx, f)
	ph := view.Session().Cache().ParseGoHandle(fh, ParseFull)
	file, m, _, err := ph.Parse(ctx)
	if err != nil {
		return nil, err
	}
	spn, err := m.PointSpan(pos)
	if err != nil {
		return nil, err
	}
	rng, err := spn.Range(m.Converter)
	if err != nil {
		return nil, err
	}
	path, _ := astutil.PathEnclosingInterval(file, rng.Start, rng.Start)
	if len(path) == 0 {
		return nil, errors.Errorf("no enclosing position found for %v:%v", int(pos.Line), int(pos.Character))
	}
	id, ok := path[0].(*ast.Ident)
	if !ok {
		// If the cursor is not within an identifier, return empty results.
		return []protocol.Range{}, nil
	}
	var result []protocol.Range
	if id.Obj != nil {
		ast.Inspect(path[len(path)-1], func(n ast.Node) bool {
			if n, ok := n.(*ast.Ident); ok && n.Obj == id.Obj {
				rng, err := nodeToProtocolRange(ctx, view, m, n)
				if err == nil {
					result = append(result, rng)
				}
			}
			return true
		})
	}
	return result, nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2020 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package observability

import (
	"context"
	"io"

	"go.uber.org/yarpc/api/transport"
	"go.uber.org/zap"
)

const (
	_successfulStreamReceive = "Successfully received stream message"
	_successfulStreamSend    = "Successfully sent stream message"
	_errorStreamReceive      = "Error receiving stream message"
	_errorStreamSend         = "Error sending stream message"
)

var _ transport.StreamCloser = (*streamWrapper)(nil)

type streamWrapper struct {
	transport.StreamCloser

	call   call
	edge   *streamEdge
	logger *zap.Logger
}

func (c call) WrapClientStream(stream *transport.ClientStream) *transport.ClientStream {
	wrapped, err := transport.NewClientStream(&streamWrapper{
		StreamCloser: stream,
		call:         c,
		edge:         c.edge.streaming,
		logger:       c.edge.logger,
	})
	if err != nil {
		// This will never happen since transport.NewClientStream only returns an
		// error for nil streams. In the nearly impossible situation where it does,
		// we fall back to using the original, unwrapped stream.
		c.edge.logger.DPanic("transport.ClientStream wrapping should never fail, streaming metrics are disabled")
		wrapped = stream
	}
	return wrapped
}

func (c call) WrapServerStream(stream *transport.ServerStream) *transport.ServerStream {
	wrapped, err := transport.NewServerStream(&streamWrapper{
		StreamCloser: nopCloser{stream},
		call:         c,
		edge:         c.edge.streaming,
		logger:       c.edge.logger,
	})
	if err != nil {
		// This will never happen since transport.NewServerStream only returns an
		// error for nil streams. In the nearly impossible situation where it does,
		// we fall back to using the original, unwrapped stream.
		c.edge.logger.DPanic("transport.ServerStream wrapping should never fail, streaming metrics are disabled")
		wrapped = stream
	}
	return wrapped
}

func (s *streamWrapper) SendMessage(ctx context.Context, msg *transport.StreamMessage) error {
	err := s.StreamCloser.SendMessage(ctx, msg)
	s.call.logStreamEvent(err, err == nil, _successfulStreamSend, _errorStreamSend)

	s.edge.sends.Inc()
	if err == nil {
		s.edge.sendSuccesses.Inc()
		return nil
	}

	if sendFailuresCounter, err2 := s.edge.sendFailures.Get(_error, errToMetricString(err)); err2 != nil {
		s.logger.DPanic("could not retrieve send failure counter", zap.Error(err2))
	} else {
		sendFailuresCounter.Inc()
	}
	return err
}

func (s *streamWrapper) ReceiveMessage(ctx context.Context) (*transport.StreamMessage, error) {
	msg, err := s.StreamCloser.ReceiveMessage(ctx)
	// Receiving EOF does not constitute an error for the purposes of metrics and alerts.
	// This is the only special case.
	// All other log events treat EOF as an error, including when sending a
	// message or concluding a handshake.
	s.call.logStreamEvent(err, err == nil || err == io.EOF, _successfulStreamReceive, _errorStreamReceive)

	s.edge.receives.Inc()
	if err == nil {
		s.edge.receiveSuccesses.Inc()
		return msg, nil
	}

	if recvFailureCounter, err2 := s.edge.receiveFailures.Get(_error, errToMetricString(err)); err2 != nil {
		s.logger.DPanic("could not retrieve receive failure counter", zap.Error(err2))
	} else {
		recvFailureCounter.Inc()
	}

	return msg, err
}

func (s *streamWrapper) Close(ctx context.Context) error {
	err := s.StreamCloser.Close(ctx)
	s.call.EndStream(err)
	return err
}

// This is a light wrapper so that we can re-use the same methods for
// instrumenting observability. The transport.ClientStream has an additional
// Close(ctx) method, unlike the transport.ServerStream.
type nopCloser struct {
	transport.Stream
}

func (c nopCloser) Close(ctx context.Context) error {
	return nil
}
<commit_msg>Measure stream receive EOF as success<commit_after>// Copyright (c) 2020 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package observability

import (
	"context"
	"io"

	"go.uber.org/yarpc/api/transport"
	"go.uber.org/zap"
)

const (
	_successfulStreamReceive = "Successfully received stream message"
	_successfulStreamSend    = "Successfully sent stream message"
	_errorStreamReceive      = "Error receiving stream message"
	_errorStreamSend         = "Error sending stream message"
)

var _ transport.StreamCloser = (*streamWrapper)(nil)

type streamWrapper struct {
	transport.StreamCloser

	call   call
	edge   *streamEdge
	logger *zap.Logger
}

func (c call) WrapClientStream(stream *transport.ClientStream) *transport.ClientStream {
	wrapped, err := transport.NewClientStream(&streamWrapper{
		StreamCloser: stream,
		call:         c,
		edge:         c.edge.streaming,
		logger:       c.edge.logger,
	})
	if err != nil {
		// This will never happen since transport.NewClientStream only returns an
		// error for nil streams. In the nearly impossible situation where it does,
		// we fall back to using the original, unwrapped stream.
		c.edge.logger.DPanic("transport.ClientStream wrapping should never fail, streaming metrics are disabled")
		wrapped = stream
	}
	return wrapped
}

func (c call) WrapServerStream(stream *transport.ServerStream) *transport.ServerStream {
	wrapped, err := transport.NewServerStream(&streamWrapper{
		StreamCloser: nopCloser{stream},
		call:         c,
		edge:         c.edge.streaming,
		logger:       c.edge.logger,
	})
	if err != nil {
		// This will never happen since transport.NewServerStream only returns an
		// error for nil streams. In the nearly impossible situation where it does,
		// we fall back to using the original, unwrapped stream.
		c.edge.logger.DPanic("transport.ServerStream wrapping should never fail, streaming metrics are disabled")
		wrapped = stream
	}
	return wrapped
}

func (s *streamWrapper) SendMessage(ctx context.Context, msg *transport.StreamMessage) error {
	err := s.StreamCloser.SendMessage(ctx, msg)
	s.call.logStreamEvent(err, err == nil, _successfulStreamSend, _errorStreamSend)

	s.edge.sends.Inc()
	if err == nil {
		s.edge.sendSuccesses.Inc()
		return nil
	}

	if sendFailuresCounter, err2 := s.edge.sendFailures.Get(_error, errToMetricString(err)); err2 != nil {
		s.logger.DPanic("could not retrieve send failure counter", zap.Error(err2))
	} else {
		sendFailuresCounter.Inc()
	}
	return err
}

func (s *streamWrapper) ReceiveMessage(ctx context.Context) (*transport.StreamMessage, error) {
	msg, err := s.StreamCloser.ReceiveMessage(ctx)
	// Receiving EOF does not constitute an error for the purposes of metrics and alerts.
	// This is the only special case.
	// All other log events treat EOF as an error, including when sending a
	// message or concluding a handshake.
	success := err == nil || err == io.EOF
	s.call.logStreamEvent(err, success, _successfulStreamReceive, _errorStreamReceive)

	s.edge.receives.Inc()
	if success {
		s.edge.receiveSuccesses.Inc()
		return msg, err
	}

	if recvFailureCounter, err2 := s.edge.receiveFailures.Get(_error, errToMetricString(err)); err2 != nil {
		s.logger.DPanic("could not retrieve receive failure counter", zap.Error(err2))
	} else {
		recvFailureCounter.Inc()
	}

	return msg, err
}

func (s *streamWrapper) Close(ctx context.Context) error {
	err := s.StreamCloser.Close(ctx)
	s.call.EndStream(err)
	return err
}

// This is a light wrapper so that we can re-use the same methods for
// instrumenting observability. The transport.ClientStream has an additional
// Close(ctx) method, unlike the transport.ServerStream.
type nopCloser struct {
	transport.Stream
}

func (c nopCloser) Close(ctx context.Context) error {
	return nil
}
<|endoftext|>


<commit_before>package cmd

import (
	"path/filepath"
)

// Shell is the interface that represents the interaction with the host shell.
type Shell interface {
	// Hook is the string that gets evaluated into the host shell config and
	// setups direnv as a prompt hook.
	Hook() (string, error)

	// Export outputs the ShellExport as an evaluatable string on the host shell
	Export(e ShellExport) string

	// Dump outputs and evaluatable string that sets the env in the host shell
	Dump(env Env) string
}

// ShellExport represents environment variables to add and remove on the host
// shell.
type ShellExport map[string]*string

// Add represents the additon of a new environment variable
func (e ShellExport) Add(key, value string) {
	e[key] = &value
}

// Remove represents the removal of a given `key` environment variable.
func (e ShellExport) Remove(key string) {
	e[key] = nil
}

// DetectShell returns a Shell instance from the given target.
//
// target is usually $0 and can also be prefixed by `-`
func DetectShell(target string) Shell {
	target = filepath.Base(target)
	// $0 starts with "-"
	if target[0:1] == "-" {
		target = target[1:]
	}

	switch target {
	case "bash":
		return Bash
	case "zsh":
		return Zsh
	case "fish":
		return Fish
	case "gzenv":
		return GzEnv
	case "vim":
		return Vim
	case "tcsh":
		return Tcsh
	case "json":
		return JSON
	case "elvish":
		return Elvish
	}

	return nil
}
<commit_msg>Sort shells in DetectShell<commit_after>package cmd

import (
	"path/filepath"
)

// Shell is the interface that represents the interaction with the host shell.
type Shell interface {
	// Hook is the string that gets evaluated into the host shell config and
	// setups direnv as a prompt hook.
	Hook() (string, error)

	// Export outputs the ShellExport as an evaluatable string on the host shell
	Export(e ShellExport) string

	// Dump outputs and evaluatable string that sets the env in the host shell
	Dump(env Env) string
}

// ShellExport represents environment variables to add and remove on the host
// shell.
type ShellExport map[string]*string

// Add represents the additon of a new environment variable
func (e ShellExport) Add(key, value string) {
	e[key] = &value
}

// Remove represents the removal of a given `key` environment variable.
func (e ShellExport) Remove(key string) {
	e[key] = nil
}

// DetectShell returns a Shell instance from the given target.
//
// target is usually $0 and can also be prefixed by `-`
func DetectShell(target string) Shell {
	target = filepath.Base(target)
	// $0 starts with "-"
	if target[0:1] == "-" {
		target = target[1:]
	}

	switch target {
	case "bash":
		return Bash
	case "elvish":
		return Elvish
	case "fish":
		return Fish
	case "gzenv":
		return GzEnv
	case "json":
		return JSON
	case "tcsh":
		return Tcsh
	case "vim":
		return Vim
	case "zsh":
		return Zsh
	}

	return nil
}
<|endoftext|>


<commit_before>package semerrgroup

import (
	"sync"
	"testing"
	"time"

	"github.com/stretchr/testify/require"
)

func TestSemaphore(t *testing.T) {
	var g = New(4)
	var lock sync.Mutex
	var counter int
	for i := 0; i < 10; i++ {
		g.Go(func() error {
			time.Sleep(10 * time.Millisecond)
			lock.Lock()
			counter++
			lock.Unlock()
			return nil
		})
	}
	require.NoError(t, g.Wait())
	require.Equal(t, counter, 10)
}

func TestSemaphoreOrder(t *testing.T) {
	num := 10
	var g = New(1)
	output := make(chan int)
	go func() {
		for i := 0; i < num; i++ {
			require.Equal(t, <-output, i)
		}
		require.NoError(t, g.Wait())
	}()
	for i := 0; i < num; i++ {
		j := i
		g.Go(func() error {
			output <- j
			return nil
		})
	}
	require.NoError(t, g.Wait())
}
<commit_msg>test: fix race<commit_after>package semerrgroup

import (
	"fmt"
	"sync"
	"testing"
	"time"

	"github.com/stretchr/testify/require"
)

func TestSemaphore(t *testing.T) {
	var g = New(4)
	var lock sync.Mutex
	var counter int
	for i := 0; i < 10; i++ {
		g.Go(func() error {
			time.Sleep(10 * time.Millisecond)
			lock.Lock()
			counter++
			lock.Unlock()
			return nil
		})
	}
	require.NoError(t, g.Wait())
	require.Equal(t, counter, 10)
}

func TestSemaphoreOrder(t *testing.T) {
	var num = 10
	var g = New(1)
	var output = []int{}
	for i := 0; i < num; i++ {
		i := i
		g.Go(func() error {
			output = append(output, i)
			return nil
		})
	}
	require.NoError(t, g.Wait())
	require.Equal(t, []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, output)
}

func TestSemaphoreOrderError(t *testing.T) {
	var g = New(1)
	var output = []int{}
	for i := 0; i < 10; i++ {
		i := i
		g.Go(func() error {
			output = append(output, i)
			return fmt.Errorf("fake err")
		})
	}
	require.EqualError(t, g.Wait(), "fake err")
	require.Equal(t, []int{0}, output)
}
<|endoftext|>


<commit_before>package sshd

import (
	"context"
	"fmt"
	"net"
	"net/http"
	"sync"
	"time"

	"github.com/pires/go-proxyproto"
	"golang.org/x/crypto/ssh"

	"gitlab.com/gitlab-org/gitlab-shell/internal/config"
	"gitlab.com/gitlab-org/gitlab-shell/internal/metrics"

	"gitlab.com/gitlab-org/labkit/correlation"
	"gitlab.com/gitlab-org/labkit/log"
)

type status int

const (
	StatusStarting status = iota
	StatusReady
	StatusOnShutdown
	StatusClosed
	ProxyHeaderTimeout = 90 * time.Second
)

type Server struct {
	Config *config.Config

	status       status
	statusMu     sync.RWMutex
	wg           sync.WaitGroup
	listener     net.Listener
	serverConfig *serverConfig
}

func NewServer(cfg *config.Config) (*Server, error) {
	serverConfig, err := newServerConfig(cfg)
	if err != nil {
		return nil, err
	}

	return &Server{Config: cfg, serverConfig: serverConfig}, nil
}

func (s *Server) ListenAndServe(ctx context.Context) error {
	if err := s.listen(ctx); err != nil {
		return err
	}
	defer s.listener.Close()

	s.serve(ctx)

	return nil
}

func (s *Server) Shutdown() error {
	if s.listener == nil {
		return nil
	}

	s.changeStatus(StatusOnShutdown)

	return s.listener.Close()
}

func (s *Server) MonitoringServeMux() *http.ServeMux {
	mux := http.NewServeMux()

	mux.HandleFunc(s.Config.Server.ReadinessProbe, func(w http.ResponseWriter, r *http.Request) {
		if s.getStatus() == StatusReady {
			w.WriteHeader(http.StatusOK)
		} else {
			w.WriteHeader(http.StatusServiceUnavailable)
		}
	})

	mux.HandleFunc(s.Config.Server.LivenessProbe, func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusOK)
	})

	return mux
}

func (s *Server) listen(ctx context.Context) error {
	sshListener, err := net.Listen("tcp", s.Config.Server.Listen)
	if err != nil {
		return fmt.Errorf("failed to listen for connection: %w", err)
	}

	if s.Config.Server.ProxyProtocol {
		sshListener = &proxyproto.Listener{
			Listener:          sshListener,
			Policy:            unconditionalRequirePolicy,
			ReadHeaderTimeout: ProxyHeaderTimeout,
		}

		log.ContextLogger(ctx).Info("Proxy protocol is enabled")
	}

	log.WithContextFields(ctx, log.Fields{"tcp_address": sshListener.Addr().String()}).Info("Listening for SSH connections")

	s.listener = sshListener

	return nil
}

func (s *Server) serve(ctx context.Context) {
	s.changeStatus(StatusReady)

	for {
		nconn, err := s.listener.Accept()
		if err != nil {
			if s.getStatus() == StatusOnShutdown {
				break
			}

			log.ContextLogger(ctx).WithError(err).Warn("Failed to accept connection")
			continue
		}

		s.wg.Add(1)
		go s.handleConn(ctx, nconn)
	}

	s.wg.Wait()

	s.changeStatus(StatusClosed)
}

func (s *Server) changeStatus(st status) {
	s.statusMu.Lock()
	s.status = st
	s.statusMu.Unlock()
}

func (s *Server) getStatus() status {
	s.statusMu.RLock()
	defer s.statusMu.RUnlock()

	return s.status
}

func (s *Server) handleConn(ctx context.Context, nconn net.Conn) {
	success := false

	metrics.SshdConnectionsInFlight.Inc()
	started := time.Now()
	defer func() {
		metrics.SshdConnectionsInFlight.Dec()
		metrics.SshdSessionDuration.Observe(time.Since(started).Seconds())

		metrics.SliSshdSessionsTotal.Inc()
		if !success {
			metrics.SliSshdSessionsErrorsTotal.Inc()
		}
	}()

	remoteAddr := nconn.RemoteAddr().String()

	defer s.wg.Done()
	defer nconn.Close()

	ctx, cancel := context.WithCancel(correlation.ContextWithCorrelation(ctx, correlation.SafeRandomID()))
	defer cancel()

	ctxlog := log.WithContextFields(ctx, log.Fields{"remote_addr": remoteAddr})

	// Prevent a panic in a single connection from taking out the whole server
	defer func() {
		if err := recover(); err != nil {
			ctxlog.Warn("panic handling session")
		}
	}()

	ctxlog.Info("server: handleConn: start")

	sconn, chans, reqs, err := ssh.NewServerConn(nconn, s.serverConfig.get(ctx))
	if err != nil {
		ctxlog.WithError(err).Error("server: handleConn: failed to initialize SSH connection")
		return
	}
	go ssh.DiscardRequests(reqs)

	var establishSessionDuration float64
	conn := newConnection(s.Config.Server.ConcurrentSessionsLimit, remoteAddr)
	conn.handle(ctx, chans, func(ctx context.Context, channel ssh.Channel, requests <-chan *ssh.Request) {
		establishSessionDuration = time.Since(started).Seconds()
		metrics.SshdSessionEstablishedDuration.Observe(establishSessionDuration)

		session := &session{
			cfg:         s.Config,
			channel:     channel,
			gitlabKeyId: sconn.Permissions.Extensions["key-id"],
			remoteAddr:  remoteAddr,
		}

		session.handle(ctx, requests)

		success = session.success
	})

	ctxlog.WithFields(log.Fields{
		"duration_s":                   time.Since(started).Seconds(),
		"establish_session_duration_s": establishSessionDuration,
	}).Info("server: handleConn: done")
}

func unconditionalRequirePolicy(_ net.Addr) (proxyproto.Policy, error) {
	return proxyproto.REQUIRE, nil
}
<commit_msg>Log the error that happens on sconn.Wait()<commit_after>package sshd

import (
	"context"
	"fmt"
	"net"
	"net/http"
	"sync"
	"time"

	"github.com/pires/go-proxyproto"
	"golang.org/x/crypto/ssh"

	"gitlab.com/gitlab-org/gitlab-shell/internal/config"
	"gitlab.com/gitlab-org/gitlab-shell/internal/metrics"

	"gitlab.com/gitlab-org/labkit/correlation"
	"gitlab.com/gitlab-org/labkit/log"
)

type status int

const (
	StatusStarting status = iota
	StatusReady
	StatusOnShutdown
	StatusClosed
	ProxyHeaderTimeout = 90 * time.Second
)

type Server struct {
	Config *config.Config

	status       status
	statusMu     sync.RWMutex
	wg           sync.WaitGroup
	listener     net.Listener
	serverConfig *serverConfig
}

func NewServer(cfg *config.Config) (*Server, error) {
	serverConfig, err := newServerConfig(cfg)
	if err != nil {
		return nil, err
	}

	return &Server{Config: cfg, serverConfig: serverConfig}, nil
}

func (s *Server) ListenAndServe(ctx context.Context) error {
	if err := s.listen(ctx); err != nil {
		return err
	}
	defer s.listener.Close()

	s.serve(ctx)

	return nil
}

func (s *Server) Shutdown() error {
	if s.listener == nil {
		return nil
	}

	s.changeStatus(StatusOnShutdown)

	return s.listener.Close()
}

func (s *Server) MonitoringServeMux() *http.ServeMux {
	mux := http.NewServeMux()

	mux.HandleFunc(s.Config.Server.ReadinessProbe, func(w http.ResponseWriter, r *http.Request) {
		if s.getStatus() == StatusReady {
			w.WriteHeader(http.StatusOK)
		} else {
			w.WriteHeader(http.StatusServiceUnavailable)
		}
	})

	mux.HandleFunc(s.Config.Server.LivenessProbe, func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusOK)
	})

	return mux
}

func (s *Server) listen(ctx context.Context) error {
	sshListener, err := net.Listen("tcp", s.Config.Server.Listen)
	if err != nil {
		return fmt.Errorf("failed to listen for connection: %w", err)
	}

	if s.Config.Server.ProxyProtocol {
		sshListener = &proxyproto.Listener{
			Listener:          sshListener,
			Policy:            unconditionalRequirePolicy,
			ReadHeaderTimeout: ProxyHeaderTimeout,
		}

		log.ContextLogger(ctx).Info("Proxy protocol is enabled")
	}

	log.WithContextFields(ctx, log.Fields{"tcp_address": sshListener.Addr().String()}).Info("Listening for SSH connections")

	s.listener = sshListener

	return nil
}

func (s *Server) serve(ctx context.Context) {
	s.changeStatus(StatusReady)

	for {
		nconn, err := s.listener.Accept()
		if err != nil {
			if s.getStatus() == StatusOnShutdown {
				break
			}

			log.ContextLogger(ctx).WithError(err).Warn("Failed to accept connection")
			continue
		}

		s.wg.Add(1)
		go s.handleConn(ctx, nconn)
	}

	s.wg.Wait()

	s.changeStatus(StatusClosed)
}

func (s *Server) changeStatus(st status) {
	s.statusMu.Lock()
	s.status = st
	s.statusMu.Unlock()
}

func (s *Server) getStatus() status {
	s.statusMu.RLock()
	defer s.statusMu.RUnlock()

	return s.status
}

func (s *Server) handleConn(ctx context.Context, nconn net.Conn) {
	success := false

	metrics.SshdConnectionsInFlight.Inc()
	started := time.Now()
	defer func() {
		metrics.SshdConnectionsInFlight.Dec()
		metrics.SshdSessionDuration.Observe(time.Since(started).Seconds())

		metrics.SliSshdSessionsTotal.Inc()
		if !success {
			metrics.SliSshdSessionsErrorsTotal.Inc()
		}
	}()

	remoteAddr := nconn.RemoteAddr().String()

	defer s.wg.Done()
	defer nconn.Close()

	ctx, cancel := context.WithCancel(correlation.ContextWithCorrelation(ctx, correlation.SafeRandomID()))
	defer cancel()

	ctxlog := log.WithContextFields(ctx, log.Fields{"remote_addr": remoteAddr})

	// Prevent a panic in a single connection from taking out the whole server
	defer func() {
		if err := recover(); err != nil {
			ctxlog.Warn("panic handling session")
		}
	}()

	ctxlog.Info("server: handleConn: start")

	sconn, chans, reqs, err := ssh.NewServerConn(nconn, s.serverConfig.get(ctx))
	if err != nil {
		ctxlog.WithError(err).Error("server: handleConn: failed to initialize SSH connection")
		return
	}
	go ssh.DiscardRequests(reqs)

	var establishSessionDuration float64
	conn := newConnection(s.Config.Server.ConcurrentSessionsLimit, remoteAddr)
	conn.handle(ctx, chans, func(ctx context.Context, channel ssh.Channel, requests <-chan *ssh.Request) {
		establishSessionDuration = time.Since(started).Seconds()
		metrics.SshdSessionEstablishedDuration.Observe(establishSessionDuration)

		session := &session{
			cfg:         s.Config,
			channel:     channel,
			gitlabKeyId: sconn.Permissions.Extensions["key-id"],
			remoteAddr:  remoteAddr,
		}

		session.handle(ctx, requests)

		success = session.success
	})

	reason := sconn.Wait()
	ctxlog.WithFields(log.Fields{
		"duration_s":                   time.Since(started).Seconds(),
		"establish_session_duration_s": establishSessionDuration,
		"reason":                       reason,
	}).Info("server: handleConn: done")
}

func unconditionalRequirePolicy(_ net.Addr) (proxyproto.Policy, error) {
	return proxyproto.REQUIRE, nil
}
<|endoftext|>


<commit_before>/*
 * Copyright 2018 Arm Limited.
 * SPDX-License-Identifier: Apache-2.0
 *
 * 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 core

import (
	"errors"
	"fmt"
	"strings"
)

type toolchain interface {
	getAssembler() (tool string, flags []string)
	getCCompiler() (tool string, flags []string)
	getCXXCompiler() (tool string, flags []string)
	getArchiver() (tool string, flags []string)
}

type toolchainGnuNative struct {
	arBinary  string
	asBinary  string
	gccBinary string
	gxxBinary string
}

type toolchainGnuCross struct {
	toolchainGnuNative
	prefix      string
	targetFlags []string
}

func (tc toolchainGnuNative) getArchiver() (tool string, flags []string) {
	tool = tc.arBinary
	return
}

func (tc toolchainGnuCross) getArchiver() (tool string, flags []string) {
	nativeTool, nativeFlags := tc.toolchainGnuNative.getArchiver()
	tool = tc.prefix + nativeTool
	flags = nativeFlags
	return
}

func (tc toolchainGnuNative) getAssembler() (tool string, flags []string) {
	tool = tc.asBinary
	return
}

func (tc toolchainGnuCross) getAssembler() (tool string, flags []string) {
	nativeTool, nativeFlags := tc.toolchainGnuNative.getAssembler()
	tool = tc.prefix + nativeTool
	flags = nativeFlags
	return
}

func (tc toolchainGnuNative) getCCompiler() (tool string, flags []string) {
	tool = tc.gccBinary
	return
}

func (tc toolchainGnuCross) getCCompiler() (tool string, flags []string) {
	nativeTool, nativeFlags := tc.toolchainGnuNative.getCCompiler()
	tool = tc.prefix + nativeTool
	flags = append(nativeFlags, tc.targetFlags...)
	return
}

func (tc toolchainGnuNative) getCXXCompiler() (tool string, flags []string) {
	tool = tc.gxxBinary
	return
}

func (tc toolchainGnuCross) getCXXCompiler() (tool string, flags []string) {
	nativeTool, nativeFlags := tc.toolchainGnuNative.getCXXCompiler()
	tool = tc.prefix + nativeTool
	flags = append(nativeFlags, tc.targetFlags...)
	return
}

func newToolchainGnuNative(config *bobConfig) (tc toolchainGnuNative) {
	props := config.Properties
	tc.arBinary = props.GetString("ar_binary")
	tc.asBinary = props.GetString("as_binary")
	tc.gccBinary = props.GetString("gcc_binary")
	tc.gxxBinary = props.GetString("gxx_binary")
	return
}

func newToolchainGnuCross(config *bobConfig) (tc toolchainGnuCross) {
	props := config.Properties
	tc.toolchainGnuNative = newToolchainGnuNative(config)
	tc.prefix = props.GetString("toolchain_prefix")
	tc.targetFlags = strings.Split(props.GetString("gcc_target_flags"), " ")
	return
}

type toolchainClangNative struct {
	clangBinary   string
	clangxxBinary string
	// Use the GNU toolchain's 'ar' and 'as'
	gnu toolchainGnuNative
}

type toolchainClangCross struct {
	toolchainClangNative
	target           string
	sysroot          string
	toolchainVersion string
	// Use the GNU toolchain's 'ar' and 'as'
	gnu toolchainGnuCross
}

func (tc toolchainClangNative) getArchiver() (string, []string) {
	return tc.gnu.getArchiver()
}

func (tc toolchainClangCross) getArchiver() (string, []string) {
	return tc.gnu.getArchiver()
}

func (tc toolchainClangNative) getAssembler() (string, []string) {
	return tc.gnu.getAssembler()
}

func (tc toolchainClangCross) getAssembler() (string, []string) {
	return tc.gnu.getAssembler()
}

func (tc toolchainClangNative) getCCompiler() (string, []string) {
	return tc.clangBinary, []string{}
}

func (tc toolchainClangCross) getCCompiler() (tool string, flags []string) {
	tool, flags = tc.toolchainClangNative.getCCompiler()

	if tc.target != "" {
		flags = append(flags, "-target", tc.target)
	}
	if tc.sysroot != "" {
		flags = append(flags, "--sysroot", tc.sysroot)
	}

	return tool, flags
}

func (tc toolchainClangNative) getCXXCompiler() (string, []string) {
	return tc.clangxxBinary, []string{}
}

func (tc toolchainClangCross) getCXXCompiler() (tool string, flags []string) {
	tool, flags = tc.toolchainClangNative.getCXXCompiler()

	if tc.target != "" {
		flags = append(flags, "-target", tc.target)
	}
	if tc.sysroot != "" {
		flags = append(flags,
			"--sysroot", tc.sysroot,
			"-isystem", fmt.Sprintf("%s/../include/c++/%s",
				tc.sysroot, tc.toolchainVersion),
			"-isystem", fmt.Sprintf("%s/../include/c++/%s/%s",
				tc.sysroot, tc.toolchainVersion,
				tc.target))
	}

	return tool, flags
}

func newToolchainClangNative(config *bobConfig) (tc toolchainClangNative) {
	props := config.Properties
	tc.clangBinary = props.GetString("clang_binary")
	tc.clangxxBinary = props.GetString("clangxx_binary")

	tc.gnu = newToolchainGnuNative(config)

	return
}

func newToolchainClangCross(config *bobConfig) (tc toolchainClangCross) {
	props := config.Properties
	tc.toolchainClangNative = newToolchainClangNative(config)
	tc.target = props.GetString("clang_target")
	tc.sysroot = props.GetString("clang_sysroot")
	tc.toolchainVersion = props.GetString("target_toolchain_version")

	if tc.sysroot != "" {
		if tc.target == "" {
			panic(errors.New("CLANG_TARGET is not set"))
		}
		if tc.toolchainVersion == "" {
			panic(errors.New("TARGET_TOOLCHAIN_VERSION is not set"))
		}
	}

	tc.gnu = newToolchainGnuCross(config)

	return
}

type toolchainSet struct {
	host   toolchain
	target toolchain
}

func (tcs *toolchainSet) getToolchain(tgtType string) toolchain {
	if tgtType == tgtTypeHost {
		return tcs.host
	}
	return tcs.target
}

func (tcs *toolchainSet) parseConfig(config *bobConfig) {
	props := config.Properties

	if props.GetBool("toolchain_clang") {
		tcs.host = newToolchainClangNative(config)
		tcs.target = newToolchainClangCross(config)
	} else if props.GetBool("toolchain_gnu") {
		tcs.host = newToolchainGnuNative(config)
		tcs.target = newToolchainGnuCross(config)
	} else {
		panic(errors.New("no usable compiler toolchain configured"))
	}
}
<commit_msg>Move shared Clang toolchain code into new type<commit_after>/*
 * Copyright 2018 Arm Limited.
 * SPDX-License-Identifier: Apache-2.0
 *
 * 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 core

import (
	"errors"
	"fmt"
	"strings"
)

type toolchain interface {
	getAssembler() (tool string, flags []string)
	getCCompiler() (tool string, flags []string)
	getCXXCompiler() (tool string, flags []string)
	getArchiver() (tool string, flags []string)
}

type toolchainGnuNative struct {
	arBinary  string
	asBinary  string
	gccBinary string
	gxxBinary string
}

type toolchainGnuCross struct {
	toolchainGnuNative
	prefix      string
	targetFlags []string
}

func (tc toolchainGnuNative) getArchiver() (tool string, flags []string) {
	tool = tc.arBinary
	return
}

func (tc toolchainGnuCross) getArchiver() (tool string, flags []string) {
	nativeTool, nativeFlags := tc.toolchainGnuNative.getArchiver()
	tool = tc.prefix + nativeTool
	flags = nativeFlags
	return
}

func (tc toolchainGnuNative) getAssembler() (tool string, flags []string) {
	tool = tc.asBinary
	return
}

func (tc toolchainGnuCross) getAssembler() (tool string, flags []string) {
	nativeTool, nativeFlags := tc.toolchainGnuNative.getAssembler()
	tool = tc.prefix + nativeTool
	flags = nativeFlags
	return
}

func (tc toolchainGnuNative) getCCompiler() (tool string, flags []string) {
	tool = tc.gccBinary
	return
}

func (tc toolchainGnuCross) getCCompiler() (tool string, flags []string) {
	nativeTool, nativeFlags := tc.toolchainGnuNative.getCCompiler()
	tool = tc.prefix + nativeTool
	flags = append(nativeFlags, tc.targetFlags...)
	return
}

func (tc toolchainGnuNative) getCXXCompiler() (tool string, flags []string) {
	tool = tc.gxxBinary
	return
}

func (tc toolchainGnuCross) getCXXCompiler() (tool string, flags []string) {
	nativeTool, nativeFlags := tc.toolchainGnuNative.getCXXCompiler()
	tool = tc.prefix + nativeTool
	flags = append(nativeFlags, tc.targetFlags...)
	return
}

func newToolchainGnuNative(config *bobConfig) (tc toolchainGnuNative) {
	props := config.Properties
	tc.arBinary = props.GetString("ar_binary")
	tc.asBinary = props.GetString("as_binary")
	tc.gccBinary = props.GetString("gcc_binary")
	tc.gxxBinary = props.GetString("gxx_binary")
	return
}

func newToolchainGnuCross(config *bobConfig) (tc toolchainGnuCross) {
	props := config.Properties
	tc.toolchainGnuNative = newToolchainGnuNative(config)
	tc.prefix = props.GetString("toolchain_prefix")
	tc.targetFlags = strings.Split(props.GetString("gcc_target_flags"), " ")
	return
}

type toolchainClangCommon struct {
	// Options read from the config:
	clangBinary   string
	clangxxBinary string

	// Use the GNU toolchain's 'ar' and 'as'
	gnu toolchain

	// Calculated during toolchain initialization:
	cflags   []string // Flags for both C and C++
	cxxflags []string // Flags just for C++
}

type toolchainClangNative struct {
	toolchainClangCommon
}

type toolchainClangCross struct {
	toolchainClangCommon
	target           string
	sysroot          string
	toolchainVersion string
}

func (tc toolchainClangCommon) getArchiver() (string, []string) {
	return tc.gnu.getArchiver()
}

func (tc toolchainClangCommon) getAssembler() (string, []string) {
	return tc.gnu.getAssembler()
}

func (tc toolchainClangCommon) getCCompiler() (string, []string) {
	return tc.clangBinary, tc.cflags
}

func (tc toolchainClangCommon) getCXXCompiler() (string, []string) {
	return tc.clangxxBinary, tc.cxxflags
}

func newToolchainClangCommon(config *bobConfig, gnu toolchain) (tc toolchainClangCommon) {
	props := config.Properties
	tc.clangBinary = props.GetString("clang_binary")
	tc.clangxxBinary = props.GetString("clangxx_binary")
	tc.gnu = gnu
	return
}

func newToolchainClangNative(config *bobConfig) (tc toolchainClangNative) {
	gnu := newToolchainGnuNative(config)
	tc.toolchainClangCommon = newToolchainClangCommon(config, gnu)
	return
}

func newToolchainClangCross(config *bobConfig) (tc toolchainClangCross) {
	gnu := newToolchainGnuCross(config)
	tc.toolchainClangCommon = newToolchainClangCommon(config, gnu)

	props := config.Properties
	tc.target = props.GetString("clang_target")
	tc.sysroot = props.GetString("clang_sysroot")
	tc.toolchainVersion = props.GetString("target_toolchain_version")

	if tc.sysroot != "" {
		if tc.target == "" {
			panic(errors.New("CLANG_TARGET is not set"))
		}
		if tc.toolchainVersion == "" {
			panic(errors.New("TARGET_TOOLCHAIN_VERSION is not set"))
		}
		tc.cflags = append(tc.cflags, "--sysroot", tc.sysroot)

		tc.cxxflags = append(tc.cxxflags,
			"-isystem", fmt.Sprintf("%s/../include/c++/%s",
				tc.sysroot, tc.toolchainVersion),
			"-isystem", fmt.Sprintf("%s/../include/c++/%s/%s",
				tc.sysroot, tc.toolchainVersion,
				tc.target))
	}
	if tc.target != "" {
		tc.cflags = append(tc.cflags, "-target", tc.target)
	}

	// Combine cflags and cxxflags once here, to avoid appending during
	// every call to getCXXCompiler().
	tc.cxxflags = append(tc.cflags, tc.cxxflags...)

	return
}

type toolchainSet struct {
	host   toolchain
	target toolchain
}

func (tcs *toolchainSet) getToolchain(tgtType string) toolchain {
	if tgtType == tgtTypeHost {
		return tcs.host
	}
	return tcs.target
}

func (tcs *toolchainSet) parseConfig(config *bobConfig) {
	props := config.Properties

	if props.GetBool("toolchain_clang") {
		tcs.host = newToolchainClangNative(config)
		tcs.target = newToolchainClangCross(config)
	} else if props.GetBool("toolchain_gnu") {
		tcs.host = newToolchainGnuNative(config)
		tcs.target = newToolchainGnuCross(config)
	} else {
		panic(errors.New("no usable compiler toolchain configured"))
	}
}
<|endoftext|>


<commit_before>package dcpu

type Word uint16

type Registers struct {
	A, B, C, X, Y, Z, I, J Word
	PC                     Word
	SP                     Word
	O                      Word
}

type State struct {
	Registers
	Ram [0x10000]Word
}

func (s *State) translateOperand(op Word) (val Word, assignable *Word) {
	switch op {
	// 0-7: register value - register values
	case 0:
		assignable = &s.A
	case 1:
		assignable = &s.B
	case 2:
		assignable = &s.C
	case 3:
		assignable = &s.X
	case 4:
		assignable = &s.Y
	case 5:
		assignable = &s.Z
	case 6:
		assignable = &s.I
	case 7:
		assignable = &s.J
	// 8-15: [register value] - value at address in registries
	case 8:
		assignable = &s.Ram[s.A]
	case 9:
		assignable = &s.Ram[s.B]
	case 10:
		assignable = &s.Ram[s.C]
	case 11:
		assignable = &s.Ram[s.X]
	case 12:
		assignable = &s.Ram[s.Y]
	case 13:
		assignable = &s.Ram[s.Z]
	case 14:
		assignable = &s.Ram[s.I]
	case 15:
		assignable = &s.Ram[s.J]
	// 16-23: [next word of ram + register value] - memory address offset by register value
	case 16:
		assignable = &s.Ram[s.PC+s.A]
		s.PC++
	case 17:
		assignable = &s.Ram[s.PC+s.B]
		s.PC++
	case 18:
		assignable = &s.Ram[s.PC+s.C]
		s.PC++
	case 19:
		assignable = &s.Ram[s.PC+s.X]
		s.PC++
	case 20:
		assignable = &s.Ram[s.PC+s.Y]
		s.PC++
	case 21:
		assignable = &s.Ram[s.PC+s.Z]
		s.PC++
	case 22:
		assignable = &s.Ram[s.PC+s.I]
		s.PC++
	case 23:
		assignable = &s.Ram[s.PC+s.J]
		s.PC++
	// 24: POP - value at stack address, then increases stack counter
	case 24:
		assignable = &s.Ram[s.SP]
		s.SP++
	// 25: PEEK - value at stack address
	case 25:
		assignable = &s.Ram[s.SP]
	case 26:
		// 26: PUSH - decreases stack address, then value at stack address
		s.SP--
		assignable = &s.Ram[s.SP]
	// 27: SP - current stack pointer value - current stack address
	case 27:
		assignable = &s.SP
	// 28: PC - program counter- current program counter
	case 28:
		assignable = &s.PC
	// 29: O - overflow - current value of the overflow
	case 29:
		assignable = &s.O
	// 30: [next word of ram] - memory address
	case 30:
		assignable = &s.Ram[s.Ram[s.PC]]
		s.PC++
	// 31: next word of ram - literal, does nothing on assign
	case 31:
		val = s.Ram[s.PC]
		s.PC++
	default:
		if op >= 64 {
			panic("Out of bounds operand")
		}
		val = op - 32
	}
	if assignable != nil {
		val = *assignable
	}
	return
}

// Step iterates the CPU by one instruction.
func (s *State) Step() {
	// fetch
	opcode := s.Ram[s.PC]
	s.PC++

	// decode
	ins := opcode & 0xF
	a := (opcode >> 4) & 0x3F
	b := (opcode >> 10) & 0x3F
	var assignable *Word

	a, assignable = s.translateOperand(a)
	b, _ = s.translateOperand(b)

	// execute
	var val Word
	switch ins {
	case 0:
		// marked RESERVED, lets just treat it as a NOP
	case 1:
		// SET a, b - sets value of b to a
		val = b
	case 2:
		// ADD a, b - adds b to a, sets O
		result := uint32(a) + uint32(b)
		val = Word(result & 0xFFFF)
		s.O = Word(result >> 16)
	case 3:
		// SUB a, b - subtracts b from a, sets O
		result := uint32(a) - uint32(b)
		val = Word(result & 0xFFFF)
		s.O = Word(result >> 16)
	case 4:
		// MUL a, b - multiplies a by b, sets O
		result := uint32(a) * uint32(b)
		val = Word(result & 0xFFFF)
		s.O = Word(result >> 16)
	case 5:
		// DIV a, b - divides a by b, sets O
		// NB: how can this overflow?
		// assuming for the moment that O is supposed to be the mod
		val = a / b
		s.O = a % b
	case 6:
		// MOD a, b - remainder of a over b
		val = a % b
	case 7:
		// SHL a, b - shifts a left b places, sets O
		result := uint32(a) << uint32(b)
		val = Word(result & 0xFFFF)
		s.O = Word(result >> 16)
	case 8:
		// SHR a, b - shifts a right b places, sets O
		// NB: how can this overflow?
		val = a >> b
	case 9:
		// AND a, b - binary and of a and b
		val = a & b
	case 10:
		// BOR a, b - binary or of a and b
		val = a | b
	case 11:
		// XOR a, b - binary xor of a and b
		val = a ^ b
	case 12:
		// IFE a, b - skips one instruction if a!=b
		if a != b {
			s.PC++
		}
	case 13:
		// IFN a, b - skips one instruction if a==b
		if a == b {
			s.PC++
		}
	case 14:
		// IFG a, b - skips one instruction if a<=b
		if a <= b {
			s.PC++
		}
	case 15:
		// IFB a, b - skips one instruction if (a&b)==0
		if (a & b) == 0 {
			s.PC++
		}
	default:
		panic("Out of bounds opcode")
	}

	// store
	if ins >= 1 && ins <= 11 && assignable != nil {
		*assignable = val
	}
}
<commit_msg>Fix the IF* opcodes to skip multi-word instructions<commit_after>package dcpu

type Word uint16

type Registers struct {
	A, B, C, X, Y, Z, I, J Word
	PC                     Word
	SP                     Word
	O                      Word
}

type State struct {
	Registers
	Ram [0x10000]Word
}

func decodeOpcode(opcode Word) (oooo, aaaaaa, bbbbbb Word) {
	oooo = opcode & 0xF
	aaaaaa = (opcode >> 4) & 0x3F
	bbbbbb = (opcode >> 10) & 0x3F
	return
}

// wordCount counts the number of words in the instruction identified by the given opcode
func wordCount(opcode Word) Word {
	_, a, b := decodeOpcode(opcode)
	count := Word(1)
	switch {
	case a >= 16 && a <= 23:
	case a == 30:
	case a == 31:
		count++
	}
	switch {
	case b >= 16 && b <= 23:
	case b == 30:
	case b == 31:
		count++
	}
	return count
}

func (s *State) translateOperand(op Word) (val Word, assignable *Word) {
	switch op {
	// 0-7: register value - register values
	case 0:
		assignable = &s.A
	case 1:
		assignable = &s.B
	case 2:
		assignable = &s.C
	case 3:
		assignable = &s.X
	case 4:
		assignable = &s.Y
	case 5:
		assignable = &s.Z
	case 6:
		assignable = &s.I
	case 7:
		assignable = &s.J
	// 8-15: [register value] - value at address in registries
	case 8:
		assignable = &s.Ram[s.A]
	case 9:
		assignable = &s.Ram[s.B]
	case 10:
		assignable = &s.Ram[s.C]
	case 11:
		assignable = &s.Ram[s.X]
	case 12:
		assignable = &s.Ram[s.Y]
	case 13:
		assignable = &s.Ram[s.Z]
	case 14:
		assignable = &s.Ram[s.I]
	case 15:
		assignable = &s.Ram[s.J]
	// 16-23: [next word of ram + register value] - memory address offset by register value
	case 16:
		assignable = &s.Ram[s.PC+s.A]
		s.PC++
	case 17:
		assignable = &s.Ram[s.PC+s.B]
		s.PC++
	case 18:
		assignable = &s.Ram[s.PC+s.C]
		s.PC++
	case 19:
		assignable = &s.Ram[s.PC+s.X]
		s.PC++
	case 20:
		assignable = &s.Ram[s.PC+s.Y]
		s.PC++
	case 21:
		assignable = &s.Ram[s.PC+s.Z]
		s.PC++
	case 22:
		assignable = &s.Ram[s.PC+s.I]
		s.PC++
	case 23:
		assignable = &s.Ram[s.PC+s.J]
		s.PC++
	// 24: POP - value at stack address, then increases stack counter
	case 24:
		assignable = &s.Ram[s.SP]
		s.SP++
	// 25: PEEK - value at stack address
	case 25:
		assignable = &s.Ram[s.SP]
	case 26:
		// 26: PUSH - decreases stack address, then value at stack address
		s.SP--
		assignable = &s.Ram[s.SP]
	// 27: SP - current stack pointer value - current stack address
	case 27:
		assignable = &s.SP
	// 28: PC - program counter- current program counter
	case 28:
		assignable = &s.PC
	// 29: O - overflow - current value of the overflow
	case 29:
		assignable = &s.O
	// 30: [next word of ram] - memory address
	case 30:
		assignable = &s.Ram[s.Ram[s.PC]]
		s.PC++
	// 31: next word of ram - literal, does nothing on assign
	case 31:
		val = s.Ram[s.PC]
		s.PC++
	default:
		if op >= 64 {
			panic("Out of bounds operand")
		}
		val = op - 32
	}
	if assignable != nil {
		val = *assignable
	}
	return
}

// Step iterates the CPU by one instruction.
func (s *State) Step() {
	// fetch
	opcode := s.Ram[s.PC]
	s.PC++

	// decode
	ins, a, b := decodeOpcode(opcode)

	var assignable *Word
	a, assignable = s.translateOperand(a)
	b, _ = s.translateOperand(b)

	// execute
	var val Word
	switch ins {
	case 0:
		// marked RESERVED, lets just treat it as a NOP
	case 1:
		// SET a, b - sets value of b to a
		val = b
	case 2:
		// ADD a, b - adds b to a, sets O
		result := uint32(a) + uint32(b)
		val = Word(result & 0xFFFF)
		s.O = Word(result >> 16)
	case 3:
		// SUB a, b - subtracts b from a, sets O
		result := uint32(a) - uint32(b)
		val = Word(result & 0xFFFF)
		s.O = Word(result >> 16)
	case 4:
		// MUL a, b - multiplies a by b, sets O
		result := uint32(a) * uint32(b)
		val = Word(result & 0xFFFF)
		s.O = Word(result >> 16)
	case 5:
		// DIV a, b - divides a by b, sets O
		// NB: how can this overflow?
		// assuming for the moment that O is supposed to be the mod
		val = a / b
		s.O = a % b
	case 6:
		// MOD a, b - remainder of a over b
		val = a % b
	case 7:
		// SHL a, b - shifts a left b places, sets O
		result := uint32(a) << uint32(b)
		val = Word(result & 0xFFFF)
		s.O = Word(result >> 16)
	case 8:
		// SHR a, b - shifts a right b places, sets O
		// NB: how can this overflow?
		val = a >> b
	case 9:
		// AND a, b - binary and of a and b
		val = a & b
	case 10:
		// BOR a, b - binary or of a and b
		val = a | b
	case 11:
		// XOR a, b - binary xor of a and b
		val = a ^ b
	case 12:
		// IFE a, b - skips one instruction if a!=b
		if a != b {
			s.PC += wordCount(s.Ram[s.PC])
		}
	case 13:
		// IFN a, b - skips one instruction if a==b
		if a == b {
			s.PC += wordCount(s.Ram[s.PC])
		}
	case 14:
		// IFG a, b - skips one instruction if a<=b
		if a <= b {
			s.PC += wordCount(s.Ram[s.PC])
		}
	case 15:
		// IFB a, b - skips one instruction if (a&b)==0
		if (a & b) == 0 {
			s.PC += wordCount(s.Ram[s.PC])
		}
	default:
		panic("Out of bounds opcode")
	}

	// store
	if ins >= 1 && ins <= 11 && assignable != nil {
		*assignable = val
	}
}
<|endoftext|>


<commit_before>// git.go
package delta

import (
	"bitbucket.org/kardianos/rsync"
	"github.com/libgit2/git2go"
	"github.com/rgeorgiev583/gonflator/remote"
)

const (
	chanCap  = 1000
	sliceCap = 1000
)

type GitRepository git2go.Repository

func (gr *GitRepository) GetRdiff(diff chan<- git2go.DiffDelta) (rdiff <-chan Delta, err error) {
	rdiff = make(chan Delta, chanCap)

	go func() {
		defer close(rdiff)

		for delta := range diff {
			switch delta.Status {
			case git2go.DeltaUnmodified:
				rdiff <- &Delta{
					NewPath: delta.NewFile.Path,
					Type:    DeltaUnmodified,
				}
			case git2go.DeltaAdded:
				blob, err := gr.LookupBlob(delta.NewFile.Oid)
				if err != nil {
					return
				}

				rdiff <- &Delta{
					Operation: &rsync.Operation{Data: blob.Contents()},
					NewPath:   delta.NewFile.Path,
					Type:      DeltaAdded,
				}
			case git2go.DeltaDeleted:
				rdiff <- &Delta{
					OldPath: delta.OldFile.Path,
					Type:    DeltaDeleted,
				}
			case git2go.DeltaModified:
				newBlob, err := gr.LookupBlob(delta.NewFile.Oid)
				if err != nil {
					return
				}

				oldBlob, err := gr.LookupBlob(delta.OldFile.Oid)
				if err != nil {
					return
				}

				rdiffMaker := &rsync.Rsync{}
				oldReader := bytes.NewReader(oldBlob.Contents())
				newReader := bytes.NewReader(newBlob.Contents())
				signature := new([]BlockHash, 0, sliceCapacity)
				err = rsync.CreateSignature(oldReader, func(bh BlockHash) error {
					append(signature, bh)
					return nil
				})
				if err != nil {
					return
				}

				err = rsync.CreateDelta(newReader, signature, func(op Operation) error {
					rdiff <- &Delta{
						Operation: op,
						OldPath:   delta.OldFile.Path,
						NewPath:   delta.NewFile.Path,
						Type:      DeltaModified,
					}
					return nil
				})
			case git2go.DeltaRenamed:
				rdiff <- &Delta{
					OldPath: delta.OldFile.Path,
					NewPath: delta.NewFile.Path,
					Type:    DeltaRenamed,
				}
			case git2go.DeltaCopied:
				rdiff <- &Delta{
					OldPath: delta.OldFile.Path,
					Path:    delta.NewFile.Path,
					Type:    DeltaCopied,
				}
			}
		}
	}()

	return
}
<commit_msg>added the GetDiffDeltas method of GitRepository which transforms a Diff object from `git2go` to a channel of deltas<commit_after>// git.go
package delta

import (
	"bitbucket.org/kardianos/rsync"
	"github.com/libgit2/git2go"
	"github.com/rgeorgiev583/gonflator/remote"
)

const (
	chanCap  = 1000
	sliceCap = 1000
)

type GitRepository git2go.Repository

func (gr *GitRepository) GetDiffDeltas(gitDiff *git2go.Diff) (diff <-chan git2go.DiffDelta, err error) {
	diff = make(chan git2go.DiffDelta)
	callback := func(delta git2go.DiffDelta, _ float64) {
		gitDiff <- delta
	}
	gitDiff.ForEach(callback, git2go.DiffDetailFiles)
}

func (gr *GitRepository) GetRdiff(diff chan<- git2go.DiffDelta) (rdiff <-chan Delta, err error) {
	rdiff = make(chan Delta, chanCap)

	go func() {
		defer close(rdiff)

		for delta := range diff {
			switch delta.Status {
			case git2go.DeltaUnmodified:
				rdiff <- &Delta{
					NewPath: delta.NewFile.Path,
					Type:    DeltaUnmodified,
				}
			case git2go.DeltaAdded:
				blob, err := gr.LookupBlob(delta.NewFile.Oid)
				if err != nil {
					return
				}

				rdiff <- &Delta{
					Operation: &rsync.Operation{Data: blob.Contents()},
					NewPath:   delta.NewFile.Path,
					Type:      DeltaAdded,
				}
			case git2go.DeltaDeleted:
				rdiff <- &Delta{
					OldPath: delta.OldFile.Path,
					Type:    DeltaDeleted,
				}
			case git2go.DeltaModified:
				newBlob, err := gr.LookupBlob(delta.NewFile.Oid)
				if err != nil {
					return
				}

				oldBlob, err := gr.LookupBlob(delta.OldFile.Oid)
				if err != nil {
					return
				}

				rdiffMaker := &rsync.Rsync{}
				oldReader := bytes.NewReader(oldBlob.Contents())
				newReader := bytes.NewReader(newBlob.Contents())
				signature := new([]BlockHash, 0, sliceCapacity)
				err = rsync.CreateSignature(oldReader, func(bh BlockHash) error {
					append(signature, bh)
					return nil
				})
				if err != nil {
					return
				}

				err = rsync.CreateDelta(newReader, signature, func(op Operation) error {
					rdiff <- &Delta{
						Operation: op,
						OldPath:   delta.OldFile.Path,
						NewPath:   delta.NewFile.Path,
						Type:      DeltaModified,
					}
					return nil
				})
			case git2go.DeltaRenamed:
				rdiff <- &Delta{
					OldPath: delta.OldFile.Path,
					NewPath: delta.NewFile.Path,
					Type:    DeltaRenamed,
				}
			case git2go.DeltaCopied:
				rdiff <- &Delta{
					OldPath: delta.OldFile.Path,
					Path:    delta.NewFile.Path,
					Type:    DeltaCopied,
				}
			}
		}
	}()

	return
}
<|endoftext|>


<commit_before>package goavro

// NOTE: This file was copied from https://github.com/karrick/gorill

import (
	"fmt"
	"strings"
	"testing"
)

func ensureBuffer(tb testing.TB, buf []byte, n int, want string) {
	tb.Helper()
	if got, want := n, len(want); got != want {
		tb.Fatalf("GOT: %v; WANT: %v", got, want)
	}
	if got, want := string(buf[:n]), want; got != want {
		tb.Errorf("GOT: %v; WANT: %v", got, want)
	}
}

func ensureError(tb testing.TB, err error, contains ...string) {
	tb.Helper()
	if len(contains) == 0 {
		if err != nil {
			tb.Errorf("GOT: %v; WANT: %v", err, contains)
		}
	} else if err == nil {
		tb.Errorf("GOT: %v; WANT: %v", err, contains)
	} else {
		for _, stub := range contains {
			if !strings.Contains(err.Error(), stub) {
				tb.Errorf("GOT: %v; WANT: %v", err, stub)
			}
		}
	}
}

func ensurePanic(tb testing.TB, want string, callback func()) {
	tb.Helper()
	defer func() {
		r := recover()
		if r == nil {
			tb.Fatalf("GOT: %v; WANT: %v", r, want)
			return
		}
		if got := fmt.Sprintf("%v", r); got != want {
			tb.Fatalf("GOT: %v; WANT: %v", got, want)
		}
	}()
	callback()
}

// ensureNoPanic prettifies the output so one knows which test case caused a
// panic.
func ensureNoPanic(tb testing.TB, test string, callback func()) {
	tb.Helper()
	defer func() {
		if r := recover(); r != nil {
			tb.Fatalf("TEST: %s: GOT: %v", test, r)
		}
	}()
	callback()
}

func ensureStringSlicesMatch(tb testing.TB, actual, expected []string) {
	tb.Helper()
	if got, want := len(actual), len(expected); got != want {
		tb.Errorf("GOT: %v; WANT: %v", got, want)
	}
	la := len(actual)
	le := len(expected)
	for i := 0; i < la || i < le; i++ {
		if i < la {
			if i < le {
				if got, want := actual[i], expected[i]; got != want {
					tb.Errorf("GOT: %q; WANT: %q", got, want)
				}
			} else {
				tb.Errorf("GOT: %q (extra)", actual[i])
			}
		} else if i < le {
			tb.Errorf("WANT: %q (missing)", expected[i])
		}
	}
}
<commit_msg>added verbosity to test helper<commit_after>package goavro

// NOTE: This file was copied from https://github.com/karrick/gorill

import (
	"fmt"
	"strings"
	"testing"
)

func ensureBuffer(tb testing.TB, buf []byte, n int, want string) {
	tb.Helper()
	if got, want := n, len(want); got != want {
		tb.Fatalf("GOT: %v; WANT: %v", got, want)
	}
	if got, want := string(buf[:n]), want; got != want {
		tb.Errorf("GOT: %v; WANT: %v", got, want)
	}
}

func ensureError(tb testing.TB, err error, contains ...string) {
	tb.Helper()
	if len(contains) == 0 {
		if err != nil {
			tb.Errorf("GOT: %v; WANT: %v", err, contains)
		}
	} else if err == nil {
		tb.Errorf("GOT: %v; WANT: %v", err, contains)
	} else {
		for _, stub := range contains {
			if !strings.Contains(err.Error(), stub) {
				tb.Errorf("GOT: %v; WANT: %v", err, stub)
			}
		}
	}
}

func ensurePanic(tb testing.TB, want string, callback func()) {
	tb.Helper()
	defer func() {
		r := recover()
		if r == nil {
			tb.Fatalf("GOT: %v; WANT: %v", r, want)
			return
		}
		if got := fmt.Sprintf("%v", r); got != want {
			tb.Fatalf("GOT: %v; WANT: %v", got, want)
		}
	}()
	callback()
}

// ensureNoPanic prettifies the output so one knows which test case caused a
// panic.
func ensureNoPanic(tb testing.TB, label string, callback func()) {
	tb.Helper()
	defer func() {
		if r := recover(); r != nil {
			tb.Fatalf("TEST: %s: GOT: %v", label, r)
		}
	}()
	callback()
}

func ensureStringSlicesMatch(tb testing.TB, actual, expected []string) {
	tb.Helper()
	if got, want := len(actual), len(expected); got != want {
		tb.Errorf("GOT: %v; WANT: %v", got, want)
	}
	la := len(actual)
	le := len(expected)
	for i := 0; i < la || i < le; i++ {
		if i < la {
			if i < le {
				if got, want := actual[i], expected[i]; got != want {
					tb.Errorf("GOT: %q; WANT: %q", got, want)
				}
			} else {
				tb.Errorf("GOT: %q (extra)", actual[i])
			}
		} else if i < le {
			tb.Errorf("WANT: %q (missing)", expected[i])
		}
	}
}
<|endoftext|>


<commit_before>package google

import (
	"github.com/hashicorp/terraform/helper/schema"
	"github.com/hashicorp/terraform/helper/validation"
	"google.golang.org/api/container/v1"
)

var schemaNodeConfig = &schema.Schema{
	Type:     schema.TypeList,
	Optional: true,
	Computed: true,
	ForceNew: true,
	MaxItems: 1,
	Elem: &schema.Resource{
		Schema: map[string]*schema.Schema{
			"machine_type": {
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
				ForceNew: true,
			},

			"disk_size_gb": {
				Type:         schema.TypeInt,
				Optional:     true,
				Computed:     true,
				ForceNew:     true,
				ValidateFunc: validation.IntAtLeast(10),
			},

			"local_ssd_count": {
				Type:         schema.TypeInt,
				Optional:     true,
				Computed:     true,
				ForceNew:     true,
				ValidateFunc: validation.IntAtLeast(0),
			},

			"oauth_scopes": {
				Type:     schema.TypeList,
				Optional: true,
				Computed: true,
				ForceNew: true,
				Elem: &schema.Schema{
					Type: schema.TypeString,
					StateFunc: func(v interface{}) string {
						return canonicalizeServiceScope(v.(string))
					},
				},
			},

			"service_account": {
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
				ForceNew: true,
			},

			"metadata": {
				Type:     schema.TypeMap,
				Optional: true,
				ForceNew: true,
				Elem:     schema.TypeString,
			},

			"image_type": {
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
				ForceNew: true,
			},

			"labels": {
				Type:     schema.TypeMap,
				Optional: true,
				ForceNew: true,
				Elem:     schema.TypeString,
			},

			"tags": {
				Type:     schema.TypeList,
				Optional: true,
				ForceNew: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},

			"preemptible": {
				Type:     schema.TypeBool,
				Optional: true,
				ForceNew: true,
				Default:  false,
			},
		},
	},
}

func expandNodeConfig(v interface{}) *container.NodeConfig {
	nodeConfigs := v.([]interface{})
	nodeConfig := nodeConfigs[0].(map[string]interface{})

	nc := &container.NodeConfig{}

	if v, ok := nodeConfig["machine_type"]; ok {
		nc.MachineType = v.(string)
	}

	if v, ok := nodeConfig["disk_size_gb"]; ok {
		nc.DiskSizeGb = int64(v.(int))
	}

	if v, ok := nodeConfig["local_ssd_count"]; ok {
		nc.LocalSsdCount = int64(v.(int))
	}

	if v, ok := nodeConfig["oauth_scopes"]; ok {
		scopesList := v.([]interface{})
		scopes := []string{}
		for _, v := range scopesList {
			scopes = append(scopes, canonicalizeServiceScope(v.(string)))
		}

		nc.OauthScopes = scopes
	}

	if v, ok := nodeConfig["service_account"]; ok {
		nc.ServiceAccount = v.(string)
	}

	if v, ok := nodeConfig["metadata"]; ok {
		m := make(map[string]string)
		for k, val := range v.(map[string]interface{}) {
			m[k] = val.(string)
		}
		nc.Metadata = m
	}

	if v, ok := nodeConfig["image_type"]; ok {
		nc.ImageType = v.(string)
	}

	if v, ok := nodeConfig["labels"]; ok {
		m := make(map[string]string)
		for k, val := range v.(map[string]interface{}) {
			m[k] = val.(string)
		}
		nc.Labels = m
	}

	if v, ok := nodeConfig["tags"]; ok {
		tagsList := v.([]interface{})
		tags := []string{}
		for _, v := range tagsList {
			tags = append(tags, v.(string))
		}
		nc.Tags = tags
	}
	// Preemptible Is Optional+Default, so it always has a value
	nc.Preemptible = nodeConfig["preemptible"].(bool)

	return nc
}

func flattenNodeConfig(c *container.NodeConfig) []map[string]interface{} {
	config := []map[string]interface{}{
		{
			"machine_type":    c.MachineType,
			"disk_size_gb":    c.DiskSizeGb,
			"local_ssd_count": c.LocalSsdCount,
			"service_account": c.ServiceAccount,
			"metadata":        c.Metadata,
			"image_type":      c.ImageType,
			"labels":          c.Labels,
			"tags":            c.Tags,
			"preemptible":     c.Preemptible,
		},
	}

	if len(c.OauthScopes) > 0 {
		config[0]["oauth_scopes"] = c.OauthScopes
	}

	return config
}
<commit_msg>Don't crash if node config is nil in google_container_cluster (#467)<commit_after>package google

import (
	"github.com/hashicorp/terraform/helper/schema"
	"github.com/hashicorp/terraform/helper/validation"
	"google.golang.org/api/container/v1"
)

var schemaNodeConfig = &schema.Schema{
	Type:     schema.TypeList,
	Optional: true,
	Computed: true,
	ForceNew: true,
	MaxItems: 1,
	Elem: &schema.Resource{
		Schema: map[string]*schema.Schema{
			"machine_type": {
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
				ForceNew: true,
			},

			"disk_size_gb": {
				Type:         schema.TypeInt,
				Optional:     true,
				Computed:     true,
				ForceNew:     true,
				ValidateFunc: validation.IntAtLeast(10),
			},

			"local_ssd_count": {
				Type:         schema.TypeInt,
				Optional:     true,
				Computed:     true,
				ForceNew:     true,
				ValidateFunc: validation.IntAtLeast(0),
			},

			"oauth_scopes": {
				Type:     schema.TypeList,
				Optional: true,
				Computed: true,
				ForceNew: true,
				Elem: &schema.Schema{
					Type: schema.TypeString,
					StateFunc: func(v interface{}) string {
						return canonicalizeServiceScope(v.(string))
					},
				},
			},

			"service_account": {
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
				ForceNew: true,
			},

			"metadata": {
				Type:     schema.TypeMap,
				Optional: true,
				ForceNew: true,
				Elem:     schema.TypeString,
			},

			"image_type": {
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
				ForceNew: true,
			},

			"labels": {
				Type:     schema.TypeMap,
				Optional: true,
				ForceNew: true,
				Elem:     schema.TypeString,
			},

			"tags": {
				Type:     schema.TypeList,
				Optional: true,
				ForceNew: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},

			"preemptible": {
				Type:     schema.TypeBool,
				Optional: true,
				ForceNew: true,
				Default:  false,
			},
		},
	},
}

func expandNodeConfig(v interface{}) *container.NodeConfig {
	nodeConfigs := v.([]interface{})
	nodeConfig := nodeConfigs[0].(map[string]interface{})

	nc := &container.NodeConfig{}

	if v, ok := nodeConfig["machine_type"]; ok {
		nc.MachineType = v.(string)
	}

	if v, ok := nodeConfig["disk_size_gb"]; ok {
		nc.DiskSizeGb = int64(v.(int))
	}

	if v, ok := nodeConfig["local_ssd_count"]; ok {
		nc.LocalSsdCount = int64(v.(int))
	}

	if v, ok := nodeConfig["oauth_scopes"]; ok {
		scopesList := v.([]interface{})
		scopes := []string{}
		for _, v := range scopesList {
			scopes = append(scopes, canonicalizeServiceScope(v.(string)))
		}

		nc.OauthScopes = scopes
	}

	if v, ok := nodeConfig["service_account"]; ok {
		nc.ServiceAccount = v.(string)
	}

	if v, ok := nodeConfig["metadata"]; ok {
		m := make(map[string]string)
		for k, val := range v.(map[string]interface{}) {
			m[k] = val.(string)
		}
		nc.Metadata = m
	}

	if v, ok := nodeConfig["image_type"]; ok {
		nc.ImageType = v.(string)
	}

	if v, ok := nodeConfig["labels"]; ok {
		m := make(map[string]string)
		for k, val := range v.(map[string]interface{}) {
			m[k] = val.(string)
		}
		nc.Labels = m
	}

	if v, ok := nodeConfig["tags"]; ok {
		tagsList := v.([]interface{})
		tags := []string{}
		for _, v := range tagsList {
			tags = append(tags, v.(string))
		}
		nc.Tags = tags
	}
	// Preemptible Is Optional+Default, so it always has a value
	nc.Preemptible = nodeConfig["preemptible"].(bool)

	return nc
}

func flattenNodeConfig(c *container.NodeConfig) []map[string]interface{} {
	config := make([]map[string]interface{}, 0, 1)

	if c == nil {
		return config
	}

	config = append(config, map[string]interface{}{
		"machine_type":    c.MachineType,
		"disk_size_gb":    c.DiskSizeGb,
		"local_ssd_count": c.LocalSsdCount,
		"service_account": c.ServiceAccount,
		"metadata":        c.Metadata,
		"image_type":      c.ImageType,
		"labels":          c.Labels,
		"tags":            c.Tags,
		"preemptible":     c.Preemptible,
	})

	if len(c.OauthScopes) > 0 {
		config[0]["oauth_scopes"] = c.OauthScopes
	}

	return config
}
<|endoftext|>


<commit_before>package proxy

import (
	"database/sql/driver"
)

// Conn adds hook points into "database/sql/driver".Conn.
type Conn struct {
	Conn  driver.Conn
	Proxy *Proxy
}

// Prepare returns a prepared statement which is wrapped by Stmt.
func (conn *Conn) Prepare(query string) (driver.Stmt, error) {
	stmt, err := conn.Conn.Prepare(query)
	if err != nil {
		return nil, err
	}
	return &Stmt{
		Stmt:        stmt,
		QueryString: query,
		Proxy:       conn.Proxy,
	}, nil
}

// Close calls the original Close method.
func (conn *Conn) Close() error {
	return conn.Conn.Close()
}

// Begin starts and returns a new transaction which is wrapped by Tx.
// It will trigger PreBegin, Begin, PostBegin hooks.
func (conn *Conn) Begin() (driver.Tx, error) {
	var err error
	var ctx interface{}

	var tx driver.Tx
	if h := conn.Proxy.Hooks.PostBegin; h != nil {
		defer func() { h(ctx, conn) }()
	}

	if h := conn.Proxy.Hooks.PreBegin; h != nil {
		if ctx, err = h(conn); err != nil {
			return nil, err
		}
	}

	tx, err = conn.Conn.Begin()
	if err != nil {
		return nil, err
	}

	if hook := conn.Proxy.Hooks.Begin; hook != nil {
		if err = hook(ctx, conn); err != nil {
			tx.Rollback()
			return nil, err
		}
	}

	return &Tx{
		Tx:    tx,
		Proxy: conn.Proxy,
	}, nil
}

// Exec calls the original Exec method of the connection.
// It will trigger PreExec, Exec, PostExec hooks.
//
// If the original connection does not satisfy "database/sql/driver".Execer, it return ErrSkip error.
func (conn *Conn) Exec(query string, args []driver.Value) (driver.Result, error) {
	execer, ok := conn.Conn.(driver.Execer)
	if !ok {
		return nil, driver.ErrSkip
	}

	stmt := &Stmt{
		QueryString: query,
		Proxy:       conn.Proxy,
	}

	var ctx interface{}
	var err error
	var result driver.Result

	if h := stmt.Proxy.Hooks.PostExec; h != nil {
		defer func() { h(ctx, stmt, args, result) }()
	}
	if h := stmt.Proxy.Hooks.PreExec; h != nil {
		if ctx, err = h(stmt, args); err != nil {
			return nil, err
		}
	}

	result, err = execer.Exec(query, args)
	if err != nil {
		return nil, err
	}

	if h := stmt.Proxy.Hooks.Exec; h != nil {
		if err := h(ctx, stmt, args, result); err != nil {
			return nil, err
		}
	}

	return result, nil
}

// Query executes a query that may return rows.
// It wil trigger PreQuery, Query, PostQuery hooks.
//
// If the orginal connection does not satisfy "database/sql/driver".Queryer, it return ErrSkip error.
func (conn *Conn) Query(query string, args []driver.Value) (driver.Rows, error) {
	queryer, ok := conn.Conn.(driver.Queryer)
	if !ok {
		return nil, driver.ErrSkip
	}

	stmt := &Stmt{
		QueryString: query,
		Proxy:       conn.Proxy,
	}

	var ctx interface{}
	var err error
	var rows driver.Rows

	if h := stmt.Proxy.Hooks.PostQuery; h != nil {
		defer func() { h(ctx, stmt, args, rows) }()
	}

	if h := stmt.Proxy.Hooks.PreQuery; h != nil {
		if ctx, err = h(stmt, args); err != nil {
			return nil, err
		}
	}

	rows, err = queryer.Query(query, args)
	if err != nil {
		return nil, err
	}

	if h := stmt.Proxy.Hooks.Query; h != nil {
		if err := h(ctx, stmt, args, rows); err != nil {
			return nil, err
		}
	}

	return rows, nil
}
<commit_msg>fix typo<commit_after>package proxy

import (
	"database/sql/driver"
)

// Conn adds hook points into "database/sql/driver".Conn.
type Conn struct {
	Conn  driver.Conn
	Proxy *Proxy
}

// Prepare returns a prepared statement which is wrapped by Stmt.
func (conn *Conn) Prepare(query string) (driver.Stmt, error) {
	stmt, err := conn.Conn.Prepare(query)
	if err != nil {
		return nil, err
	}
	return &Stmt{
		Stmt:        stmt,
		QueryString: query,
		Proxy:       conn.Proxy,
	}, nil
}

// Close calls the original Close method.
func (conn *Conn) Close() error {
	return conn.Conn.Close()
}

// Begin starts and returns a new transaction which is wrapped by Tx.
// It will trigger PreBegin, Begin, PostBegin hooks.
func (conn *Conn) Begin() (driver.Tx, error) {
	var err error
	var ctx interface{}

	var tx driver.Tx
	if h := conn.Proxy.Hooks.PostBegin; h != nil {
		defer func() { h(ctx, conn) }()
	}

	if h := conn.Proxy.Hooks.PreBegin; h != nil {
		if ctx, err = h(conn); err != nil {
			return nil, err
		}
	}

	tx, err = conn.Conn.Begin()
	if err != nil {
		return nil, err
	}

	if hook := conn.Proxy.Hooks.Begin; hook != nil {
		if err = hook(ctx, conn); err != nil {
			tx.Rollback()
			return nil, err
		}
	}

	return &Tx{
		Tx:    tx,
		Proxy: conn.Proxy,
	}, nil
}

// Exec calls the original Exec method of the connection.
// It will trigger PreExec, Exec, PostExec hooks.
//
// If the original connection does not satisfy "database/sql/driver".Execer, it return ErrSkip error.
func (conn *Conn) Exec(query string, args []driver.Value) (driver.Result, error) {
	execer, ok := conn.Conn.(driver.Execer)
	if !ok {
		return nil, driver.ErrSkip
	}

	stmt := &Stmt{
		QueryString: query,
		Proxy:       conn.Proxy,
	}

	var ctx interface{}
	var err error
	var result driver.Result

	if h := stmt.Proxy.Hooks.PostExec; h != nil {
		defer func() { h(ctx, stmt, args, result) }()
	}
	if h := stmt.Proxy.Hooks.PreExec; h != nil {
		if ctx, err = h(stmt, args); err != nil {
			return nil, err
		}
	}

	result, err = execer.Exec(query, args)
	if err != nil {
		return nil, err
	}

	if h := stmt.Proxy.Hooks.Exec; h != nil {
		if err := h(ctx, stmt, args, result); err != nil {
			return nil, err
		}
	}

	return result, nil
}

// Query executes a query that may return rows.
// It wil trigger PreQuery, Query, PostQuery hooks.
//
// If the original connection does not satisfy "database/sql/driver".Queryer, it return ErrSkip error.
func (conn *Conn) Query(query string, args []driver.Value) (driver.Rows, error) {
	queryer, ok := conn.Conn.(driver.Queryer)
	if !ok {
		return nil, driver.ErrSkip
	}

	stmt := &Stmt{
		QueryString: query,
		Proxy:       conn.Proxy,
	}

	var ctx interface{}
	var err error
	var rows driver.Rows

	if h := stmt.Proxy.Hooks.PostQuery; h != nil {
		defer func() { h(ctx, stmt, args, rows) }()
	}

	if h := stmt.Proxy.Hooks.PreQuery; h != nil {
		if ctx, err = h(stmt, args); err != nil {
			return nil, err
		}
	}

	rows, err = queryer.Query(query, args)
	if err != nil {
		return nil, err
	}

	if h := stmt.Proxy.Hooks.Query; h != nil {
		if err := h(ctx, stmt, args, rows); err != nil {
			return nil, err
		}
	}

	return rows, nil
}
<|endoftext|>


<commit_before>package gqt_test

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strconv"
	"testing"
	"time"

	"code.cloudfoundry.org/garden"
	"code.cloudfoundry.org/guardian/gqt/containerdrunner"
	"code.cloudfoundry.org/guardian/gqt/runner"
	"code.cloudfoundry.org/guardian/kawasaki/iptables"
	"code.cloudfoundry.org/guardian/pkg/locksmith"
	"github.com/burntsushi/toml"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gexec"
)

var (
	ginkgoIO = garden.ProcessIO{Stdout: GinkgoWriter, Stderr: GinkgoWriter}
	// the unprivileged user is baked into the cfgarden/garden-ci-ubuntu image
	unprivilegedUID = uint32(5000)
	unprivilegedGID = uint32(5000)

	config             runner.GdnRunnerConfig
	binaries           runner.Binaries
	containerdBinaries containerdrunner.Binaries
	defaultTestRootFS  string
)

func goCompile(mainPackagePath string, buildArgs ...string) string {
	if os.Getenv("RACE_DETECTION") != "" {
		buildArgs = append(buildArgs, "-race")
	}
	bin, err := gexec.Build(mainPackagePath, buildArgs...)
	Expect(err).NotTo(HaveOccurred())
	return bin
}

type runnerBinaries struct {
	Garden     runner.Binaries
	Containerd containerdrunner.Binaries
}

func TestGqt(t *testing.T) {
	RegisterFailHandler(Fail)

	SynchronizedBeforeSuite(func() []byte {
		return jsonMarshal(runnerBinaries{
			Garden:     getGardenBinaries(),
			Containerd: getContainerdBinaries(),
		})
	}, func(data []byte) {
		bins := new(runnerBinaries)
		jsonUnmarshal(data, bins)
		binaries = bins.Garden
		containerdBinaries = bins.Containerd
		defaultTestRootFS = os.Getenv("GARDEN_TEST_ROOTFS")
	})

	SynchronizedAfterSuite(func() {}, func() {
		gexec.CleanupBuildArtifacts()
	})

	BeforeEach(func() {
		if defaultTestRootFS == "" {
			Skip("No Garden RootFS")
		}

		// chmod all the artifacts
		Expect(os.Chmod(filepath.Join(binaries.Gdn, "..", ".."), 0755)).To(Succeed())
		filepath.Walk(filepath.Join(binaries.Gdn, "..", ".."), func(path string, info os.FileInfo, err error) error {
			Expect(err).NotTo(HaveOccurred())
			Expect(os.Chmod(path, 0755)).To(Succeed())
			return nil
		})

		config = defaultConfig()
		if runtime.GOOS == "linux" {
			initGrootStore(config.ImagePluginBin, config.StorePath, []string{"0:4294967294:1", "1:65536:4294901758"})
			initGrootStore(config.PrivilegedImagePluginBin, config.PrivilegedStorePath, nil)
		}
	})

	AfterEach(func() {
		// Windows worker is not containerised and therefore the test needs to take care to delete the temporary folder
		if runtime.GOOS == "windows" {
			Expect(os.RemoveAll(config.TmpDir)).To(Succeed())
		}
	})

	SetDefaultEventuallyTimeout(5 * time.Second)
	RunSpecs(t, "GQT Suite")
}

func getGardenBinaries() runner.Binaries {
	gardenBinaries := runner.Binaries{
		Tar:           os.Getenv("GARDEN_TAR_PATH"),
		Gdn:           goCompile("code.cloudfoundry.org/guardian/cmd/gdn", "-tags", "daemon", "-ldflags", "-extldflags '-static'"),
		NetworkPlugin: goCompile("code.cloudfoundry.org/guardian/gqt/cmd/fake_network_plugin"),
		ImagePlugin:   goCompile("code.cloudfoundry.org/guardian/gqt/cmd/fake_image_plugin"),
		RuntimePlugin: goCompile("code.cloudfoundry.org/guardian/gqt/cmd/fake_runtime_plugin"),
		NoopPlugin:    goCompile("code.cloudfoundry.org/guardian/gqt/cmd/noop_plugin"),
	}

	gardenBinaries.PrivilegedImagePlugin = gardenBinaries.ImagePlugin + "-priv"
	Expect(copyFile(gardenBinaries.ImagePlugin, gardenBinaries.PrivilegedImagePlugin)).To(Succeed())

	if runtime.GOOS == "linux" {
		gardenBinaries.ExecRunner = goCompile("code.cloudfoundry.org/guardian/cmd/dadoo")
		gardenBinaries.Socket2me = goCompile("code.cloudfoundry.org/guardian/cmd/socket2me")

		cmd := exec.Command("make")
		runCommandInDir(cmd, "../rundmc/nstar")
		gardenBinaries.NSTar = "../rundmc/nstar/nstar"

		cmd = exec.Command("gcc", "-static", "-o", "init", "init.c")
		runCommandInDir(cmd, "../cmd/init")
		gardenBinaries.Init = "../cmd/init/init"

		gardenBinaries.Groot = goCompile("code.cloudfoundry.org/grootfs")
		gardenBinaries.Tardis = goCompile("code.cloudfoundry.org/grootfs/store/filesystems/overlayxfs/tardis")
		Expect(os.Chmod(gardenBinaries.Tardis, 04755)).To(Succeed())
	}

	return gardenBinaries
}

func getContainerdBinaries() containerdrunner.Binaries {
	containerdBin := makeContainerd()

	return containerdrunner.Binaries{
		Dir:        containerdBin,
		Containerd: filepath.Join(containerdBin, "containerd"),
		Ctr:        filepath.Join(containerdBin, "ctr"),
	}
}

func initGrootStore(grootBin, storePath string, idMappings []string) {
	initStoreArgs := []string{"--store", storePath, "init-store", "--store-size-bytes", fmt.Sprintf("%d", 2*1024*1024*1024)}
	for _, idMapping := range idMappings {
		initStoreArgs = append(initStoreArgs, "--uid-mapping", idMapping, "--gid-mapping", idMapping)
	}

	initStore := exec.Command(grootBin, initStoreArgs...)
	initStore.Stdout = GinkgoWriter
	initStore.Stderr = GinkgoWriter
	Expect(initStore.Run()).To(Succeed())
}

func runCommandInDir(cmd *exec.Cmd, workingDir string) string {
	var stdout bytes.Buffer
	cmd.Dir = workingDir
	cmd.Stdout = io.MultiWriter(&stdout, GinkgoWriter)
	cmd.Stderr = GinkgoWriter
	Expect(cmd.Run()).To(Succeed())
	return stdout.String()
}

func runCommand(cmd *exec.Cmd) string {
	return runCommandInDir(cmd, "")
}

func defaultConfig() runner.GdnRunnerConfig {
	cfg := runner.DefaultGdnRunnerConfig(binaries)
	cfg.DefaultRootFS = defaultTestRootFS
	cfg.GdnBin = binaries.Gdn
	cfg.GrootBin = binaries.Groot
	cfg.Socket2meBin = binaries.Socket2me
	cfg.ExecRunnerBin = binaries.ExecRunner
	cfg.InitBin = binaries.Init
	cfg.TarBin = binaries.Tar
	cfg.NSTarBin = binaries.NSTar
	cfg.ImagePluginBin = binaries.Groot
	cfg.PrivilegedImagePluginBin = binaries.Groot

	return cfg
}

func restartGarden(client *runner.RunningGarden, config runner.GdnRunnerConfig) *runner.RunningGarden {
	Expect(client.Ping()).To(Succeed(), "tried to restart garden while it was not running")
	Expect(client.Stop()).To(Succeed())
	return runner.Start(config)
}

func runIPTables(ipTablesArgs ...string) ([]byte, error) {
	lock, err := locksmith.NewFileSystem().Lock(iptables.LockKey)
	if err != nil {
		return nil, err
	}
	defer lock.Unlock()

	outBuffer := bytes.NewBuffer([]byte{})
	errBuffer := bytes.NewBuffer([]byte{})
	cmd := exec.Command("iptables", append([]string{"-w"}, ipTablesArgs...)...)
	cmd.Stdout = outBuffer
	cmd.Stderr = errBuffer
	err = cmd.Run()

	fmt.Fprintln(GinkgoWriter, outBuffer.String())
	fmt.Fprintln(GinkgoWriter, errBuffer.String())
	return outBuffer.Bytes(), err
}

// returns the n'th ASCII character starting from 'a' through 'z'
// E.g. nodeToString(1) = a, nodeToString(2) = b, etc ...
func nodeToString(ginkgoNode int) string {
	r := 'a' + ginkgoNode - 1
	Expect(r).To(BeNumerically(">=", 'a'))
	Expect(r).To(BeNumerically("<=", 'z'))
	return string(r)
}

func intptr(i int) *int {
	return &i
}

func uint64ptr(i uint64) *uint64 {
	return &i
}

func uint32ptr(i uint32) *uint32 {
	return &i
}

func boolptr(b bool) *bool {
	return &b
}

func stringptr(s string) *string {
	return &s
}

func idToStr(id uint32) string {
	return strconv.FormatUint(uint64(id), 10)
}

func readFile(path string) string {
	content, err := ioutil.ReadFile(path)
	Expect(err).NotTo(HaveOccurred())
	return string(content)
}

func copyFile(srcPath, dstPath string) error {
	dirPath := filepath.Dir(dstPath)
	if err := os.MkdirAll(dirPath, 0777); err != nil {
		return err
	}

	reader, err := os.Open(srcPath)
	if err != nil {
		return err
	}
	writer, err := os.Create(dstPath)
	if err != nil {
		reader.Close()
		return err
	}

	if _, err := io.Copy(writer, reader); err != nil {
		writer.Close()
		reader.Close()
		return err
	}

	writer.Close()
	reader.Close()

	return os.Chmod(writer.Name(), 0777)
}

func removeSocket() {
	_, err := os.Stat(config.BindSocket)
	if err == nil {
		Expect(os.Remove(config.BindSocket)).To(Succeed())
	} else if !os.IsNotExist(err) {
		Expect(err).NotTo(HaveOccurred())
	}
}

func createPeaRootfs() string {
	return createRootfs(func(root string) {
		Expect(exec.Command("chown", "-R", "4294967294:4294967294", root).Run()).To(Succeed())
		Expect(ioutil.WriteFile(filepath.Join(root, "ima-pea"), []byte("pea!"), 0644)).To(Succeed())
	}, 0777)
}

func createRootfsTar(modifyRootfs func(string)) string {
	return tarUpDir(createRootfs(modifyRootfs, 0755))
}

func createRootfs(modifyRootfs func(string), perm os.FileMode) string {
	var err error
	tmpDir, err := ioutil.TempDir("", "test-rootfs")
	Expect(err).NotTo(HaveOccurred())
	unpackedRootfs := filepath.Join(tmpDir, "unpacked")
	Expect(os.Mkdir(unpackedRootfs, perm)).To(Succeed())
	runCommand(exec.Command("tar", "xf", defaultTestRootFS, "-C", unpackedRootfs))

	Expect(os.Chmod(tmpDir, perm)).To(Succeed())
	modifyRootfs(unpackedRootfs)

	return unpackedRootfs
}

func tarUpDir(path string) string {
	tarPath := filepath.Join(filepath.Dir(path), filepath.Base(path)+".tar")
	repackCmd := exec.Command("sh", "-c", fmt.Sprintf("tar cf %s *", tarPath))
	runCommandInDir(repackCmd, path)

	return tarPath
}

func resetImagePluginConfig() runner.GdnRunnerConfig {
	config.ImagePluginBin = ""
	config.PrivilegedImagePluginBin = ""
	config.ImagePluginExtraArgs = []string{}
	config.PrivilegedImagePluginExtraArgs = []string{}
	return config
}

func mustGetEnv(env string) string {
	if value := os.Getenv(env); value != "" {
		return value
	}
	panic(fmt.Sprintf("%s env must be non-empty", env))
}

func makeContainerd() string {
	if runtime.GOOS == "windows" {
		return ""
	}
	containerdPath := filepath.Join(mustGetEnv("GOPATH"), filepath.FromSlash("src/github.com/containerd/containerd"))
	makeContainerdCommand := exec.Command("make")
	makeContainerdCommand.Env = append(os.Environ(), "BUILDTAGS=no_btrfs")
	runCommandInDir(makeContainerdCommand, containerdPath)
	return filepath.Join(containerdPath, "bin")
}

func jsonMarshal(v interface{}) []byte {
	buf := bytes.NewBuffer([]byte{})
	Expect(toml.NewEncoder(buf).Encode(v)).To(Succeed())
	return buf.Bytes()
}

func jsonUnmarshal(data []byte, v interface{}) {
	Expect(toml.Unmarshal(data, v)).To(Succeed())
}
<commit_msg>Cleanup gqt suite<commit_after>package gqt_test

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strconv"
	"testing"
	"time"

	"code.cloudfoundry.org/garden"
	"code.cloudfoundry.org/guardian/gqt/containerdrunner"
	"code.cloudfoundry.org/guardian/gqt/runner"
	"code.cloudfoundry.org/guardian/kawasaki/iptables"
	"code.cloudfoundry.org/guardian/pkg/locksmith"
	"github.com/burntsushi/toml"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gexec"
)

var (
	ginkgoIO = garden.ProcessIO{Stdout: GinkgoWriter, Stderr: GinkgoWriter}
	// the unprivileged user is baked into the cfgarden/garden-ci-ubuntu image
	unprivilegedUID = uint32(5000)
	unprivilegedGID = uint32(5000)

	config             runner.GdnRunnerConfig
	binaries           runner.Binaries
	containerdBinaries containerdrunner.Binaries
	defaultTestRootFS  string
)

func goCompile(mainPackagePath string, buildArgs ...string) string {
	if os.Getenv("RACE_DETECTION") != "" {
		buildArgs = append(buildArgs, "-race")
	}
	bin, err := gexec.Build(mainPackagePath, buildArgs...)
	Expect(err).NotTo(HaveOccurred())
	return bin
}

type runnerBinaries struct {
	Garden     runner.Binaries
	Containerd containerdrunner.Binaries
}

func TestGqt(t *testing.T) {
	RegisterFailHandler(Fail)
	SetDefaultEventuallyTimeout(5 * time.Second)
	RunSpecs(t, "GQT Suite")
}

var _ = SynchronizedBeforeSuite(func() []byte {
	binaries := runnerBinaries{
		Garden:     getGardenBinaries(),
		Containerd: getContainerdBinaries(),
	}

	// chmod all the artifacts
	Expect(os.Chmod(filepath.Join(binaries.Garden.Gdn, "..", ".."), 0755)).To(Succeed())
	filepath.Walk(filepath.Join(binaries.Garden.Gdn, "..", ".."), func(path string, info os.FileInfo, err error) error {
		Expect(err).NotTo(HaveOccurred())
		Expect(os.Chmod(path, 0755)).To(Succeed())
		return nil
	})

	return jsonMarshal(binaries)
}, func(data []byte) {
	bins := new(runnerBinaries)
	jsonUnmarshal(data, bins)
	binaries = bins.Garden
	containerdBinaries = bins.Containerd
	defaultTestRootFS = os.Getenv("GARDEN_TEST_ROOTFS")
})

var _ = SynchronizedAfterSuite(func() {}, func() {
	gexec.CleanupBuildArtifacts()
})

var _ = BeforeEach(func() {
	if defaultTestRootFS == "" {
		Skip("No Garden RootFS")
	}

	config = defaultConfig()
	if runtime.GOOS == "linux" {
		initGrootStore(config.ImagePluginBin, config.StorePath, []string{"0:4294967294:1", "1:65536:4294901758"})
		initGrootStore(config.PrivilegedImagePluginBin, config.PrivilegedStorePath, nil)
	}
})

var _ = AfterEach(func() {
	// Windows worker is not containerised and therefore the test needs to take care to delete the temporary folder
	if runtime.GOOS == "windows" {
		Expect(os.RemoveAll(config.TmpDir)).To(Succeed())
	}
})

func getGardenBinaries() runner.Binaries {
	gardenBinaries := runner.Binaries{
		Tar:           os.Getenv("GARDEN_TAR_PATH"),
		Gdn:           goCompile("code.cloudfoundry.org/guardian/cmd/gdn", "-tags", "daemon", "-ldflags", "-extldflags '-static'"),
		NetworkPlugin: goCompile("code.cloudfoundry.org/guardian/gqt/cmd/fake_network_plugin"),
		ImagePlugin:   goCompile("code.cloudfoundry.org/guardian/gqt/cmd/fake_image_plugin"),
		RuntimePlugin: goCompile("code.cloudfoundry.org/guardian/gqt/cmd/fake_runtime_plugin"),
		NoopPlugin:    goCompile("code.cloudfoundry.org/guardian/gqt/cmd/noop_plugin"),
	}

	gardenBinaries.PrivilegedImagePlugin = gardenBinaries.ImagePlugin + "-priv"
	Expect(copyFile(gardenBinaries.ImagePlugin, gardenBinaries.PrivilegedImagePlugin)).To(Succeed())

	if runtime.GOOS == "linux" {
		gardenBinaries.ExecRunner = goCompile("code.cloudfoundry.org/guardian/cmd/dadoo")
		gardenBinaries.Socket2me = goCompile("code.cloudfoundry.org/guardian/cmd/socket2me")

		cmd := exec.Command("make")
		runCommandInDir(cmd, "../rundmc/nstar")
		gardenBinaries.NSTar = "../rundmc/nstar/nstar"

		cmd = exec.Command("gcc", "-static", "-o", "init", "init.c")
		runCommandInDir(cmd, "../cmd/init")
		gardenBinaries.Init = "../cmd/init/init"

		gardenBinaries.Groot = goCompile("code.cloudfoundry.org/grootfs")
		gardenBinaries.Tardis = goCompile("code.cloudfoundry.org/grootfs/store/filesystems/overlayxfs/tardis")
		Expect(os.Chmod(gardenBinaries.Tardis, 04755)).To(Succeed())
	}

	return gardenBinaries
}

func getContainerdBinaries() containerdrunner.Binaries {
	containerdBin := makeContainerd()

	return containerdrunner.Binaries{
		Dir:        containerdBin,
		Containerd: filepath.Join(containerdBin, "containerd"),
		Ctr:        filepath.Join(containerdBin, "ctr"),
	}
}

func initGrootStore(grootBin, storePath string, idMappings []string) {
	initStoreArgs := []string{"--store", storePath, "init-store", "--store-size-bytes", fmt.Sprintf("%d", 2*1024*1024*1024)}
	for _, idMapping := range idMappings {
		initStoreArgs = append(initStoreArgs, "--uid-mapping", idMapping, "--gid-mapping", idMapping)
	}

	initStore := exec.Command(grootBin, initStoreArgs...)
	initStore.Stdout = GinkgoWriter
	initStore.Stderr = GinkgoWriter
	Expect(initStore.Run()).To(Succeed())
}

func runCommandInDir(cmd *exec.Cmd, workingDir string) string {
	var stdout bytes.Buffer
	cmd.Dir = workingDir
	cmd.Stdout = io.MultiWriter(&stdout, GinkgoWriter)
	cmd.Stderr = GinkgoWriter
	Expect(cmd.Run()).To(Succeed())
	return stdout.String()
}

func runCommand(cmd *exec.Cmd) string {
	return runCommandInDir(cmd, "")
}

func defaultConfig() runner.GdnRunnerConfig {
	cfg := runner.DefaultGdnRunnerConfig(binaries)
	cfg.DefaultRootFS = defaultTestRootFS
	cfg.GdnBin = binaries.Gdn
	cfg.GrootBin = binaries.Groot
	cfg.Socket2meBin = binaries.Socket2me
	cfg.ExecRunnerBin = binaries.ExecRunner
	cfg.InitBin = binaries.Init
	cfg.TarBin = binaries.Tar
	cfg.NSTarBin = binaries.NSTar
	cfg.ImagePluginBin = binaries.Groot
	cfg.PrivilegedImagePluginBin = binaries.Groot

	return cfg
}

func restartGarden(client *runner.RunningGarden, config runner.GdnRunnerConfig) *runner.RunningGarden {
	Expect(client.Ping()).To(Succeed(), "tried to restart garden while it was not running")
	Expect(client.Stop()).To(Succeed())
	return runner.Start(config)
}

func runIPTables(ipTablesArgs ...string) ([]byte, error) {
	lock, err := locksmith.NewFileSystem().Lock(iptables.LockKey)
	if err != nil {
		return nil, err
	}
	defer lock.Unlock()

	outBuffer := bytes.NewBuffer([]byte{})
	errBuffer := bytes.NewBuffer([]byte{})
	cmd := exec.Command("iptables", append([]string{"-w"}, ipTablesArgs...)...)
	cmd.Stdout = outBuffer
	cmd.Stderr = errBuffer
	err = cmd.Run()

	fmt.Fprintln(GinkgoWriter, outBuffer.String())
	fmt.Fprintln(GinkgoWriter, errBuffer.String())
	return outBuffer.Bytes(), err
}

// returns the n'th ASCII character starting from 'a' through 'z'
// E.g. nodeToString(1) = a, nodeToString(2) = b, etc ...
func nodeToString(ginkgoNode int) string {
	r := 'a' + ginkgoNode - 1
	Expect(r).To(BeNumerically(">=", 'a'))
	Expect(r).To(BeNumerically("<=", 'z'))
	return string(r)
}

func intptr(i int) *int {
	return &i
}

func uint64ptr(i uint64) *uint64 {
	return &i
}

func uint32ptr(i uint32) *uint32 {
	return &i
}

func boolptr(b bool) *bool {
	return &b
}

func stringptr(s string) *string {
	return &s
}

func idToStr(id uint32) string {
	return strconv.FormatUint(uint64(id), 10)
}

func readFile(path string) string {
	content, err := ioutil.ReadFile(path)
	Expect(err).NotTo(HaveOccurred())
	return string(content)
}

func copyFile(srcPath, dstPath string) error {
	dirPath := filepath.Dir(dstPath)
	if err := os.MkdirAll(dirPath, 0777); err != nil {
		return err
	}

	reader, err := os.Open(srcPath)
	if err != nil {
		return err
	}
	writer, err := os.Create(dstPath)
	if err != nil {
		reader.Close()
		return err
	}

	if _, err := io.Copy(writer, reader); err != nil {
		writer.Close()
		reader.Close()
		return err
	}

	writer.Close()
	reader.Close()

	return os.Chmod(writer.Name(), 0777)
}

func removeSocket() {
	_, err := os.Stat(config.BindSocket)
	if err == nil {
		Expect(os.Remove(config.BindSocket)).To(Succeed())
	} else if !os.IsNotExist(err) {
		Expect(err).NotTo(HaveOccurred())
	}
}

func createPeaRootfs() string {
	return createRootfs(func(root string) {
		Expect(exec.Command("chown", "-R", "4294967294:4294967294", root).Run()).To(Succeed())
		Expect(ioutil.WriteFile(filepath.Join(root, "ima-pea"), []byte("pea!"), 0644)).To(Succeed())
	}, 0777)
}

func createRootfsTar(modifyRootfs func(string)) string {
	return tarUpDir(createRootfs(modifyRootfs, 0755))
}

func createRootfs(modifyRootfs func(string), perm os.FileMode) string {
	var err error
	tmpDir, err := ioutil.TempDir("", "test-rootfs")
	Expect(err).NotTo(HaveOccurred())
	unpackedRootfs := filepath.Join(tmpDir, "unpacked")
	Expect(os.Mkdir(unpackedRootfs, perm)).To(Succeed())
	runCommand(exec.Command("tar", "xf", defaultTestRootFS, "-C", unpackedRootfs))

	Expect(os.Chmod(tmpDir, perm)).To(Succeed())
	modifyRootfs(unpackedRootfs)

	return unpackedRootfs
}

func tarUpDir(path string) string {
	tarPath := filepath.Join(filepath.Dir(path), filepath.Base(path)+".tar")
	repackCmd := exec.Command("sh", "-c", fmt.Sprintf("tar cf %s *", tarPath))
	runCommandInDir(repackCmd, path)

	return tarPath
}

func resetImagePluginConfig() runner.GdnRunnerConfig {
	config.ImagePluginBin = ""
	config.PrivilegedImagePluginBin = ""
	config.ImagePluginExtraArgs = []string{}
	config.PrivilegedImagePluginExtraArgs = []string{}
	return config
}

func mustGetEnv(env string) string {
	if value := os.Getenv(env); value != "" {
		return value
	}
	panic(fmt.Sprintf("%s env must be non-empty", env))
}

func makeContainerd() string {
	if runtime.GOOS == "windows" {
		return ""
	}
	containerdPath := filepath.Join(mustGetEnv("GOPATH"), filepath.FromSlash("src/github.com/containerd/containerd"))
	makeContainerdCommand := exec.Command("make")
	makeContainerdCommand.Env = append(os.Environ(), "BUILDTAGS=no_btrfs")
	runCommandInDir(makeContainerdCommand, containerdPath)
	return filepath.Join(containerdPath, "bin")
}

func jsonMarshal(v interface{}) []byte {
	buf := bytes.NewBuffer([]byte{})
	Expect(toml.NewEncoder(buf).Encode(v)).To(Succeed())
	return buf.Bytes()
}

func jsonUnmarshal(data []byte, v interface{}) {
	Expect(toml.Unmarshal(data, v)).To(Succeed())
}
<|endoftext|>


<commit_before>package gqt_test

import (
	"os"
	"os/exec"
	"runtime"
	"time"

	"github.com/cloudfoundry-incubator/garden"
	"github.com/cloudfoundry-incubator/guardian/gqt/runner"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gexec"

	"encoding/json"
	"testing"
)

var defaultRuntime = map[string]string{
	"linux": "runc",
}

var ginkgoIO = garden.ProcessIO{Stdout: GinkgoWriter, Stderr: GinkgoWriter}

var ociRuntimeBin, gardenBin, iodaemonBin, nstarBin string

func TestGqt(t *testing.T) {
	RegisterFailHandler(Fail)

	SynchronizedBeforeSuite(func() []byte {
		var err error
		bins := make(map[string]string)

		bins["oci_runtime_path"] = os.Getenv("OCI_RUNTIME")
		if bins["oci_runtime_path"] == "" {
			bins["oci_runtime_path"] = defaultRuntime[runtime.GOOS]
		}

		if bins["oci_runtime_path"] != "" {
			bins["garden_bin_path"], err = gexec.Build("github.com/cloudfoundry-incubator/guardian/cmd/guardian", "-tags", "daemon")
			Expect(err).NotTo(HaveOccurred())

			bins["iodaemon_bin_path"], err = gexec.Build("github.com/cloudfoundry-incubator/guardian/rundmc/iodaemon/cmd/iodaemon")
			Expect(err).NotTo(HaveOccurred())

			cmd := exec.Command("make")
			cmd.Dir = "../rundmc/nstar"
			cmd.Stdout = GinkgoWriter
			cmd.Stderr = GinkgoWriter
			Expect(cmd.Run()).To(Succeed())
			bins["nstar_bin_path"] = "../rundmc/nstar/nstar"
		}

		data, err := json.Marshal(bins)
		Expect(err).NotTo(HaveOccurred())

		return data
	}, func(data []byte) {
		bins := make(map[string]string)
		Expect(json.Unmarshal(data, &bins)).To(Succeed())

		ociRuntimeBin = bins["oci_runtime_path"]
		gardenBin = bins["garden_bin_path"]
		iodaemonBin = bins["iodaemon_bin_path"]
		nstarBin = bins["nstar_bin_path"]
	})

	BeforeEach(func() {
		if ociRuntimeBin == "" {
			Skip("No OCI Runtime for Platform: " + runtime.GOOS)
		}
	})

	SetDefaultEventuallyTimeout(5 * time.Second)
	RunSpecs(t, "GQT Suite")
}

func startGarden(argv ...string) *runner.RunningGarden {
	if networkModulePath := os.Getenv("NETWORK_MODULE_PATH"); networkModulePath != "" {
		argv = append(argv, "--networkModulePath="+networkModulePath)
	}

	return runner.Start(gardenBin, iodaemonBin, nstarBin, argv...)
}
<commit_msg>Skip GQT test if GARDEN_TEST_ROOTFS environment variable is missing<commit_after>package gqt_test

import (
	"os"
	"os/exec"
	"runtime"
	"time"

	"github.com/cloudfoundry-incubator/garden"
	"github.com/cloudfoundry-incubator/guardian/gqt/runner"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gexec"

	"encoding/json"
	"testing"
)

var defaultRuntime = map[string]string{
	"linux": "runc",
}

var ginkgoIO = garden.ProcessIO{Stdout: GinkgoWriter, Stderr: GinkgoWriter}

var ociRuntimeBin, gardenBin, iodaemonBin, nstarBin string

func TestGqt(t *testing.T) {
	RegisterFailHandler(Fail)

	SynchronizedBeforeSuite(func() []byte {
		var err error
		bins := make(map[string]string)

		bins["oci_runtime_path"] = os.Getenv("OCI_RUNTIME")
		if bins["oci_runtime_path"] == "" {
			bins["oci_runtime_path"] = defaultRuntime[runtime.GOOS]
		}

		if bins["oci_runtime_path"] != "" {
			bins["garden_bin_path"], err = gexec.Build("github.com/cloudfoundry-incubator/guardian/cmd/guardian", "-tags", "daemon")
			Expect(err).NotTo(HaveOccurred())

			bins["iodaemon_bin_path"], err = gexec.Build("github.com/cloudfoundry-incubator/guardian/rundmc/iodaemon/cmd/iodaemon")
			Expect(err).NotTo(HaveOccurred())

			cmd := exec.Command("make")
			cmd.Dir = "../rundmc/nstar"
			cmd.Stdout = GinkgoWriter
			cmd.Stderr = GinkgoWriter
			Expect(cmd.Run()).To(Succeed())
			bins["nstar_bin_path"] = "../rundmc/nstar/nstar"
		}

		data, err := json.Marshal(bins)
		Expect(err).NotTo(HaveOccurred())

		return data
	}, func(data []byte) {
		bins := make(map[string]string)
		Expect(json.Unmarshal(data, &bins)).To(Succeed())

		ociRuntimeBin = bins["oci_runtime_path"]
		gardenBin = bins["garden_bin_path"]
		iodaemonBin = bins["iodaemon_bin_path"]
		nstarBin = bins["nstar_bin_path"]
	})

	BeforeEach(func() {
		if ociRuntimeBin == "" {
			Skip("No OCI Runtime for Platform: " + runtime.GOOS)
		}

		if os.Getenv("GARDEN_TEST_ROOTFS") == "" {
			Skip("No Garden RootFS")
		}
	})

	SetDefaultEventuallyTimeout(5 * time.Second)
	RunSpecs(t, "GQT Suite")
}

func startGarden(argv ...string) *runner.RunningGarden {
	if networkModulePath := os.Getenv("NETWORK_MODULE_PATH"); networkModulePath != "" {
		argv = append(argv, "--networkModulePath="+networkModulePath)
	}

	return runner.Start(gardenBin, iodaemonBin, nstarBin, argv...)
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"net/http"

	"github.com/cafebazaar/healthz"
)

const addr = "127.0.0.1:8090"

func main() {
	h := healthz.NewHandler("Demo (v1.0.0)", true)

	h.RegisterComponent("component-major-redundant", healthz.Major)
	h.SetHealth("component-major-redundant", healthz.Redundant)
	h.RegisterComponent("component-major-warning", healthz.Major)
	h.SetHealth("component-major-warning", healthz.Warning)
	h.RegisterComponent("component-unspecified-warning", healthz.Unspecified)
	h.SetHealth("component-unspecified-warning", healthz.Warning)
	h.RegisterComponent("component-minor-error", healthz.Minor)
	h.SetHealth("component-minor-error", healthz.Error)

	healthzServer := &http.Server{
		Addr:    addr,
		Handler: h,
	}
	log.Printf("http://%s/\n", addr)
	err := healthzServer.ListenAndServe()
	if err != nil && err != http.ErrServerClosed {
		log.Fatalln("Error while healthzServer.ListenAndServe():", err)
	}
}
<commit_msg>Fix build using go1.7<commit_after>package main

import (
	"log"
	"net/http"

	"github.com/cafebazaar/healthz"
)

const addr = "127.0.0.1:8090"

func main() {
	h := healthz.NewHandler("Demo (v1.0.0)", true)

	h.RegisterComponent("component-major-redundant", healthz.Major)
	h.SetHealth("component-major-redundant", healthz.Redundant)
	h.RegisterComponent("component-major-warning", healthz.Major)
	h.SetHealth("component-major-warning", healthz.Warning)
	h.RegisterComponent("component-unspecified-warning", healthz.Unspecified)
	h.SetHealth("component-unspecified-warning", healthz.Warning)
	h.RegisterComponent("component-minor-error", healthz.Minor)
	h.SetHealth("component-minor-error", healthz.Error)

	healthzServer := &http.Server{
		Addr:    addr,
		Handler: h,
	}
	log.Printf("http://%s/\n", addr)
	err := healthzServer.ListenAndServe()
	if err != nil {
		log.Fatalln("Error while healthzServer.ListenAndServe():", err)
	}
}
<|endoftext|>


<commit_before>package test

import (
	"testing"

	"github.com/gocontrib/pubsub/redis"
)

func TestRedis_Basic(t *testing.T) {
	hub, err := redis.Open("tcp://127.0.0.1:6379/11")
	ok(t, "Open", err)
	verifyBasicAPI(t, hub)
}
<commit_msg>fixing redis test<commit_after>package test

import (
	"os"
	"testing"

	"github.com/gocontrib/pubsub/redis"
)

func TestRedis_Basic(t *testing.T) {
	url := os.Getenv("REDIS_URL")
	if len(url) == 0 {
		url = "tcp://127.0.0.1:6379/11"
	}
	hub, err := redis.Open(url)
	ok(t, "Open", err)
	verifyBasicAPI(t, hub)
}
<|endoftext|>