<commit_before>// Copyright 2015 ThoughtWorks, Inc.

// This file is part of getgauge/html-report.

// getgauge/html-report is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// getgauge/html-report is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with getgauge/html-report.  If not, see <http://www.gnu.org/licenses/>.

package main

import (
	"archive/zip"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"runtime"
	"strings"
)

const (
	BUILD_DIR   = "tmp"
	CGO_ENABLED = "CGO_ENABLED"
)

const (
	dotGauge          = ".gauge"
	plugins           = "plugins"
	GOARCH            = "GOARCH"
	GOOS              = "GOOS"
	X86               = "386"
	X86_64            = "amd64"
	DARWIN            = "darwin"
	LINUX             = "linux"
	WINDOWS           = "windows"
	bin               = "bin"
	newDirPermissions = 0755
	gauge             = "gauge"
	htmlReport        = "html-report"
	deploy            = "deploy"
	pluginJsonFile    = "plugin.json"
	reportTemplate    = "report-template"
	commonDep         = "github.com/getgauge/common"
	protoDep          = "github.com/golang/protobuf/proto"
	GAUGE_MESSAGES    = "gauge_messages"
)

var BUILD_DIR_BIN = filepath.Join(BUILD_DIR, bin)
var BUILD_DIR_SRC = filepath.Join(BUILD_DIR, "src")
var BUILD_DIR_PKG = filepath.Join(BUILD_DIR, "pkg")
var BUILD_DIR_HTML_REPORT = filepath.Join(BUILD_DIR_SRC, htmlReport)
var platformBinDir = filepath.Join(bin, fmt.Sprintf("%s_%s", runtime.GOOS, runtime.GOARCH))
var deployDir = filepath.Join(deploy, htmlReport)

func isExecMode(mode os.FileMode) bool {
	return (mode&0111) != 0
}

func mirrorFile(src, dst string) error {
	sfi, err := os.Stat(src)
	if err != nil {
		return err
	}
	if sfi.Mode()&os.ModeType != 0 {
		log.Fatalf("mirrorFile can't deal with non-regular file %s", src)
	}
	dfi, err := os.Stat(dst)
	if err == nil &&
		isExecMode(sfi.Mode()) == isExecMode(dfi.Mode()) &&
			(dfi.Mode()&os.ModeType == 0) &&
		dfi.Size() == sfi.Size() &&
		dfi.ModTime().Unix() == sfi.ModTime().Unix() {
		// Seems to not be modified.
		return nil
	}

	dstDir := filepath.Dir(dst)
	if err := os.MkdirAll(dstDir, newDirPermissions); err != nil {
		return err
	}

	df, err := os.Create(dst)
	if err != nil {
		return err
	}
	sf, err := os.Open(src)
	if err != nil {
		return err
	}
	defer sf.Close()

	n, err := io.Copy(df, sf)
	if err == nil && n != sfi.Size() {
		err = fmt.Errorf("copied wrong size for %s -> %s: copied %d; want %d", src, dst, n, sfi.Size())
	}
	cerr := df.Close()
	if err == nil {
		err = cerr
	}
	if err == nil {
		err = os.Chmod(dst, sfi.Mode())
	}
	if err == nil {
		err = os.Chtimes(dst, sfi.ModTime(), sfi.ModTime())
	}
	return err
}

func mirrorDir(src, dst string) error {
	log.Printf("Copying '%s' -> '%s'\n", src, dst)
	err := filepath.Walk(src, func(path string, fi os.FileInfo, err error) error {
			if err != nil {
				return err
			}
			if fi.IsDir() {
				return nil
			}
			suffix, err := filepath.Rel(src, path)
			if err != nil {
				return fmt.Errorf("Failed to find Rel(%q, %q): %v", src, path, err)
			}
			return mirrorFile(path, filepath.Join(dst, suffix))
		})
	return err
}

func createGoPathForBuild() {
	err := os.MkdirAll(BUILD_DIR_SRC, newDirPermissions)
	if err != nil {
		panic(err)
	}

	err = os.MkdirAll(BUILD_DIR_BIN, newDirPermissions)
	if err != nil {
		panic(err)
	}

	err = os.MkdirAll(BUILD_DIR_PKG, newDirPermissions)
	if err != nil {
		panic(err)
	}

	err = os.MkdirAll(BUILD_DIR_HTML_REPORT, newDirPermissions)
	if err != nil {
		panic(err)
	}
}

func copyHTMLPluginFilesToGoPath() {
	pwd, err := os.Getwd()
	if err != nil {
		panic(err)
	}

	d, err := os.Open(pwd)
	if err != nil {
		panic(err)
	}
	defer d.Close()

	files, err := d.Readdir(-1)
	if err != nil {
		panic(err)
	}
	mirrorDir(GAUGE_MESSAGES,path.Join(BUILD_DIR_SRC,GAUGE_MESSAGES))
	for _, f := range files {
		if filepath.Ext(f.Name()) == ".go" {
			mirrorFile(f.Name(), path.Join(BUILD_DIR_SRC, htmlReport, f.Name()))
		}
	}
}

func setGoEnv() {
	absBuildDir, err := filepath.Abs(BUILD_DIR)
	if err != nil {
		panic(err)
	}
	set("GOPATH", absBuildDir)
	set("GOBIN", filepath.Join(absBuildDir, bin))
}

func set(envName, envValue string) {
	log.Printf("%s = %s\n", envName, envValue)
	err := os.Setenv(envName, envValue)
	if err != nil {
		panic(err)
	}
}

func runProcess(command string, workingDir string, arg ...string) {
	cmd := exec.Command(command, arg...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	cmd.Dir = workingDir
	log.Printf("Execute %v\n", cmd.Args)
	err := cmd.Run()
	if err != nil {
		panic(err)
	}
}

func executeCommand(command string, arg ...string) (string, error) {
	cmd := exec.Command(command, arg...)
	bytes, err := cmd.Output()
	return strings.TrimSpace(fmt.Sprintf("%s", bytes)), err
}

func compileGoPackage(packageName string) {
	setGoEnv()
	runProcess("go", BUILD_DIR, "get", "-d", "-u", commonDep)
	runProcess("go", BUILD_DIR, "get", "-d", "-u", protoDep)
	runProcess("go", BUILD_DIR, "install", "-v", packageName)
}

func copyBinaries() {
	err := os.MkdirAll(bin, newDirPermissions)
	if err != nil {
		panic(err)
	}

	err = mirrorDir(BUILD_DIR_BIN, bin)
	if err != nil {
		panic(err)
	}

	absBin, err := filepath.Abs(bin)
	if err != nil {
		panic(err)
	}
	log.Printf("Binaries are available at: %s\n", absBin)
}

// key will be the source file and value will be the target
func copyFiles(files map[string]string, installDir string) {
	for src, dst := range files {
		base := filepath.Base(src)
		installDst := filepath.Join(installDir, dst)
		log.Printf("Copying %s -> %s\n", src, installDst)
		stat, err := os.Stat(src)
		if err != nil {
			panic(err)
		}
		if stat.IsDir() {
			err = mirrorDir(src, installDst)
		} else {
			err = mirrorFile(src, filepath.Join(installDst, base))
		}
		if err != nil {
			panic(err)
		}
	}
}

func copyPluginFiles(destDir string) {
	files := make(map[string]string)
	if getGOOS() == "windows" {
		files[filepath.Join(getBinDir(), htmlReport+".exe")] = bin
	} else {
		files[filepath.Join(getBinDir(), htmlReport)] = bin
	}
	files[pluginJsonFile] = ""
	files[reportTemplate] = reportTemplate
	copyFiles(files, destDir)
}

func getPluginVersion() string {
	pluginProperties, err := getPluginProperties(pluginJsonFile)
	if err != nil {
		panic(fmt.Sprintf("Failed to get properties file. %s", err))
	}
	return pluginProperties["version"].(string)
}

func getBinDir() string {
	if *binDir == "" {
		return platformBinDir
	}
	return path.Join(bin, *binDir)
}

func moveOSBinaryToCurrentOSArchDirectory(targetName string) {
	destDir := path.Join(bin, fmt.Sprintf("%s_%s", runtime.GOOS, runtime.GOARCH))
	moveBinaryToDirectory(path.Base(targetName), destDir)
}

func moveBinaryToDirectory(target, destDir string) error {
	if runtime.GOOS == "windows" {
		target = target + ".exe"
	}
	srcFile := path.Join(bin, target)
	destFile := path.Join(destDir, target)
	if err := os.MkdirAll(destDir, newDirPermissions); err != nil {
		return err
	}
	if err := mirrorFile(srcFile, destFile); err != nil {
		return err
	}
	return os.Remove(srcFile)
}

func setEnv(envVariables map[string]string) {
	for k, v := range envVariables {
		os.Setenv(k, v)
	}
}

var install = flag.Bool("install", false, "Install to the specified prefix")
var pluginInstallPrefix = flag.String("plugin-prefix", "", "Specifies the prefix where the plugin will be installed")
var distro = flag.Bool("distro", false, "Creates distributables for the plugin")
var allPlatforms = flag.Bool("all-platforms", false, "Compiles or creates distributables for all platforms windows, linux, darwin both x86 and x86_64")
var binDir = flag.String("bin-dir", "", "Specifies OS_PLATFORM specific binaries to install when cross compiling")

var (
	platformEnvs = []map[string]string{
		map[string]string{GOARCH: X86, GOOS: DARWIN, CGO_ENABLED: "0"},
		map[string]string{GOARCH: X86_64, GOOS: DARWIN, CGO_ENABLED: "0"},
		map[string]string{GOARCH: X86, GOOS: LINUX, CGO_ENABLED: "0"},
		map[string]string{GOARCH: X86_64, GOOS: LINUX, CGO_ENABLED: "0"},
		map[string]string{GOARCH: X86, GOOS: WINDOWS, CGO_ENABLED: "0"},
		map[string]string{GOARCH: X86_64, GOOS: WINDOWS, CGO_ENABLED: "0"},
	}
)

func getPluginProperties(jsonPropertiesFile string) (map[string]interface{}, error) {
	pluginPropertiesJson, err := ioutil.ReadFile(jsonPropertiesFile)
	if err != nil {
		fmt.Printf("Could not read %s: %s\n", filepath.Base(jsonPropertiesFile), err)
		return nil, err
	}
	var pluginJson interface{}
	if err = json.Unmarshal([]byte(pluginPropertiesJson), &pluginJson); err != nil {
		fmt.Printf("Could not read %s: %s\n", filepath.Base(jsonPropertiesFile), err)
		return nil, err
	}
	return pluginJson.(map[string]interface{}), nil
}

func main() {
	createGoPathForBuild()
	copyHTMLPluginFilesToGoPath()
	flag.Parse()

	if *install {
		updatePluginInstallPrefix()
		installPlugin(*pluginInstallPrefix)
	} else if *distro {
		createPluginDistro(*allPlatforms)
	} else {
		compile()
	}
}

func compile() {
	if *allPlatforms {
		compileAcrossPlatforms()
	} else {
		compileGoPackage(htmlReport)
	}
	copyBinaries()
	moveOSBinaryToCurrentOSArchDirectory(htmlReport)
}

func createPluginDistro(forAllPlatforms bool) {
	if forAllPlatforms {
		for _, platformEnv := range platformEnvs {
			setEnv(platformEnv)
			*binDir = fmt.Sprintf("%s_%s", platformEnv[GOOS], platformEnv[GOARCH])
			fmt.Printf("Creating distro for platform => OS:%s ARCH:%s \n", platformEnv[GOOS], platformEnv[GOARCH])
			createDistro()
		}
	} else {
		createDistro()
	}
}

func createDistro() {
	packageName := fmt.Sprintf("%s-%s-%s.%s", htmlReport, getPluginVersion(), getGOOS(), getArch())
	distroDir := filepath.Join(deploy, packageName)
	copyPluginFiles(distroDir)
	createZip(deploy, packageName)
	os.RemoveAll(distroDir)
}

func createZip(dir, packageName string) {
	wd, err := os.Getwd()
	if err != nil {
		panic(err)
	}
	os.Chdir(dir)

	zipFileName := packageName + ".zip"
	newfile, err := os.Create(zipFileName)
	if err != nil {
		panic(err)
	}
	defer newfile.Close()

	zipWriter := zip.NewWriter(newfile)
	defer zipWriter.Close()

	filepath.Walk(packageName, func(path string, info os.FileInfo, err error) error {
		infoHeader, err := zip.FileInfoHeader(info)
		if err != nil {
			panic(err)
		}
		infoHeader.Name = strings.Replace(path, fmt.Sprintf("%s%c", packageName, filepath.Separator), "", 1)
		if info.IsDir() {
			return nil
		}
		writer, err := zipWriter.CreateHeader(infoHeader)
		if err != nil {
			panic(err)
		}
		file, err := os.Open(path)
		if err != nil {
			panic(err)
		}
		defer file.Close()
		_, err = io.Copy(writer, file)
		if err != nil {
			panic(err)
		}
		return nil
	})

	os.Chdir(wd)
}

func compileAcrossPlatforms() {
	for _, platformEnv := range platformEnvs {
		setEnv(platformEnv)
		fmt.Printf("Compiling for platform => OS:%s ARCH:%s \n", platformEnv[GOOS], platformEnv[GOARCH])
		compileGoPackage(htmlReport)
	}
}

func installPlugin(installPrefix string) {
	copyPluginFiles(deployDir)
	pluginInstallPath := filepath.Join(installPrefix, htmlReport, getPluginVersion())
	mirrorDir(deployDir, pluginInstallPath)
}

func updatePluginInstallPrefix() {
	if *pluginInstallPrefix == "" {
		if runtime.GOOS == "windows" {
			*pluginInstallPrefix = os.Getenv("APPDATA")
			if *pluginInstallPrefix == "" {
				panic(fmt.Errorf("Failed to find AppData directory"))
			}
			*pluginInstallPrefix = filepath.Join(*pluginInstallPrefix, gauge, plugins)
		} else {
			userHome := getUserHome()
			if userHome == "" {
				panic(fmt.Errorf("Failed to find User Home directory"))
			}
			*pluginInstallPrefix = filepath.Join(userHome, dotGauge, plugins)
		}
	}
}

func getUserHome() string {
	return os.Getenv("HOME")
}

func getArch() string {
	arch := getGOARCH()
	if arch == X86 {
		return "x86"
	}
	return "x86_64"
}

func getGOARCH() string {
	goArch := os.Getenv(GOARCH)
	if goArch == "" {
		return runtime.GOARCH

	}
	return goArch
}

func getGOOS() string {
	os := os.Getenv(GOOS)
	if os == "" {
		return runtime.GOOS

	}
	return os
}
<commit_msg>updating build<commit_after>// Copyright 2015 ThoughtWorks, Inc.

// This file is part of getgauge/html-report.

// getgauge/html-report is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// getgauge/html-report is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with getgauge/html-report.  If not, see <http://www.gnu.org/licenses/>.

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"runtime"
	"strings"
)

