<commit_before>package kit

import (
	"fmt"
	"net/http"
	"net/url"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/suite"
)

type ShopifyResponseTestSuite struct {
	suite.Suite
}

func (suite *ShopifyResponseTestSuite) TestRequestError() {
	errorMessage := "something went wrong"
	badErr := fmt.Errorf(errorMessage)
	resp, err := newShopifyResponse(themeRequest, Create, &http.Response{}, badErr)
	assert.Nil(suite.T(), resp)
	if assert.NotNil(suite.T(), err) {
		assert.Equal(suite.T(), errorMessage, err.Error())
	}
}

func (suite *ShopifyResponseTestSuite) TestNoBody() {
	mock := &http.Response{
		Request: &http.Request{URL: &url.URL{}},
		Body:    fileFixture("responses/general_error"),
	}
	mock.Body.Close()
	resp, err := newShopifyResponse(themeRequest, Create, mock, nil)
	assert.Nil(suite.T(), resp)
	assert.NotNil(suite.T(), err)
}

func (suite *ShopifyResponseTestSuite) TestErrorResponse() {
	resp, err := suite.shopifyResp("responses/general_error")
	assert.NotNil(suite.T(), resp)
	if assert.NotNil(suite.T(), err) {
		assert.Equal(suite.T(), "[API] Invalid API key or access token (unrecognized login or wrong password)", resp.Errors.Error())
	}
}

func (suite *ShopifyResponseTestSuite) TestThemeResponse() {
	resp, err := suite.shopifyResp("responses/theme")
	assert.NotNil(suite.T(), resp)
	assert.Nil(suite.T(), err)
	assert.Equal(suite.T(), "timberland", resp.Theme.Name)
}

func (suite *ShopifyResponseTestSuite) TestThemeErrorResponse() {
	resp, err := suite.shopifyResp("responses/theme_error")
	assert.NotNil(suite.T(), resp)
	if assert.NotNil(suite.T(), err) {
		assert.Equal(suite.T(), "is empty", resp.Errors.Error())
	}
}

func (suite *ShopifyResponseTestSuite) TestAssetResponse() {
	resp, err := suite.shopifyResp("responses/asset")
	assert.NotNil(suite.T(), resp)
	assert.Nil(suite.T(), err)
	assert.Equal(suite.T(), "assets/hello.txt", resp.Asset.Key)
}

func (suite *ShopifyResponseTestSuite) TestAssetErrorResponse() {
	resp, err := suite.shopifyResp("responses/asset_error")
	assert.NotNil(suite.T(), resp)
	if assert.NotNil(suite.T(), err) {
		assert.Equal(suite.T(), "Liquid syntax error (line 10): 'comment' tag was never closed", resp.Errors.Error())
	}
}

func (suite *ShopifyResponseTestSuite) TestListResponse() {
	resp, err := suite.shopifyResp("responses/assets")
	assert.NotNil(suite.T(), resp)
	assert.Nil(suite.T(), err)
	assert.Equal(suite.T(), 2, len(resp.Assets))
	assert.Equal(suite.T(), "assets/goodbye.txt", resp.Assets[1].Key)
}

func (suite *ShopifyResponseTestSuite) TestSuccessful() {
	resp := ShopifyResponse{Code: 200}
	assert.Equal(suite.T(), true, resp.Successful())
	resp = ShopifyResponse{Code: 500}
	assert.Equal(suite.T(), false, resp.Successful())
	resp = ShopifyResponse{Code: 200, Errors: requestError{Other: []string{"nope"}}}
	assert.Equal(suite.T(), false, resp.Successful())
}

func (suite *ShopifyResponseTestSuite) TestError() {
	resp := ShopifyResponse{Code: 200}
	assert.Nil(suite.T(), resp.Error())
	resp = ShopifyResponse{Code: 500, Type: themeRequest}
	assert.IsType(suite.T(), themeError{}, resp.Error())
	resp = ShopifyResponse{Code: 500, Type: assetRequest}
	assert.IsType(suite.T(), assetError{}, resp.Error())
	resp = ShopifyResponse{Code: 500, Type: listRequest}
	assert.IsType(suite.T(), listError{}, resp.Error())
	resp = ShopifyResponse{Code: 500, Type: 20}
	assert.IsType(suite.T(), kitError{}, resp.Error())
}

func (suite *ShopifyResponseTestSuite) shopifyResp(path string) (*ShopifyResponse, Error) {
	return newShopifyResponse(themeRequest, Create, suite.respFixture(path), nil)
}

func (suite *ShopifyResponseTestSuite) respFixture(path string) *http.Response {
	return &http.Response{
		Status:     "200 OK",
		StatusCode: 200,
		Request:    &http.Request{URL: &url.URL{}},
		Body:       fileFixture(path),
	}
}

func TestShopifyResponseTestSuite(t *testing.T) {
	suite.Run(t, new(ShopifyResponseTestSuite))
}
<commit_msg>fix tests<commit_after>package kit

import (
	"fmt"
	"net/http"
	"net/url"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/suite"
)

type ShopifyResponseTestSuite struct {
	suite.Suite
}

func (suite *ShopifyResponseTestSuite) TestRequestError() {
	errorMessage := "something went wrong"
	badErr := fmt.Errorf(errorMessage)
	resp, err := newShopifyResponse(themeRequest, Create, &http.Response{}, badErr)
	assert.NotNil(suite.T(), resp)
	if assert.NotNil(suite.T(), err) {
		assert.Equal(suite.T(), errorMessage, err.Error())
	}
}

func (suite *ShopifyResponseTestSuite) TestNoBody() {
	mock := &http.Response{
		Request: &http.Request{URL: &url.URL{}},
		Body:    fileFixture("responses/general_error"),
	}
	mock.Body.Close()
	resp, err := newShopifyResponse(themeRequest, Create, mock, nil)
	assert.NotNil(suite.T(), resp)
	assert.NotNil(suite.T(), err)
}

func (suite *ShopifyResponseTestSuite) TestErrorResponse() {
	resp, err := suite.shopifyResp("responses/general_error")
	assert.NotNil(suite.T(), resp)
	if assert.NotNil(suite.T(), err) {
		assert.Equal(suite.T(), "[API] Invalid API key or access token (unrecognized login or wrong password)", resp.Errors.Error())
	}
}

func (suite *ShopifyResponseTestSuite) TestThemeResponse() {
	resp, err := suite.shopifyResp("responses/theme")
	assert.NotNil(suite.T(), resp)
	assert.Nil(suite.T(), err)
	assert.Equal(suite.T(), "timberland", resp.Theme.Name)
}

func (suite *ShopifyResponseTestSuite) TestThemeErrorResponse() {
	resp, err := suite.shopifyResp("responses/theme_error")
	assert.NotNil(suite.T(), resp)
	if assert.NotNil(suite.T(), err) {
		assert.Equal(suite.T(), "is empty", resp.Errors.Error())
	}
}

func (suite *ShopifyResponseTestSuite) TestAssetResponse() {
	resp, err := suite.shopifyResp("responses/asset")
	assert.NotNil(suite.T(), resp)
	assert.Nil(suite.T(), err)
	assert.Equal(suite.T(), "assets/hello.txt", resp.Asset.Key)
}

func (suite *ShopifyResponseTestSuite) TestAssetErrorResponse() {
	resp, err := suite.shopifyResp("responses/asset_error")
	assert.NotNil(suite.T(), resp)
	if assert.NotNil(suite.T(), err) {
		assert.Equal(suite.T(), "Liquid syntax error (line 10): 'comment' tag was never closed", resp.Errors.Error())
	}
}

func (suite *ShopifyResponseTestSuite) TestListResponse() {
	resp, err := suite.shopifyResp("responses/assets")
	assert.NotNil(suite.T(), resp)
	assert.Nil(suite.T(), err)
	assert.Equal(suite.T(), 2, len(resp.Assets))
	assert.Equal(suite.T(), "assets/goodbye.txt", resp.Assets[1].Key)
}

func (suite *ShopifyResponseTestSuite) TestSuccessful() {
	resp := ShopifyResponse{Code: 200}
	assert.Equal(suite.T(), true, resp.Successful())
	resp = ShopifyResponse{Code: 500}
	assert.Equal(suite.T(), false, resp.Successful())
	resp = ShopifyResponse{Code: 200, Errors: requestError{Other: []string{"nope"}}}
	assert.Equal(suite.T(), false, resp.Successful())
}

func (suite *ShopifyResponseTestSuite) TestError() {
	resp := ShopifyResponse{Code: 200}
	assert.Nil(suite.T(), resp.Error())
	resp = ShopifyResponse{Code: 500, Type: themeRequest}
	assert.IsType(suite.T(), themeError{}, resp.Error())
	resp = ShopifyResponse{Code: 500, Type: assetRequest}
	assert.IsType(suite.T(), assetError{}, resp.Error())
	resp = ShopifyResponse{Code: 500, Type: listRequest}
	assert.IsType(suite.T(), listError{}, resp.Error())
	resp = ShopifyResponse{Code: 500, Type: 20}
	assert.IsType(suite.T(), kitError{}, resp.Error())
}

func (suite *ShopifyResponseTestSuite) shopifyResp(path string) (*ShopifyResponse, Error) {
	return newShopifyResponse(themeRequest, Create, suite.respFixture(path), nil)
}

func (suite *ShopifyResponseTestSuite) respFixture(path string) *http.Response {
	return &http.Response{
		Status:     "200 OK",
		StatusCode: 200,
		Request:    &http.Request{URL: &url.URL{}},
		Body:       fileFixture(path),
	}
}

func TestShopifyResponseTestSuite(t *testing.T) {
	suite.Run(t, new(ShopifyResponseTestSuite))
}
<|endoftext|>


<commit_before>// config package contains reused config variables.
package config

import (
	"fmt"
	"net/url"
	"path"
	"path/filepath"
	"runtime"
	"strconv"
)

const (
	// Name is the user facing name for this binary. Internally we call it
	// klientctl to avoid confusion.
	Name = "kd"

	// KlientName is the user facing name for klient.
	KlientName = "KD Daemon"

	// KlientAddress is url of locally running klient to connect to send
	// user commands.
	KlientAddress = "http://127.0.0.1:56789/kite"

	// KiteHome is full path to the kite key that we will use to authenticate
	// to the given klient.
	KiteHome = "/etc/kite"

	// SSHDefaultKeyDir is the default directory that stores users ssh key pairs.
	SSHDefaultKeyDir = ".ssh"

	// SSHDefaultKeyName is the default name of the ssh key pair.
	SSHDefaultKeyName = "kd-ssh-key"
)

var (
	// Version is the current version of klientctl. This number is used
	// by CheckUpdate to determine if current version is behind or equal to latest
	// version on S3 bucket.
	Version = "35"

	// Environment is the target channel of klientctl. This value is used
	// to register with Kontrol and to install klient.
	Environment = "production"

	// KiteVersion is the version identifier used to connect to Kontrol.
	KiteVersion = fmt.Sprintf("0.0.%s", Version)

	// KiteKeyPath is the full path to kite.key.
	KiteKeyPath = filepath.Join(KiteHome, "kite.key")

	// KontrolURL is the url to connect to authenticate local klient and get
	// list of machines.
	KontrolURL = "https://koding.com/kontrol/kite"

	// S3KlientLatest is URL to the latest version of the klient.
	S3KlientLatest = "https://koding-klient.s3.amazonaws.com/" + Environment + "/latest-version.txt"

	// S3KlientctlLatest is URL to the latest version of the klientctl.
	S3KlientctlLatest = "https://koding-kd.s3.amazonaws.com/" + Environment + "/latest-version.txt"
)

func dirURL(s string) string {
	u, err := url.Parse(s)
	if err != nil {
		panic(err)
	}
	u.Path = path.Dir(u.Path)
	return u.String()
}

func VersionNum() int {
	version, err := strconv.ParseUint(Version, 10, 32)
	if err != nil {
		return 0
	}

	return int(version)
}

func S3Klient(version int) string {
	s3dir := dirURL(S3KlientLatest)

	// TODO(rjeczalik): klient uses a URL without $GOOS_$GOARCH suffix for
	// auto-updates. Remove the special case when a redirect is deployed
	// to the suffixed file.
	if runtime.GOOS == "linux" {
		return fmt.Sprintf("%[1]s/%[2]d/klient-0.1.%[2]d.gz", s3dir, version)
	}

	return fmt.Sprintf("%[1]s/%[2]d/klient-0.1.%[2]d.%[3]s_%[4]s.gz",
		s3dir, version, runtime.GOOS, runtime.GOARCH)
}

func S3Klientctl(version int) string {
	return fmt.Sprintf("%s/klientctl-0.1.%d.%s_%s.gz", dirURL(S3KlientctlLatest),
		version, runtime.GOOS, runtime.GOARCH)
}
<commit_msg>klientctl: debugging kd builds<commit_after>// config package contains reused config variables.
package config

import (
	"fmt"
	"net/url"
	"os"
	"path"
	"path/filepath"
	"runtime"
	"strconv"
)

const (
	// Name is the user facing name for this binary. Internally we call it
	// klientctl to avoid confusion.
	Name = "kd"

	// KlientName is the user facing name for klient.
	KlientName = "KD Daemon"

	// KlientAddress is url of locally running klient to connect to send
	// user commands.
	KlientAddress = "http://127.0.0.1:56789/kite"

	// KiteHome is full path to the kite key that we will use to authenticate
	// to the given klient.
	KiteHome = "/etc/kite"

	// SSHDefaultKeyDir is the default directory that stores users ssh key pairs.
	SSHDefaultKeyDir = ".ssh"

	// SSHDefaultKeyName is the default name of the ssh key pair.
	SSHDefaultKeyName = "kd-ssh-key"
)

var (
	// Version is the current version of klientctl. This number is used
	// by CheckUpdate to determine if current version is behind or equal to latest
	// version on S3 bucket.
	Version = "35"

	// Environment is the target channel of klientctl. This value is used
	// to register with Kontrol and to install klient.
	Environment = "production"

	// KiteVersion is the version identifier used to connect to Kontrol.
	KiteVersion = fmt.Sprintf("0.0.%s", Version)

	// KiteKeyPath is the full path to kite.key.
	KiteKeyPath = filepath.Join(KiteHome, "kite.key")

	// KontrolURL is the url to connect to authenticate local klient and get
	// list of machines.
	KontrolURL = "https://koding.com/kontrol/kite"

	// S3KlientLatest is URL to the latest version of the klient.
	S3KlientLatest = "https://koding-klient.s3.amazonaws.com/" + Environment + "/latest-version.txt"

	// S3KlientctlLatest is URL to the latest version of the klientctl.
	S3KlientctlLatest = "https://koding-kd.s3.amazonaws.com/" + Environment + "/latest-version.txt"
)

func init() {
	if os.Getenv("KD_DEBUG") == "1" {
		// For debugging kd build.
		fmt.Println("Version", Version)
		fmt.Println("Environment", Environment)
		fmt.Println("KiteVersion", KiteVersion)
		fmt.Println("KiteKeyPath", KiteKeyPath)
		fmt.Println("KontrolURL", KontrolURL)
		fmt.Println("S3KlientLatest", S3KlientLatest)
		fmt.Println("S3KlientctlLatest", S3KlientctlLatest)
	}
}

func dirURL(s string) string {
	u, err := url.Parse(s)
	if err != nil {
		panic(err)
	}
	u.Path = path.Dir(u.Path)
	return u.String()
}

func VersionNum() int {
	version, err := strconv.ParseUint(Version, 10, 32)
	if err != nil {
		return 0
	}

	return int(version)
}

func S3Klient(version int) string {
	s3dir := dirURL(S3KlientLatest)

	// TODO(rjeczalik): klient uses a URL without $GOOS_$GOARCH suffix for
	// auto-updates. Remove the special case when a redirect is deployed
	// to the suffixed file.
	if runtime.GOOS == "linux" {
		return fmt.Sprintf("%[1]s/%[2]d/klient-0.1.%[2]d.gz", s3dir, version)
	}

	return fmt.Sprintf("%[1]s/%[2]d/klient-0.1.%[2]d.%[3]s_%[4]s.gz",
		s3dir, version, runtime.GOOS, runtime.GOARCH)
}

func S3Klientctl(version int) string {
	return fmt.Sprintf("%s/klientctl-0.1.%d.%s_%s.gz", dirURL(S3KlientctlLatest),
		version, runtime.GOOS, runtime.GOARCH)
}
<|endoftext|>


<commit_before>package postbird

import (
	"errors"
	"fmt"
	"log"
	"net"
	"reflect"
)

// Info struct
// PostBird 에서 사용될 값들
type Info struct {
	BindPort      uint
	BindAddress   string
	RemotePort    uint
	RemoteAddress string
	Mode          uint
}

const DefaultPort uint = 8787                   // Default Bind Port
const DefaultBindAddress string = "127.0.0.1"   // Default Bind Address
const DefaultRemoteAddress string = "127.0.0.1" // Defualt Server Address

const (
	ServerMode = 0
	ClientMode = 1
)

var info Info
var ServerConnection net.Conn

// funcs map
// 원격에서 호출가능한 함수들을 등록해놓은 map
// RegisterFunc 함수로 이 맵에 등록한다
var funcs map[string]interface{} = make(map[string]interface{})

// SetBindAddress func
// StartServer로 ServerMode 로 실행할때 바인드될 아이피 주소. ""로 설정하면 모든 NIC에 바인딩된다.
// 이 함수를 호출하지 않으면 DefaultBindAddress인 127.0.0.1로 바인딩된다.
func SetBindAddress(BindAddress string) {
	info.BindAddress = BindAddress
}

// SetBindPort func
// StartServer로 ServerMode 로 실행할때 바인드될 포트 번호.
// 이 함수를 호출하지 않으면 DefaultPortd인 8787로 바인딩된다.
func SetBindPort(BindPort uint) {
	info.BindPort = BindPort
}

// SetRemoteAddress func
//
func SetRemoteAddress(ServerAddress string) {
	info.RemoteAddress = ServerAddress
}

func SetRemotePort(ServerPort uint) {
	info.RemotePort = ServerPort
}

func init() {

	if info.BindAddress == "" {
		info.BindAddress = DefaultBindAddress
	}

	if info.BindPort == 0 {
		info.BindPort = DefaultPort
	}

	if info.RemoteAddress == "" {
		info.RemoteAddress = DefaultRemoteAddress
	}

	if info.RemotePort == 0 {
		info.RemotePort = DefaultPort
	}

}

// RegisterFunc func
// CallLocalFunc 함수에 의해 실행될 수 있는, 즉 원격에서 호출가능한 함수를 등록하는 함수
// funcs 맵에 등록되며 이 함수에 등록되지 않은 함수는 원격에서 호출할 수 없다.
func RegisterFunc(FuncName string, Function interface{}) {
	funcs[FuncName] = Function
}

// StartServer func
// 프로그램을 서버역할로 사용하려면 이 함수를 호출해서 tcp 서버를 시작하면 된다.
// 시작되면 Binder 함수를 비동기로 호출하여 비동기로 tcp Listen
// 이 함수가 호출되면 무조건 Mode가 ServerMode 로 바뀐다
func StartServer() {
	info.Mode = ServerMode
	go Binder(info.BindAddress, info.BindPort)
}

// Binder func
// ServerMode일때 main func
func Binder(BindAddr string, Port uint) {
	ln, err := net.Listen("tcp", BindAddr+":"+string(Port)) // 전달받은 BindAddr:Port 에 TCP로 바인딩
	if err != nil {
		log.Println(err)
	}
	defer ln.Close()

	for {
		conn, err := ln.Accept()
		if err != nil {
			log.Println(err)
			continue
		}
		defer conn.Close()

		go requestHandler(conn)
	}
}

// requestHandler func
// tcp 연결되었을때 request 핸들러
func requestHandler(c net.Conn) {
	data := make([]byte, 4096) // 4096 크기의 바이트 슬라이스 생성

	for {
		n, err := c.Read(data) // 클라이언트에서 받은 데이터를 읽음
		if err != nil {
			fmt.Println(err)
			return
		}

		fmt.Println(string(data[:n])) // 데이터 출력

		_, err = c.Write(data[:n]) // 클라이언트로 데이터를 보냄
		if err != nil {
			fmt.Println(err)
			return
		}
	}
}

func ConnectToRemote() {
	client, err := net.Dial("tcp", info.RemoteAddress+":"+string(info.RemotePort))
	if err != nil {
		fmt.Println(err)
		return
	}
	ServerConnection = client
}

// CallLocalFunc func
// RegisterFunc 로 등록된 함수가 원격에서 함수를 호출했을때
// 이함수를 통해 실행된다
func CallLocalFunc(name string, params ...interface{}) (result []reflect.Value, err error) {
	f := reflect.ValueOf(funcs[name])
	if len(params) != f.Type().NumIn() {
		err = errors.New("The number of params is not adapted.")
		return
	}
	in := make([]reflect.Value, len(params))
	for k, param := range params {
		in[k] = reflect.ValueOf(param)
	}
	result = f.Call(in)
	return
}

// CallRemoteFunc func
// 연결된 (서버)의 함수를 호출하고 싶을때 사용하는 함수
// json형식으로 변환해서 tcp로 서버에 전달.
func CallRemoteFunc() {

}
<commit_msg>some changes<commit_after>package postbird

import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"log"
	"net"
	"reflect"
)

// Info struct
// PostBird 에서 사용될 값들
type Info struct {
	BindPort      uint
	BindAddress   string
	RemotePort    uint
	RemoteAddress string
	Mode          uint
}

const DefaultPort uint = 8787                   // Default Bind Port
const DefaultBindAddress string = "127.0.0.1"   // Default Bind Address
const DefaultRemoteAddress string = "127.0.0.1" // Defualt Server Address

const (
	ServerMode = 0
	ClientMode = 1
)

var info Info
var ServerConnection net.Conn

// funcs map
// 원격에서 호출가능한 함수들을 등록해놓은 map
// RegisterFunc 함수로 이 맵에 등록한다
var funcs map[string]interface{} = make(map[string]interface{})

// SetBindAddress func
// StartServer로 ServerMode 로 실행할때 바인드될 아이피 주소. ""로 설정하면 모든 NIC에 바인딩된다.
// 이 함수를 호출하지 않으면 DefaultBindAddress인 127.0.0.1로 바인딩된다.
func SetBindAddress(BindAddress string) {
	info.BindAddress = BindAddress
}

// SetBindPort func
// StartServer로 ServerMode 로 실행할때 바인드될 포트 번호.
// 이 함수를 호출하지 않으면 DefaultPortd인 8787로 바인딩된다.
func SetBindPort(BindPort uint) {
	info.BindPort = BindPort
}

// SetRemoteAddress func
//
func SetRemoteAddress(ServerAddress string) {
	info.RemoteAddress = ServerAddress
}

func SetRemotePort(ServerPort uint) {
	info.RemotePort = ServerPort
}

func init() {

	if info.BindAddress == "" {
		info.BindAddress = DefaultBindAddress
	}

	if info.BindPort == 0 {
		info.BindPort = DefaultPort
	}

	if info.RemoteAddress == "" {
		info.RemoteAddress = DefaultRemoteAddress
	}

	if info.RemotePort == 0 {
		info.RemotePort = DefaultPort
	}

}

// RegisterFunc func
// CallLocalFunc 함수에 의해 실행될 수 있는, 즉 원격에서 호출가능한 함수를 등록하는 함수
// funcs 맵에 등록되며 이 함수에 등록되지 않은 함수는 원격에서 호출할 수 없다.
func RegisterFunc(FuncName string, Function interface{}) {
	funcs[FuncName] = Function
}

// StartServer func
// 프로그램을 서버역할로 사용하려면 이 함수를 호출해서 tcp 서버를 시작하면 된다.
// 시작되면 Binder 함수를 비동기로 호출하여 비동기로 tcp Listen
// 이 함수가 호출되면 무조건 Mode가 ServerMode 로 바뀐다
func StartServer() {
	info.Mode = ServerMode
	go Binder(info.BindAddress, info.BindPort)
}

// Binder func
// ServerMode일때 main func
func Binder(BindAddr string, Port uint) {
	ln, err := net.Listen("tcp", BindAddr+":"+string(Port)) // 전달받은 BindAddr:Port 에 TCP로 바인딩
	if err != nil {
		log.Println(err)
	}

	for {
		conn, err := ln.Accept()
		if err != nil {
			log.Println(err)
			continue
		}
		defer conn.Close()

		go requestHandler(conn)
	}
}

// requestHandler func
// tcp 연결되었을때 request 핸들러
func requestHandler(c net.Conn) {
	data := make([]byte, 4096) // 4096 크기의 바이트 슬라이스 생성

	for {
		n, err := c.Read(data) // 클라이언트에서 받은 데이터를 읽음
		if err != nil {
			fmt.Println(err)
			return
		}

		fmt.Println(string(data[:n])) // 데이터 출력

		_, err = c.Write(data[:n]) // 클라이언트로 데이터를 보냄
		if err != nil {
			fmt.Println(err)
			return
		}
	}
}