const (
	CGO_ENABLED = "CGO_ENABLED"
)

const (
	dotGauge          = ".gauge"
	plugins           = "plugins"
	GOARCH            = "GOARCH"
	GOOS              = "GOOS"
	X86               = "386"
	X86_64            = "amd64"
	DARWIN            = "darwin"
	LINUX             = "linux"
	WINDOWS           = "windows"
	bin               = "bin"
	newDirPermissions = 0755
	gauge             = "gauge"
	htmlReport        = "html-report"
	deploy            = "deploy"
	pluginJsonFile    = "plugin.json"
	reportTemplate    = "report-template"
	GAUGE_MESSAGES    = "gauge_messages"
)

var deployDir = filepath.Join(deploy, htmlReport)

func main() {
	flag.Parse()
	if *install {
		updatePluginInstallPrefix()
		installPlugin(*pluginInstallPrefix)
	} else if *distro {
		createPluginDistro(*allPlatforms)
	} else {
		compile()
	}
}

func compile() {
	if *allPlatforms {
		compileAcrossPlatforms()
	} else {
		compileGoPackage(htmlReport)
	}
}

func createPluginDistro(forAllPlatforms bool) {
	if forAllPlatforms {
		for _, platformEnv := range platformEnvs {
			setEnv(platformEnv)
			*binDir = filepath.Join(bin, fmt.Sprintf("%s_%s", platformEnv[GOOS], platformEnv[GOARCH]))
			fmt.Printf("Creating distro for platform => OS:%s ARCH:%s \n", platformEnv[GOOS], platformEnv[GOARCH])
			createDistro()
		}
	} else {
		createDistro()
	}
	log.Printf("Distributables created in directory => %s \n", deploy)
}

func createDistro() {
	packageName := fmt.Sprintf("%s-%s-%s.%s", htmlReport, getPluginVersion(), getGOOS(), getArch())
	distroDir := filepath.Join(deploy, packageName)
	copyPluginFiles(distroDir)
	createZipFromUtil(deploy, packageName)
	os.RemoveAll(distroDir)
}

func createZipFromUtil(dir, name string) {
	wd, err := os.Getwd()
	if err != nil {
		panic(err)
	}
	os.Chdir(filepath.Join(dir, name))
	output, err := executeCommand("zip", "-r", filepath.Join("..", name+".zip"), ".")
	fmt.Println(output)
	if err != nil {
		panic(fmt.Sprintf("Failed to zip: %s", err))
	}
	os.Chdir(wd)
}

func isExecMode(mode os.FileMode) bool {
	return (mode & 0111) != 0
}

func mirrorFile(src, dst string) error {
	sfi, err := os.Stat(src)
	if err != nil {
		return err
	}
	if sfi.Mode()&os.ModeType != 0 {
		log.Fatalf("mirrorFile can't deal with non-regular file %s", src)
	}
	dfi, err := os.Stat(dst)
	if err == nil &&
		isExecMode(sfi.Mode()) == isExecMode(dfi.Mode()) &&
		(dfi.Mode()&os.ModeType == 0) &&
		dfi.Size() == sfi.Size() &&
		dfi.ModTime().Unix() == sfi.ModTime().Unix() {
		// Seems to not be modified.
		return nil
	}

	dstDir := filepath.Dir(dst)
	if err := os.MkdirAll(dstDir, newDirPermissions); err != nil {
		return err
	}

	df, err := os.Create(dst)
	if err != nil {
		return err
	}
	sf, err := os.Open(src)
	if err != nil {
		return err
	}
	defer sf.Close()

	n, err := io.Copy(df, sf)
	if err == nil && n != sfi.Size() {
		err = fmt.Errorf("copied wrong size for %s -> %s: copied %d; want %d", src, dst, n, sfi.Size())
	}
	cerr := df.Close()
	if err == nil {
		err = cerr
	}
	if err == nil {
		err = os.Chmod(dst, sfi.Mode())
	}
	if err == nil {
		err = os.Chtimes(dst, sfi.ModTime(), sfi.ModTime())
	}
	return err
}

func mirrorDir(src, dst string) error {
	log.Printf("Copying '%s' -> '%s'\n", src, dst)
	err := filepath.Walk(src, func(path string, fi os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if fi.IsDir() {
			return nil
		}
		suffix, err := filepath.Rel(src, path)
		if err != nil {
			return fmt.Errorf("Failed to find Rel(%q, %q): %v", src, path, err)
		}
		return mirrorFile(path, filepath.Join(dst, suffix))
	})
	return err
}

func set(envName, envValue string) {
	log.Printf("%s = %s\n", envName, envValue)
	err := os.Setenv(envName, envValue)
	if err != nil {
		panic(err)
	}
}