func ConnectToRemote() {
	client, err := net.Dial("tcp", info.RemoteAddress+":"+string(info.RemotePort))
	if err != nil {
		fmt.Println(err)
		return
	}
	ServerConnection = client
}

// CallLocalFunc func
// RegisterFunc 로 등록된 함수가 원격에서 함수를 호출했을때
// 이함수를 통해 실행된다
func CallLocalFunc(name string, params ...interface{}) (result []reflect.Value, err error) {
	f := reflect.ValueOf(funcs[name])
	if len(params) != f.Type().NumIn() {
		err = errors.New("The number of params is not adapted.")
		return
	}
	in := make([]reflect.Value, len(params))
	for k, param := range params {
		in[k] = reflect.ValueOf(param)
	}
	result = f.Call(in)
	return
}

// CallRemoteFunc func
// 연결된 (서버)의 함수를 호출하고 싶을때 사용하는 함수
// json형식으로 변환해서 tcp로 서버에 전달.
func CallRemoteFunc(FunctionName string, args ...interface{}) {

}

func readFully(conn net.Conn) ([]byte, error) {
	result := bytes.NewBuffer(nil)
	var buf [512]byte
	for {
		n, err := conn.Read(buf[0:])
		result.Write(buf[0:n])
		if err != nil {
			if err == io.EOF {
				break
			}
			return nil, err
		}
	}
	return result.Bytes(), nil
}
<|endoftext|>


<commit_before>// Copyright 2017 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 appengine contains an AppEngine app for perf.golang.org
package appengine

import (
	"log"
	"net/http"
	"os"

	"golang.org/x/perf/analysis/app"
	"golang.org/x/perf/storage"
	"google.golang.org/appengine"
	"google.golang.org/appengine/urlfetch"
)

func mustGetenv(k string) string {
	v := os.Getenv(k)
	if v == "" {
		log.Panicf("%s environment variable not set.", k)
	}
	return v
}

// appHandler is the default handler, registered to serve "/".
// It creates a new App instance using the appengine Context and then
// dispatches the request to the App. The environment variable
// STORAGE_URL_BASE must be set in app.yaml with the name of the bucket to
// write to.
func appHandler(w http.ResponseWriter, r *http.Request) {
	ctx := appengine.NewContext(r)
	app := &app.App{
		StorageClient: &storage.Client{
			BaseURL:    mustGetenv("STORAGE_URL_BASE"),
			HTTPClient: urlfetch.Client(ctx),
		},
	}
	mux := http.NewServeMux()
	app.RegisterOnMux(mux)
	mux.ServeHTTP(w, r)
}

func init() {
	http.HandleFunc("/", appHandler)
}
<commit_msg>analysis/appengine: use a 60s timeout when fetching query results<commit_after>// Copyright 2017 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 appengine contains an AppEngine app for perf.golang.org
package appengine

import (
	"log"
	"net/http"
	"os"
	"time"

	"golang.org/x/net/context"
	"golang.org/x/perf/analysis/app"
	"golang.org/x/perf/storage"
	"google.golang.org/appengine"
	"google.golang.org/appengine/urlfetch"
)

func mustGetenv(k string) string {
	v := os.Getenv(k)
	if v == "" {
		log.Panicf("%s environment variable not set.", k)
	}
	return v
}

// appHandler is the default handler, registered to serve "/".
// It creates a new App instance using the appengine Context and then
// dispatches the request to the App. The environment variable
// STORAGE_URL_BASE must be set in app.yaml with the name of the bucket to
// write to.
func appHandler(w http.ResponseWriter, r *http.Request) {
	ctx := appengine.NewContext(r)
	// urlfetch defaults to 5s timeout if the context has no timeout.
	// The underlying request has a 60 second timeout, so we might as well propagate that here.
	// (Why doesn't appengine do that for us?)
	ctx, cancel := context.WithTimeout(ctx, 60*time.Second)
	defer cancel()
	app := &app.App{
		StorageClient: &storage.Client{
			BaseURL:    mustGetenv("STORAGE_URL_BASE"),
			HTTPClient: urlfetch.Client(ctx),
		},
	}
	mux := http.NewServeMux()
	app.RegisterOnMux(mux)
	mux.ServeHTTP(w, r)
}

func init() {
	http.HandleFunc("/", appHandler)
}
<|endoftext|>


<commit_before>// © 2014 Steve McCoy under the MIT license. See LICENSE for details.

package ogg

import (
	"bytes"
	"encoding/binary"
	"errors"
	"hash/crc32"
	"io"
	"strconv"
)

// A Decoder decodes an ogg stream page-by-page with its Decode method.
type Decoder struct {
	r   io.Reader
	buf [maxPageSize]byte
}

// NewDecoder creates an ogg Decoder.
func NewDecoder(r io.Reader) *Decoder {
	return &Decoder{r: r}
}

// A Page represents a logical ogg page.
type Page struct {
	// Type is a bitmask of COP, BOS, and/or EOS.
	Type byte
	// Serial is the bitstream serial number.
	Serial uint32
	// Granule is the granule position, whose meaning is dependent on the encapsulated codec.
	Granule int64
	// Packet is the raw packet data.
	// If Type & COP != 0, this is a continuation of the previous page's packet.
	Packet []byte
}

// ErrBadSegs is the error used when trying to decode a page with a segment table size less than 1.
var ErrBadSegs = errors.New("invalid segment table size")

// ErrBadCrc is the error used when an ogg page's CRC field does not match the CRC calculated by the Decoder.
type ErrBadCrc struct {
	Found    uint32
	Expected uint32
}

func (bc ErrBadCrc) Error() string {
	return "invalid crc in packet: got " + strconv.FormatInt(int64(bc.Found), 16) +
		", expected " + strconv.FormatInt(int64(bc.Expected), 16)
}

var oggs = []byte{'O', 'g', 'g', 'S'}

// Decode reads from d's Reader to the next ogg page, then returns the decoded Page or an error.
// The error may be io.EOF if that's what the Reader returned.
//
// The buffer underlying the returned Page's Packet is owned by the Decoder.
// It may be overwritten by subsequent calls to Decode.
//
// It is safe to call Decode concurrently on distinct Decoders if their Readers are distinct.
// Otherwise, the behavior is undefined.
func (d *Decoder) Decode() (Page, error) {
	hbuf := d.buf[0:headsz]
	b := 0
	for {
		_, err := io.ReadFull(d.r, hbuf[b:])
		if err != nil {
			return Page{}, err
		}

		i := bytes.Index(hbuf, oggs)
		if i == 0 {
			break
		}

		if i < 0 {
			const n = headsz
			if hbuf[n-1] == 'O' {
				i = n - 1
			} else if hbuf[n-2] == 'O' && hbuf[n-1] == 'g' {
				i = n - 2
			} else if hbuf[n-3] == 'O' && hbuf[n-2] == 'g' && hbuf[n-1] == 'g' {
				i = n - 3
			}
		}

		if i > 0 {
			b = copy(hbuf, hbuf[i:])
		}
	}

	var h pageHeader
	err := binary.Read(bytes.NewBuffer(hbuf), byteOrder, &h)
	if err != nil {
		return Page{}, err
	}

	if h.Nsegs < 1 {
		return Page{}, ErrBadSegs
	}

	nsegs := int(h.Nsegs)
	segtbl := d.buf[headsz : headsz+nsegs]
	_, err = io.ReadFull(d.r, segtbl)
	if err != nil {
		return Page{}, err
	}

	packetlen := mss*(nsegs-1) + int(segtbl[nsegs-1])
	packet := d.buf[headsz+nsegs : headsz+nsegs+packetlen]
	_, err = io.ReadFull(d.r, packet)
	if err != nil {
		return Page{}, err
	}

	page := d.buf[0 : headsz+nsegs+packetlen]
	// Clear out existing crc before calculating it
	page[22] = 0
	page[23] = 0
	page[24] = 0
	page[25] = 0
	crc := crc32.Checksum(page, crcTable)
	if crc != h.Crc {
		return Page{}, ErrBadCrc{h.Crc, crc}
	}

	return Page{h.HeaderType, h.Serial, h.Granule, packet}, nil
}
<commit_msg>Decode: fix packet length<commit_after>// © 2014 Steve McCoy under the MIT license. See LICENSE for details.

package ogg

import (
	"bytes"
	"encoding/binary"
	"errors"
	"hash/crc32"
	"io"
	"strconv"
)

// A Decoder decodes an ogg stream page-by-page with its Decode method.
type Decoder struct {
	r   io.Reader
	buf [maxPageSize]byte
}

// NewDecoder creates an ogg Decoder.
func NewDecoder(r io.Reader) *Decoder {
	return &Decoder{r: r}
}

// A Page represents a logical ogg page.
type Page struct {
	// Type is a bitmask of COP, BOS, and/or EOS.
	Type byte
	// Serial is the bitstream serial number.
	Serial uint32
	// Granule is the granule position, whose meaning is dependent on the encapsulated codec.
	Granule int64
	// Packet is the raw packet data.
	// If Type & COP != 0, this is a continuation of the previous page's packet.
	Packet []byte
}

// ErrBadSegs is the error used when trying to decode a page with a segment table size less than 1.
var ErrBadSegs = errors.New("invalid segment table size")

// ErrBadCrc is the error used when an ogg page's CRC field does not match the CRC calculated by the Decoder.
type ErrBadCrc struct {
	Found    uint32
	Expected uint32
}

func (bc ErrBadCrc) Error() string {
	return "invalid crc in packet: got " + strconv.FormatInt(int64(bc.Found), 16) +
		", expected " + strconv.FormatInt(int64(bc.Expected), 16)
}

var oggs = []byte{'O', 'g', 'g', 'S'}

// Decode reads from d's Reader to the next ogg page, then returns the decoded Page or an error.
// The error may be io.EOF if that's what the Reader returned.
//
// The buffer underlying the returned Page's Packet is owned by the Decoder.
// It may be overwritten by subsequent calls to Decode.
//
// It is safe to call Decode concurrently on distinct Decoders if their Readers are distinct.
// Otherwise, the behavior is undefined.
func (d *Decoder) Decode() (Page, error) {
	hbuf := d.buf[0:headsz]
	b := 0
	for {
		_, err := io.ReadFull(d.r, hbuf[b:])
		if err != nil {
			return Page{}, err
		}

		i := bytes.Index(hbuf, oggs)
		if i == 0 {
			break
		}

		if i < 0 {
			const n = headsz
			if hbuf[n-1] == 'O' {
				i = n - 1
			} else if hbuf[n-2] == 'O' && hbuf[n-1] == 'g' {
				i = n - 2
			} else if hbuf[n-3] == 'O' && hbuf[n-2] == 'g' && hbuf[n-1] == 'g' {
				i = n - 3
			}
		}

		if i > 0 {
			b = copy(hbuf, hbuf[i:])
		}
	}

	var h pageHeader
	err := binary.Read(bytes.NewBuffer(hbuf), byteOrder, &h)
	if err != nil {
		return Page{}, err
	}

	if h.Nsegs < 1 {
		return Page{}, ErrBadSegs
	}

	nsegs := int(h.Nsegs)
	segtbl := d.buf[headsz : headsz+nsegs]
	_, err = io.ReadFull(d.r, segtbl)
	if err != nil {
		return Page{}, err
	}

	packetlen := 0
	// This seems to contradict the spec, which says a segment with length < 255
	// indicates the end of a packet. But hey, libogg puts out short non-final segments,
	// so what can I do.
	for _, l := range segtbl {
		packetlen += int(l)
	}

	packet := d.buf[headsz+nsegs : headsz+nsegs+packetlen]
	_, err = io.ReadFull(d.r, packet)
	if err != nil {
		return Page{}, err
	}

	page := d.buf[0 : headsz+nsegs+packetlen]
	// Clear out existing crc before calculating it
	page[22] = 0
	page[23] = 0
	page[24] = 0
	page[25] = 0
	crc := crc32.Checksum(page, crcTable)
	if crc != h.Crc {
		return Page{}, ErrBadCrc{h.Crc, crc}
	}

	return Page{h.HeaderType, h.Serial, h.Granule, packet}, nil
}
<|endoftext|>


<commit_before>package transport

import "os"

// DualTransport is an implementation of Transport that directs methods to the
// transports in order depending on operation. All write operations are first
// sent to RemoteTransport, while read operations are first sent to
// CacheTransport. Currently we don't cascade requests to transports.
//
// The ordering of transports are so the disk cache doesn't get stale in case of
// connection disruptions. Imagine connection to remote is disconnected, but
// operations continue to happen, this would lead to disk cache become out of
// sync with remote. To prevent this from happening, it sends all write
// operations to remote first.
type DualTransport struct {
	RemoteTransport Transport
	CacheTransport  Transport
}

// NewDualTransport is an initializer for DualTransport.
func NewDualTransport(rt *RemoteTransport, dt *DiskTransport) *DualTransport {
	// DiskTransport does not ignore any dirs, if RemoteTransport ignores some
	// dirs it'll lead to state mismatch; hence don't ignore any dirs
	rt.SetIgnoreDirs(nil)

	return &DualTransport{
		RemoteTransport: rt,
		CacheTransport:  dt,
	}
}

// CreateDir is sent to RemoteTransport, then CacheTransport.
func (d *DualTransport) CreateDir(path string, mode os.FileMode) error {
	if err := d.RemoteTransport.CreateDir(path, mode); err != nil {
		return err
	}

	return d.CacheTransport.CreateDir(path, mode)
}

// ReadDir is sent to CacheTransport only.
func (d *DualTransport) ReadDir(path string, r bool) (*ReadDirRes, error) {
	return d.CacheTransport.ReadDir(path, r)
}

// Rename is sent to RemoteTransport, then CacheTransport.
func (d *DualTransport) Rename(oldName, newName string) error {
	if err := d.RemoteTransport.Rename(oldName, newName); err != nil {
		return err
	}

	return d.CacheTransport.Rename(oldName, newName)
}

// Remove is sent to RemoteTransport, then CacheTransport.
func (d *DualTransport) Remove(path string) error {
	if err := d.RemoteTransport.Remove(path); err != nil {
		return err
	}

	return d.CacheTransport.Remove(path)
}

// ReadFileAt is sent to CacheTransport only.
func (d *DualTransport) ReadFileAt(dst []byte, path string, offset, blockSize int64) (int, error) {
	return d.CacheTransport.ReadFileAt(dst, path, offset, blockSize)
}

// WriteFile is sent to RemoteTransport, then CacheTransport.
func (d *DualTransport) WriteFile(path string, data []byte) error {
	if err := d.RemoteTransport.WriteFile(path, data); err != nil {
		return err
	}

	return d.CacheTransport.WriteFile(path, data)
}

// Exec is sent to RemoteTransport only.
func (d *DualTransport) Exec(cmd string) (*ExecRes, error) {
	return d.RemoteTransport.Exec(cmd)
}

// GetDiskInfo is sent to CacheTransport only.
func (d *DualTransport) GetDiskInfo(path string) (*GetDiskInfoRes, error) {
	return d.CacheTransport.GetDiskInfo(path)
}

// GetInfo is sent to CacheTransport only.
func (d *DualTransport) GetInfo(path string) (*GetInfoRes, error) {
	return d.CacheTransport.GetInfo(path)
}

// GetRemotePath is sent to RemoteTransport only.
func (d *DualTransport) GetRemotePath() string {
	return d.RemoteTransport.GetRemotePath()
}
<commit_msg>fuseklient: get disk info always from remote<commit_after>package transport

import "os"

// DualTransport is an implementation of Transport that directs methods to the
// transports in order depending on operation. All write operations are first
// sent to RemoteTransport, while read operations are first sent to
// CacheTransport. Currently we don't cascade requests to transports.
//
// The ordering of transports are so the disk cache doesn't get stale in case of
// connection disruptions. Imagine connection to remote is disconnected, but
// operations continue to happen, this would lead to disk cache become out of
// sync with remote. To prevent this from happening, it sends all write
// operations to remote first.
type DualTransport struct {
	RemoteTransport Transport
	CacheTransport  Transport
}

// NewDualTransport is an initializer for DualTransport.
func NewDualTransport(rt *RemoteTransport, dt *DiskTransport) *DualTransport {
	// DiskTransport does not ignore any dirs, if RemoteTransport ignores some
	// dirs it'll lead to state mismatch; hence don't ignore any dirs
	rt.SetIgnoreDirs(nil)

	return &DualTransport{
		RemoteTransport: rt,
		CacheTransport:  dt,
	}
}

// CreateDir is sent to RemoteTransport, then CacheTransport.
func (d *DualTransport) CreateDir(path string, mode os.FileMode) error {
	if err := d.RemoteTransport.CreateDir(path, mode); err != nil {
		return err
	}

	return d.CacheTransport.CreateDir(path, mode)
}

// ReadDir is sent to CacheTransport only.
func (d *DualTransport) ReadDir(path string, r bool) (*ReadDirRes, error) {
	return d.CacheTransport.ReadDir(path, r)
}

// Rename is sent to RemoteTransport, then CacheTransport.
func (d *DualTransport) Rename(oldName, newName string) error {
	if err := d.RemoteTransport.Rename(oldName, newName); err != nil {
		return err
	}

	return d.CacheTransport.Rename(oldName, newName)
}

// Remove is sent to RemoteTransport, then CacheTransport.
func (d *DualTransport) Remove(path string) error {
	if err := d.RemoteTransport.Remove(path); err != nil {
		return err
	}

	return d.CacheTransport.Remove(path)
}

// ReadFileAt is sent to CacheTransport only.
func (d *DualTransport) ReadFileAt(dst []byte, path string, offset, blockSize int64) (int, error) {
	return d.CacheTransport.ReadFileAt(dst, path, offset, blockSize)
}

// WriteFile is sent to RemoteTransport, then CacheTransport.
func (d *DualTransport) WriteFile(path string, data []byte) error {
	if err := d.RemoteTransport.WriteFile(path, data); err != nil {
		return err
	}

	return d.CacheTransport.WriteFile(path, data)
}

// Exec is sent to RemoteTransport only.
func (d *DualTransport) Exec(cmd string) (*ExecRes, error) {
	return d.RemoteTransport.Exec(cmd)
}

// GetDiskInfo is sent to RemoteTransport only.
func (d *DualTransport) GetDiskInfo(path string) (*GetDiskInfoRes, error) {
	return d.RemoteTransport.GetDiskInfo(path)
}

// GetInfo is sent to CacheTransport only.
func (d *DualTransport) GetInfo(path string) (*GetInfoRes, error) {
	return d.CacheTransport.GetInfo(path)
}

// GetRemotePath is sent to RemoteTransport only.
func (d *DualTransport) GetRemotePath() string {
	return d.RemoteTransport.GetRemotePath()
}
<|endoftext|>


<commit_before>package slimgfast

import (
	"encoding/json"
	"errors"
	"net/url"
	"strconv"
)

type ImageRequest struct {
	Url    string
	Width  int
	Height int
	Fit    string
}

// URL: /NAMESPACE/BUCKET/FILENAME.jpg?w=100&h=100&fit=abc
func ImageRequestFromURLString(rawUrl string) (*ImageRequest, error) {
	req := ImageRequest{Url: rawUrl}
	parsedUrl, err := url.Parse(rawUrl)
	if err != nil {
		return nil, err
	}
	// Purposely ignore the strcon errors here, if they're empty strings we'll
	// notice that later and serve the image at its original size.
	req.Width, _ = strconv.Atoi(parsedUrl.Query().Get("w"))
	req.Height, _ = strconv.Atoi(parsedUrl.Query().Get("h"))
	req.Fit = parsedUrl.Query().Get("fit")
	return &req, nil
}

func ImageRequestFromCacheKey(cacheKey string) (*ImageRequest, error) {
	req := ImageRequest{}
	err := json.Unmarshal([]byte(cacheKey), &req)
	return &req, err
}

func (req *ImageRequest) CacheKey() (string, error) {
	b, err := json.Marshal(req)
	if err != nil {
		return "", err
	}
	return string(b), nil
}

func (req *ImageRequest) Size() (*Size, error) {
	if req.Width == 0 || req.Width == -1 {
		return nil, errors.New("Image does not have a specified width")
	}
	if req.Height == 0 || req.Width == -1 {
		return nil, errors.New("Image does not have a specified height")
	}
	return &Size{Width: uint(req.Width), Height: uint(req.Height)}, nil
}
<commit_msg>Remove misleading comment.<commit_after>package slimgfast

import (
	"encoding/json"
	"errors"
	"net/url"
	"strconv"
)

type ImageRequest struct {
	Url    string
	Width  int
	Height int
	Fit    string
}

func ImageRequestFromURLString(rawUrl string) (*ImageRequest, error) {
	req := ImageRequest{Url: rawUrl}
	parsedUrl, err := url.Parse(rawUrl)
	if err != nil {
		return nil, err
	}
	// Purposely ignore the strcon errors here, if they're empty strings we'll
	// notice that later and serve the image at its original size.
	req.Width, _ = strconv.Atoi(parsedUrl.Query().Get("w"))
	req.Height, _ = strconv.Atoi(parsedUrl.Query().Get("h"))
	req.Fit = parsedUrl.Query().Get("fit")
	return &req, nil
}

func ImageRequestFromCacheKey(cacheKey string) (*ImageRequest, error) {
	req := ImageRequest{}
	err := json.Unmarshal([]byte(cacheKey), &req)
	return &req, err
}

func (req *ImageRequest) CacheKey() (string, error) {
	b, err := json.Marshal(req)
	if err != nil {
		return "", err
	}
	return string(b), nil
}

func (req *ImageRequest) Size() (*Size, error) {
	if req.Width == 0 || req.Width == -1 {
		return nil, errors.New("Image does not have a specified width")
	}
	if req.Height == 0 || req.Width == -1 {
		return nil, errors.New("Image does not have a specified height")
	}
	return &Size{Width: uint(req.Width), Height: uint(req.Height)}, nil
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"log"
	"regexp"
	"strconv"
	"strings"
)

type (
	InvalidExpression struct{
		msg string
	}
)

func (e *InvalidExpression) Error() string {
	return e.msg
}

type (
	Variable struct {
		data map[string]interface{}
		// quoteString boolean
		separator string
	}
)

const (
	DefaultExpandedArraySeparator = "[[GCSPROXY:SEP]]"
)

func (v *Variable) expand(str string) (string, error) {
	if v.separator == "" {
		v.separator = DefaultExpandedArraySeparator
	}
	re0 := regexp.MustCompile(`\%\{\s*([\w.]+)\s*\}`)
	re1 := regexp.MustCompile(`\A\%\{\s*`)
	re2 := regexp.MustCompile(`\s*\}\z`)
	res := re0.ReplaceAllStringFunc(str, func(raw string) string {
		expr := re1.ReplaceAllString(re2.ReplaceAllString(raw, ""), "")
		value, err := v.dive(expr)
		if err != nil {
			log.Printf("Error to dive: %v: %v\n", expr, err)
			// return err
			value = ""
		}
		switch value.(type) {
		case string:
			return value.(string)
		case []interface{}:
			return v.flatten(value)
		case map[string]interface{}:
			return v.flatten(value)
		case map[string]string:
			return v.flatten(value)
		default:
			return fmt.Sprintf("%v", value)
		}
	})
	return res, nil
}

func (v *Variable) dive(expr string) (interface{}, error) {
	var_names := strings.Split(expr, expr_separator)
	// fmt.Printf("var_names: %v\n", var_names)
	res, err := v.inject(var_names, v.data, func(tmp interface{}, name string) (interface{}, error) {
		res, err := v.dig(tmp, name, expr)
		// fmt.Printf("res: %v err: %v\n", res, err)
		if err != nil {
			return nil, err
		}
		return res, nil
	})
	if err != nil {
		return nil, err
	}
	return res, nil
}

func (v *Variable) dig(tmp interface{}, name, expr string) (interface{}, error) {
	result, err := v.digIn(tmp, name, expr)
	if err != nil {
		return nil, err
	}
	// fmt.Printf("name: %v, result: %v\n", name, result)
	switch result.(type) {
	case string:
		re := regexp.MustCompile(`\A\{.*\}\z|\A\[.*\]\z`)
		matched := re.MatchString(result.(string))
		if matched {
			var obj interface{}
			src := []byte(result.(string))
			err := json.Unmarshal(src, &obj)
			if err != nil {
				return result.(string), nil
			}
			return obj, nil
		} else {
			return result, nil
		}
	default:
		return result, nil
	}
}

func (v *Variable) digIn(tmp interface{}, name, expr string) (interface{}, error) {
	switch tmp.(type) {
	case []string:
		return v.getFromArray(tmp, name)
	case []interface{}:
		return v.getFromArray(tmp, name)
	case map[string]interface{}:
		return v.getFromMap(tmp, name)
	case map[string]string:
		return v.getFromMap(tmp, name)
	default:
		return nil, fmt.Errorf("Unsupported Object type: [%T]%v", tmp, tmp)
	}
}