func runProcess(command string, arg ...string) {
	cmd := exec.Command(command, arg...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	log.Printf("Execute %v\n", cmd.Args)
	err := cmd.Run()
	if err != nil {
		panic(err)
	}
}

func executeCommand(command string, arg ...string) (string, error) {
	cmd := exec.Command(command, arg...)
	bytes, err := cmd.Output()
	return strings.TrimSpace(fmt.Sprintf("%s", bytes)), err
}

func compileGoPackage(packageName string) {
	runProcess("go", "build", "-o", getGaugeExecutablePath(htmlReport))
}

func getGaugeExecutablePath(file string) string {
	return filepath.Join(getBinDir(), getExecutableName(file))
}

func getExecutableName(file string) string {
	if getGOOS() == "windows" {
		return file + ".exe"
	}
	return file
}

func getBinDir() string {
	if *binDir != "" {
		return *binDir
	}
	return filepath.Join(bin, fmt.Sprintf("%s_%s", getGOOS(), getGOARCH()))
}

// key will be the source file and value will be the target
func copyFiles(files map[string]string, installDir string) {
	for src, dst := range files {
		base := filepath.Base(src)
		installDst := filepath.Join(installDir, dst)
		log.Printf("Copying %s -> %s\n", src, installDst)
		stat, err := os.Stat(src)
		if err != nil {
			panic(err)
		}
		if stat.IsDir() {
			err = mirrorDir(src, installDst)
		} else {
			err = mirrorFile(src, filepath.Join(installDst, base))
		}
		if err != nil {
			panic(err)
		}
	}
}

func copyPluginFiles(destDir string) {
	files := make(map[string]string)
	if getGOOS() == "windows" {
		files[filepath.Join(getBinDir(), htmlReport+".exe")] = bin
	} else {
		files[filepath.Join(getBinDir(), htmlReport)] = bin
	}
	files[pluginJsonFile] = ""
	files[reportTemplate] = reportTemplate
	copyFiles(files, destDir)
}

func getPluginVersion() string {
	pluginProperties, err := getPluginProperties(pluginJsonFile)
	if err != nil {
		panic(fmt.Sprintf("Failed to get properties file. %s", err))
	}
	return pluginProperties["version"].(string)
}

func moveOSBinaryToCurrentOSArchDirectory(targetName string) {
	destDir := path.Join(bin, fmt.Sprintf("%s_%s", runtime.GOOS, runtime.GOARCH))
	moveBinaryToDirectory(path.Base(targetName), destDir)
}

func moveBinaryToDirectory(target, destDir string) error {
	if runtime.GOOS == "windows" {
		target = target + ".exe"
	}
	srcFile := path.Join(bin, target)
	destFile := path.Join(destDir, target)
	if err := os.MkdirAll(destDir, newDirPermissions); err != nil {
		return err
	}
	if err := mirrorFile(srcFile, destFile); err != nil {
		return err
	}
	return os.Remove(srcFile)
}

func setEnv(envVariables map[string]string) {
	for k, v := range envVariables {
		os.Setenv(k, v)
	}
}

var install = flag.Bool("install", false, "Install to the specified prefix")
var pluginInstallPrefix = flag.String("plugin-prefix", "", "Specifies the prefix where the plugin will be installed")
var distro = flag.Bool("distro", false, "Creates distributables for the plugin")
var allPlatforms = flag.Bool("all-platforms", false, "Compiles or creates distributables for all platforms windows, linux, darwin both x86 and x86_64")
var binDir = flag.String("bin-dir", "", "Specifies OS_PLATFORM specific binaries to install when cross compiling")

var (
	platformEnvs = []map[string]string{
		map[string]string{GOARCH: X86, GOOS: DARWIN, CGO_ENABLED: "0"},
		map[string]string{GOARCH: X86_64, GOOS: DARWIN, CGO_ENABLED: "0"},
		map[string]string{GOARCH: X86, GOOS: LINUX, CGO_ENABLED: "0"},
		map[string]string{GOARCH: X86_64, GOOS: LINUX, CGO_ENABLED: "0"},
		map[string]string{GOARCH: X86, GOOS: WINDOWS, CGO_ENABLED: "0"},
		map[string]string{GOARCH: X86_64, GOOS: WINDOWS, CGO_ENABLED: "0"},
	}
)

func getPluginProperties(jsonPropertiesFile string) (map[string]interface{}, error) {
	pluginPropertiesJson, err := ioutil.ReadFile(jsonPropertiesFile)
	if err != nil {
		fmt.Printf("Could not read %s: %s\n", filepath.Base(jsonPropertiesFile), err)
		return nil, err
	}
	var pluginJson interface{}
	if err = json.Unmarshal([]byte(pluginPropertiesJson), &pluginJson); err != nil {
		fmt.Printf("Could not read %s: %s\n", filepath.Base(jsonPropertiesFile), err)
		return nil, err
	}
	return pluginJson.(map[string]interface{}), nil
}

func compileAcrossPlatforms() {
	for _, platformEnv := range platformEnvs {
		setEnv(platformEnv)
		fmt.Printf("Compiling for platform => OS:%s ARCH:%s \n", platformEnv[GOOS], platformEnv[GOARCH])
		compileGoPackage(htmlReport)
	}
}

func installPlugin(installPrefix string) {
	copyPluginFiles(deployDir)
	pluginInstallPath := filepath.Join(installPrefix, htmlReport, getPluginVersion())
	mirrorDir(deployDir, pluginInstallPath)
}

func updatePluginInstallPrefix() {
	if *pluginInstallPrefix == "" {
		if runtime.GOOS == "windows" {
			*pluginInstallPrefix = os.Getenv("APPDATA")
			if *pluginInstallPrefix == "" {
				panic(fmt.Errorf("Failed to find AppData directory"))
			}
			*pluginInstallPrefix = filepath.Join(*pluginInstallPrefix, gauge, plugins)
		} else {
			userHome := getUserHome()
			if userHome == "" {
				panic(fmt.Errorf("Failed to find User Home directory"))
			}
			*pluginInstallPrefix = filepath.Join(userHome, dotGauge, plugins)
		}
	}
}

func getUserHome() string {
	return os.Getenv("HOME")
}

func getArch() string {
	arch := getGOARCH()
	if arch == X86 {
		return "x86"
	}
	return "x86_64"
}

func getGOARCH() string {
	goArch := os.Getenv(GOARCH)
	if goArch == "" {
		return runtime.GOARCH

	}
	return goArch
}

func getGOOS() string {
	os := os.Getenv(GOOS)
	if os == "" {
		return runtime.GOOS

	}
	return os
}
<|endoftext|>


<commit_before>// MIT License

// Copyright (c) 2016 rutcode-go

package worth

import (
	"fmt"
	"math/rand"
	"strings"
	"sync"
	"time"

	"github.com/go-rut/algorithm"
	"github.com/go-rut/config_reader"
	"github.com/go-rut/format"
)

const (
	FlagPathToEnd = iota
	FlagPathToTarget
)

type SPFA struct {
	mapGraphs map[string][]*algorithm.Graph
	mapFromTo map[string]*algorithm.Graph

	sync.RWMutex
}

func NewSPFA() NetworkWorth {
	return new(SPFA)
}

func (p *SPFA) Init(confPath string) {

	model := &algorithm.Graphs{}
	err := config_reader.NewConfigReader().JsonFileReader(confPath, model)
	if err != nil {
		panic(err)
	}

	for _, v := range model.Graphs {
		item := v
		p.Add(&item)
	}
}

func (p *SPFA) Add(g *algorithm.Graph) {
	p.Lock()
	defer p.Unlock()
	p.add(g)
}

func (p *SPFA) add(g *algorithm.Graph) {
	if g == nil {
		return
	}

	if p.mapGraphs == nil {
		p.mapGraphs = make(map[string][]*algorithm.Graph, 0)
	}

	if p.mapFromTo == nil {
		p.mapFromTo = make(map[string]*algorithm.Graph, 0)
	}

	p.mapGraphs[g.GraphFrom] = append(p.mapGraphs[g.GraphFrom], g)
	p.mapFromTo[p.genKey(g.GraphFrom, g.GraphTo)] = g
}

func (p *SPFA) RemoveFromTo(from, to string) {
	p.Lock()
	defer p.Unlock()
	p.removeFromTo(from, to)
}

func (p *SPFA) removeFromTo(from, to string) {

	if p.mapFromTo == nil {
		return
	}

	fromTo := p.genKey(from, to)

	if p.mapFromTo[fromTo] == nil {
		return
	}

	delete(p.mapFromTo, fromTo)

	fGraphs := p.mapGraphs[from]
	tmpPosition := 0

	for i, v := range fGraphs {
		if v.GraphTo == to {
			tmpPosition = i
		}
	}

	p.mapGraphs[from] = append(fGraphs[:tmpPosition], fGraphs[tmpPosition+1:]...)
}

func (p *SPFA) Remove() {
	p.Lock()
	defer p.Unlock()
	p.remove()
}

func (p *SPFA) remove() {
	p.mapGraphs = nil
	p.mapFromTo = nil
}

func (p *SPFA) GetPathTo(from, to string, flow float64) (gs *algorithm.Graphs, err error) {
	p.RLock()
	defer p.RUnlock()

	if p.mapGraphs == nil {
		return nil, ErrGraphFromNotExists
	}

	fGraphs := p.mapGraphs[from]
	if fGraphs == nil {
		err = ErrGraphFromNotExists
		return
	}

	costs, flag := p.getPathTo(fGraphs, to, flow)
	if flag == FlagPathToEnd {
		err = ErrNotFoundPathToTarget
		return
	}

	s, cost := p.getMinPath(costs)

	gs = &algorithm.Graphs{
		Cost: cost,
	}

	paths := p.rollbackKey(s)
	for i, v := range paths {
		if v == to {
			return
		} else {
			gs.Graphs = append(gs.Graphs, *p.mapFromTo[p.genKey(v, paths[i+1])])
		}
	}

	return
}

func (p *SPFA) getPathTo(fGraphs []*algorithm.Graph, to string, flow float64) (mapCosts map[string]int64, flag int) {
	if len(fGraphs) == 0 {
		return
	}

	mapCosts = make(map[string]int64, 0)

	for _, v := range fGraphs {
		if v.Capacity < flow {
			continue
		}
		if v.GraphTo == to {
			mapCosts[p.genKey(v.GraphFrom, v.GraphTo)] = format.RoundFund(flow * float64(v.CostPerUnit))
			continue
		}

		if tempMapCosts, tmpFlag := p.getPathTo(p.mapGraphs[v.GraphTo], to, flow); tmpFlag == FlagPathToEnd {
			continue
		} else {
			for k, cost := range tempMapCosts {
				mapCosts[p.genKey(v.GraphFrom, k)] = cost + format.RoundFund(flow*float64(v.CostPerUnit))
			}
		}
	}

	if len(mapCosts) > 0 {
		flag = FlagPathToTarget
	}
	return
}

func (p *SPFA) getMinPath(costs map[string]int64) (path string, min int64) {

	var paths []string
	for k, v := range costs {

		if v > min && min != 0 {
			continue
		}

		if v < min {
			paths = nil
		}
		min = v
		paths = append(paths, k)
	}

	rand.Seed(time.Now().UnixNano())
	path = paths[rand.Intn(len(paths))]
	return
}

func (p *SPFA) genKey(from, to string) string {
	return fmt.Sprintf("%s::%s", from, to)
}

func (p *SPFA) rollbackKey(s string) []string {
	return strings.Split(s, "::")
}

func (p *SPFA) PrintGraphs() {
	for k, vs := range p.mapGraphs {
		for _, v := range vs {
			fmt.Println(k, *v)
		}
	}
}
<commit_msg>fix bug: print graphs need lock and defer unlock<commit_after>// MIT License

// Copyright (c) 2016 rutcode-go

package worth

import (
	"fmt"
	"math/rand"
	"strings"
	"sync"
	"time"

	"github.com/go-rut/algorithm"
	"github.com/go-rut/config_reader"
	"github.com/go-rut/format"
)

const (
	FlagPathToEnd = iota
	FlagPathToTarget
)

type SPFA struct {
	mapGraphs map[string][]*algorithm.Graph
	mapFromTo map[string]*algorithm.Graph

	sync.RWMutex
}

func NewSPFA() NetworkWorth {
	return new(SPFA)
}

func (p *SPFA) Init(confPath string) {

	model := &algorithm.Graphs{}
	err := config_reader.NewConfigReader().JsonFileReader(confPath, model)
	if err != nil {
		panic(err)
	}

	for _, v := range model.Graphs {
		item := v
		p.Add(&item)
	}
}

func (p *SPFA) Add(g *algorithm.Graph) {
	p.Lock()
	defer p.Unlock()
	p.add(g)
}

func (p *SPFA) add(g *algorithm.Graph) {
	if g == nil {
		return
	}

	if p.mapGraphs == nil {
		p.mapGraphs = make(map[string][]*algorithm.Graph, 0)
	}

	if p.mapFromTo == nil {
		p.mapFromTo = make(map[string]*algorithm.Graph, 0)
	}

	p.mapGraphs[g.GraphFrom] = append(p.mapGraphs[g.GraphFrom], g)
	p.mapFromTo[p.genKey(g.GraphFrom, g.GraphTo)] = g
}

func (p *SPFA) RemoveFromTo(from, to string) {
	p.Lock()
	defer p.Unlock()
	p.removeFromTo(from, to)
}

func (p *SPFA) removeFromTo(from, to string) {

	if p.mapFromTo == nil {
		return
	}

	fromTo := p.genKey(from, to)

	if p.mapFromTo[fromTo] == nil {
		return
	}

	delete(p.mapFromTo, fromTo)

	fGraphs := p.mapGraphs[from]
	tmpPosition := 0

	for i, v := range fGraphs {
		if v.GraphTo == to {
			tmpPosition = i
		}
	}

	p.mapGraphs[from] = append(fGraphs[:tmpPosition], fGraphs[tmpPosition+1:]...)
}

func (p *SPFA) Remove() {
	p.Lock()
	defer p.Unlock()
	p.remove()
}

func (p *SPFA) remove() {
	p.mapGraphs = nil
	p.mapFromTo = nil
}

func (p *SPFA) GetPathTo(from, to string, flow float64) (gs *algorithm.Graphs, err error) {
	p.RLock()
	defer p.RUnlock()

	if p.mapGraphs == nil {
		return nil, ErrGraphFromNotExists
	}

	fGraphs := p.mapGraphs[from]
	if fGraphs == nil {
		err = ErrGraphFromNotExists
		return
	}

	costs, flag := p.getPathTo(fGraphs, to, flow)
	if flag == FlagPathToEnd {
		err = ErrNotFoundPathToTarget
		return
	}

	s, cost := p.getMinPath(costs)

	gs = &algorithm.Graphs{
		Cost: cost,
	}

	paths := p.rollbackKey(s)
	for i, v := range paths {
		if v == to {
			return
		} else {
			gs.Graphs = append(gs.Graphs, *p.mapFromTo[p.genKey(v, paths[i+1])])
		}
	}

	return
}

func (p *SPFA) getPathTo(fGraphs []*algorithm.Graph, to string, flow float64) (mapCosts map[string]int64, flag int) {
	if len(fGraphs) == 0 {
		return
	}

	mapCosts = make(map[string]int64, 0)

	for _, v := range fGraphs {
		if v.Capacity < flow {
			continue
		}
		if v.GraphTo == to {
			mapCosts[p.genKey(v.GraphFrom, v.GraphTo)] = format.RoundFund(flow * float64(v.CostPerUnit))
			continue
		}

		if tempMapCosts, tmpFlag := p.getPathTo(p.mapGraphs[v.GraphTo], to, flow); tmpFlag == FlagPathToEnd {
			continue
		} else {
			for k, cost := range tempMapCosts {
				mapCosts[p.genKey(v.GraphFrom, k)] = cost + format.RoundFund(flow*float64(v.CostPerUnit))
			}
		}
	}

	if len(mapCosts) > 0 {
		flag = FlagPathToTarget
	}
	return
}

func (p *SPFA) getMinPath(costs map[string]int64) (path string, min int64) {

	var paths []string
	for k, v := range costs {

		if v > min && min != 0 {
			continue
		}

		if v < min {
			paths = nil
		}
		min = v
		paths = append(paths, k)
	}

	rand.Seed(time.Now().UnixNano())
	path = paths[rand.Intn(len(paths))]
	return
}

func (p *SPFA) genKey(from, to string) string {
	return fmt.Sprintf("%s::%s", from, to)
}

func (p *SPFA) rollbackKey(s string) []string {
	return strings.Split(s, "::")
}

func (p *SPFA) PrintGraphs() {
	p.RLock()
	defer p.RUnlock()
	for k, vs := range p.mapGraphs {
		for _, v := range vs {
			fmt.Println(k, *v)
		}
	}
}
<|endoftext|>


<commit_before>package gosql

import "testing"

func TestSQLXLimit_Example1(t *testing.T) {
	example := `5%12%1`                        // 定义Example
	limit := NewSQLXLimit()                    // 初始化
	limit.SetDefaultLimit(10).SetMaxLimit(100) // 设置限制规则
	sql, err := limit.JSONtoSQLString(example) // 生成SQL语句
	if err != nil {
		t.Fatal(err)
	}
	t.Log(sql)
}

func TestSQLXLimit_Example2(t *testing.T) {
	example := `2`                             // 定义Example
	limit := NewSQLXLimit()                    // 初始化
	limit.SetDefaultLimit(10)                  // 设置限制规则
	sql, err := limit.JSONtoSQLString(example) // 生成SQL语句
	if err != nil {
		t.Fatal(err)
	}
	t.Log(sql)
}

func TestSQLXLimit_Example3(t *testing.T) {
	example := `%-12%2`                        // 定义Example
	limit := NewSQLXLimit()                    // 初始化
	limit.SetDefaultLimit(10)                  // 设置限制规则
	sql, err := limit.JSONtoSQLString(example) // 生成SQL语句
	if err != nil {
		t.Fatal(err)
	}
	t.Log(sql)
}

func TestSQLXLimit_Example4(t *testing.T) {
	example := `-2%0%2`                        // 定义Example
	limit := NewSQLXLimit()                    // 初始化
	limit.SetMaxLimit(10)                      // 设置限制规则
	sql, err := limit.JSONtoSQLString(example) // 生成SQL语句
	if err != nil {
		t.Fatal(err)
	}
	t.Log(sql)
}
<commit_msg>test: refactor limit sqlx<commit_after>package gosql

import "testing"

func TestSQLXLimit_Example1(t *testing.T) {
	example := `{"%l":5,"%s":12,"%p":1}`       // 定义Example
	limit := NewSQLXLimit()                    // 初始化
	limit.SetMaxLimit(100)                     // 设置限制规则
	sql, err := limit.JSONtoSQLString(example) // 生成SQL语句
	if err != nil {
		t.Fatal(err)
	}
	t.Log(sql)
}

func TestSQLXLimit_Example2(t *testing.T) {
	example := `{"%l":5,"%s":12}`              // 定义Example
	limit := NewSQLXLimit()                    // 初始化
	sql, err := limit.JSONtoSQLString(example) // 生成SQL语句
	if err != nil {
		t.Fatal(err)
	}
	t.Log(sql)
}

func TestSQLXLimit_Example3(t *testing.T) {
	example := `{"%l":5,"%s":-12,"%p":3}`      // 定义Example
	limit := NewSQLXLimit()                    // 初始化
	sql, err := limit.JSONtoSQLString(example) // 生成SQL语句
	if err != nil {
		t.Fatal(err)
	}
	t.Log(sql)
}

func TestSQLXLimit_Example4(t *testing.T) {
	example := `{"%l":-1,"%s":2,"%p":2}`       // 定义Example
	limit := NewSQLXLimit()                    // 初始化
	limit.SetMaxLimit(10)                      // 设置限制规则
	sql, err := limit.JSONtoSQLString(example) // 生成SQL语句
	if err != nil {
		t.Fatal(err)
	}
	t.Log(sql)
}
<|endoftext|>


<commit_before>package gosql

import "testing"

func TestSQLXOrder_ExampleJSON1(t *testing.T) {
	example := `["key1", "+key2", "+key3", "-key4", "-key5"]` // 定义Example
	order := NewSQLXOrder()                                   // 初始化
	order.Allow("key1", "key2", "key5")                       // 设置关键字过滤规则
	sql, err := order.JSONtoSQLString(example)                // 生成SQL语句
	if err != nil {
		t.Fatal(err)
	}
	t.Log(sql)
}

func TestSQLXOrder_Example1(t *testing.T) {
	example := []string{"key1", "+key2", "+key3", "-key4", "-key5"} // 定义Example，注意前缀设定
	order := NewSQLXOrder()                                         // 初始化
	order.Allow("key1", "key2", "key5")                             // 设置关键字过滤规则
	sql, err := order.SQLString(example)                            // 生成SQL语句
	if err != nil {
		t.Fatal(err)
	}
	t.Log(sql)
}
<commit_msg>feat: order sqlx impl<commit_after>package gosql

import "testing"

func TestSQLXOrder_ExampleJSON1(t *testing.T) {
	example := `{"%asc":"key1","%desc":"key2"}` // 定义Example
	order := NewSQLXOrder()                     // 初始化
	order.Allow("key1", "key2")                 // 设置关键字过滤规则
	sql, err := order.JSONtoSQLString(example)  // 生成SQL语句
	if err != nil {
		t.Fatal(err)
	}
	t.Log(sql)
}

func TestSQLXOrder_ExampleJSON2(t *testing.T) {
	example := `{"%asc":"key1","%desc":"key2","%desc":"key5"}` // 定义Example，注意前缀设定
	order := NewSQLXOrder()                                    // 初始化
	order.Allow("key1", "key2", "key5")                        // 设置关键字过滤规则
	sql, err := order.JSONtoSQLString(example)                 // 生成SQL语句
	if err != nil {
		t.Fatal(err)
	}
	t.Log(sql)
}
<|endoftext|>


<commit_before>package crawler

import (
	"net/url"
)

type Filter interface {
	Filter(*url.URL) bool
}

//is url Filter
type UrlFilter struct{}

func (f *UrlFilter) Filter(u *url.URL) bool {
	return u.Scheme == "" || u.Scheme == "http" || u.Scheme == "https"
}

//no duplicated Filter
type UniqueFilter struct {
	urls []*url.URL
}

func (f *UniqueFilter) Filter(u *url.URL) bool {
	for _, old_u := range f.urls {
		if *u == *old_u {
			return false
		}

		another_u := *u
		another_old_u := *old_u

		another_u.Fragment = ""
		another_old_u.Fragment = ""

		if another_u == another_old_u {
			return false
		}
	}

	f.urls = append(f.urls, u)

	return true
}

//same hostname only
type SameHostFilter struct {
	root_url *url.URL
}

func (f *SameHostFilter) Filter(u *url.URL) bool {
	return f.root_url.Host == u.Host
}
<commit_msg>expose Filters properties<commit_after>package crawler

import (
	"net/url"
)

type Filter interface {
	Filter(*url.URL) bool
}

//is url Filter
type UrlFilter struct{}

func (f *UrlFilter) Filter(u *url.URL) bool {
	return u.Scheme == "" || u.Scheme == "http" || u.Scheme == "https"
}

//no duplicated Filter
type UniqueFilter struct {
	Us []*url.URL
}

func (f *UniqueFilter) Filter(u *url.URL) bool {
	for _, old_u := range f.Us {
		if *u == *old_u {
			return false
		}

		another_u := *u
		another_old_u := *old_u

		another_u.Fragment = ""
		another_old_u.Fragment = ""

		if another_u == another_old_u {
			return false
		}
	}

	f.Us = append(f.Us, u)

	return true
}

//same hostname only
type SameHostFilter struct {
	U *url.URL
}

func (f *SameHostFilter) Filter(u *url.URL) bool {
	return f.U.Host == u.Host
}
<|endoftext|>


<commit_before>package main

import (
	"testing"

	"fmt"
	. "github.com/smartystreets/goconvey/convey"
)

func TestBuildInfo_OptionPrefix(t *testing.T) {
	Convey("GIVEN: A `BuildInfo` with empty variable definitioins", t, func() {
		info := BuildInfo{}
		Convey("WHEN: Call `OptionPrefix`", func() {
			actual := info.OptionPrefix()
			Convey("THEN: Should return \"-\"", func() {
				So(actual, ShouldEqual, "-")
			})
		})
		Convey("WHEN: Defines `option_prefix = \"/\"`", func() {
			info.variables = map[string]string{"option_prefix": "/"}
			Convey("AND WHEN: Call `OptionPrefix`", func() {
				actual := info.OptionPrefix()
				Convey("THEN: Should return \"/\"", func() {
					So(actual, ShouldEqual, "/")
				})
			})
		})
	})
}

func TestBuildInfo_AddInclude(t *testing.T) {
	Convey("GIVEN: An empty `BuildInfo`", t, func() {
		info := BuildInfo{}
		for _, opfx := range []string{"/", "--"} {
			Convey(fmt.Sprintf("WHEN: option_prefix = \"%s\"", opfx), func() {
				info.variables = map[string]string{"option_prefix": opfx}
				Convey("AND WHEN: Call `AddInclude (\"/usr/local\")`", func() {
					info.AddInclude("/usr/local")
					Convey(fmt.Sprintf("THEN: info.includes should be [\"%sI/usr/local\"]", opfx), func() {
						So(len(info.includes), ShouldEqual, 1)
						So(info.includes, ShouldContain, fmt.Sprintf("%sI/usr/local", opfx))
					})
					Convey("AND WHEN: Call `AddInclude (\"/usr/foo bar\")`", func() {
						info.AddInclude("/usr/foo bar")
						Convey(fmt.Sprintf("THEN: info includes should be [\"%[1]sI/usr/local\", \"\\\"%[1]sI/usr/foo bar\\\"\"]", opfx), func() {
							So(len(info.includes), ShouldEqual, 2)
							So(info.includes[0], ShouldEqual, fmt.Sprintf("%sI/usr/local", opfx))
							So(info.includes[1], ShouldEqual, fmt.Sprintf("\"%sI/usr/foo bar\"", opfx))
						})
					})
				})
			})
		}
	})
}

func TestBuildInfo_AddDefines(t *testing.T) {
	Convey("GIVEN: An empty `BuildInfo`", t, func() {
		info := BuildInfo{}
		for _, opfx := range []string{"/", "--"} {
			Convey(fmt.Sprintf("WHEN: option_prefix = \"%s\"", opfx), func() {
				info.variables = map[string]string{"option_prefix": opfx}
				Convey("AND WHEN: Call `AddDefine (\"FOO\")`", func() {
					info.AddDefines("FOO")
					expected := fmt.Sprintf("%sDFOO", opfx)
					Convey(fmt.Sprintf("THEN: info.defines should be [\"%s\"]", expected), func() {
						So(len(info.defines), ShouldEqual, 1)
						So(info.defines, ShouldContain, expected)
					})
					Convey("AND WHEN: Call `AddDefine (\"BAR=BAZ\")`", func() {
						info.AddDefines("BAR=BAZ")
						Convey(fmt.Sprintf("THEN: info.defines should be [\"%[1]sDFOO\", \"%[1]sDBAR=BAZ\"]", opfx), func() {
							So(len(info.defines), ShouldEqual, 2)
							So(info.defines[0], ShouldEqual, fmt.Sprintf("%sDFOO", opfx))
							So(info.defines[1], ShouldEqual, fmt.Sprintf("%sDBAR=BAZ", opfx))
						})
					})
				})
			})
		}
	})
}

func TestBuildInfo_MakeExecutablePath(t *testing.T) {
	Convey("GIVEN: A BuildInfo with .outputdir = \"/usr/local\"", t, func() {
		info := BuildInfo{variables: map[string]string{}, outputdir: "/usr/local"}
		Convey("WHEN: Call with \"TEST\"", func() {
			actual := info.MakeExecutablePath("TEST")
			Convey("THEN: Should return \"/usr/local/TEST\"", func() {
				So(actual, ShouldEqual, "/usr/local/TEST")
			})
		})
		Convey("WHEN: Set \".THE-SUFFIX\" as ${execute_suffix}", func() {
			info.variables["execute_suffix"] = ".THE-SUFFIX"
			Convey("AND WHEN: Call with \"TEST\"", func() {
				actual := info.MakeExecutablePath("TEST")
				Convey("THEN: Should return \"/usr/local/TEST.THE-SUFFIX\"", func() {
					So(actual, ShouldEqual, "/usr/local/TEST.THE-SUFFIX")
				})
			})
		})
	})
}
<commit_msg>test: Run successfully on Windows<commit_after>package main

import (
	"testing"

	"fmt"
	. "github.com/smartystreets/goconvey/convey"
	"path/filepath"
)

func TestBuildInfo_OptionPrefix(t *testing.T) {
	Convey("GIVEN: A `BuildInfo` with empty variable definitioins", t, func() {
		info := BuildInfo{}
		Convey("WHEN: Call `OptionPrefix`", func() {
			actual := info.OptionPrefix()
			Convey("THEN: Should return \"-\"", func() {
				So(actual, ShouldEqual, "-")
			})
		})
		Convey("WHEN: Defines `option_prefix = \"/\"`", func() {
			info.variables = map[string]string{"option_prefix": "/"}
			Convey("AND WHEN: Call `OptionPrefix`", func() {
				actual := info.OptionPrefix()
				Convey("THEN: Should return \"/\"", func() {
					So(actual, ShouldEqual, "/")
				})
			})
		})
	})
}

func TestBuildInfo_AddInclude(t *testing.T) {
	Convey("GIVEN: An empty `BuildInfo`", t, func() {
		info := BuildInfo{}
		for _, opfx := range []string{"/", "--"} {
			Convey(fmt.Sprintf("WHEN: option_prefix = \"%s\"", opfx), func() {
				info.variables = map[string]string{"option_prefix": opfx}
				Convey("AND WHEN: Call `AddInclude (\"/usr/local\")`", func() {
					info.AddInclude("/usr/local")
					Convey(fmt.Sprintf("THEN: info.includes should be [\"%sI/usr/local\"]", opfx), func() {
						So(len(info.includes), ShouldEqual, 1)
						So(info.includes, ShouldContain, fmt.Sprintf("%sI/usr/local", opfx))
					})
					Convey("AND WHEN: Call `AddInclude (\"/usr/foo bar\")`", func() {
						info.AddInclude("/usr/foo bar")
						Convey(fmt.Sprintf("THEN: info includes should be [\"%[1]sI/usr/local\", \"\\\"%[1]sI/usr/foo bar\\\"\"]", opfx), func() {
							So(len(info.includes), ShouldEqual, 2)
							So(info.includes[0], ShouldEqual, fmt.Sprintf("%sI/usr/local", opfx))
							So(info.includes[1], ShouldEqual, fmt.Sprintf("\"%sI/usr/foo bar\"", opfx))
						})
					})
				})
			})
		}
	})
}

func TestBuildInfo_AddDefines(t *testing.T) {
	Convey("GIVEN: An empty `BuildInfo`", t, func() {
		info := BuildInfo{}
		for _, opfx := range []string{"/", "--"} {
			Convey(fmt.Sprintf("WHEN: option_prefix = \"%s\"", opfx), func() {
				info.variables = map[string]string{"option_prefix": opfx}
				Convey("AND WHEN: Call `AddDefine (\"FOO\")`", func() {
					info.AddDefines("FOO")
					expected := fmt.Sprintf("%sDFOO", opfx)
					Convey(fmt.Sprintf("THEN: info.defines should be [\"%s\"]", expected), func() {
						So(len(info.defines), ShouldEqual, 1)
						So(info.defines, ShouldContain, expected)
					})
					Convey("AND WHEN: Call `AddDefine (\"BAR=BAZ\")`", func() {
						info.AddDefines("BAR=BAZ")
						Convey(fmt.Sprintf("THEN: info.defines should be [\"%[1]sDFOO\", \"%[1]sDBAR=BAZ\"]", opfx), func() {
							So(len(info.defines), ShouldEqual, 2)
							So(info.defines[0], ShouldEqual, fmt.Sprintf("%sDFOO", opfx))
							So(info.defines[1], ShouldEqual, fmt.Sprintf("%sDBAR=BAZ", opfx))
						})
					})
				})
			})
		}
	})
}

func TestBuildInfo_MakeExecutablePath(t *testing.T) {
	Convey("GIVEN: A BuildInfo with .outputdir = \"/usr/local\"", t, func() {
		info := BuildInfo{variables: map[string]string{}, outputdir: "/usr/local"}
		Convey("WHEN: Call with \"TEST\"", func() {
			actual := filepath.ToSlash (info.MakeExecutablePath("TEST"))
			Convey("THEN: Should return \"/usr/local/TEST\"", func() {
				So(actual, ShouldEqual, "/usr/local/TEST")
			})
		})
		Convey("WHEN: Set \".THE-SUFFIX\" as ${execute_suffix}", func() {
			info.variables["execute_suffix"] = ".THE-SUFFIX"
			Convey("AND WHEN: Call with \"TEST\"", func() {
				actual := filepath.ToSlash (info.MakeExecutablePath("TEST"))
				Convey("THEN: Should return \"/usr/local/TEST.THE-SUFFIX\"", func() {
					So(actual, ShouldEqual, "/usr/local/TEST.THE-SUFFIX")
				})
			})
		})
	})
}
<|endoftext|>


<commit_before>package node

import (
	"context"
	"fmt"

	"google.golang.org/grpc/codes"

	"google.golang.org/grpc"

	"github.com/n0stack/n0stack/n0proto.go/pool/v0"
	"github.com/pkg/errors"
)

// TODO: APIを叩く回数を減らす
type NodeConnections struct {
	NodeAPI ppool.NodeServiceClient
}

// func NewNodeConnections(api string) (*NodeConnections, error) {
// 	conn, err := grpc.Dial(api, grpc.WithInsecure())
// 	if err != nil {
// 		return nil, fmt.Errorf("Fail to dial to node, err:%v", err.Error())
// 	}

// 	nc := &NodeConnections{
// 		NodeAPI: ppool.NewNodeServiceClient(conn),
// 	}

// 	return nc, nil
// }

func (nc NodeConnections) IsExisting(nodeName string) (bool, error) {
	_, err := nc.NodeAPI.GetNode(context.Background(), &ppool.GetNodeRequest{Name: nodeName})
	if err != nil {
		if grpc.Code(err) == codes.NotFound {
			return false, nil
		}

		return false, errors.Wrap(err, "Failed to get node from API")
	}

	return true, nil
}

// GetConnection return a connection to Node having name of arguments.
func (nc NodeConnections) GetConnection(nodeName string) (*grpc.ClientConn, error) {
	n, err := nc.NodeAPI.GetNode(context.Background(), &ppool.GetNodeRequest{Name: nodeName})
	if err != nil {
		return nil, errors.Wrap(err, "Failed to get node from API")
	}

	if n.State == ppool.Node_NotReady {
		return nil, nil
	}

	// port を何かから取れるようにする
	conn, err := grpc.Dial(fmt.Sprintf("%s:%d", n.Address, 20181), grpc.WithInsecure())
	if err != nil {
		return nil, errors.Wrap(err, "Fail to dial to node")
	}

	return conn, nil
}
<commit_msg>fix small test<commit_after>package node

import (
	"context"
	"fmt"

	"google.golang.org/grpc/codes"

	"google.golang.org/grpc"

	"github.com/n0stack/n0stack/n0proto.go/pool/v0"
	"github.com/pkg/errors"
)

// TODO: APIを叩く回数を減らす
type NodeConnections struct {
	NodeAPI ppool.NodeServiceClient
}

// func NewNodeConnections(api string) (*NodeConnections, error) {
// 	conn, err := grpc.Dial(api, grpc.WithInsecure())
// 	if err != nil {
// 		return nil, fmt.Errorf("Fail to dial to node, err:%v", err.Error())
// 	}

// 	nc := &NodeConnections{
// 		NodeAPI: ppool.NewNodeServiceClient(conn),
// 	}

// 	return nc, nil
// }

func (nc NodeConnections) IsExisting(nodeName string) (bool, error) {
	_, err := nc.NodeAPI.GetNode(context.Background(), &ppool.GetNodeRequest{Name: nodeName})
	if err != nil {
		if grpc.Code(err) == codes.NotFound {
			return false, nil
		}

		return false, errors.Wrap(err, "Failed to get node from API")
	}

	return true, nil
}

// GetConnection return a connection to Node having name of arguments.
func (nc NodeConnections) GetConnection(nodeName string) (*grpc.ClientConn, error) {
	n, err := nc.NodeAPI.GetNode(context.Background(), &ppool.GetNodeRequest{Name: nodeName})
	if err != nil {
		return nil, errors.Wrap(err, "Failed to get node from API")
	}

	if n.State == ppool.Node_NotReady {
		return nil, nil
	}

	// port を何かから取れるようにする
	conn, err := grpc.Dial(fmt.Sprintf("%s:%d", n.Address, 20181), grpc.WithInsecure())
	if err != nil {
		return nil, errors.Wrap(err, "Fail to dial to node")
	}

	return conn, nil
}

func GetConnection(ctx context.Context, api ppool.NodeServiceClient, nodeName string) (*grpc.ClientConn, error) {
	n, err := api.GetNode(ctx, &ppool.GetNodeRequest{Name: nodeName})
	if err != nil {
		return nil, errors.Wrap(err, "Failed to get node from API")
	}

	if n.State != ppool.Node_Ready {
		return nil, nil
	}

	// port を何かから取れるようにする
	conn, err := grpc.Dial(fmt.Sprintf("%s:%d", n.Address, 20181), grpc.WithInsecure())
	if err != nil {
		return nil, errors.Wrap(err, "Fail to dial to node")
	}

	return conn, nil
}
<|endoftext|>


<commit_before>// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.

package gtrace_test

import (
	"context"
	"github.com/gogf/gf/net/gtrace"
	"github.com/gogf/gf/test/gtest"
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/oteltest"
	"go.opentelemetry.io/otel/trace"
	"testing"
)

const (
	traceIDStr = "4bf92f3577b34da6a3ce929d0e0e4736"
	spanIDStr  = "00f067aa0ba902b7"
)

var (
	traceID = mustTraceIDFromHex(traceIDStr)
	spanID  = mustSpanIDFromHex(spanIDStr)
)

func mustTraceIDFromHex(s string) (t trace.TraceID) {
	var err error
	t, err = trace.TraceIDFromHex(s)
	if err != nil {
		panic(err)
	}
	return
}

func mustSpanIDFromHex(s string) (t trace.SpanID) {
	var err error
	t, err = trace.SpanIDFromHex(s)
	if err != nil {
		panic(err)
	}
	return
}

func TestNewCarrier(t *testing.T) {
	gtest.C(t, func(t *gtest.T) {
		ctx := trace.ContextWithRemoteSpanContext(context.Background(), trace.NewSpanContext(trace.SpanContextConfig{
			TraceID:    traceID,
			SpanID:     spanID,
			TraceFlags: trace.FlagsSampled,
		}))
		ctx, _ = oteltest.DefaultTracer().Start(ctx, "inject")
		carrier1 := gtrace.NewCarrier()
		otel.GetTextMapPropagator().Inject(ctx, carrier1)
		t.Assert(carrier1.String(), `{"traceparent":"00-4bf92f3577b34da6a3ce929d0e0e4736-0000000000000002-01","tracestate":""}`)

		ctx = otel.GetTextMapPropagator().Extract(ctx, carrier1)
		gotSc := trace.SpanContextFromContext(ctx)
		t.Assert(gotSc.TraceID().String(), traceID.String())
		t.Assert(gotSc.SpanID().String(), "0000000000000002")
	})
}
<commit_msg>fix unit testing case for package gtrace<commit_after>// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.

package gtrace_test

import (
	"context"
	"github.com/gogf/gf/net/gtrace"
	"github.com/gogf/gf/test/gtest"
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/oteltest"
	"go.opentelemetry.io/otel/trace"
	"testing"
)

const (
	traceIDStr = "4bf92f3577b34da6a3ce929d0e0e4736"
	spanIDStr  = "00f067aa0ba902b7"
)

var (
	traceID = mustTraceIDFromHex(traceIDStr)
	spanID  = mustSpanIDFromHex(spanIDStr)
)

func mustTraceIDFromHex(s string) (t trace.TraceID) {
	var err error
	t, err = trace.TraceIDFromHex(s)
	if err != nil {
		panic(err)
	}
	return
}

func mustSpanIDFromHex(s string) (t trace.SpanID) {
	var err error
	t, err = trace.SpanIDFromHex(s)
	if err != nil {
		panic(err)
	}
	return
}

func TestNewCarrier(t *testing.T) {
	gtest.C(t, func(t *gtest.T) {
		ctx := trace.ContextWithRemoteSpanContext(context.Background(), trace.NewSpanContext(trace.SpanContextConfig{
			TraceID:    traceID,
			SpanID:     spanID,
			TraceFlags: trace.FlagsSampled,
		}))
		ctx, _ = oteltest.DefaultTracer().Start(ctx, "inject")
		carrier1 := gtrace.NewCarrier()
		otel.GetTextMapPropagator().Inject(ctx, carrier1)
		t.Assert(carrier1.String(), `{"traceparent":"00-4bf92f3577b34da6a3ce929d0e0e4736-0000000000000002-01"}`)

		ctx = otel.GetTextMapPropagator().Extract(ctx, carrier1)
		gotSc := trace.SpanContextFromContext(ctx)
		t.Assert(gotSc.TraceID().String(), traceID.String())
		t.Assert(gotSc.SpanID().String(), "0000000000000002")
	})
}
<|endoftext|>


<commit_before>package vorbis

import "sort"

type floor1 struct {
	partitionClassList []uint8
	classes            []floor1Class
	multiplier         uint8
	rangebits          uint8
	xList              []uint32
	sort               []uint32

	step2  []bool
	finalY []uint32
}

type floor1Class struct {
	dimension     uint8
	subclass      uint8
	masterbook    uint8
	subclassBooks []uint8
}

func (f *floor1) ReadFrom(r *bitReader) error {
	f.partitionClassList = make([]uint8, r.Read8(5))
	var maximumClass uint8
	for i := range f.partitionClassList {
		class := r.Read8(4)
		f.partitionClassList[i] = class
		if class > maximumClass {
			maximumClass = class
		}
	}

	f.classes = make([]floor1Class, maximumClass+1)
	for i := range f.classes {
		class := &f.classes[i]
		class.dimension = r.Read8(3) + 1
		class.subclass = r.Read8(2)
		if class.subclass != 0 {
			class.masterbook = r.Read8(8)
		}
		class.subclassBooks = make([]uint8, 1<<class.subclass)
		for i := range class.subclassBooks {
			class.subclassBooks[i] = r.Read8(8) - 1
		}
	}

	f.multiplier = r.Read8(2) + 1
	f.rangebits = r.Read8(4)
	f.xList = append(f.xList, 0, 1<<f.rangebits)
	for _, class := range f.partitionClassList {
		for i := uint8(0); i < f.classes[class].dimension; i++ {
			f.xList = append(f.xList, r.Read32(uint(f.rangebits)))
		}
	}

	f.sort = make([]uint32, len(f.xList))
	for i := range f.sort {
		f.sort[i] = uint32(i)
	}
	sort.Sort(f)

	f.step2 = make([]bool, len(f.xList))
	f.finalY = make([]uint32, len(f.xList))
	return nil
}

func (f *floor1) Decode(r *bitReader, books []codebook, n uint32) interface{} {
	if !r.ReadBool() {
		return nil
	}

	range_ := [4]uint32{256, 128, 86, 64}[f.multiplier-1]
	y := make([]uint32, 0, len(f.xList))
	y = append(y, r.Read32(ilog(int(range_)-1)), r.Read32(ilog(int(range_)-1)))
	for _, classIndex := range f.partitionClassList {
		class := f.classes[classIndex]
		cdim := class.dimension
		cbits := class.subclass
		csub := (uint32(1) << cbits) - 1
		cval := uint32(0)
		if cbits > 0 {
			cval = books[class.masterbook].DecodeScalar(r)
		}
		for j := 0; j < int(cdim); j++ {
			book := class.subclassBooks[cval&csub]
			cval >>= cbits
			if book != 0xFF {
				y = append(y, books[book].DecodeScalar(r))
			} else {
				y = append(y, 0)
			}
		}
	}
	return y
}

func (f *floor1) Apply(out []float32, data interface{}) {
	y := data.([]uint32)
	n := uint32(len(out))
	range_ := [4]uint32{256, 128, 86, 64}[f.multiplier-1]

	f.step2[0], f.step2[1] = true, true
	f.finalY[0], f.finalY[1] = y[0], y[1]

	for i := 2; i < len(f.xList); i++ {
		low := lowNeighbor(f.xList, i)
		high := highNeighbor(f.xList, i)
		predicted := renderPoint(f.xList[low], f.finalY[low], f.xList[high], f.finalY[high], f.xList[i])
		val := y[i]

		highRoom := range_ - predicted
		lowRoom := predicted
		var room uint32
		if highRoom < lowRoom {
			room = highRoom * 2
		} else {
			room = lowRoom * 2
		}

		if val == 0 {
			f.step2[i] = false
			f.finalY[i] = predicted
		} else {
			f.step2[low] = true
			f.step2[high] = true
			f.step2[i] = true
			if val >= room {
				if highRoom > lowRoom {
					f.finalY[i] = val - lowRoom + predicted
				} else {
					f.finalY[i] = predicted - val + highRoom - 1
				}
			} else {
				if val%2 == 1 {
					f.finalY[i] = predicted - (val+1)/2
				} else {
					f.finalY[i] = predicted + val/2
				}
			}
		}
	}

	var hx, lx uint32
	ly := f.finalY[0] * uint32(f.multiplier)

	var hy uint32
	for j := 1; j < len(f.finalY); j++ {
		i := f.sort[j]
		if f.step2[i] {
			hy = f.finalY[i] * uint32(f.multiplier)
			hx = f.xList[i]
			renderLine(lx, ly, hx, hy, out)
			lx = hx
			ly = hy
		}
	}

	if hx < n {
		for i := hx; i < n; i++ {
			out[i] *= inverseDBTable[hy]
		}
	}
}

func (f *floor1) Len() int {
	return len(f.xList)
}
func (f *floor1) Less(i, j int) bool {
	return f.xList[f.sort[i]] < f.xList[f.sort[j]]
}
func (f *floor1) Swap(i, j int) {
	f.sort[i], f.sort[j] = f.sort[j], f.sort[i]
}

func lowNeighbor(v []uint32, index int) int {
	val := v[index]
	best := 0
	max := val
	for i := 1; i < index; i++ {
		if v[i] >= val {
			continue
		}
		if v[i] > max || max == val {
			best = i
			max = v[i]
		}
	}
	return best
}
func highNeighbor(v []uint32, index int) int {
	val := v[index]
	best := 0
	min := val
	for i := 1; i < index; i++ {
		if v[i] <= val {
			continue
		}
		if v[i] < min || min == val {
			best = i
			min = v[i]
		}
	}
	return best
}

func renderPoint(x0, y0, x1, y1, x uint32) uint32 {
	dy := int(y1) - int(y0)
	adx := x1 - x0
	ady := y1 - y0
	if dy < 0 {
		ady = uint32(-dy)
	}
	err := ady * (x - x0)
	off := err / adx
	if dy < 0 {
		return y0 - off
	}
	return y0 + off
}

func renderLine(x0, y0, x1, y1 uint32, v []float32) {
	dy := int(y1) - int(y0)
	adx := x1 - x0
	ady := y1 - y0
	if dy < 0 {
		ady = uint32(-dy)
	}
	base := dy / int(adx)
	x := x0
	y := y0
	err := uint32(0)
	var sy int
	if dy < 0 {
		sy = base - 1
	} else {
		sy = base + 1
	}

	absBase := uint32(base)
	if base < 0 {
		absBase = uint32(-absBase)
	}
	ady = ady - absBase*adx

	v[x] *= inverseDBTable[y]
	for x := x0 + 1; x < x1; x++ {
		err += ady
		if err >= adx {
			err -= adx
			y = uint32(int(y) + sy)
		} else {
			y = uint32(int(y) + base)
		}
		v[x] *= inverseDBTable[y]
	}
}
<commit_msg>Refactor low/highNeighbor (#4)<commit_after>package vorbis

import "sort"

type floor1 struct {
	partitionClassList []uint8
	classes            []floor1Class
	multiplier         uint8
	rangebits          uint8
	xList              []uint32
	sort               []uint32

	step2  []bool
	finalY []uint32
}

type floor1Class struct {
	dimension     uint8
	subclass      uint8
	masterbook    uint8
	subclassBooks []uint8
}

func (f *floor1) ReadFrom(r *bitReader) error {
	f.partitionClassList = make([]uint8, r.Read8(5))
	var maximumClass uint8
	for i := range f.partitionClassList {
		class := r.Read8(4)
		f.partitionClassList[i] = class
		if class > maximumClass {
			maximumClass = class
		}
	}

	f.classes = make([]floor1Class, maximumClass+1)
	for i := range f.classes {
		class := &f.classes[i]
		class.dimension = r.Read8(3) + 1
		class.subclass = r.Read8(2)
		if class.subclass != 0 {
			class.masterbook = r.Read8(8)
		}
		class.subclassBooks = make([]uint8, 1<<class.subclass)
		for i := range class.subclassBooks {
			class.subclassBooks[i] = r.Read8(8) - 1
		}
	}

	f.multiplier = r.Read8(2) + 1
	f.rangebits = r.Read8(4)
	f.xList = append(f.xList, 0, 1<<f.rangebits)
	for _, class := range f.partitionClassList {
		for i := uint8(0); i < f.classes[class].dimension; i++ {
			f.xList = append(f.xList, r.Read32(uint(f.rangebits)))
		}
	}

	f.sort = make([]uint32, len(f.xList))
	for i := range f.sort {
		f.sort[i] = uint32(i)
	}
	sort.Sort(f)

	f.step2 = make([]bool, len(f.xList))
	f.finalY = make([]uint32, len(f.xList))
	return nil
}

func (f *floor1) Decode(r *bitReader, books []codebook, n uint32) interface{} {
	if !r.ReadBool() {
		return nil
	}

	range_ := [4]uint32{256, 128, 86, 64}[f.multiplier-1]
	y := make([]uint32, 0, len(f.xList))
	y = append(y, r.Read32(ilog(int(range_)-1)), r.Read32(ilog(int(range_)-1)))
	for _, classIndex := range f.partitionClassList {
		class := f.classes[classIndex]
		cdim := class.dimension
		cbits := class.subclass
		csub := (uint32(1) << cbits) - 1
		cval := uint32(0)
		if cbits > 0 {
			cval = books[class.masterbook].DecodeScalar(r)
		}
		for j := 0; j < int(cdim); j++ {
			book := class.subclassBooks[cval&csub]
			cval >>= cbits
			if book != 0xFF {
				y = append(y, books[book].DecodeScalar(r))
			} else {
				y = append(y, 0)
			}
		}
	}
	return y
}

func (f *floor1) Apply(out []float32, data interface{}) {
	y := data.([]uint32)
	n := uint32(len(out))
	range_ := [4]uint32{256, 128, 86, 64}[f.multiplier-1]

	f.step2[0], f.step2[1] = true, true
	f.finalY[0], f.finalY[1] = y[0], y[1]

	for i := 2; i < len(f.xList); i++ {
		low := lowNeighbor(f.xList, i)
		high := highNeighbor(f.xList, i)
		predicted := renderPoint(f.xList[low], f.finalY[low], f.xList[high], f.finalY[high], f.xList[i])
		val := y[i]

		highRoom := range_ - predicted
		lowRoom := predicted
		var room uint32
		if highRoom < lowRoom {
			room = highRoom * 2
		} else {
			room = lowRoom * 2
		}

		if val == 0 {
			f.step2[i] = false
			f.finalY[i] = predicted
		} else {
			f.step2[low] = true
			f.step2[high] = true
			f.step2[i] = true
			if val >= room {
				if highRoom > lowRoom {
					f.finalY[i] = val - lowRoom + predicted
				} else {
					f.finalY[i] = predicted - val + highRoom - 1
				}
			} else {
				if val%2 == 1 {
					f.finalY[i] = predicted - (val+1)/2
				} else {
					f.finalY[i] = predicted + val/2
				}
			}
		}
	}

	var hx, lx uint32
	ly := f.finalY[0] * uint32(f.multiplier)

	var hy uint32
	for j := 1; j < len(f.finalY); j++ {
		i := f.sort[j]
		if f.step2[i] {
			hy = f.finalY[i] * uint32(f.multiplier)
			hx = f.xList[i]
			renderLine(lx, ly, hx, hy, out)
			lx = hx
			ly = hy
		}
	}

	if hx < n {
		for i := hx; i < n; i++ {
			out[i] *= inverseDBTable[hy]
		}
	}
}

func (f *floor1) Len() int {
	return len(f.xList)
}
func (f *floor1) Less(i, j int) bool {
	return f.xList[f.sort[i]] < f.xList[f.sort[j]]
}
func (f *floor1) Swap(i, j int) {
	f.sort[i], f.sort[j] = f.sort[j], f.sort[i]
}

func lowNeighbor(v []uint32, index int) int {
	val := v[index]
	best := 0
	max := uint32(0)
	for i := 1; i < index; i++ {
		if v[i] >= val {
			continue
		}
		if v[i] > max {
			best = i
			max = v[i]
		}
	}
	return best
}
func highNeighbor(v []uint32, index int) int {
	val := v[index]
	best := 0
	min := uint32(0xffffffff)
	for i := 1; i < index; i++ {
		if v[i] <= val {
			continue
		}
		if v[i] < min {
			best = i
			min = v[i]
		}
	}
	return best
}

func renderPoint(x0, y0, x1, y1, x uint32) uint32 {
	dy := int(y1) - int(y0)
	adx := x1 - x0
	ady := y1 - y0
	if dy < 0 {
		ady = uint32(-dy)
	}
	err := ady * (x - x0)
	off := err / adx
	if dy < 0 {
		return y0 - off
	}
	return y0 + off
}

func renderLine(x0, y0, x1, y1 uint32, v []float32) {
	dy := int(y1) - int(y0)
	adx := x1 - x0
	ady := y1 - y0
	if dy < 0 {
		ady = uint32(-dy)
	}
	base := dy / int(adx)
	x := x0
	y := y0
	err := uint32(0)
	var sy int
	if dy < 0 {
		sy = base - 1
	} else {
		sy = base + 1
	}

	absBase := uint32(base)
	if base < 0 {
		absBase = uint32(-absBase)
	}
	ady -= absBase*adx

	v[x] *= inverseDBTable[y]
	for x := x0 + 1; x < x1; x++ {
		err += ady
		if err >= adx {
			err -= adx
			y = uint32(int(y) + sy)
		} else {
			y = uint32(int(y) + base)
		}
		v[x] *= inverseDBTable[y]
	}
}
<|endoftext|>


<commit_before>package transManager

import (
    "../queue"
    "../network"
    "net"
    "time"
    "fmt"
    "definitions"
)

func MessageTx(receiveChan chan Message) {

	storedChan := make(chan []byte)

	go network.Listen(network.GetListenSocket(), storedChan)
	go network.sendStatus(broadcastChan)

	for {
		RxMessageBs := <-receive
		RxMessage := Message{}
		err := json.Unmarshal(RxMessageBs, &RxMessage)
		if err != nil {
			fmt.Println("Error: ", err)
		}
		if RxMessage.SenderIP != GetLocalIP() {
			receiveChan <- RxMessage
		}
	}
}

func HeartbeatTx(newElevatorChan chan string, deadElevatorChan chan string) {

	storedChan := make(chan []byte, 1)
	heartbeats := make(map[string]*time.Time)
	go network.Listen(network.GetListenSocket(), storedChan)
	go network.sendHeartBeat()

	for {
		otherBeatBs := <-receive
		otherBeat := network.Heartbeat{}
		err := json.Unmarshal(otherBeatBs, &otherBeat)
		if err!= nil {
			fmt.Println("Error: ", err)
		}
		_, exist := heartbeats[otherBeat.Id]
		if exist {
			heartbeats[otherBeat.Id] = &otherBeat.Time
		} else {
			newElevatorChan <- otherBeat.Id
			heartbeats[otherBeat.Id] = &otherBeat.Time
		}
		for i, t := range heartbeats {
			dur := time.Since(*t)
			if dur.Seconds() > 1 {
				fmt.Println("Warning, time is running out: ", dur)
				deadElevatorChan <- i
				delete(heartbeats, i)
			}
		}
	}
}

func MessageReceiver(incommingMsgChan chan Message, orderOnSameFloorChan chan int, orderInEmptyQueueChan chan int) {
	for {
		message := <-incommingMsgChan
		switch message.MessageType {
		case "newOrder":
			i := addExternalOrder(message.TargetIP, message.Order)
			switch i {
			case "empty":
				orderInEmptyQueueChan <- message.Order.Floor
			case "sameFloor":
				orderOnSameFloorChan <- message.Order.Floor
			}
		case "newDirection":
			elevators[message.TargetIP].Direction = message.Order.Type
		case "newFloor":
			elevators[message.TargetIP].LastPassedFloor = message.Order.Floor
			elevators[message.TargetIP].InFloor = true
		case "completedOrder":
			OrderCompleted(message.Order.Floor, message.TargetIP)
		case "statusUpdate":
			if message.SenderIP != myIP {
				_, exist := elevators[message.TargetIP]
				if !exist {
					newElev := Elevator{true, true, 1, 0, []bool{false, false, false, false}, []bool{false, false, false, false}, []bool{false, false, false, false}}
					elevators[message.TargetIP] = &newElev
				}
				elevators[message.TargetIP].InFloor = message.Elevator.InFloor
				elevators[message.TargetIP].LastPassedFloor = message.Elevator.LastPassedFloor
				elevators[message.TargetIP].Direction = message.Elevator.Direction

				for floor := 0; floor < N_FLOORS; floor++ {
					elevators[message.TargetIP].UpOrders[floor] = elevators[message.TargetIP].UpOrders[floor] || message.Elevator.UpOrders[floor]
					elevators[message.TargetIP].DownOrders[floor] = elevators[message.TargetIP].DownOrders[floor] || message.Elevator.DownOrders[floor]
					elevators[message.TargetIP].CommandOrders[floor] = elevators[message.TargetIP].CommandOrders[floor] || message.Elevator.CommandOrders[floor]
				}
				orderInEmptyQueueChan <- 1
				lightUpdateChan <- 1
			}

		case "leftFloor":
			fmt.Printf("Heis %s har forlatt etasjen:\n", message.TargetIP)
			LeftFloor(message.TargetIP)
		}
	}
}

func HeartbeatReceiver(newElevatorChan chan string, deadElevatorChan chan string) {
	for {
		select {
		case IP := <-newElevatorChan:
			if IP != myIP {
				fmt.Printf("Det er dukket opp en ny heis me IP: %s\n", IP)
				_, exist := elevators[IP]
				if exist {
					elevators[IP].Active = true

					messageTransmitter("statusUpdate", myIP, Order{-1, -1})
					time.Sleep(1 * time.Millisecond)

					messageTransmitter("statusUpdate", IP, Order{-1, -1})
				} else {
					newElev := Elevator{true, true, 1, 0, []bool{false, false, false, false}, []bool{false, false, false, false}, []bool{false, false, false, false}}
					elevators[IP] = &newElev
					messageTransmitter("statusUpdate", myIP, Order{-1, -1})
				}
			}
		case IP := <-deadElevatorChan:
			elevators[IP].Active = false
			fmt.Printf("Det er fjernet en heis med IP: %s\n", IP)
		}
	}
}

func Init(){
	runtime.GOMAXPROCS(runtime.NumCPU()) //sets the number of cpu cores the program can use simultaneously.
	//sets it here to Numcpu which is the number of cores available.

	orderOnSameFloorChan := make(chan int)
	orderInEmptyQueueChan := make(chan int)

	newElevatorChan := make(chan string)
	deadElevatorChan := make(chan string)
	go HeartbeatTx(newElevatorChan, deadElevatorChan)
	go HeartbeatReceiver(newElevatorChan, deadElevatorChan)

	receiveChan := make(chan Message)
	go MessageTx(receiveChan)
    go queue.MessageReceiver(receiveChan, orderOnSameFloorChan, orderInEmptyQueueChan)

	time.Sleep(time.Second*5)
}<commit_msg>Updated network and transmanager<commit_after>package transManager

import (
    "../queue"
    "../network"
    "net"
    "time"
    "fmt"
    "definitions"
)

func messageTransmitter(msgType string, targetIP string, order Order) {
	newMessage := Message{
		msgType,
		myIP,
		targetIP,
		*(elevators[targetIP]),
		order,
	}
	network.BroadcastMessage(newMessage)
}

func MessageTRX(receiveChan chan Message) {

	storedChan := make(chan []byte)

	go network.Listen(network.GetListenSocket(), storedChan)
	go network.sendStatus(broadcastChan)

	for {
		RxMessageBs := <-receive
		RxMessage := Message{}
		err := json.Unmarshal(RxMessageBs, &RxMessage)
		if err != nil {
			fmt.Println("Error: ", err)
		}
		if RxMessage.SenderIP != network.GetLocalIP() {
			receiveChan <- RxMessage
		}
	}
}

func HeartbeatTRX(newElevatorChan chan string, deadElevatorChan chan string) {

	storedChan := make(chan []byte, 1)
	heartbeats := make(map[string]*time.Time)
	go network.Listen(network.GetListenSocket(), storedChan)
	go network.sendHeartBeat()

	for {
		otherBeatBs := <-receive
		otherBeat := Heartbeat{}
		err := json.Unmarshal(otherBeatBs, &otherBeat)
		if err!= nil {
			fmt.Println("Error: ", err)
		}
		_, exist := heartbeats[otherBeat.Id]
		if exist {
			heartbeats[otherBeat.Id] = &otherBeat.Time
		} else {
			newElevatorChan <- otherBeat.Id
			heartbeats[otherBeat.Id] = &otherBeat.Time
		}
		for i, t := range heartbeats {
			dur := time.Since(*t)
			if dur.Seconds() > 1 {
				fmt.Println("Warning, time is running out: ", dur)
				deadElevatorChan <- i
				delete(heartbeats, i)
			}
		}
	}
}

func MessageReceiver(incommingMsgChan chan Message, orderOnSameFloorChan chan int, orderInEmptyQueueChan chan int) {
	for {
		message := <-incommingMsgChan
		switch message.MessageType {
		case "newOrder":
			i := addExternalOrder(message.TargetIP, message.Order)
			switch i {
			case "empty":
				orderInEmptyQueueChan <- message.Order.Floor
			case "sameFloor":
				orderOnSameFloorChan <- message.Order.Floor
			}
		case "newDirection":
			elevators[message.TargetIP].Direction = message.Order.Type
		case "newFloor":
			elevators[message.TargetIP].LastPassedFloor = message.Order.Floor
			elevators[message.TargetIP].InFloor = true
		case "completedOrder":
			queue.OrderCompleted(message.Order.Floor, message.TargetIP)
		case "statusUpdate":
			if message.SenderIP != network.GetLocalIP( {
				_, exist := elevators[message.TargetIP]
				if !exist {
					newElev := Elevator{true, true, 1, 0, []bool{false, false, false, false}, []bool{false, false, false, false}, []bool{false, false, false, false}}
					elevators[message.TargetIP] = &newElev
				}
				elevators[message.TargetIP].InFloor = message.Elevator.InFloor
				elevators[message.TargetIP].LastPassedFloor = message.Elevator.LastPassedFloor
				elevators[message.TargetIP].Direction = message.Elevator.Direction

				for floor := 0; floor < N_FLOORS; floor++ {
					elevators[message.TargetIP].UpOrders[floor] = elevators[message.TargetIP].UpOrders[floor] || message.Elevator.UpOrders[floor]
					elevators[message.TargetIP].DownOrders[floor] = elevators[message.TargetIP].DownOrders[floor] || message.Elevator.DownOrders[floor]
					elevators[message.TargetIP].CommandOrders[floor] = elevators[message.TargetIP].CommandOrders[floor] || message.Elevator.CommandOrders[floor]
				}
				queue.orderInEmptyQueueChan <- 1
				queue.lightUpdateChan <- 1
			}

		case "leftFloor":
			fmt.Printf("Heis %s har forlatt etasjen:\n", message.TargetIP)
			queue.LeftFloor(message.TargetIP)
		}
	}
}

func HeartbeatReceiver(newElevatorChan chan string, deadElevatorChan chan string) {
	for {
		select {
		case IP := <-newElevatorChan:
			if IP != network.GetLocalIP( {
				fmt.Printf("Det er dukket opp en ny heis me IP: %s\n", IP)
				_, exist := elevators[IP]
				if exist {
					elevators[IP].Active = true

					messageTransmitter("statusUpdate", myIP, Order{-1, -1})
					time.Sleep(1 * time.Millisecond)

					messageTransmitter("statusUpdate", IP, Order{-1, -1})
				} else {
					newElev := Elevator{true, true, 1, 0, []bool{false, false, false, false}, []bool{false, false, false, false}, []bool{false, false, false, false}}
					elevators[IP] = &newElev
					messageTransmitter("statusUpdate", myIP, Order{-1, -1})
				}
			}
		case IP := <-deadElevatorChan:
			elevators[IP].Active = false
			fmt.Printf("Det er fjernet en heis med IP: %s\n", IP)
		}
	}
}

func Init(){
	runtime.GOMAXPROCS(runtime.NumCPU()) //sets the number of cpu cores the program can use simultaneously.
	//sets it here to Numcpu which is the number of cores available.

	orderOnSameFloorChan := make(chan int)
	orderInEmptyQueueChan := make(chan int)

	newElevatorChan := make(chan string)
	deadElevatorChan := make(chan string)
	go HeartbeatTRX(newElevatorChan, deadElevatorChan)
	go HeartbeatReceiver(newElevatorChan, deadElevatorChan)

	receiveChan := make(chan Message)
	go MessageTRX(receiveChan)
    go queue.MessageReceiver(receiveChan, orderOnSameFloorChan, orderInEmptyQueueChan)

	time.Sleep(time.Second*5)
}<|endoftext|>


<commit_before>// Copyright 2016 PLUMgrid
//
// 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 bcc

import (
	"bytes"
	"fmt"
	"regexp"
	"runtime"
	"sync"
	"syscall"
	"unsafe"
)

/*
#cgo CFLAGS: -I/usr/include/bcc/compat
#cgo LDFLAGS: -lbcc
#include <bcc/bpf_common.h>
#include <bcc/libbpf.h>
void perf_reader_free(void *ptr);
*/
import "C"

// Module type
type Module struct {
	p       unsafe.Pointer
	funcs   map[string]int
	kprobes map[string]unsafe.Pointer
}

type compileRequest struct {
	code   string
	cflags []string
	rspCh  chan *Module
}

var (
	defaultCflags []string
	compileCh     chan compileRequest
	bpfInitOnce   sync.Once
)

func bpfInit() {
	defaultCflags = []string{
		fmt.Sprintf("-DNUMCPUS=%d", runtime.NumCPU()),
	}
	compileCh = make(chan compileRequest)
	go compile()
}

// NewModule constructor
func newModule(code string, cflags []string) *Module {
	cflagsC := make([]*C.char, len(defaultCflags)+len(cflags))
	defer func() {
		for _, cflag := range cflagsC {
			C.free(unsafe.Pointer(cflag))
		}
	}()
	for i, cflag := range cflags {
		cflagsC[i] = C.CString(cflag)
	}
	for i, cflag := range defaultCflags {
		cflagsC[len(cflags)+i] = C.CString(cflag)
	}
	cs := C.CString(code)
	defer C.free(unsafe.Pointer(cs))
	c := C.bpf_module_create_c_from_string(cs, 2, (**C.char)(&cflagsC[0]), C.int(len(cflagsC)))
	if c == nil {
		return nil
	}
	return &Module{
		p:       c,
		funcs:   make(map[string]int),
		kprobes: make(map[string]unsafe.Pointer),
	}
}

// NewModule asynchronously compiles the code, generates a new BPF
// module and returns it.
func NewModule(code string, cflags []string) *Module {
	bpfInitOnce.Do(bpfInit)
	ch := make(chan *Module)
	compileCh <- compileRequest{code, cflags, ch}
	return <-ch
}

func compile() {
	for {
		req := <-compileCh
		req.rspCh <- newModule(req.code, req.cflags)
	}
}

// Close takes care of closing all kprobes opened by this modules and
// destroys the underlying libbpf module.
func (bpf *Module) Close() {
	C.bpf_module_destroy(bpf.p)
	for k, v := range bpf.kprobes {
		C.perf_reader_free(v)
		desc := fmt.Sprintf("-:kprobes/%s", k)
		descCS := C.CString(desc)
		C.bpf_detach_kprobe(descCS)
		C.free(unsafe.Pointer(descCS))
	}
	for _, fd := range bpf.funcs {
		syscall.Close(fd)
	}
}

// LoadNet loads a program of type BPF_PROG_TYPE_SCHED_ACT.
func (bpf *Module) LoadNet(name string) (int, error) {
	return bpf.Load(name, C.BPF_PROG_TYPE_SCHED_ACT)
}

// LoadKprobe loads a program of type BPF_PROG_TYPE_KPROBE.
func (bpf *Module) LoadKprobe(name string) (int, error) {
	return bpf.Load(name, C.BPF_PROG_TYPE_KPROBE)
}

// Load a program.
func (bpf *Module) Load(name string, progType int) (int, error) {
	fd, ok := bpf.funcs[name]
	if ok {
		return fd, nil
	}
	fd, err := bpf.load(name, progType)
	if err != nil {
		return -1, err
	}
	bpf.funcs[name] = fd
	return fd, nil
}

func (bpf *Module) load(name string, progType int) (int, error) {
	nameCS := C.CString(name)
	defer C.free(unsafe.Pointer(nameCS))
	start := (*C.struct_bpf_insn)(C.bpf_function_start(bpf.p, nameCS))
	size := C.int(C.bpf_function_size(bpf.p, nameCS))
	license := C.bpf_module_license(bpf.p)
	version := C.bpf_module_kern_version(bpf.p)
	if start == nil {
		return -1, fmt.Errorf("Module: unable to find %s", name)
	}
	logbuf := make([]byte, 65536)
	logbufP := (*C.char)(unsafe.Pointer(&logbuf[0]))
	fd := C.bpf_prog_load(uint32(progType), start, size, license, version, logbufP, C.uint(len(logbuf)))
	if fd < 0 {
		msg := string(logbuf[:bytes.IndexByte(logbuf, 0)])
		return -1, fmt.Errorf("Error loading bpf program:\n%s", msg)
	}
	return int(fd), nil
}

var kprobeRegexp = regexp.MustCompile("[+.]")

func (bpf *Module) attachProbe(evName, desc string, fd int) error {
	if _, ok := bpf.kprobes[evName]; ok {
		return nil
	}

	evNameCS := C.CString(evName)
	descCS := C.CString(desc)
	res := C.bpf_attach_kprobe(C.int(fd), evNameCS, descCS, -1, 0, -1, nil, nil)
	C.free(unsafe.Pointer(evNameCS))
	C.free(unsafe.Pointer(descCS))

	if res == nil {
		return fmt.Errorf("Failed to attach BPF kprobe")
	}
	bpf.kprobes[evName] = res
	return nil
}

// AttachKprobe attaches a kprobe fd to an event.
func (bpf *Module) AttachKprobe(event string, fd int) error {
	evName := "p_" + kprobeRegexp.ReplaceAllString(event, "_")
	desc := fmt.Sprintf("p:kprobes/%s %s", evName, event)

	return bpf.attachProbe(evName, desc, fd)
}

// AttachKretprobe attaches a kretprobe fd to an event.
func (bpf *Module) AttachKretprobe(event string, fd int) error {
	evName := "r_" + kprobeRegexp.ReplaceAllString(event, "_")
	desc := fmt.Sprintf("r:kprobes/%s %s", evName, event)

	return bpf.attachProbe(evName, desc, fd)
}

// TableSize returns the number of tables in the module.
func (bpf *Module) TableSize() uint64 {
	size := C.bpf_num_tables(bpf.p)
	return uint64(size)
}

// TableId returns the id of a table.
func (bpf *Module) TableId(name string) C.size_t {
	cs := C.CString(name)
	defer C.free(unsafe.Pointer(cs))
	return C.bpf_table_id(bpf.p, cs)
}

// TableDesc returns a map with table properties (name, fd, ...).
func (bpf *Module) TableDesc(id uint64) map[string]interface{} {
	i := C.size_t(id)
	return map[string]interface{}{
		"name":      C.GoString(C.bpf_table_name(bpf.p, i)),
		"fd":        int(C.bpf_table_fd_id(bpf.p, i)),
		"key_size":  uint64(C.bpf_table_key_size_id(bpf.p, i)),
		"leaf_size": uint64(C.bpf_table_leaf_size_id(bpf.p, i)),
		"key_desc":  C.GoString(C.bpf_table_key_desc_id(bpf.p, i)),
		"leaf_desc": C.GoString(C.bpf_table_leaf_desc_id(bpf.p, i)),
	}
}

// TableIter returns a receveier channel to iterate over entries.
func (bpf *Module) TableIter() <-chan map[string]interface{} {
	ch := make(chan map[string]interface{})
	go func() {
		size := C.bpf_num_tables(bpf.p)
		for i := C.size_t(0); i < size; i++ {
			ch <- bpf.TableDesc(uint64(i))
		}
		close(ch)
	}()
	return ch
}
<commit_msg>bcc/module: update to new `bpf_attach_kprobe` sig<commit_after>// Copyright 2016 PLUMgrid
//
// 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 bcc

import (
	"bytes"
	"fmt"
	"regexp"
	"runtime"
	"sync"
	"syscall"
	"unsafe"
)

/*
#cgo CFLAGS: -I/usr/include/bcc/compat
#cgo LDFLAGS: -lbcc
#include <bcc/bpf_common.h>
#include <bcc/libbpf.h>
void perf_reader_free(void *ptr);
*/
import "C"

// Module type
type Module struct {
	p       unsafe.Pointer
	funcs   map[string]int
	kprobes map[string]unsafe.Pointer
}

type compileRequest struct {
	code   string
	cflags []string
	rspCh  chan *Module
}

const (
	BPF_PROBE_ENTRY = iota
	BPF_PROBE_RETURN
)

var (
	defaultCflags []string
	compileCh     chan compileRequest
	bpfInitOnce   sync.Once
)

func bpfInit() {
	defaultCflags = []string{
		fmt.Sprintf("-DNUMCPUS=%d", runtime.NumCPU()),
	}
	compileCh = make(chan compileRequest)
	go compile()
}

// NewModule constructor
func newModule(code string, cflags []string) *Module {
	cflagsC := make([]*C.char, len(defaultCflags)+len(cflags))
	defer func() {
		for _, cflag := range cflagsC {
			C.free(unsafe.Pointer(cflag))
		}
	}()
	for i, cflag := range cflags {
		cflagsC[i] = C.CString(cflag)
	}
	for i, cflag := range defaultCflags {
		cflagsC[len(cflags)+i] = C.CString(cflag)
	}
	cs := C.CString(code)
	defer C.free(unsafe.Pointer(cs))
	c := C.bpf_module_create_c_from_string(cs, 2, (**C.char)(&cflagsC[0]), C.int(len(cflagsC)))
	if c == nil {
		return nil
	}
	return &Module{
		p:       c,
		funcs:   make(map[string]int),
		kprobes: make(map[string]unsafe.Pointer),
	}
}

// NewModule asynchronously compiles the code, generates a new BPF
// module and returns it.
func NewModule(code string, cflags []string) *Module {
	bpfInitOnce.Do(bpfInit)
	ch := make(chan *Module)
	compileCh <- compileRequest{code, cflags, ch}
	return <-ch
}

func compile() {
	for {
		req := <-compileCh
		req.rspCh <- newModule(req.code, req.cflags)
	}
}

// Close takes care of closing all kprobes opened by this modules and
// destroys the underlying libbpf module.
func (bpf *Module) Close() {
	C.bpf_module_destroy(bpf.p)
	for k, v := range bpf.kprobes {
		C.perf_reader_free(v)
		desc := fmt.Sprintf("-:kprobes/%s", k)
		descCS := C.CString(desc)
		C.bpf_detach_kprobe(descCS)
		C.free(unsafe.Pointer(descCS))
	}
	for _, fd := range bpf.funcs {
		syscall.Close(fd)
	}
}

// LoadNet loads a program of type BPF_PROG_TYPE_SCHED_ACT.
func (bpf *Module) LoadNet(name string) (int, error) {
	return bpf.Load(name, C.BPF_PROG_TYPE_SCHED_ACT)
}

// LoadKprobe loads a program of type BPF_PROG_TYPE_KPROBE.
func (bpf *Module) LoadKprobe(name string) (int, error) {
	return bpf.Load(name, C.BPF_PROG_TYPE_KPROBE)
}

// Load a program.
func (bpf *Module) Load(name string, progType int) (int, error) {
	fd, ok := bpf.funcs[name]
	if ok {
		return fd, nil
	}
	fd, err := bpf.load(name, progType)
	if err != nil {
		return -1, err
	}
	bpf.funcs[name] = fd
	return fd, nil
}

func (bpf *Module) load(name string, progType int) (int, error) {
	nameCS := C.CString(name)
	defer C.free(unsafe.Pointer(nameCS))
	start := (*C.struct_bpf_insn)(C.bpf_function_start(bpf.p, nameCS))
	size := C.int(C.bpf_function_size(bpf.p, nameCS))
	license := C.bpf_module_license(bpf.p)
	version := C.bpf_module_kern_version(bpf.p)
	if start == nil {
		return -1, fmt.Errorf("Module: unable to find %s", name)
	}
	logbuf := make([]byte, 65536)
	logbufP := (*C.char)(unsafe.Pointer(&logbuf[0]))
	fd := C.bpf_prog_load(uint32(progType), start, size, license, version, logbufP, C.uint(len(logbuf)))
	if fd < 0 {
		msg := string(logbuf[:bytes.IndexByte(logbuf, 0)])
		return -1, fmt.Errorf("Error loading bpf program:\n%s", msg)
	}
	return int(fd), nil
}

var kprobeRegexp = regexp.MustCompile("[+.]")

func (bpf *Module) attachProbe(evName string, attachType uint32, fnName string, fd int) error {
	if _, ok := bpf.kprobes[evName]; ok {
		return nil
	}

	evNameCS := C.CString(evName)
	fnNameCS := C.CString(fnName)
	res := C.bpf_attach_kprobe(C.int(fd), attachType, evNameCS, fnNameCS, -1, 0, -1, nil, nil)
	C.free(unsafe.Pointer(evNameCS))
	C.free(unsafe.Pointer(fnNameCS))

	if res == nil {
		return fmt.Errorf("Failed to attach BPF kprobe")
	}
	bpf.kprobes[evName] = res
	return nil
}

// AttachKprobe attaches a kprobe fd to a function.
func (bpf *Module) AttachKprobe(fnName string, fd int) error {
	evName := "p_" + kprobeRegexp.ReplaceAllString(fnName, "_")

	return bpf.attachProbe(evName, BPF_PROBE_ENTRY, fnName, fd)
}

// AttachKretprobe attaches a kretprobe fd to a function.
func (bpf *Module) AttachKretprobe(fnName string, fd int) error {
	evName := "r_" + kprobeRegexp.ReplaceAllString(fnName, "_")

	return bpf.attachProbe(evName, BPF_PROBE_RETURN, fnName, fd)
}

// TableSize returns the number of tables in the module.
func (bpf *Module) TableSize() uint64 {
	size := C.bpf_num_tables(bpf.p)
	return uint64(size)
}

// TableId returns the id of a table.
func (bpf *Module) TableId(name string) C.size_t {
	cs := C.CString(name)
	defer C.free(unsafe.Pointer(cs))
	return C.bpf_table_id(bpf.p, cs)
}

// TableDesc returns a map with table properties (name, fd, ...).
func (bpf *Module) TableDesc(id uint64) map[string]interface{} {
	i := C.size_t(id)
	return map[string]interface{}{
		"name":      C.GoString(C.bpf_table_name(bpf.p, i)),
		"fd":        int(C.bpf_table_fd_id(bpf.p, i)),
		"key_size":  uint64(C.bpf_table_key_size_id(bpf.p, i)),
		"leaf_size": uint64(C.bpf_table_leaf_size_id(bpf.p, i)),
		"key_desc":  C.GoString(C.bpf_table_key_desc_id(bpf.p, i)),
		"leaf_desc": C.GoString(C.bpf_table_leaf_desc_id(bpf.p, i)),
	}
}

// TableIter returns a receveier channel to iterate over entries.
func (bpf *Module) TableIter() <-chan map[string]interface{} {
	ch := make(chan map[string]interface{})
	go func() {
		size := C.bpf_num_tables(bpf.p)
		for i := C.size_t(0); i < size; i++ {
			ch <- bpf.TableDesc(uint64(i))
		}
		close(ch)
	}()
	return ch
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"gnd.la/html"
	"go/printer"
	"go/token"
	"regexp"
)

var (
	commentRe          = regexp.MustCompile("//[^\n]+")
	multilineCommentRe = regexp.MustCompile("/\\*.*?\\*/")
)

func FormatNode(fset *token.FileSet, node interface{}) (string, error) {
	var buf bytes.Buffer
	if err := printer.Fprint(&buf, fset, node); err != nil {
		return "", err
	}
	escaped := html.Escape(buf.String())
	return FormatComments(escaped), nil
}

func FormatComments(text string) string {
	repl := func(s string) string {
		return "" + s + ""
	}
	return multilineCommentRe.ReplaceAllStringFunc(commentRe.ReplaceAllStringFunc(text, repl), repl)
}
<commit_msg>Don't use a closure to format comments<commit_after>package main

import (
	"bytes"
	"gnd.la/html"
	"go/printer"
	"go/token"
	"regexp"
)

var (
	commentRe          = regexp.MustCompile("//[^\n]+")
	multilineCommentRe = regexp.MustCompile("/\\*.*?\\*/")
)

func FormatNode(fset *token.FileSet, node interface{}) (string, error) {
	var buf bytes.Buffer
	if err := printer.Fprint(&buf, fset, node); err != nil {
		return "", err
	}
	escaped := html.Escape(buf.String())
	return FormatComments(escaped), nil
}

func commentRepl(text string) string {
	return "" + text + ""
}

func FormatComments(text string) string {
	return multilineCommentRe.ReplaceAllStringFunc(commentRe.ReplaceAllStringFunc(text, commentRepl), commentRepl)
}
<|endoftext|>


<commit_before>/*
Copyright 2014 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package transport

import (
	"net/http"
	"reflect"
	"strings"
	"testing"
)

type testRoundTripper struct {
	Request  *http.Request
	Response *http.Response
	Err      error
}

func (rt *testRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
	rt.Request = req
	return rt.Response, rt.Err
}

func TestBearerAuthRoundTripper(t *testing.T) {
	rt := &testRoundTripper{}
	req := &http.Request{}
	NewBearerAuthRoundTripper("test", rt).RoundTrip(req)
	if rt.Request == nil {
		t.Fatalf("unexpected nil request: %v", rt)
	}
	if rt.Request == req {
		t.Fatalf("round tripper should have copied request object: %#v", rt.Request)
	}
	if rt.Request.Header.Get("Authorization") != "Bearer test" {
		t.Errorf("unexpected authorization header: %#v", rt.Request)
	}
}

func TestBasicAuthRoundTripper(t *testing.T) {
	for n, tc := range map[string]struct {
		user string
		pass string
	}{
		"basic":   {user: "user", pass: "pass"},
		"no pass": {user: "user"},
	} {
		rt := &testRoundTripper{}
		req := &http.Request{}
		NewBasicAuthRoundTripper(tc.user, tc.pass, rt).RoundTrip(req)
		if rt.Request == nil {
			t.Fatalf("%s: unexpected nil request: %v", n, rt)
		}
		if rt.Request == req {
			t.Fatalf("%s: round tripper should have copied request object: %#v", n, rt.Request)
		}
		if user, pass, found := rt.Request.BasicAuth(); !found || user != tc.user || pass != tc.pass {
			t.Errorf("%s: unexpected authorization header: %#v", n, rt.Request)
		}
	}
}

func TestUserAgentRoundTripper(t *testing.T) {
	rt := &testRoundTripper{}
	req := &http.Request{
		Header: make(http.Header),
	}
	req.Header.Set("User-Agent", "other")
	NewUserAgentRoundTripper("test", rt).RoundTrip(req)
	if rt.Request == nil {
		t.Fatalf("unexpected nil request: %v", rt)
	}
	if rt.Request != req {
		t.Fatalf("round tripper should not have copied request object: %#v", rt.Request)
	}
	if rt.Request.Header.Get("User-Agent") != "other" {
		t.Errorf("unexpected user agent header: %#v", rt.Request)
	}

	req = &http.Request{}
	NewUserAgentRoundTripper("test", rt).RoundTrip(req)
	if rt.Request == nil {
		t.Fatalf("unexpected nil request: %v", rt)
	}
	if rt.Request == req {
		t.Fatalf("round tripper should have copied request object: %#v", rt.Request)
	}
	if rt.Request.Header.Get("User-Agent") != "test" {
		t.Errorf("unexpected user agent header: %#v", rt.Request)
	}
}

func TestImpersonationRoundTripper(t *testing.T) {
	tcs := []struct {
		name                string
		impersonationConfig ImpersonationConfig
		expected            map[string][]string
	}{
		{
			name: "all",
			impersonationConfig: ImpersonationConfig{
				UserName: "user",
				Groups:   []string{"one", "two"},
				Extra: map[string][]string{
					"first":  {"A", "a"},
					"second": {"B", "b"},
				},
			},
			expected: map[string][]string{
				ImpersonateUserHeader:                       {"user"},
				ImpersonateGroupHeader:                      {"one", "two"},
				ImpersonateUserExtraHeaderPrefix + "First":  {"A", "a"},
				ImpersonateUserExtraHeaderPrefix + "Second": {"B", "b"},
			},
		},
	}

	for _, tc := range tcs {
		rt := &testRoundTripper{}
		req := &http.Request{
			Header: make(http.Header),
		}
		NewImpersonatingRoundTripper(tc.impersonationConfig, rt).RoundTrip(req)

		for k, v := range rt.Request.Header {
			expected, ok := tc.expected[k]
			if !ok {
				t.Errorf("%v missing %v=%v", tc.name, k, v)
				continue
			}
			if !reflect.DeepEqual(expected, v) {
				t.Errorf("%v expected %v: %v, got %v", tc.name, k, expected, v)
			}
		}
		for k, v := range tc.expected {
			expected, ok := rt.Request.Header[k]
			if !ok {
				t.Errorf("%v missing %v=%v", tc.name, k, v)
				continue
			}
			if !reflect.DeepEqual(expected, v) {
				t.Errorf("%v expected %v: %v, got %v", tc.name, k, expected, v)
			}
		}
	}
}

func TestAuthProxyRoundTripper(t *testing.T) {
	for n, tc := range map[string]struct {
		username string
		groups   []string
		extra    map[string][]string
	}{
		"allfields": {
			username: "user",
			groups:   []string{"groupA", "groupB"},
			extra: map[string][]string{
				"one": {"alpha", "bravo"},
				"two": {"charlie", "delta"},
			},
		},
	} {
		rt := &testRoundTripper{}
		req := &http.Request{}
		NewAuthProxyRoundTripper(tc.username, tc.groups, tc.extra, rt).RoundTrip(req)
		if rt.Request == nil {
			t.Errorf("%s: unexpected nil request: %v", n, rt)
			continue
		}
		if rt.Request == req {
			t.Errorf("%s: round tripper should have copied request object: %#v", n, rt.Request)
			continue
		}

		actualUsernames, ok := rt.Request.Header["X-Remote-User"]
		if !ok {
			t.Errorf("%s missing value", n)
			continue
		}
		if e, a := []string{tc.username}, actualUsernames; !reflect.DeepEqual(e, a) {
			t.Errorf("%s expected %v, got %v", n, e, a)
			continue
		}
		actualGroups, ok := rt.Request.Header["X-Remote-Group"]
		if !ok {
			t.Errorf("%s missing value", n)
			continue
		}
		if e, a := tc.groups, actualGroups; !reflect.DeepEqual(e, a) {
			t.Errorf("%s expected %v, got %v", n, e, a)
			continue
		}

		actualExtra := map[string][]string{}
		for key, values := range rt.Request.Header {
			if strings.HasPrefix(strings.ToLower(key), strings.ToLower("X-Remote-Extra-")) {
				extraKey := strings.ToLower(key[len("X-Remote-Extra-"):])
				actualExtra[extraKey] = append(actualExtra[key], values...)
			}
		}
		if e, a := tc.extra, actualExtra; !reflect.DeepEqual(e, a) {
			t.Errorf("%s expected %v, got %v", n, e, a)
			continue
		}
	}
}
<commit_msg>c-go/transport: Add test for CacheRoundTripper<commit_after>/*
Copyright 2014 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package transport

import (
	"bytes"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"reflect"
	"strings"
	"testing"
)

type testRoundTripper struct {
	Request  *http.Request
	Response *http.Response
	Err      error
}

func (rt *testRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
	rt.Request = req
	return rt.Response, rt.Err
}

func TestBearerAuthRoundTripper(t *testing.T) {
	rt := &testRoundTripper{}
	req := &http.Request{}
	NewBearerAuthRoundTripper("test", rt).RoundTrip(req)
	if rt.Request == nil {
		t.Fatalf("unexpected nil request: %v", rt)
	}
	if rt.Request == req {
		t.Fatalf("round tripper should have copied request object: %#v", rt.Request)
	}
	if rt.Request.Header.Get("Authorization") != "Bearer test" {
		t.Errorf("unexpected authorization header: %#v", rt.Request)
	}
}

func TestBasicAuthRoundTripper(t *testing.T) {
	for n, tc := range map[string]struct {
		user string
		pass string
	}{
		"basic":   {user: "user", pass: "pass"},
		"no pass": {user: "user"},
	} {
		rt := &testRoundTripper{}
		req := &http.Request{}
		NewBasicAuthRoundTripper(tc.user, tc.pass, rt).RoundTrip(req)
		if rt.Request == nil {
			t.Fatalf("%s: unexpected nil request: %v", n, rt)
		}
		if rt.Request == req {
			t.Fatalf("%s: round tripper should have copied request object: %#v", n, rt.Request)
		}
		if user, pass, found := rt.Request.BasicAuth(); !found || user != tc.user || pass != tc.pass {
			t.Errorf("%s: unexpected authorization header: %#v", n, rt.Request)
		}
	}
}

func TestUserAgentRoundTripper(t *testing.T) {
	rt := &testRoundTripper{}
	req := &http.Request{
		Header: make(http.Header),
	}
	req.Header.Set("User-Agent", "other")
	NewUserAgentRoundTripper("test", rt).RoundTrip(req)
	if rt.Request == nil {
		t.Fatalf("unexpected nil request: %v", rt)
	}
	if rt.Request != req {
		t.Fatalf("round tripper should not have copied request object: %#v", rt.Request)
	}
	if rt.Request.Header.Get("User-Agent") != "other" {
		t.Errorf("unexpected user agent header: %#v", rt.Request)
	}

	req = &http.Request{}
	NewUserAgentRoundTripper("test", rt).RoundTrip(req)
	if rt.Request == nil {
		t.Fatalf("unexpected nil request: %v", rt)
	}
	if rt.Request == req {
		t.Fatalf("round tripper should have copied request object: %#v", rt.Request)
	}
	if rt.Request.Header.Get("User-Agent") != "test" {
		t.Errorf("unexpected user agent header: %#v", rt.Request)
	}
}

func TestImpersonationRoundTripper(t *testing.T) {
	tcs := []struct {
		name                string
		impersonationConfig ImpersonationConfig
		expected            map[string][]string
	}{
		{
			name: "all",
			impersonationConfig: ImpersonationConfig{
				UserName: "user",
				Groups:   []string{"one", "two"},
				Extra: map[string][]string{
					"first":  {"A", "a"},
					"second": {"B", "b"},
				},
			},
			expected: map[string][]string{
				ImpersonateUserHeader:                       {"user"},
				ImpersonateGroupHeader:                      {"one", "two"},
				ImpersonateUserExtraHeaderPrefix + "First":  {"A", "a"},
				ImpersonateUserExtraHeaderPrefix + "Second": {"B", "b"},
			},
		},
	}

	for _, tc := range tcs {
		rt := &testRoundTripper{}
		req := &http.Request{
			Header: make(http.Header),
		}
		NewImpersonatingRoundTripper(tc.impersonationConfig, rt).RoundTrip(req)

		for k, v := range rt.Request.Header {
			expected, ok := tc.expected[k]
			if !ok {
				t.Errorf("%v missing %v=%v", tc.name, k, v)
				continue
			}
			if !reflect.DeepEqual(expected, v) {
				t.Errorf("%v expected %v: %v, got %v", tc.name, k, expected, v)
			}
		}
		for k, v := range tc.expected {
			expected, ok := rt.Request.Header[k]
			if !ok {
				t.Errorf("%v missing %v=%v", tc.name, k, v)
				continue
			}
			if !reflect.DeepEqual(expected, v) {
				t.Errorf("%v expected %v: %v, got %v", tc.name, k, expected, v)
			}
		}
	}
}

func TestAuthProxyRoundTripper(t *testing.T) {
	for n, tc := range map[string]struct {
		username string
		groups   []string
		extra    map[string][]string
	}{
		"allfields": {
			username: "user",
			groups:   []string{"groupA", "groupB"},
			extra: map[string][]string{
				"one": {"alpha", "bravo"},
				"two": {"charlie", "delta"},
			},
		},
	} {
		rt := &testRoundTripper{}
		req := &http.Request{}
		NewAuthProxyRoundTripper(tc.username, tc.groups, tc.extra, rt).RoundTrip(req)
		if rt.Request == nil {
			t.Errorf("%s: unexpected nil request: %v", n, rt)
			continue
		}
		if rt.Request == req {
			t.Errorf("%s: round tripper should have copied request object: %#v", n, rt.Request)
			continue
		}

		actualUsernames, ok := rt.Request.Header["X-Remote-User"]
		if !ok {
			t.Errorf("%s missing value", n)
			continue
		}
		if e, a := []string{tc.username}, actualUsernames; !reflect.DeepEqual(e, a) {
			t.Errorf("%s expected %v, got %v", n, e, a)
			continue
		}
		actualGroups, ok := rt.Request.Header["X-Remote-Group"]
		if !ok {
			t.Errorf("%s missing value", n)
			continue
		}
		if e, a := tc.groups, actualGroups; !reflect.DeepEqual(e, a) {
			t.Errorf("%s expected %v, got %v", n, e, a)
			continue
		}

		actualExtra := map[string][]string{}
		for key, values := range rt.Request.Header {
			if strings.HasPrefix(strings.ToLower(key), strings.ToLower("X-Remote-Extra-")) {
				extraKey := strings.ToLower(key[len("X-Remote-Extra-"):])
				actualExtra[extraKey] = append(actualExtra[key], values...)
			}
		}
		if e, a := tc.extra, actualExtra; !reflect.DeepEqual(e, a) {
			t.Errorf("%s expected %v, got %v", n, e, a)
			continue
		}
	}
}

func TestCacheRoundTripper(t *testing.T) {
	rt := &testRoundTripper{}
	cacheDir, err := ioutil.TempDir("", "cache-rt")
	defer os.RemoveAll(cacheDir)
	if err != nil {
		t.Fatal(err)
	}
	cache := NewCacheRoundTripper(cacheDir, rt)

	// First call, caches the response
	req := &http.Request{
		Method: http.MethodGet,
		URL:    &url.URL{Host: "localhost"},
	}
	rt.Response = &http.Response{
		Header:     http.Header{"ETag": []string{`"123456"`}},
		Body:       ioutil.NopCloser(bytes.NewReader([]byte("Content"))),
		StatusCode: http.StatusOK,
	}
	resp, err := cache.RoundTrip(req)
	if err != nil {
		t.Fatal(err)
	}
	content, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		t.Fatal(err)
	}
	if string(content) != "Content" {
		t.Errorf(`Expected Body to be "Content", got %q`, string(content))
	}

	// Second call, returns cached response
	req = &http.Request{
		Method: http.MethodGet,
		URL:    &url.URL{Host: "localhost"},
	}
	rt.Response = &http.Response{
		StatusCode: http.StatusNotModified,
		Body:       ioutil.NopCloser(bytes.NewReader([]byte("Other Content"))),
	}

	resp, err = cache.RoundTrip(req)
	if err != nil {
		t.Fatal(err)
	}

	// Read body and make sure we have the initial content
	content, err = ioutil.ReadAll(resp.Body)
	resp.Body.Close()
	if err != nil {
		t.Fatal(err)
	}
	if string(content) != "Content" {
		t.Errorf("Invalid content read from cache %q", string(content))
	}
}
<|endoftext|>