func (v *Variable) getFromArray(array interface{}, name string) (interface{}, error) {
	idx, err := v.parseIndex(name)
	if err != nil {
		return nil, &InvalidExpression{ "Invalid index for array: " + name }
	}
	switch array.(type) {
	case []string:
		l := len(array.([]string))
		if idx >= l {
			return nil, &InvalidExpression{ fmt.Sprintf("Invalid index %v for array who has %v items", idx, l) }
		}
		return array.([]string)[idx], nil
	case []interface{}:
		l := len(array.([]interface{}))
		if idx >= l {
			return nil, &InvalidExpression{ fmt.Sprintf("Invalid index %v for array who has %v items", idx, l) }
		}
		return array.([]interface{})[idx], nil
	default:
		return nil, fmt.Errorf("Unsupported object given as an array: [%T]%v", array, array)
	}
}

func (v *Variable) getFromMap(obj interface{}, name string) (interface{}, error) {
	switch obj.(type) {
	case map[string]interface{}:
		return obj.(map[string]interface{})[name], nil
	case map[string]string:
		return obj.(map[string]string)[name], nil
	default:
		return nil, fmt.Errorf("Unsupported object given as a map: [%T]%v", obj, obj)
	}
}

func (v *Variable) parseIndex(str string) (int, error) {
	re := regexp.MustCompile(`\A\d+\z`)
	matched := re.MatchString(str)
	if !matched {
		return 0, fmt.Errorf("Invalid Reference: %v", str)
	}
	idx, err := strconv.Atoi(str)
	if err != nil {
		log.Printf("Error to Atoi(%v): %v\n", str, err)
		return 0, err
	}
	return idx, nil
}

func (v *Variable) inject(var_names []string, tmp interface{}, f func(interface{}, string) (interface{}, error)) (interface{}, error) {
	name := var_names[0]
	rest := var_names[1:]
	res, err := f(tmp, name)
	if err != nil {
		return nil, err
	}
	if len(rest) == 0 {
		return res, nil
	} else {
		return v.inject(rest, res, f)
	}
}

const (
	expr_separator = "."
)

func (v *Variable) flatten(obj interface{}) string {
	switch obj.(type) {
	case string:
		return obj.(string)
	case []string:
		return strings.Join(obj.([]string), v.separator)
	case []interface{}:
		res := []string{}
		for _, i := range obj.([]interface{}) {
			res = append(res, v.flatten(i))
		}
		return strings.Join(res, v.separator)
	case map[string]interface{}:
		res := []string{}
		for _, i := range obj.(map[string]interface{}) {
			res = append(res, v.flatten(i))
		}
		return strings.Join(res, v.separator)
	case map[string]string:
		res := []string{}
		for _, i := range obj.(map[string]string) {
			res = append(res, v.flatten(i))
		}
		return strings.Join(res, v.separator)
	default:
		return fmt.Sprintf("%v", obj)
	}
}
<commit_msg>:+1: Add check to get value from map<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"log"
	"regexp"
	"strconv"
	"strings"
)

type (
	InvalidExpression struct{
		msg string
	}
)

func (e *InvalidExpression) Error() string {
	return e.msg
}

type (
	Variable struct {
		data map[string]interface{}
		// quoteString boolean
		separator string
	}
)

const (
	DefaultExpandedArraySeparator = "[[GCSPROXY:SEP]]"
)

func (v *Variable) expand(str string) (string, error) {
	if v.separator == "" {
		v.separator = DefaultExpandedArraySeparator
	}
	re0 := regexp.MustCompile(`\%\{\s*([\w.]+)\s*\}`)
	re1 := regexp.MustCompile(`\A\%\{\s*`)
	re2 := regexp.MustCompile(`\s*\}\z`)
	res := re0.ReplaceAllStringFunc(str, func(raw string) string {
		expr := re1.ReplaceAllString(re2.ReplaceAllString(raw, ""), "")
		value, err := v.dive(expr)
		if err != nil {
			log.Printf("Error to dive: %v: %v\n", expr, err)
			// return err
			value = ""
		}
		switch value.(type) {
		case string:
			return value.(string)
		case []interface{}:
			return v.flatten(value)
		case map[string]interface{}:
			return v.flatten(value)
		case map[string]string:
			return v.flatten(value)
		default:
			return fmt.Sprintf("%v", value)
		}
	})
	return res, nil
}

func (v *Variable) dive(expr string) (interface{}, error) {
	var_names := strings.Split(expr, expr_separator)
	// fmt.Printf("var_names: %v\n", var_names)
	res, err := v.inject(var_names, v.data, func(tmp interface{}, name string) (interface{}, error) {
		res, err := v.dig(tmp, name, expr)
		// fmt.Printf("res: %v err: %v\n", res, err)
		if err != nil {
			return nil, err
		}
		return res, nil
	})
	if err != nil {
		return nil, err
	}
	return res, nil
}

func (v *Variable) dig(tmp interface{}, name, expr string) (interface{}, error) {
	result, err := v.digIn(tmp, name, expr)
	if err != nil {
		return nil, err
	}
	// fmt.Printf("name: %v, result: %v\n", name, result)
	switch result.(type) {
	case string:
		re := regexp.MustCompile(`\A\{.*\}\z|\A\[.*\]\z`)
		matched := re.MatchString(result.(string))
		if matched {
			var obj interface{}
			src := []byte(result.(string))
			err := json.Unmarshal(src, &obj)
			if err != nil {
				return result.(string), nil
			}
			return obj, nil
		} else {
			return result, nil
		}
	default:
		return result, nil
	}
}

func (v *Variable) digIn(tmp interface{}, name, expr string) (interface{}, error) {
	switch tmp.(type) {
	case []string:
		return v.getFromArray(tmp, name)
	case []interface{}:
		return v.getFromArray(tmp, name)
	case map[string]interface{}:
		return v.getFromMap(tmp, name)
	case map[string]string:
		return v.getFromMap(tmp, name)
	default:
		return nil, fmt.Errorf("Unsupported Object type: [%T]%v", tmp, tmp)
	}
}

func (v *Variable) getFromArray(array interface{}, name string) (interface{}, error) {
	idx, err := v.parseIndex(name)
	if err != nil {
		return nil, &InvalidExpression{ "Invalid index for array: " + name }
	}
	switch array.(type) {
	case []string:
		l := len(array.([]string))
		if idx >= l {
			return nil, &InvalidExpression{ fmt.Sprintf("Invalid index %v for array who has %v items", idx, l) }
		}
		return array.([]string)[idx], nil
	case []interface{}:
		l := len(array.([]interface{}))
		if idx >= l {
			return nil, &InvalidExpression{ fmt.Sprintf("Invalid index %v for array who has %v items", idx, l) }
		}
		return array.([]interface{})[idx], nil
	default:
		return nil, fmt.Errorf("Unsupported object given as an array: [%T]%v", array, array)
	}
}

func (v *Variable) getFromMap(obj interface{}, name string) (interface{}, error) {
	switch obj.(type) {
	case map[string]interface{}:
		m := obj.(map[string]interface{})
		v, ok := m[name]
		if !ok {
			return nil, &InvalidExpression{ fmt.Sprintf("Invalid key %v for map %v", name, m) }
		}
		return v, nil
	case map[string]string:
		m := obj.(map[string]string)
		v, ok := m[name]
		if !ok {
			return nil, &InvalidExpression{ fmt.Sprintf("Invalid key %v for map %v", name, m) }
		}
		return v, nil
	default:
		return nil, fmt.Errorf("Unsupported object given as a map: [%T]%v", obj, obj)
	}
}

func (v *Variable) parseIndex(str string) (int, error) {
	re := regexp.MustCompile(`\A\d+\z`)
	matched := re.MatchString(str)
	if !matched {
		return 0, fmt.Errorf("Invalid Reference: %v", str)
	}
	idx, err := strconv.Atoi(str)
	if err != nil {
		log.Printf("Error to Atoi(%v): %v\n", str, err)
		return 0, err
	}
	return idx, nil
}

func (v *Variable) inject(var_names []string, tmp interface{}, f func(interface{}, string) (interface{}, error)) (interface{}, error) {
	name := var_names[0]
	rest := var_names[1:]
	res, err := f(tmp, name)
	if err != nil {
		return nil, err
	}
	if len(rest) == 0 {
		return res, nil
	} else {
		return v.inject(rest, res, f)
	}
}

const (
	expr_separator = "."
)

func (v *Variable) flatten(obj interface{}) string {
	switch obj.(type) {
	case string:
		return obj.(string)
	case []string:
		return strings.Join(obj.([]string), v.separator)
	case []interface{}:
		res := []string{}
		for _, i := range obj.([]interface{}) {
			res = append(res, v.flatten(i))
		}
		return strings.Join(res, v.separator)
	case map[string]interface{}:
		res := []string{}
		for _, i := range obj.(map[string]interface{}) {
			res = append(res, v.flatten(i))
		}
		return strings.Join(res, v.separator)
	case map[string]string:
		res := []string{}
		for _, i := range obj.(map[string]string) {
			res = append(res, v.flatten(i))
		}
		return strings.Join(res, v.separator)
	default:
		return fmt.Sprintf("%v", obj)
	}
}
<|endoftext|>


<commit_before>package permissions

import (
	"crypto/subtle"
	"encoding/hex"
	"net/http"
	"strings"

	"github.com/cozy/cozy-stack/pkg/crypto"
	"github.com/cozy/cozy-stack/pkg/instance"
	"github.com/cozy/cozy-stack/pkg/oauth"
	"github.com/cozy/cozy-stack/pkg/permissions"
	"github.com/cozy/cozy-stack/web/middlewares"
	"github.com/labstack/echo"
	jwt "gopkg.in/dgrijalva/jwt-go.v3"
)

const bearerAuthScheme = "Bearer "
const basicAuthScheme = "Basic "
const contextPermissionDoc = "permissions_doc"

var errNoToken = echo.NewHTTPError(http.StatusUnauthorized, "No token in request")

// CheckRegisterToken returns true if the registerToken is set and match the
// one from the instance.
func CheckRegisterToken(c echo.Context, i *instance.Instance) bool {
	if len(i.RegisterToken) == 0 {
		return false
	}
	hexToken := c.QueryParam("registerToken")
	if hexToken == "" {
		return false
	}
	tok, err := hex.DecodeString(hexToken)
	if err != nil {
		return false
	}
	return subtle.ConstantTimeCompare(tok, i.RegisterToken) == 1
}

// GetRequestToken retrieves the token from the incoming request.
func GetRequestToken(c echo.Context) string {
	req := c.Request()
	if header := req.Header.Get(echo.HeaderAuthorization); header != "" {
		if strings.HasPrefix(header, bearerAuthScheme) {
			return header[len(bearerAuthScheme):]
		}
		if strings.HasPrefix(header, basicAuthScheme) {
			_, pass, _ := req.BasicAuth()
			return pass
		}
	}
	return c.QueryParam("bearer_token")
}

// ParseJWT parses a JSON Web Token, and returns the associated permissions.
func ParseJWT(c echo.Context, instance *instance.Instance, token string) (*permissions.Permission, error) {
	var claims permissions.Claims
	err := crypto.ParseJWT(token, func(token *jwt.Token) (interface{}, error) {
		return instance.PickKey(token.Claims.(*permissions.Claims).Audience)
	}, &claims)

	if err != nil {
		return nil, permissions.ErrInvalidToken
	}

	// check if the claim is valid
	if claims.Issuer != instance.Domain {
		return nil, permissions.ErrInvalidToken
	}

	if claims.Expired() {
		return nil, permissions.ErrExpiredToken
	}

	// TODO: find out how we have a mismatch between the session cookie and the
	// application token.
	if claims.SessionID != "" {
		s, ok := middlewares.GetSession(c)
		if !ok || s.ID() != claims.SessionID {
			return nil, permissions.ErrInvalidToken
		}
	}

	switch claims.Audience {
	case permissions.AccessTokenAudience:
		// An OAuth2 token is only valid if the client has not been revoked
		if _, err := oauth.FindClient(instance, claims.Subject); err != nil {
			return nil, permissions.ErrInvalidToken
		}
		return permissions.GetForOauth(&claims)

	case permissions.CLIAudience:
		// do not check client existence
		return permissions.GetForCLI(&claims)

	case permissions.AppAudience:
		pdoc, err := permissions.GetForWebapp(instance, claims.Subject)
		if err != nil {
			return nil, err
		}
		return pdoc, nil

	case permissions.KonnectorAudience:
		pdoc, err := permissions.GetForKonnector(instance, claims.Subject)
		if err != nil {
			return nil, err
		}
		return pdoc, nil

	case permissions.ShareAudience:
		pdoc, err := permissions.GetForShareCode(instance, token)
		if err != nil {
			return nil, err
		}
		return pdoc, nil

	default:
		return nil, echo.NewHTTPError(http.StatusBadRequest, "Unrecognized token audience "+claims.Audience)
	}
}

// GetPermission extracts the permission from the echo context and checks their validity
func GetPermission(c echo.Context) (*permissions.Permission, error) {
	var err error

	pdoc, ok := c.Get(contextPermissionDoc).(*permissions.Permission)
	if ok && pdoc != nil {
		return pdoc, nil
	}

	inst := middlewares.GetInstance(c)
	if CheckRegisterToken(c, inst) {
		return permissions.GetForRegisterToken(), nil
	}

	tok := GetRequestToken(c)
	if tok == "" {
		return nil, errNoToken
	}

	pdoc, err = ParseJWT(c, inst, tok)
	if err != nil {
		return nil, err
	}

	c.Set(contextPermissionDoc, pdoc)
	return pdoc, nil
}
<commit_msg>Remove outdated TODO<commit_after>package permissions

import (
	"crypto/subtle"
	"encoding/hex"
	"net/http"
	"strings"

	"github.com/cozy/cozy-stack/pkg/crypto"
	"github.com/cozy/cozy-stack/pkg/instance"
	"github.com/cozy/cozy-stack/pkg/oauth"
	"github.com/cozy/cozy-stack/pkg/permissions"
	"github.com/cozy/cozy-stack/web/middlewares"
	"github.com/labstack/echo"
	jwt "gopkg.in/dgrijalva/jwt-go.v3"
)

const bearerAuthScheme = "Bearer "
const basicAuthScheme = "Basic "
const contextPermissionDoc = "permissions_doc"

var errNoToken = echo.NewHTTPError(http.StatusUnauthorized, "No token in request")

// CheckRegisterToken returns true if the registerToken is set and match the
// one from the instance.
func CheckRegisterToken(c echo.Context, i *instance.Instance) bool {
	if len(i.RegisterToken) == 0 {
		return false
	}
	hexToken := c.QueryParam("registerToken")
	if hexToken == "" {
		return false
	}
	tok, err := hex.DecodeString(hexToken)
	if err != nil {
		return false
	}
	return subtle.ConstantTimeCompare(tok, i.RegisterToken) == 1
}

// GetRequestToken retrieves the token from the incoming request.
func GetRequestToken(c echo.Context) string {
	req := c.Request()
	if header := req.Header.Get(echo.HeaderAuthorization); header != "" {
		if strings.HasPrefix(header, bearerAuthScheme) {
			return header[len(bearerAuthScheme):]
		}
		if strings.HasPrefix(header, basicAuthScheme) {
			_, pass, _ := req.BasicAuth()
			return pass
		}
	}
	return c.QueryParam("bearer_token")
}

// ParseJWT parses a JSON Web Token, and returns the associated permissions.
func ParseJWT(c echo.Context, instance *instance.Instance, token string) (*permissions.Permission, error) {
	var claims permissions.Claims
	err := crypto.ParseJWT(token, func(token *jwt.Token) (interface{}, error) {
		return instance.PickKey(token.Claims.(*permissions.Claims).Audience)
	}, &claims)

	if err != nil {
		return nil, permissions.ErrInvalidToken
	}

	// check if the claim is valid
	if claims.Issuer != instance.Domain {
		return nil, permissions.ErrInvalidToken
	}

	if claims.Expired() {
		return nil, permissions.ErrExpiredToken
	}

	// If claims contains a SessionID, we check that we are actually authorized
	// with the corresponding session.
	if claims.SessionID != "" {
		s, ok := middlewares.GetSession(c)
		if !ok || s.ID() != claims.SessionID {
			return nil, permissions.ErrInvalidToken
		}
	}

	switch claims.Audience {
	case permissions.AccessTokenAudience:
		// An OAuth2 token is only valid if the client has not been revoked
		if _, err := oauth.FindClient(instance, claims.Subject); err != nil {
			return nil, permissions.ErrInvalidToken
		}
		return permissions.GetForOauth(&claims)

	case permissions.CLIAudience:
		// do not check client existence
		return permissions.GetForCLI(&claims)

	case permissions.AppAudience:
		pdoc, err := permissions.GetForWebapp(instance, claims.Subject)
		if err != nil {
			return nil, err
		}
		return pdoc, nil

	case permissions.KonnectorAudience:
		pdoc, err := permissions.GetForKonnector(instance, claims.Subject)
		if err != nil {
			return nil, err
		}
		return pdoc, nil

	case permissions.ShareAudience:
		pdoc, err := permissions.GetForShareCode(instance, token)
		if err != nil {
			return nil, err
		}
		return pdoc, nil

	default:
		return nil, echo.NewHTTPError(http.StatusBadRequest, "Unrecognized token audience "+claims.Audience)
	}
}

// GetPermission extracts the permission from the echo context and checks their validity
func GetPermission(c echo.Context) (*permissions.Permission, error) {
	var err error

	pdoc, ok := c.Get(contextPermissionDoc).(*permissions.Permission)
	if ok && pdoc != nil {
		return pdoc, nil
	}

	inst := middlewares.GetInstance(c)
	if CheckRegisterToken(c, inst) {
		return permissions.GetForRegisterToken(), nil
	}

	tok := GetRequestToken(c)
	if tok == "" {
		return nil, errNoToken
	}

	pdoc, err = ParseJWT(c, inst, tok)
	if err != nil {
		return nil, err
	}

	c.Set(contextPermissionDoc, pdoc)
	return pdoc, nil
}
<|endoftext|>


<commit_before>package isolated

import (
	"code.cloudfoundry.org/cli/integration/helpers"
	"code.cloudfoundry.org/cli/util/configv3"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gbytes"
	. "github.com/onsi/gomega/gexec"
)

var _ = Describe("oauth-token command", func() {
	Context("help", func() {
		It("displays the help information", func() {
			session := helpers.CF("oauth-token", "--help")

			Eventually(session.Out).Should(Say("NAME:"))
			Eventually(session.Out).Should(Say("oauth-token - Retrieve and display the OAuth token for the current session"))
			Eventually(session.Out).Should(Say("USAGE:"))
			Eventually(session.Out).Should(Say("cf oauth-token"))
			Eventually(session.Out).Should(Say("SEE ALSO:"))
			Eventually(session.Out).Should(Say("curl"))
			Eventually(session).Should(Exit(0))
		})
	})

	Context("when the environment is not setup correctly", func() {
		Context("when no API endpoint is set", func() {
			BeforeEach(func() {
				helpers.UnsetAPI()
			})

			It("fails with no API endpoint set message", func() {
				session := helpers.CF("oauth-token")

				Eventually(session.Out).Should(Say("FAILED"))
				Eventually(session.Err).Should(Say("No API endpoint set\\. Use 'cf login' or 'cf api' to target an endpoint\\."))
				Eventually(session).Should(Exit(1))
			})
		})

		Context("when not logged in", func() {
			BeforeEach(func() {
				helpers.LogoutCF()
			})

			It("fails with not logged in message", func() {
				session := helpers.CF("oauth-token")

				Eventually(session.Out).Should(Say("FAILED"))
				Eventually(session.Err).Should(Say("Not logged in\\. Use 'cf login' to log in\\."))
				Eventually(session).Should(Exit(1))
			})
		})
	})

	Context("when the environment is setup correctly", func() {
		BeforeEach(func() {
			helpers.LoginCF()
		})

		Context("when the refresh token is invalid", func() {
			BeforeEach(func() {
				helpers.SetConfig(func(conf *configv3.Config) {
					conf.ConfigFile.RefreshToken = "invalid-refresh-token"
				})
			})

			It("displays an error and exits 1", func() {
				session := helpers.CF("oauth-token")

				Eventually(session.Out).Should(Say("FAILED"))
				Eventually(session.Err).Should(Say("The token expired, was revoked, or the token ID is incorrect: invalid-refresh-token"))
				// Eventually(session.Err).Should(Say("Authentication has expired\\.  Please log back in to re-authenticate\\."))
				// Eventually(session.Err).Should(Say("TIP: Use `cf login -a <endpoint> -u <user> -o <org> -s <space>` to log back in and re-authenticate\\."))
				Eventually(session).Should(Exit(1))
			})
		})

		Context("when the oauth client ID and secret combination is invalid", func() {
			BeforeEach(func() {
				helpers.SetConfig(func(conf *configv3.Config) {
					conf.ConfigFile.UAAOAuthClient = "foo"
					conf.ConfigFile.UAAOAuthClientSecret = "bar"
				})
			})

			It("displays an error and exits 1", func() {
				session := helpers.CF("oauth-token")

				Eventually(session.Out).Should(Say("FAILED"))
				Eventually(session.Err).Should(Say("Bad credentials"))
				Eventually(session).Should(Exit(1))
			})
		})

		Context("when the refresh token and oauth creds are valid", func() {
			It("refreshes the access token and displays it", func() {
				session := helpers.CF("oauth-token")

				Eventually(session.Out).Should(Say("bearer .+"))
				Eventually(session).Should(Exit(0))
			})
		})
	})
})
<commit_msg>update oauth-token integration tests to reflect new error messages<commit_after>package isolated

import (
	"code.cloudfoundry.org/cli/integration/helpers"
	"code.cloudfoundry.org/cli/util/configv3"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gbytes"
	. "github.com/onsi/gomega/gexec"
)

var _ = Describe("oauth-token command", func() {
	Context("help", func() {
		It("displays the help information", func() {
			session := helpers.CF("oauth-token", "--help")

			Eventually(session.Out).Should(Say("NAME:"))
			Eventually(session.Out).Should(Say("oauth-token - Retrieve and display the OAuth token for the current session"))
			Eventually(session.Out).Should(Say("USAGE:"))
			Eventually(session.Out).Should(Say("cf oauth-token"))
			Eventually(session.Out).Should(Say("SEE ALSO:"))
			Eventually(session.Out).Should(Say("curl"))
			Eventually(session).Should(Exit(0))
		})
	})

	Context("when the environment is not setup correctly", func() {
		Context("when no API endpoint is set", func() {
			BeforeEach(func() {
				helpers.UnsetAPI()
			})

			It("fails with no API endpoint set message", func() {
				session := helpers.CF("oauth-token")

				Eventually(session.Out).Should(Say("FAILED"))
				Eventually(session.Err).Should(Say("No API endpoint set\\. Use 'cf login' or 'cf api' to target an endpoint\\."))
				Eventually(session).Should(Exit(1))
			})
		})

		Context("when not logged in", func() {
			BeforeEach(func() {
				helpers.LogoutCF()
			})

			It("fails with not logged in message", func() {
				session := helpers.CF("oauth-token")

				Eventually(session.Out).Should(Say("FAILED"))
				Eventually(session.Err).Should(Say("Not logged in\\. Use 'cf login' to log in\\."))
				Eventually(session).Should(Exit(1))
			})
		})
	})

	Context("when the environment is setup correctly", func() {
		BeforeEach(func() {
			helpers.LoginCF()
		})

		Context("when the refresh token is invalid", func() {
			BeforeEach(func() {
				helpers.SetConfig(func(conf *configv3.Config) {
					conf.ConfigFile.RefreshToken = "invalid-refresh-token"
				})
			})

			It("displays an error and exits 1", func() {
				session := helpers.CF("oauth-token")

				Eventually(session.Out).Should(Say("FAILED"))
				Eventually(session.Err).Should(Say("The token expired, was revoked, or the token ID is incorrect\\. Please log back in to re-authenticate\\."))
				Eventually(session).Should(Exit(1))
			})
		})

		Context("when the oauth client ID and secret combination is invalid", func() {
			BeforeEach(func() {
				helpers.SetConfig(func(conf *configv3.Config) {
					conf.ConfigFile.UAAOAuthClient = "foo"
					conf.ConfigFile.UAAOAuthClientSecret = "bar"
				})
			})

			It("displays an error and exits 1", func() {
				session := helpers.CF("oauth-token")

				Eventually(session.Out).Should(Say("FAILED"))
				Eventually(session.Err).Should(Say("Credentials were rejected, please try again\\."))
				Eventually(session).Should(Exit(1))
			})
		})

		Context("when the refresh token and oauth creds are valid", func() {
			It("refreshes the access token and displays it", func() {
				session := helpers.CF("oauth-token")

				Eventually(session.Out).Should(Say("bearer .+"))
				Eventually(session).Should(Exit(0))
			})
		})
	})
})
<|endoftext|>


<commit_before>package output

import (
	"reflect"
	"testing"

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

func TestTextDoesRegisterItself(t *testing.T) {
	assert.Equal(t, "*output.Text", reflect.TypeOf(ForName("text")).String())
}
<commit_msg>Add example tests for text<commit_after>package output

import (
	"reflect"
	"testing"
	"time"

	"github.com/hoop33/limo/model"
	"github.com/stretchr/testify/assert"
)

var text Text

func TestTextDoesRegisterItself(t *testing.T) {
	assert.Equal(t, "*output.Text", reflect.TypeOf(ForName("text")).String())
}

func ExampleText_Info() {
	text.Info("This is info")
	// Output: This is info
}

func ExampleText_Tick() {
	text.Tick()
	// Output: .
}

func ExampleText_StarLine() {
	fullName := "hoop33/limo"
	language := "Go"
	star := &model.Star{
		FullName:   &fullName,
		Stargazers: 1000000,
		Language:   &language,
	}
	text.StarLine(star)
	// Output: hoop33/limo (*: 1000000) (Go)
}

func ExampleText_Star() {
	fullName := "hoop33/limo"
	language := "Go"
	description := "A CLI for managing starred Git repositories"
	homepage := "https://github.com/hoop33/limo"
	url := "https://github.com/hoop33/limo.git"
	star := &model.Star{
		FullName:    &fullName,
		Stargazers:  1000000,
		Language:    &language,
		Description: &description,
		Homepage:    &homepage,
		URL:         &url,
		StarredAt:   time.Date(2016, time.June, 21, 14, 56, 5, 0, time.UTC),
		Tags: []model.Tag{
			{
				Name: "cli",
			},
			{
				Name: "git",
			},
		},
	}
	text.Star(star)
	// Output:
	// hoop33/limo (*: 1000000) (Go)
	// cli, git
	// A CLI for managing starred Git repositories
	// Home page: https://github.com/hoop33/limo
	// URL: https://github.com/hoop33/limo.git
	// Starred at Tue Jun 21 14:56:05 UTC 2016
}
<|endoftext|>


<commit_before>// go-rst - A reStructuredText parser for Go
// 2014 (c) The go-rst Authors
// MIT Licensed. See LICENSE for details.

// To enable debug output when testing, use "go test -debug"

package parse

import (
	"github.com/demizer/go-elog"
	"reflect"
	"strings"
	"testing"
	"os"
)

type checkNode struct {
	t          *testing.T
	testName   string
	pNodeName  string
	pFieldName string
	pFieldVal  interface{}
	pFieldType reflect.Type
	eFieldName string
	eFieldVal  interface{}
	eFieldType reflect.Type
	id         int
}

func (c *checkNode) error(args ...interface{}) {
	c.t.Error(args...)
}

func (c *checkNode) errorf(format string, args ...interface{}) {
	c.t.Errorf(format, args...)
}

func (c *checkNode) dError() {
	if c.pFieldName == "Rune" {
		c.t.Errorf("Got: %s.%s = %#v (%v) (%v) (Id: %d),\n\tExpect: %s.%s = %#v (%v)\n",
			c.pNodeName, c.pFieldName, c.pFieldVal, string(c.pFieldVal.(int32)),
			c.pFieldType, c.id, "#parse-tree", c.eFieldName, c.eFieldVal, c.eFieldType)
		return
	}
	c.t.Errorf("Got: %s.%s = %#v (%v) (Id: %d),\n\tExpect: %s.%s = %#v (%v)\n",
		c.pNodeName, c.pFieldName, c.pFieldVal, c.pFieldType, c.id, "#parse-tree",
		c.eFieldName, c.eFieldVal, c.eFieldType)
}

func poop() {
	os.Exit(1)
}

func (c *checkNode) updateState(eKey string, eVal interface{}, pVal reflect.Value) bool {
	// Expected parser metadata
	c.eFieldName = eKey
	c.eFieldVal = eVal
	c.eFieldType = reflect.TypeOf(c.eFieldVal)
	if eKey == "id" {
		c.id = int(eVal.(float64))
	}

	// Actual parsed metadata
	c.pNodeName = pVal.Type().Name()
	c.pFieldName = strings.ToUpper(string(c.eFieldName[0])) + c.eFieldName[1:]
	c.pFieldVal = pVal.FieldByName(c.pFieldName).Interface()
	c.pFieldType = pVal.FieldByName(c.pFieldName).Type()

	// Overline adornment nodes can be null
	if c.eFieldName == "overLine" && c.eFieldVal == nil {
		return false
	} else if c.eFieldVal == nil {
		c.dError()
		return false
	}

	return true
}

func (c *checkNode) checkFields(eNodes interface{}, pNode Node) {
	for eKey, eVal := range eNodes.(map[string]interface{}) {
		pVal := reflect.Indirect(reflect.ValueOf(pNode))
		if c.updateState(eKey, eVal, pVal) == false {
			continue
		}
		switch c.eFieldName {
		case "type":
			if c.eFieldVal != c.pFieldVal.(NodeType).String() {
				c.dError()
			}
		case "id", "level", "length":
			if c.eFieldVal != float64(c.pFieldVal.(int)) {
				c.dError()
			}
		case "line":
			if c.eFieldVal != float64(c.pFieldVal.(Line)) {
				c.dError()
			}
		case "startPosition":
			if c.eFieldVal != float64(c.pFieldVal.(StartPosition)) {
				c.dError()
			}
		case "overLine", "underLine":
			c.checkFields(c.eFieldVal, c.pFieldVal.(Node))
		case "nodeList":
			for num, node := range c.eFieldVal.([]interface{}) {
				// Store and reset the parser value, otherwise a panic will occur on
				// the next iteration
				pFieldVal := c.pFieldVal
				c.checkFields(node, c.pFieldVal.(NodeList)[num])
				c.pFieldVal = pFieldVal
			}
		case "rune":
			if c.eFieldVal != string(c.pFieldVal.(rune)) {
				c.dError()
			}
		default:
			if c.eFieldVal != c.pFieldVal {
				c.dError()
			}
		}
	}

}

func checkParseNodes(t *testing.T, eTree []interface{}, pNodes []Node, testName string) {
	state := &checkNode{t: t, testName: testName}
	for eNum, eNode := range eTree {
		state.checkFields(eNode, pNodes[eNum])
	}
	return
}

func TestSectionLevelsAdd(t *testing.T) {
	var p sectionLevels
	lvl := p.Add('=', true, 5)
	if lvl != 1 {
		t.Errorf("Improper level on first add, Got level: %d, expected: %d", lvl, 1)
	}
}

func TestSectionLevelsString(t *testing.T) {
	var p sectionLevels
	p.Add('=', true, 5)
	p.Add('-', true, 8)
	p.Add('~', false, 6)
	out := p.String()
	expect := "level: 1, rune: '=', overline: true, length: 5\nlevel: 2, rune: '-', " +
		"overline: true, length: 8\nlevel: 3, rune: '~', overline: false, length: 6\n"
	if out != expect {
		t.Errorf("String output mismatch!\nExpect:\n\n\t%q,\nGot:\n\n\t%q\n", expect, out)
	}
}

func TestSectionLevelsFind(t *testing.T) {
	var p sectionLevels
	p.Add('=', true, 5)
	p.Add('-', true, 8)
	p.Add('~', false, 6)
	lvl := p.Find('-')
	if lvl == -1 {
		t.Errorf("Level not found!\nExpect:\n\n\t%d\nGot:\n\n\t%t\n", 2, lvl)
	}
	if lvl != 2 {
		t.Errorf("Level not correct!\nExpect:\n\n\t%d\nGot:\n\n\t%d\n", 2, lvl)
	}
}

func TestSectionLevelsFindNoResult(t *testing.T) {
	var p sectionLevels
	lvl := p.Find('-')
	if lvl > 0 {
		t.Errorf("Should not find any levels!\nExpect:\n\n\t%d\nGot:\n\n\t%d\n", -1, lvl)
	}
}

func TestSectionLevelsLevelEmpty(t *testing.T) {
	var p sectionLevels
	lvl := p.Level()
	expect := 0
	if lvl != expect {
		t.Errorf("Empty sectionLevels should return \"%d\"!\nExpect:\t%d\nGot:\t%d\n",
			expect, expect, lvl)
	}

}

func TestSectionLevelsLevel(t *testing.T) {
	var p sectionLevels
	p.Add('=', true, 5)
	p.Add('-', true, 8)
	p.Add('~', false, 6)
	lvl := p.Level()
	if lvl != 3 {
		t.Errorf("Level() returned incorrect level!\nExpect:\n\n\t%d\nGot:\n\n\t%d\n", 3, lvl)
	}
}

func parseTest(t *testing.T, lexTest *LexTest) (tree *Tree) {
	var errs []error
	log.Debugf("Test Name: %s\n", lexTest.name)
	log.Debugf("Description: %s\n", lexTest.description)
	log.Debugf("Test Input:\n-----------\n%s\n----------\n", lexTest.data)
	tree, errs = Parse(lexTest.name, lexTest.data)
	if errs != nil {
		for _, err := range errs {
			t.Error(err)
		}
	}
	return
}

func TestParseSectionTitleParagraph(t *testing.T) {
	testName := "SectionTitlePara"
	test := lexTests.testByName(testName)
	pTree := parseTest(t, test)
	eNodes := test.expectJson()
	checkParseNodes(t, eNodes, *pTree.Nodes, testName)
}

func TestParseSectionTitleParaNoBlankLine(t *testing.T) {
	testName := "SectionTitleParaNoBlankLine"
	test := lexTests.testByName(testName)
	pTree := parseTest(t, test)
	eNodes := test.expectJson()
	checkParseNodes(t, eNodes, *pTree.Nodes, testName)
}

func TestParseSectionParaHeadPara(t *testing.T) {
	testName := "SectionParaHeadPara"
	test := lexTests.testByName(testName)
	pTree := parseTest(t, test)
	eNodes := test.expectJson()
	checkParseNodes(t, eNodes, *pTree.Nodes, testName)
}

func TestParseSectionLevelTest1(t *testing.T) {
	testName := "SectionLevelTest1"
	test := lexTests.testByName(testName)
	pTree := parseTest(t, test)
	// spd.Dump(pTree)
	eNodes := test.expectJson()
	checkParseNodes(t, eNodes, *pTree.Nodes, testName)
}

func TestParseSectionUnexpectedTitles(t *testing.T) {
	testName := "SectionUnexpectedTitles"
	test := lexTests.testByName(testName)
	pTree := parseTest(t, test)
	eNodes := test.expectJson()
	checkParseNodes(t, eNodes, *pTree.Nodes, testName)
}
<commit_msg>parse_test.go: Remove poop() function<commit_after>// go-rst - A reStructuredText parser for Go
// 2014 (c) The go-rst Authors
// MIT Licensed. See LICENSE for details.

// To enable debug output when testing, use "go test -debug"

package parse

import (
	"github.com/demizer/go-elog"
	"reflect"
	"strings"
	"testing"
)

type checkNode struct {
	t          *testing.T
	testName   string
	pNodeName  string
	pFieldName string
	pFieldVal  interface{}
	pFieldType reflect.Type
	eFieldName string
	eFieldVal  interface{}
	eFieldType reflect.Type
	id         int
}

func (c *checkNode) error(args ...interface{}) {
	c.t.Error(args...)
}

func (c *checkNode) errorf(format string, args ...interface{}) {
	c.t.Errorf(format, args...)
}

func (c *checkNode) dError() {
	if c.pFieldName == "Rune" {
		c.t.Errorf("Got: %s.%s = %#v (%v) (%v) (Id: %d),\n\tExpect: %s.%s = %#v (%v)\n",
			c.pNodeName, c.pFieldName, c.pFieldVal, string(c.pFieldVal.(int32)),
			c.pFieldType, c.id, "#parse-tree", c.eFieldName, c.eFieldVal, c.eFieldType)
		return
	}
	c.t.Errorf("Got: %s.%s = %#v (%v) (Id: %d),\n\tExpect: %s.%s = %#v (%v)\n",
		c.pNodeName, c.pFieldName, c.pFieldVal, c.pFieldType, c.id, "#parse-tree",
		c.eFieldName, c.eFieldVal, c.eFieldType)
}

func (c *checkNode) updateState(eKey string, eVal interface{}, pVal reflect.Value) bool {
	// Expected parser metadata
	c.eFieldName = eKey
	c.eFieldVal = eVal
	c.eFieldType = reflect.TypeOf(c.eFieldVal)
	if eKey == "id" {
		c.id = int(eVal.(float64))
	}

	// Actual parsed metadata
	c.pNodeName = pVal.Type().Name()
	c.pFieldName = strings.ToUpper(string(c.eFieldName[0])) + c.eFieldName[1:]
	c.pFieldVal = pVal.FieldByName(c.pFieldName).Interface()
	c.pFieldType = pVal.FieldByName(c.pFieldName).Type()

	// Overline adornment nodes can be null
	if c.eFieldName == "overLine" && c.eFieldVal == nil {
		return false
	} else if c.eFieldVal == nil {
		c.dError()
		return false
	}

	return true
}

func (c *checkNode) checkFields(eNodes interface{}, pNode Node) {
	for eKey, eVal := range eNodes.(map[string]interface{}) {
		pVal := reflect.Indirect(reflect.ValueOf(pNode))
		if c.updateState(eKey, eVal, pVal) == false {
			continue
		}
		switch c.eFieldName {
		case "type":
			if c.eFieldVal != c.pFieldVal.(NodeType).String() {
				c.dError()
			}
		case "id", "level", "length":
			if c.eFieldVal != float64(c.pFieldVal.(int)) {
				c.dError()
			}
		case "line":
			if c.eFieldVal != float64(c.pFieldVal.(Line)) {
				c.dError()
			}
		case "startPosition":
			if c.eFieldVal != float64(c.pFieldVal.(StartPosition)) {
				c.dError()
			}
		case "overLine", "underLine":
			c.checkFields(c.eFieldVal, c.pFieldVal.(Node))
		case "nodeList":
			for num, node := range c.eFieldVal.([]interface{}) {
				// Store and reset the parser value, otherwise a panic will occur on
				// the next iteration
				pFieldVal := c.pFieldVal
				c.checkFields(node, c.pFieldVal.(NodeList)[num])
				c.pFieldVal = pFieldVal
			}
		case "rune":
			if c.eFieldVal != string(c.pFieldVal.(rune)) {
				c.dError()
			}
		default:
			if c.eFieldVal != c.pFieldVal {
				c.dError()
			}
		}
	}

}

func checkParseNodes(t *testing.T, eTree []interface{}, pNodes []Node, testName string) {
	state := &checkNode{t: t, testName: testName}
	for eNum, eNode := range eTree {
		state.checkFields(eNode, pNodes[eNum])
	}
	return
}

func TestSectionLevelsAdd(t *testing.T) {
	var p sectionLevels
	lvl := p.Add('=', true, 5)
	if lvl != 1 {
		t.Errorf("Improper level on first add, Got level: %d, expected: %d", lvl, 1)
	}
}

func TestSectionLevelsString(t *testing.T) {
	var p sectionLevels
	p.Add('=', true, 5)
	p.Add('-', true, 8)
	p.Add('~', false, 6)
	out := p.String()
	expect := "level: 1, rune: '=', overline: true, length: 5\nlevel: 2, rune: '-', " +
		"overline: true, length: 8\nlevel: 3, rune: '~', overline: false, length: 6\n"
	if out != expect {
		t.Errorf("String output mismatch!\nExpect:\n\n\t%q,\nGot:\n\n\t%q\n", expect, out)
	}
}

func TestSectionLevelsFind(t *testing.T) {
	var p sectionLevels
	p.Add('=', true, 5)
	p.Add('-', true, 8)
	p.Add('~', false, 6)
	lvl := p.Find('-')
	if lvl == -1 {
		t.Errorf("Level not found!\nExpect:\n\n\t%d\nGot:\n\n\t%t\n", 2, lvl)
	}
	if lvl != 2 {
		t.Errorf("Level not correct!\nExpect:\n\n\t%d\nGot:\n\n\t%d\n", 2, lvl)
	}
}

func TestSectionLevelsFindNoResult(t *testing.T) {
	var p sectionLevels
	lvl := p.Find('-')
	if lvl > 0 {
		t.Errorf("Should not find any levels!\nExpect:\n\n\t%d\nGot:\n\n\t%d\n", -1, lvl)
	}
}

func TestSectionLevelsLevelEmpty(t *testing.T) {
	var p sectionLevels
	lvl := p.Level()
	expect := 0
	if lvl != expect {
		t.Errorf("Empty sectionLevels should return \"%d\"!\nExpect:\t%d\nGot:\t%d\n",
			expect, expect, lvl)
	}

}

func TestSectionLevelsLevel(t *testing.T) {
	var p sectionLevels
	p.Add('=', true, 5)
	p.Add('-', true, 8)
	p.Add('~', false, 6)
	lvl := p.Level()
	if lvl != 3 {
		t.Errorf("Level() returned incorrect level!\nExpect:\n\n\t%d\nGot:\n\n\t%d\n", 3, lvl)
	}
}

func parseTest(t *testing.T, lexTest *LexTest) (tree *Tree) {
	var errs []error
	log.Debugf("Test Name: %s\n", lexTest.name)
	log.Debugf("Description: %s\n", lexTest.description)
	log.Debugf("Test Input:\n-----------\n%s\n----------\n", lexTest.data)
	tree, errs = Parse(lexTest.name, lexTest.data)
	if errs != nil {
		for _, err := range errs {
			t.Error(err)
		}
	}
	return
}

func TestParseSectionTitleParagraph(t *testing.T) {
	testName := "SectionTitlePara"
	test := lexTests.testByName(testName)
	pTree := parseTest(t, test)
	eNodes := test.expectJson()
	checkParseNodes(t, eNodes, *pTree.Nodes, testName)
}

func TestParseSectionTitleParaNoBlankLine(t *testing.T) {
	testName := "SectionTitleParaNoBlankLine"
	test := lexTests.testByName(testName)
	pTree := parseTest(t, test)
	eNodes := test.expectJson()
	checkParseNodes(t, eNodes, *pTree.Nodes, testName)
}

func TestParseSectionParaHeadPara(t *testing.T) {
	testName := "SectionParaHeadPara"
	test := lexTests.testByName(testName)
	pTree := parseTest(t, test)
	eNodes := test.expectJson()
	checkParseNodes(t, eNodes, *pTree.Nodes, testName)
}

func TestParseSectionLevelTest1(t *testing.T) {
	testName := "SectionLevelTest1"
	test := lexTests.testByName(testName)
	pTree := parseTest(t, test)
	// spd.Dump(pTree)
	eNodes := test.expectJson()
	checkParseNodes(t, eNodes, *pTree.Nodes, testName)
}

func TestParseSectionUnexpectedTitles(t *testing.T) {
	testName := "SectionUnexpectedTitles"
	test := lexTests.testByName(testName)
	pTree := parseTest(t, test)
	eNodes := test.expectJson()
	checkParseNodes(t, eNodes, *pTree.Nodes, testName)
}
<|endoftext|>


<commit_before>// Copyright 2011 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 main

import (
	"go/ast"
)

var osopenFix = fix{
	"osopen",
	osopen,
	`Adapt os.Open calls to new, easier API and rename O_CREAT O_CREATE.

	http://codereview.appspot.com/4357052
`,
}

func init() {
	register(osopenFix)
}

func osopen(f *ast.File) bool {
	if !imports(f, "os") {
		return false
	}

	fixed := false
	walk(f, func(n interface{}) {
		// Rename O_CREAT to O_CREATE.
		if expr, ok := n.(ast.Expr); ok && isPkgDot(expr, "os", "O_CREAT") {
			expr.(*ast.SelectorExpr).Sel.Name = "O_CREATE"
			return
		}

		// Fix up calls to Open.
		call, ok := n.(*ast.CallExpr)
		if !ok || len(call.Args) != 3 {
			return
		}
		if !isPkgDot(call.Fun, "os", "Open") {
			return
		}
		sel := call.Fun.(*ast.SelectorExpr)
		args := call.Args
		// os.Open(a, os.O_RDONLY, c) -> os.Open(a)
		if isPkgDot(args[1], "os", "O_RDONLY") || isPkgDot(args[1], "syscall", "O_RDONLY") {
			call.Args = call.Args[0:1]
			fixed = true
			return
		}
		// os.Open(a, createlike_flags, c) -> os.Create(a, c)
		if isCreateFlag(args[1]) {
			sel.Sel.Name = "Create"
			if !isSimplePerm(args[2]) {
				warn(sel.Pos(), "rewrote os.Open to os.Create with permission not 0666")
			}
			call.Args = args[0:1]
			fixed = true
			return
		}
		// Fallback: os.Open(a, b, c) -> os.OpenFile(a, b, c)
		sel.Sel.Name = "OpenFile"
		fixed = true
	})
	return fixed
}

func isCreateFlag(flag ast.Expr) bool {
	foundCreate := false
	foundTrunc := false
	// OR'ing of flags: is O_CREATE on?  + or | would be fine; we just look for os.O_CREATE
	// and don't worry about the actual opeator.
	p := flag.Pos()
	for {
		lhs := flag
		expr, isBinary := flag.(*ast.BinaryExpr)
		if isBinary {
			lhs = expr.Y
		}
		sel, ok := lhs.(*ast.SelectorExpr)
		if !ok || !isTopName(sel.X, "os") {
			return false
		}
		switch sel.Sel.Name {
		case "O_CREATE":
			foundCreate = true
		case "O_TRUNC":
			foundTrunc = true
		case "O_RDONLY", "O_WRONLY", "O_RDWR":
			// okay
		default:
			// Unexpected flag, like O_APPEND or O_EXCL.
			// Be conservative and do not rewrite.
			return false
		}
		if !isBinary {
			break
		}
		flag = expr.X
	}
	if !foundCreate {
		return false
	}
	if !foundTrunc {
		warn(p, "rewrote os.Open with O_CREATE but not O_TRUNC to os.Create")
	}
	return foundCreate
}

func isSimplePerm(perm ast.Expr) bool {
	basicLit, ok := perm.(*ast.BasicLit)
	if !ok {
		return false
	}
	switch basicLit.Value {
	case "0666":
		return true
	}
	return false
}
<commit_msg>gofix: fix embarrassing typo in osopen.go<commit_after>// Copyright 2011 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 main

import (
	"go/ast"
)

var osopenFix = fix{
	"osopen",
	osopen,
	`Adapt os.Open calls to new, easier API and rename O_CREAT O_CREATE.

	http://codereview.appspot.com/4357052
`,
}

func init() {
	register(osopenFix)
}

func osopen(f *ast.File) bool {
	if !imports(f, "os") {
		return false
	}

	fixed := false
	walk(f, func(n interface{}) {
		// Rename O_CREAT to O_CREATE.
		if expr, ok := n.(ast.Expr); ok && isPkgDot(expr, "os", "O_CREAT") {
			expr.(*ast.SelectorExpr).Sel.Name = "O_CREATE"
			return
		}

		// Fix up calls to Open.
		call, ok := n.(*ast.CallExpr)
		if !ok || len(call.Args) != 3 {
			return
		}
		if !isPkgDot(call.Fun, "os", "Open") {
			return
		}
		sel := call.Fun.(*ast.SelectorExpr)
		args := call.Args
		// os.Open(a, os.O_RDONLY, c) -> os.Open(a)
		if isPkgDot(args[1], "os", "O_RDONLY") || isPkgDot(args[1], "syscall", "O_RDONLY") {
			call.Args = call.Args[0:1]
			fixed = true
			return
		}
		// os.Open(a, createlike_flags, c) -> os.Create(a, c)
		if isCreateFlag(args[1]) {
			sel.Sel.Name = "Create"
			if !isSimplePerm(args[2]) {
				warn(sel.Pos(), "rewrote os.Open to os.Create with permission not 0666")
			}
			call.Args = args[0:1]
			fixed = true
			return
		}
		// Fallback: os.Open(a, b, c) -> os.OpenFile(a, b, c)
		sel.Sel.Name = "OpenFile"
		fixed = true
	})
	return fixed
}

func isCreateFlag(flag ast.Expr) bool {
	foundCreate := false
	foundTrunc := false
	// OR'ing of flags: is O_CREATE on?  + or | would be fine; we just look for os.O_CREATE
	// and don't worry about the actual operator.
	p := flag.Pos()
	for {
		lhs := flag
		expr, isBinary := flag.(*ast.BinaryExpr)
		if isBinary {
			lhs = expr.Y
		}
		sel, ok := lhs.(*ast.SelectorExpr)
		if !ok || !isTopName(sel.X, "os") {
			return false
		}
		switch sel.Sel.Name {
		case "O_CREATE":
			foundCreate = true
		case "O_TRUNC":
			foundTrunc = true
		case "O_RDONLY", "O_WRONLY", "O_RDWR":
			// okay
		default:
			// Unexpected flag, like O_APPEND or O_EXCL.
			// Be conservative and do not rewrite.
			return false
		}
		if !isBinary {
			break
		}
		flag = expr.X
	}
	if !foundCreate {
		return false
	}
	if !foundTrunc {
		warn(p, "rewrote os.Open with O_CREATE but not O_TRUNC to os.Create")
	}
	return foundCreate
}

func isSimplePerm(perm ast.Expr) bool {
	basicLit, ok := perm.(*ast.BasicLit)
	if !ok {
		return false
	}
	switch basicLit.Value {
	case "0666":
		return true
	}
	return false
}
<|endoftext|>