<commit_before>package corehttp

import (
	"net/http"
	"time"

	manners "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/braintree/manners"
	ma "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
	manet "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr-net"
	core "github.com/ipfs/go-ipfs/core"
	eventlog "github.com/ipfs/go-ipfs/thirdparty/eventlog"
)

var log = eventlog.Logger("core/server")

// ServeOption registers any HTTP handlers it provides on the given mux.
// It returns the mux to expose to future options, which may be a new mux if it
// is interested in mediating requests to future options, or the same mux
// initially passed in if not.
type ServeOption func(*core.IpfsNode, *http.ServeMux) (*http.ServeMux, error)

// makeHandler turns a list of ServeOptions into a http.Handler that implements
// all of the given options, in order.
func makeHandler(n *core.IpfsNode, options ...ServeOption) (http.Handler, error) {
	topMux := http.NewServeMux()
	mux := topMux
	for _, option := range options {
		var err error
		mux, err = option(n, mux)
		if err != nil {
			return nil, err
		}
	}
	return topMux, nil
}

// ListenAndServe runs an HTTP server listening at |listeningMultiAddr| with
// the given serve options. The address must be provided in multiaddr format.
//
// TODO intelligently parse address strings in other formats so long as they
// unambiguously map to a valid multiaddr. e.g. for convenience, ":8080" should
// map to "/ip4/0.0.0.0/tcp/8080".
func ListenAndServe(n *core.IpfsNode, listeningMultiAddr string, options ...ServeOption) error {
	addr, err := ma.NewMultiaddr(listeningMultiAddr)
	if err != nil {
		return err
	}
	handler, err := makeHandler(n, options...)
	if err != nil {
		return err
	}
	return listenAndServe(n, addr, handler)
}

func listenAndServe(node *core.IpfsNode, addr ma.Multiaddr, handler http.Handler) error {
	_, host, err := manet.DialArgs(addr)
	if err != nil {
		return err
	}

	server := manners.NewServer()

	// if the server exits beforehand
	var serverError error
	serverExited := make(chan struct{})

	node.Children().Add(1)
	defer node.Children().Done()

	go func() {
		serverError = server.ListenAndServe(host, handler)
		close(serverExited)
	}()

	// wait for server to exit.
	select {
	case <-serverExited:

	// if node being closed before server exits, close server
	case <-node.Closing():
		log.Infof("server at %s terminating...", addr)

		// make sure keep-alive connections do not keep the server running
		server.InnerServer.SetKeepAlivesEnabled(false)

		server.Shutdown <- true

	outer:
		for {
			// wait until server exits
			select {
			case <-serverExited:
				break outer
			case <-time.After(5 * time.Second):
				log.Infof("waiting for server at %s to terminate...", addr)
			}
		}
	}

	log.Infof("server at %s terminated", addr)
	return serverError
}
<commit_msg>core/corehttp/corehttp: Add a package comment<commit_after>/*
Package corehttp provides utilities for the webui, gateways, and other
high-level HTTP interfaces to IPFS.
*/
package corehttp

import (
	"net/http"
	"time"

	manners "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/braintree/manners"
	ma "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
	manet "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr-net"
	core "github.com/ipfs/go-ipfs/core"
	eventlog "github.com/ipfs/go-ipfs/thirdparty/eventlog"
)

var log = eventlog.Logger("core/server")

// ServeOption registers any HTTP handlers it provides on the given mux.
// It returns the mux to expose to future options, which may be a new mux if it
// is interested in mediating requests to future options, or the same mux
// initially passed in if not.
type ServeOption func(*core.IpfsNode, *http.ServeMux) (*http.ServeMux, error)

// makeHandler turns a list of ServeOptions into a http.Handler that implements
// all of the given options, in order.
func makeHandler(n *core.IpfsNode, options ...ServeOption) (http.Handler, error) {
	topMux := http.NewServeMux()
	mux := topMux
	for _, option := range options {
		var err error
		mux, err = option(n, mux)
		if err != nil {
			return nil, err
		}
	}
	return topMux, nil
}

// ListenAndServe runs an HTTP server listening at |listeningMultiAddr| with
// the given serve options. The address must be provided in multiaddr format.
//
// TODO intelligently parse address strings in other formats so long as they
// unambiguously map to a valid multiaddr. e.g. for convenience, ":8080" should
// map to "/ip4/0.0.0.0/tcp/8080".
func ListenAndServe(n *core.IpfsNode, listeningMultiAddr string, options ...ServeOption) error {
	addr, err := ma.NewMultiaddr(listeningMultiAddr)
	if err != nil {
		return err
	}
	handler, err := makeHandler(n, options...)
	if err != nil {
		return err
	}
	return listenAndServe(n, addr, handler)
}

func listenAndServe(node *core.IpfsNode, addr ma.Multiaddr, handler http.Handler) error {
	_, host, err := manet.DialArgs(addr)
	if err != nil {
		return err
	}

	server := manners.NewServer()

	// if the server exits beforehand
	var serverError error
	serverExited := make(chan struct{})

	node.Children().Add(1)
	defer node.Children().Done()

	go func() {
		serverError = server.ListenAndServe(host, handler)
		close(serverExited)
	}()

	// wait for server to exit.
	select {
	case <-serverExited:

	// if node being closed before server exits, close server
	case <-node.Closing():
		log.Infof("server at %s terminating...", addr)

		// make sure keep-alive connections do not keep the server running
		server.InnerServer.SetKeepAlivesEnabled(false)

		server.Shutdown <- true

	outer:
		for {
			// wait until server exits
			select {
			case <-serverExited:
				break outer
			case <-time.After(5 * time.Second):
				log.Infof("waiting for server at %s to terminate...", addr)
			}
		}
	}

	log.Infof("server at %s terminated", addr)
	return serverError
}
<|endoftext|>


<commit_before>// Copyright Microsoft Corp.
// All rights reserved.

package ebtables

import (
	"fmt"
	"os/exec"
)

// SetupSnatForOutgoingPackets sets up snat
func SetupSnatForOutgoingPackets(interfaceName string, snatAddress string) error {
	command := fmt.Sprintf("ebtables -t nat -A POSTROUTING -o %s -j snat --to-source %s --snat-arp", interfaceName, snatAddress)
	err := executeShellCommand(command)
	if err != nil {
		return err
	}
	return nil
}

// CleanupSnatForOutgoingPackets cleans up snat
func CleanupSnatForOutgoingPackets(interfaceName string, snatAddress string) error {
	command := fmt.Sprintf("ebtables -t nat -D POSTROUTING -o %s -j snat --to-source %s --snat-arp", interfaceName, snatAddress)
	err := executeShellCommand(command)
	if err != nil {
		return err
	}
	return nil
}

// SetupDnatForArpReplies sets up dnat
func SetupDnatForArpReplies(interfaceName string) error {
	command := fmt.Sprintf("ebtables -t nat -A PREROUTING -i %s -p arp -j dnat --to-destination ff:ff:ff:ff:ff:ff", interfaceName)
	err := executeShellCommand(command)
	if err != nil {
		return err
	}
	return nil
}

// CleanupDnatForArpReplies cleans up dnat
func CleanupDnatForArpReplies(interfaceName string) error {
	command := fmt.Sprintf("ebtables -t nat -D PREROUTING -i %s -p arp -j dnat --to-destination ff:ff:ff:ff:ff:ff", interfaceName)
	err := executeShellCommand(command)
	if err != nil {
		return err
	}
	return nil
}

// SetupDnatBasedOnIPV4Address sets up dnat
func SetupDnatBasedOnIPV4Address(ipv4Address string, macAddress string) error {
	command := fmt.Sprintf("ebtables -t nat -A PREROUTING -p IPv4  --ip-dst %s -j dnat --to-dst %s --dnat-target ACCEPT", ipv4Address, macAddress)
	err := executeShellCommand(command)
	if err != nil {
		return err
	}
	return nil
}

// RemoveDnatBasedOnIPV4Address cleans up dnat
func RemoveDnatBasedOnIPV4Address(ipv4Address string, macAddress string) error {
	command := fmt.Sprintf("ebtables -t nat -D PREROUTING -p IPv4  --ip-dst %s -j dnat --to-dst %s --dnat-target ACCEPT", ipv4Address, macAddress)
	err := executeShellCommand(command)
	if err != nil {
		return err
	}
	return nil
}

func executeShellCommand(command string) error {
	fmt.Println("going to execute: " + command)
	cmd := exec.Command("sh", "-c", command)
	err := cmd.Start()
	if err != nil {
		return err
	}
	return cmd.Wait()
}
<commit_msg>Added logs for ebtables<commit_after>// Copyright Microsoft Corp.
// All rights reserved.

package ebtables

import (
	"fmt"
	"os/exec"

	"github.com/Azure/Aqua/log"
)

// SetupSnatForOutgoingPackets sets up snat
func SetupSnatForOutgoingPackets(interfaceName string, snatAddress string) error {
	command := fmt.Sprintf("ebtables -t nat -A POSTROUTING -o %s -j snat --to-source %s --snat-arp", interfaceName, snatAddress)
	err := executeShellCommand(command)
	if err != nil {
		return err
	}
	return nil
}

// CleanupSnatForOutgoingPackets cleans up snat
func CleanupSnatForOutgoingPackets(interfaceName string, snatAddress string) error {
	command := fmt.Sprintf("ebtables -t nat -D POSTROUTING -o %s -j snat --to-source %s --snat-arp", interfaceName, snatAddress)
	err := executeShellCommand(command)
	if err != nil {
		return err
	}
	return nil
}

// SetupDnatForArpReplies sets up dnat
func SetupDnatForArpReplies(interfaceName string) error {
	command := fmt.Sprintf("ebtables -t nat -A PREROUTING -i %s -p arp -j dnat --to-destination ff:ff:ff:ff:ff:ff", interfaceName)
	err := executeShellCommand(command)
	if err != nil {
		return err
	}
	return nil
}

// CleanupDnatForArpReplies cleans up dnat
func CleanupDnatForArpReplies(interfaceName string) error {
	command := fmt.Sprintf("ebtables -t nat -D PREROUTING -i %s -p arp -j dnat --to-destination ff:ff:ff:ff:ff:ff", interfaceName)
	err := executeShellCommand(command)
	if err != nil {
		return err
	}
	return nil
}

// SetupDnatBasedOnIPV4Address sets up dnat
func SetupDnatBasedOnIPV4Address(ipv4Address string, macAddress string) error {
	command := fmt.Sprintf("ebtables -t nat -A PREROUTING -p IPv4  --ip-dst %s -j dnat --to-dst %s --dnat-target ACCEPT", ipv4Address, macAddress)
	err := executeShellCommand(command)
	if err != nil {
		return err
	}
	return nil
}

// RemoveDnatBasedOnIPV4Address cleans up dnat
func RemoveDnatBasedOnIPV4Address(ipv4Address string, macAddress string) error {
	command := fmt.Sprintf("ebtables -t nat -D PREROUTING -p IPv4  --ip-dst %s -j dnat --to-dst %s --dnat-target ACCEPT", ipv4Address, macAddress)
	err := executeShellCommand(command)
	if err != nil {
		return err
	}
	return nil
}

func executeShellCommand(command string) error {
	log.Printf("[ebtables] %s", command)
	cmd := exec.Command("sh", "-c", command)
	err := cmd.Start()
	if err != nil {
		return err
	}
	return cmd.Wait()
}
<|endoftext|>


<commit_before>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 builder

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"

	log "github.com/sirupsen/logrus"

	"mynewt.apache.org/newt/newt/interfaces"
	"mynewt.apache.org/newt/newt/project"
	"mynewt.apache.org/newt/newt/target"
	"mynewt.apache.org/newt/newt/toolchain"
	"mynewt.apache.org/newt/util"
)

const CMAKELISTS_FILENAME string = "CMakeLists.txt"

func CmakeListsPath() string {
	return project.GetProject().BasePath + "/" + CMAKELISTS_FILENAME
}

func EscapeName(name string) string {
	return strings.Replace(name, "/", "_", -1)
}

func replaceBackslashes(path string) string {
	return strings.Replace(path, "\\", "/", -1)
}

func replaceBackslashesSlice(elements []string) {
	for e := range elements {
		elements[e] = replaceBackslashes(elements[e])
	}
}

func escapeFlags(flag string) string {
	flag = strings.Replace(flag, "\"", "\\\\\\\"", -1)
	flag = strings.Replace(flag, "(", "\\\\(", -1)
	flag = strings.Replace(flag, ")", "\\\\)", -1)
	return flag
}

func escapeFlagsSlice(flags []string) []string {
	for f := range flags {
		flags[f] = escapeFlags(flags[f])
	}

	return flags
}

func trimProjectPath(path string) string {
	proj := interfaces.GetProject()
	path = strings.TrimPrefix(path, proj.Path()+"/")
	return path
}

func trimProjectPathSlice(elements []string) {
	for e := range elements {
		elements[e] = trimProjectPath(elements[e])
	}
}

func extractIncludes(flags *[]string, includes *[]string, other *[]string) {
	for _, f := range *flags {
		if strings.HasPrefix(f, "-I") {
			*includes = append(*includes, strings.TrimPrefix(f, "-I"))
		} else {
			*other = append(*other, f)
		}
	}
}

func CmakeSourceObjectWrite(w io.Writer, cj toolchain.CompilerJob,
	includeDirs *[]string, linkFlags *[]string) {
	c := cj.Compiler

	flags := []string{}
	otherFlags := []string{}

	switch cj.CompilerType {
	case toolchain.COMPILER_TYPE_C:
		flags = append(flags, c.GetCompilerInfo().Cflags...)
		flags = append(flags, c.GetLocalCompilerInfo().Cflags...)
	case toolchain.COMPILER_TYPE_ASM:
		flags = append(flags, c.GetCompilerInfo().Cflags...)
		flags = append(flags, c.GetLocalCompilerInfo().Cflags...)
		flags = append(flags, c.GetCompilerInfo().Aflags...)
		flags = append(flags, c.GetLocalCompilerInfo().Aflags...)
	case toolchain.COMPILER_TYPE_CPP:
		flags = append(flags, c.GetCompilerInfo().Cflags...)
		flags = append(flags, c.GetLocalCompilerInfo().Cflags...)
		flags = append(flags, c.GetCompilerInfo().CXXflags...)
		flags = append(flags, c.GetLocalCompilerInfo().CXXflags...)
	}

	*linkFlags = append(*linkFlags, c.GetCompilerInfo().Lflags...)
	*linkFlags = append(*linkFlags, c.GetLocalCompilerInfo().Lflags...)

	extractIncludes(&flags, includeDirs, &otherFlags)
	cj.Filename = trimProjectPath(cj.Filename)

	// Sort and remove duplicate flags
	otherFlags = util.SortFields(otherFlags...)

	fmt.Fprintf(w,
`set_property(SOURCE %s APPEND_STRING
             PROPERTY COMPILE_FLAGS
             "%s")`,
		cj.Filename,
		strings.Join(escapeFlagsSlice(otherFlags), " "))
	fmt.Fprintln(w)
}

func (b *Builder) CMakeBuildPackageWrite(w io.Writer, bpkg *BuildPackage,
	linkFlags *[]string) (*BuildPackage, error) {
	entries, err := b.collectCompileEntriesBpkg(bpkg)
	if err != nil {
		return nil, err
	}

	if len(entries) <= 0 {
		return nil, nil
	}

	otherIncludes := []string{}
	files := []string{}

	for _, s := range entries {
		filename := filepath.ToSlash(s.Filename)
		if s.Compiler.ShouldIgnoreFile(filename) {
			log.Infof("Ignoring %s because package dictates it.\n", filename)
			continue
		}

		CmakeSourceObjectWrite(w, s, &otherIncludes, linkFlags)
		s.Filename = trimProjectPath(s.Filename)
		files = append(files, s.Filename)
	}

	if len(files) <= 0 {
		return nil, nil
	}

	pkgName := bpkg.rpkg.Lpkg.Name()

	util.StatusMessage(util.VERBOSITY_DEFAULT, "Generating CMakeLists.txt for %s\n", pkgName)
	fmt.Fprintf(w, "\n# Generating CMakeLists.txt for %s\n", pkgName)
	fmt.Fprintf(w, "add_library(%s %s)\n\n",
		EscapeName(pkgName),
		strings.Join(files, " "))

	archivePath := replaceBackslashes(trimProjectPath(filepath.Dir(b.ArchivePath(bpkg))))
	CmakeCompilerInfoWrite(w, archivePath, bpkg, entries[0], otherIncludes)

	return bpkg, nil
}

func (b *Builder) CMakeTargetWrite(w io.Writer, targetCompiler *toolchain.Compiler) error {
	bpkgs := b.sortedBuildPackages()
	var compileFlags []string
	var linkFlags []string

	c := targetCompiler
	c.AddInfo(b.GetCompilerInfo())

	builtPackages := []*BuildPackage{}
	for _, bpkg := range bpkgs {
		builtPackage, err := b.CMakeBuildPackageWrite(w, bpkg, &linkFlags)
		if err != nil {
			return err
		}

		if builtPackage != nil {
			builtPackages = append(builtPackages, builtPackage)
		}
	}

	elfName := "cmake_" + filepath.Base(b.AppElfPath())
	fmt.Fprintf(w, "# Generating code for %s\n", elfName)

	var targetObjectsBuffer bytes.Buffer

	for _, bpkg := range builtPackages {
		targetObjectsBuffer.WriteString(fmt.Sprintf("%s ",
			EscapeName(bpkg.rpkg.Lpkg.Name())))
	}

	elfOutputDir := replaceBackslashes(trimProjectPath(filepath.Dir(b.AppElfPath())))
	fmt.Fprintf(w, "file(WRITE %s \"\")\n", replaceBackslashes(filepath.Join(elfOutputDir, "null.c")))
	fmt.Fprintf(w, "add_executable(%s %s)\n\n", elfName,
		replaceBackslashes(filepath.Join(elfOutputDir, "null.c")))

	if c.GetLdResolveCircularDeps() {
		fmt.Fprintf(w, "target_link_libraries(%s -Wl,--start-group %s -Wl,--end-group)\n",
			elfName, targetObjectsBuffer.String())
	} else {
		fmt.Fprintf(w, "target_link_libraries(%s %s)\n",
			elfName, targetObjectsBuffer.String())
	}

	compileFlags = append(compileFlags, c.GetCompilerInfo().Cflags...)
	compileFlags = append(compileFlags, c.GetLocalCompilerInfo().Cflags...)
	compileFlags = append(compileFlags, c.GetCompilerInfo().CXXflags...)
	compileFlags = append(compileFlags, c.GetLocalCompilerInfo().CXXflags...)
	compileFlags = util.SortFields(compileFlags...)

	fmt.Fprintf(w,
`set_property(TARGET %s APPEND_STRING
             PROPERTY
             COMPILE_FLAGS
             "%s")`,
		elfName,
		strings.Join(escapeFlagsSlice(compileFlags), " "))
	fmt.Fprintln(w)

	lFlags := append(c.GetCompilerInfo().Lflags, c.GetLocalCompilerInfo().Lflags...)
	lFlags = append(lFlags, linkFlags...)
	lFlags = util.SortFields(lFlags...)

	for _, ld := range c.LinkerScripts {
		lFlags = append(lFlags, "-T"+ld)
	}

	var cFlags []string
	cFlags = append(cFlags, c.GetCompilerInfo().Cflags...)
	cFlags = append(cFlags, c.GetLocalCompilerInfo().Cflags...)
	cFlags = util.SortFields(cFlags...)
	lFlags = append(lFlags, cFlags...)

	var cxxFlags []string
	cxxFlags = append(cxxFlags, c.GetCompilerInfo().CXXflags...)
	cxxFlags = append(cxxFlags, c.GetLocalCompilerInfo().CXXflags...)
	cxxFlags = util.SortFields(cxxFlags...)
	lFlags = append(lFlags, cxxFlags...)

	fmt.Fprintf(w,
`set_target_properties(%s
                      PROPERTIES
                      ARCHIVE_OUTPUT_DIRECTORY %s
                      LIBRARY_OUTPUT_DIRECTORY %s
                      RUNTIME_OUTPUT_DIRECTORY %s
                      LINK_FLAGS "%s"
                      LINKER_LANGUAGE C)`,
		elfName,
		elfOutputDir,
		elfOutputDir,
		elfOutputDir,
		strings.Join(escapeFlagsSlice(lFlags), " "))

	fmt.Fprintln(w)

	libs := strings.Join(getLibsFromLinkerFlags(lFlags), " ")
	fmt.Fprintf(w, "# Workaround for gcc linker woes\n")
	fmt.Fprintf(w, "set(CMAKE_C_LINK_EXECUTABLE \"${CMAKE_C_LINK_EXECUTABLE} %s\")\n", libs)
	fmt.Fprintln(w)

	return nil
}

func getLibsFromLinkerFlags(lflags []string) []string {
	libs := []string{}

	for _, flag := range lflags {
		if strings.HasPrefix(flag, "-l") {
			libs = append(libs, flag)
		}
	}

	return libs
}

func CmakeCompilerInfoWrite(w io.Writer, archiveFile string, bpkg *BuildPackage,
	cj toolchain.CompilerJob, otherIncludes []string) {
	c := cj.Compiler

	var includes []string

	includes = append(includes, c.GetCompilerInfo().Includes...)
	includes = append(includes, c.GetLocalCompilerInfo().Includes...)
	includes = append(includes, otherIncludes...)

	// Sort and remove duplicate flags
	includes = util.SortFields(includes...)
	trimProjectPathSlice(includes)
	replaceBackslashesSlice(includes)

	fmt.Fprintf(w,
`set_target_properties(%s
                      PROPERTIES
                      ARCHIVE_OUTPUT_DIRECTORY %s
                      LIBRARY_OUTPUT_DIRECTORY %s
                      RUNTIME_OUTPUT_DIRECTORY %s)`,
		EscapeName(bpkg.rpkg.Lpkg.Name()),
		archiveFile,
		archiveFile,
		archiveFile,
	)
	fmt.Fprintln(w)
	fmt.Fprintf(w, "target_include_directories(%s PUBLIC %s)\n\n",
		EscapeName(bpkg.rpkg.Lpkg.Name()),
		strings.Join(includes, " "))
}

func (t *TargetBuilder) CMakeTargetBuilderWrite(w io.Writer, targetCompiler *toolchain.Compiler) error {
	if err := t.PrepBuild(); err != nil {
		return err
	}

	if len(t.res.PreBuildCmdCfg.StageFuncs) > 0 ||
		len(t.res.PreLinkCmdCfg.StageFuncs) > 0 ||
		len(t.res.PostLinkCmdCfg.StageFuncs) > 0 {

		util.OneTimeWarning(
			"custom commands not included in cmake output (unsupported)")
	}

	/* Build the Apps */
	project.ResetDeps(t.AppList)

	targetCompiler.LinkerScripts = t.bspPkg.LinkerScripts

	if err := t.bspPkg.Reload(t.AppBuilder.cfg.SettingValues()); err != nil {
		return err
	}

	if err := t.AppBuilder.CMakeTargetWrite(w, targetCompiler); err != nil {
		return err
	}

	return nil
}

func CmakeCompilerWrite(w io.Writer, c *toolchain.Compiler) {
	/* Since CMake 3 it is required to set a full path to the compiler */
	/* TODO: get rid of the prefix to /usr/bin */
	fmt.Fprintln(w, "set(CMAKE_SYSTEM_NAME Generic)")
	fmt.Fprintln(w, "set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)")
	fmt.Fprintf(w, "set(CMAKE_C_COMPILER %s)\n", c.GetCcPath())
	fmt.Fprintf(w, "set(CMAKE_CXX_COMPILER %s)\n", c.GetCppPath())
	fmt.Fprintf(w, "set(CMAKE_ASM_COMPILER %s)\n", c.GetAsPath())
	/* TODO: cmake returns error on link */
	//fmt.Fprintf(w, "set(CMAKE_AR %s)\n", c.GetArPath())
	fmt.Fprintln(w)
}

func CmakeHeaderWrite(w io.Writer, c *toolchain.Compiler, targetName string) {
	fmt.Fprintln(w, "cmake_minimum_required(VERSION 3.7)\n")
	CmakeCompilerWrite(w, c)
	fmt.Fprintf(w, "project(%s VERSION 0.0.0 LANGUAGES C CXX ASM)\n\n", targetName)
	fmt.Fprintln(w, "SET(CMAKE_C_FLAGS_BACKUP  \"${CMAKE_C_FLAGS}\")")
	fmt.Fprintln(w, "SET(CMAKE_CXX_FLAGS_BACKUP  \"${CMAKE_CXX_FLAGS}\")")
	fmt.Fprintln(w, "SET(CMAKE_ASM_FLAGS_BACKUP  \"${CMAKE_ASM_FLAGS}\")")
	fmt.Fprintln(w)
}

func CMakeTargetGenerate(target *target.Target) error {
	CmakeFileHandle, err := os.Create(CmakeListsPath())
	if err != nil {
		return util.ChildNewtError(err)
	}

	var b = bytes.Buffer{}
	w := bufio.NewWriter(&b)
	defer CmakeFileHandle.Close()

	targetBuilder, err := NewTargetBuilder(target)
	if err != nil {
		return err
	}

	targetCompiler, err := targetBuilder.NewCompiler("", "")
	if err != nil {
		return err
	}

	CmakeHeaderWrite(w, targetCompiler, target.ShortName())

	if err := targetBuilder.CMakeTargetBuilderWrite(w, targetCompiler); err != nil {
		return err
	}

	w.Flush()

	CmakeFileHandle.Write(b.Bytes())
	return nil
}
<commit_msg>cmake: Fix processing archive files<commit_after>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 builder

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"os"
	"path"
	"path/filepath"
	"strings"

	log "github.com/sirupsen/logrus"

	"mynewt.apache.org/newt/newt/interfaces"
	"mynewt.apache.org/newt/newt/project"
	"mynewt.apache.org/newt/newt/target"
	"mynewt.apache.org/newt/newt/toolchain"
	"mynewt.apache.org/newt/util"
)

const CMAKELISTS_FILENAME string = "CMakeLists.txt"

func CmakeListsPath() string {
	return project.GetProject().BasePath + "/" + CMAKELISTS_FILENAME
}

func EscapeName(name string) string {
	return strings.Replace(name, "/", "_", -1)
}

func ExtractLibraryName(filepath string) string {
	_, name := path.Split(filepath)
	name = strings.TrimPrefix(name, "lib")
	name = strings.TrimSuffix(name, ".a")
	return name
}

func replaceBackslashes(path string) string {
	return strings.Replace(path, "\\", "/", -1)
}

func replaceBackslashesSlice(elements []string) {
	for e := range elements {
		elements[e] = replaceBackslashes(elements[e])
	}
}

func escapeFlags(flag string) string {
	flag = strings.Replace(flag, "\"", "\\\\\\\"", -1)
	flag = strings.Replace(flag, "(", "\\\\(", -1)
	flag = strings.Replace(flag, ")", "\\\\)", -1)
	return flag
}

func escapeFlagsSlice(flags []string) []string {
	for f := range flags {
		flags[f] = escapeFlags(flags[f])
	}

	return flags
}

func trimProjectPath(path string) string {
	proj := interfaces.GetProject()
	path = strings.TrimPrefix(path, proj.Path()+"/")
	return path
}

func trimProjectPathSlice(elements []string) {
	for e := range elements {
		elements[e] = trimProjectPath(elements[e])
	}
}

func extractIncludes(flags *[]string, includes *[]string, other *[]string) {
	for _, f := range *flags {
		if strings.HasPrefix(f, "-I") {
			*includes = append(*includes, strings.TrimPrefix(f, "-I"))
		} else {
			*other = append(*other, f)
		}
	}
}

func CmakeSourceObjectWrite(w io.Writer, cj toolchain.CompilerJob,
	includeDirs *[]string, linkFlags *[]string) {
	c := cj.Compiler

	flags := []string{}
	otherFlags := []string{}

	switch cj.CompilerType {
	case toolchain.COMPILER_TYPE_C:
		flags = append(flags, c.GetCompilerInfo().Cflags...)
		flags = append(flags, c.GetLocalCompilerInfo().Cflags...)
	case toolchain.COMPILER_TYPE_ASM:
		flags = append(flags, c.GetCompilerInfo().Cflags...)
		flags = append(flags, c.GetLocalCompilerInfo().Cflags...)
		flags = append(flags, c.GetCompilerInfo().Aflags...)
		flags = append(flags, c.GetLocalCompilerInfo().Aflags...)
	case toolchain.COMPILER_TYPE_CPP:
		flags = append(flags, c.GetCompilerInfo().Cflags...)
		flags = append(flags, c.GetLocalCompilerInfo().Cflags...)
		flags = append(flags, c.GetCompilerInfo().CXXflags...)
		flags = append(flags, c.GetLocalCompilerInfo().CXXflags...)
	}

	*linkFlags = append(*linkFlags, c.GetCompilerInfo().Lflags...)
	*linkFlags = append(*linkFlags, c.GetLocalCompilerInfo().Lflags...)

	extractIncludes(&flags, includeDirs, &otherFlags)
	cj.Filename = trimProjectPath(cj.Filename)

	// Sort and remove duplicate flags
	otherFlags = util.SortFields(otherFlags...)

	fmt.Fprintf(w,
`set_property(SOURCE %s APPEND_STRING
             PROPERTY COMPILE_FLAGS
             "%s")`,
		cj.Filename,
		strings.Join(escapeFlagsSlice(otherFlags), " "))
	fmt.Fprintln(w)
}

func (b *Builder) CMakeBuildPackageWrite(w io.Writer, bpkg *BuildPackage,
	linkFlags *[]string, libraries *[]string) (*BuildPackage, error) {
	entries, err := b.collectCompileEntriesBpkg(bpkg)
	if err != nil {
		return nil, err
	}

	if len(entries) <= 0 {
		return nil, nil
	}

	otherIncludes := []string{}
	files := []string{}
	linkDirs := []string{}

	for _, s := range entries {
		filename := filepath.ToSlash(s.Filename)
		if s.Compiler.ShouldIgnoreFile(filename) {
			log.Infof("Ignoring %s because package dictates it.\n", filename)
			continue
		}

		if s.CompilerType == toolchain.COMPILER_TYPE_ARCHIVE {
			arFile := trimProjectPath(s.Filename)
			linkDirs = append(linkDirs, filepath.Dir(arFile))
			*libraries = append(*libraries, arFile)
		} else {
			CmakeSourceObjectWrite(w, s, &otherIncludes, linkFlags)
			s.Filename = trimProjectPath(s.Filename)
			files = append(files, s.Filename)
		}
	}

	if len(linkDirs) > 0 {
		fmt.Fprintf(w, "link_directories(%s)\n", strings.Join(util.SortFields(linkDirs...), " "))
	}

	if len(files) <= 0 {
		return nil, nil
	}

	pkgName := bpkg.rpkg.Lpkg.Name()

	util.StatusMessage(util.VERBOSITY_DEFAULT, "Generating CMakeLists.txt for %s\n", pkgName)
	fmt.Fprintf(w, "\n# Generating CMakeLists.txt for %s\n", pkgName)
	fmt.Fprintf(w, "add_library(%s %s)\n",
		EscapeName(pkgName),
		strings.Join(files, " "))
	archivePath := replaceBackslashes(trimProjectPath(filepath.Dir(b.ArchivePath(bpkg))))
	CmakeCompilerInfoWrite(w, archivePath, bpkg, entries[0], otherIncludes)

	return bpkg, nil
}

func (b *Builder) CMakeTargetWrite(w io.Writer, targetCompiler *toolchain.Compiler) error {
	bpkgs := b.sortedBuildPackages()
	var compileFlags []string
	var linkFlags []string
	var libraries []string

	c := targetCompiler
	c.AddInfo(b.GetCompilerInfo())

	builtPackages := []*BuildPackage{}
	for _, bpkg := range bpkgs {
		builtPackage, err := b.CMakeBuildPackageWrite(w, bpkg,
			&linkFlags, &libraries)
		if err != nil {
			return err
		}

		if builtPackage != nil {
			builtPackages = append(builtPackages, builtPackage)
		}
	}

	elfName := "cmake_" + filepath.Base(b.AppElfPath())
	fmt.Fprintf(w, "# Generating code for %s\n", elfName)

	var targetObjectsBuffer bytes.Buffer

	for _, bpkg := range builtPackages {
		targetObjectsBuffer.WriteString(fmt.Sprintf("%s ",
			EscapeName(bpkg.rpkg.Lpkg.Name())))
	}

	for _, filename := range libraries {
		targetObjectsBuffer.WriteString(fmt.Sprintf("%s ",
			ExtractLibraryName(filename)))
	}

	elfOutputDir := replaceBackslashes(trimProjectPath(filepath.Dir(b.AppElfPath())))
	fmt.Fprintf(w, "file(WRITE %s \"\")\n", replaceBackslashes(filepath.Join(elfOutputDir, "null.c")))
	fmt.Fprintf(w, "add_executable(%s %s)\n\n", elfName,
		replaceBackslashes(filepath.Join(elfOutputDir, "null.c")))

	if c.GetLdResolveCircularDeps() {
		fmt.Fprintf(w, "target_link_libraries(%s -Wl,--start-group %s -Wl,--end-group)\n",
			elfName, targetObjectsBuffer.String())
	} else {
		fmt.Fprintf(w, "target_link_libraries(%s %s)\n",
			elfName, targetObjectsBuffer.String())
	}

	compileFlags = append(compileFlags, c.GetCompilerInfo().Cflags...)
	compileFlags = append(compileFlags, c.GetLocalCompilerInfo().Cflags...)
	compileFlags = append(compileFlags, c.GetCompilerInfo().CXXflags...)
	compileFlags = append(compileFlags, c.GetLocalCompilerInfo().CXXflags...)
	compileFlags = util.SortFields(compileFlags...)

	fmt.Fprintf(w,
`set_property(TARGET %s APPEND_STRING
             PROPERTY
             COMPILE_FLAGS
             "%s")`,
		elfName,
		strings.Join(escapeFlagsSlice(compileFlags), " "))
	fmt.Fprintln(w)

	lFlags := append(c.GetCompilerInfo().Lflags, c.GetLocalCompilerInfo().Lflags...)
	lFlags = append(lFlags, linkFlags...)
	lFlags = util.SortFields(lFlags...)

	for _, ld := range c.LinkerScripts {
		lFlags = append(lFlags, "-T"+ld)
	}

	var cFlags []string
	cFlags = append(cFlags, c.GetCompilerInfo().Cflags...)
	cFlags = append(cFlags, c.GetLocalCompilerInfo().Cflags...)
	cFlags = util.SortFields(cFlags...)
	lFlags = append(lFlags, cFlags...)

	var cxxFlags []string
	cxxFlags = append(cxxFlags, c.GetCompilerInfo().CXXflags...)
	cxxFlags = append(cxxFlags, c.GetLocalCompilerInfo().CXXflags...)
	cxxFlags = util.SortFields(cxxFlags...)
	lFlags = append(lFlags, cxxFlags...)

	fmt.Fprintf(w,
`set_target_properties(%s
                      PROPERTIES
                      ARCHIVE_OUTPUT_DIRECTORY %s
                      LIBRARY_OUTPUT_DIRECTORY %s
                      RUNTIME_OUTPUT_DIRECTORY %s
                      LINK_FLAGS "%s"
                      LINKER_LANGUAGE C)`,
		elfName,
		elfOutputDir,
		elfOutputDir,
		elfOutputDir,
		strings.Join(escapeFlagsSlice(lFlags), " "))

	fmt.Fprintln(w)

	libs := strings.Join(getLibsFromLinkerFlags(lFlags), " ")
	fmt.Fprintf(w, "# Workaround for gcc linker woes\n")
	fmt.Fprintf(w, "set(CMAKE_C_LINK_EXECUTABLE \"${CMAKE_C_LINK_EXECUTABLE} %s\")\n", libs)
	fmt.Fprintln(w)

	return nil
}

func getLibsFromLinkerFlags(lflags []string) []string {
	libs := []string{}

	for _, flag := range lflags {
		if strings.HasPrefix(flag, "-l") {
			libs = append(libs, flag)
		}
	}

	return libs
}

func CmakeCompilerInfoWrite(w io.Writer, archiveFile string, bpkg *BuildPackage,
	cj toolchain.CompilerJob, otherIncludes []string) {
	c := cj.Compiler

	var includes []string

	includes = append(includes, c.GetCompilerInfo().Includes...)
	includes = append(includes, c.GetLocalCompilerInfo().Includes...)
	includes = append(includes, otherIncludes...)

	// Sort and remove duplicate flags
	includes = util.SortFields(includes...)
	trimProjectPathSlice(includes)
	replaceBackslashesSlice(includes)

	fmt.Fprintf(w,
`set_target_properties(%s
                      PROPERTIES
                      ARCHIVE_OUTPUT_DIRECTORY %s
                      LIBRARY_OUTPUT_DIRECTORY %s
                      RUNTIME_OUTPUT_DIRECTORY %s)`,
		EscapeName(bpkg.rpkg.Lpkg.Name()),
		archiveFile,
		archiveFile,
		archiveFile,
	)
	fmt.Fprintln(w)
	fmt.Fprintf(w, "target_include_directories(%s PUBLIC %s)\n\n",
		EscapeName(bpkg.rpkg.Lpkg.Name()),
		strings.Join(includes, " "))
}

func (t *TargetBuilder) CMakeTargetBuilderWrite(w io.Writer, targetCompiler *toolchain.Compiler) error {
	if err := t.PrepBuild(); err != nil {
		return err
	}

	if len(t.res.PreBuildCmdCfg.StageFuncs) > 0 ||
		len(t.res.PreLinkCmdCfg.StageFuncs) > 0 ||
		len(t.res.PostLinkCmdCfg.StageFuncs) > 0 {

		util.OneTimeWarning(
			"custom commands not included in cmake output (unsupported)")
	}

	/* Build the Apps */
	project.ResetDeps(t.AppList)

	targetCompiler.LinkerScripts = t.bspPkg.LinkerScripts

	if err := t.bspPkg.Reload(t.AppBuilder.cfg.SettingValues()); err != nil {
		return err
	}

	if err := t.AppBuilder.CMakeTargetWrite(w, targetCompiler); err != nil {
		return err
	}

	return nil
}

func CmakeCompilerWrite(w io.Writer, c *toolchain.Compiler) {
	/* Since CMake 3 it is required to set a full path to the compiler */
	/* TODO: get rid of the prefix to /usr/bin */
	fmt.Fprintln(w, "set(CMAKE_SYSTEM_NAME Generic)")
	fmt.Fprintln(w, "set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)")
	fmt.Fprintf(w, "set(CMAKE_C_COMPILER %s)\n", c.GetCcPath())
	fmt.Fprintf(w, "set(CMAKE_CXX_COMPILER %s)\n", c.GetCppPath())
	fmt.Fprintf(w, "set(CMAKE_ASM_COMPILER %s)\n", c.GetAsPath())
	/* TODO: cmake returns error on link */
	//fmt.Fprintf(w, "set(CMAKE_AR %s)\n", c.GetArPath())
	fmt.Fprintln(w)
}

func CmakeHeaderWrite(w io.Writer, c *toolchain.Compiler, targetName string) {
	fmt.Fprintln(w, "cmake_minimum_required(VERSION 3.7)\n")
	CmakeCompilerWrite(w, c)
	fmt.Fprintf(w, "project(%s VERSION 0.0.0 LANGUAGES C CXX ASM)\n\n", targetName)
	fmt.Fprintln(w, "SET(CMAKE_C_FLAGS_BACKUP  \"${CMAKE_C_FLAGS}\")")
	fmt.Fprintln(w, "SET(CMAKE_CXX_FLAGS_BACKUP  \"${CMAKE_CXX_FLAGS}\")")
	fmt.Fprintln(w, "SET(CMAKE_ASM_FLAGS_BACKUP  \"${CMAKE_ASM_FLAGS}\")")
	fmt.Fprintln(w)
}

func CMakeTargetGenerate(target *target.Target) error {
	CmakeFileHandle, err := os.Create(CmakeListsPath())
	if err != nil {
		return util.ChildNewtError(err)
	}

	var b = bytes.Buffer{}
	w := bufio.NewWriter(&b)
	defer CmakeFileHandle.Close()

	targetBuilder, err := NewTargetBuilder(target)
	if err != nil {
		return err
	}

	targetCompiler, err := targetBuilder.NewCompiler("", "")
	if err != nil {
		return err
	}

	CmakeHeaderWrite(w, targetCompiler, target.ShortName())

	if err := targetBuilder.CMakeTargetBuilderWrite(w, targetCompiler); err != nil {
		return err
	}

	w.Flush()

	CmakeFileHandle.Write(b.Bytes())
	return nil
}
<|endoftext|>


<commit_before>package eloqua

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

var (
	// mux is the HTTP request multiplexer used with the test server.
	mux *http.ServeMux

	// client is the Eloqua client being tested.
	client *Client

	// server is a test HTTP server used to provide mock API responses.
	server *httptest.Server
)

// setup creates a test server and client instance to test against.
func setup() {
	// Create test servers
	mux = http.NewServeMux()
	server = httptest.NewServer(mux)
	// Create Eloqua test client
	client = NewClient(server.URL, "TestCompany", "John.Smith", "mysecret")
}

func addRestHandlerFunc(endpoint string, handler func(http.ResponseWriter, *http.Request)) {
	mux.HandleFunc("/api/rest/2.0/"+strings.Trim(endpoint, " /"), handler)
}

// teardown does any cleanup operations, Specifically closes down the http server
func teardown() {
	server.Close()
}

// testURLParam is a helper to check url parameters are as expected
func testURLParam(t *testing.T, req *http.Request, name string, expectedVal string) {
	receivedVal := req.URL.Query().Get(name)
	if receivedVal != expectedVal {
		t.Errorf("URL parameter '%s' is %s, expected %s", name, receivedVal, expectedVal)
	}
}

// testMethod ensures the http method for a request is as expected
func testMethod(t *testing.T, req *http.Request, method string) {
	if req.Method != strings.ToUpper(method) {
		t.Errorf("HTTP method is not as expected\nExpected: %s\nReceived: %s", strings.ToUpper(method), req.Method)
	}
}

// testModels tests two structs against eachother
func testModels(t *testing.T, testDesc string, test interface{}, expected interface{}) {
	if !reflect.DeepEqual(test, expected) {
		t.Errorf("%s data is not as expected.\nReturned \n%+v,\nWanted \n%+v", testDesc, test, expected)
	}
}

func TestAuthHeader(t *testing.T) {
	setup()
	defer teardown()

	expectedString := "Basic VGVzdENvbXBhbnlcSm9obi5TbWl0aDpteXNlY3JldA=="

	if client.authHeader != expectedString {
		t.Errorf("Auth header is not as expected \nExpected: %s \nReceived: %s", expectedString, client.authHeader)
	}
}

func TestRestRequestErrorHandling(t *testing.T) {
	setup()
	defer teardown()

	resp, err := client.RestRequest("", "C/A/T", "")

	if err == nil {
		t.Error("Invalid HTTP request error expected but no error was returned")
	}
	if resp != nil {
		t.Error("Response expected to be nil due to early errors but is not")
	}

	resp, err = client.RestRequest("/test/endpoint", "GET", "")
	if err != nil {
		t.Error("HTTP error expected but no error was returned")
	}
	if resp == nil {
		t.Error("Response expected from failed request but was found as nil")
	}
}

func TestRequestDecodeJSONErrorHandling(t *testing.T) {
	setup()
	defer teardown()

	tMap := make(chan int)
	_, err := client.requestDecode("/test/endpoint", "POST", tMap)

	if err.Error() != "json: unsupported type: chan int" {
		t.Error("Delete request with invalid postdata not returning an error as expected")
	}
}

func TestDeleteRequestErrorHandling(t *testing.T) {
	setup()
	defer teardown()

	user := User{Name: "Test User"}
	_, err := client.deleteRequest("/test/endpoint", user)

	if err == nil {
		t.Error("Request did not return an error but a 404 was expected")
	}
}

func TestDeleteRequestJSONErrorHandling(t *testing.T) {
	setup()
	defer teardown()

	tMap := make(chan int)
	_, err := client.deleteRequest("/test/endpoint", tMap)

	if err.Error() != "json: unsupported type: chan int" {
		t.Error("Delete request with invalid postdata not returning an error as expected")
	}
}

func TestEloquaErrorResponse(t *testing.T) {
	setup()
	defer teardown()

	responseMessage := "This is a test error message string response"

	addRestHandlerFunc("/assets/contact/lists", func(w http.ResponseWriter, req *http.Request) {
		w.WriteHeader(401)
		fmt.Fprint(w, responseMessage)
	})

	_, resp, err := client.ContactLists.List(nil)

	if resp.StatusCode != 401 {
		t.Errorf("Wrong response status code, Expected %d, Received %d", 401, resp.StatusCode)
	}

	if err.Error() != errorMessages[401] {
		t.Errorf("Wrong error message received, \nExpected: %s\nRecieved: %s", errorMessages[401], err.Error())
	}

	if resp.ErrorContent != responseMessage {
		t.Errorf("Failed request content not in request body as expected.\nExpected: %s\nRecieved:%s", responseMessage, resp.ErrorContent)
	}
}

func TestEloquaDefaultErrorResponse(t *testing.T) {
	setup()
	defer teardown()

	responseMessage := "There was an issue performing your request"

	addRestHandlerFunc("/assets/contact/lists", func(w http.ResponseWriter, req *http.Request) {
		w.WriteHeader(608)
		fmt.Fprint(w, responseMessage)
	})

	_, resp, _ := client.ContactLists.List(nil)

	if resp.ErrorContent != responseMessage {
		t.Errorf("Failed request content not in request body as expected.\nExpected: %s\nRecieved:%s", responseMessage, resp.ErrorContent)
	}
}
<commit_msg>--amend<commit_after>package eloqua

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

var (
	// mux is the HTTP request multiplexer used with the test server.
	mux *http.ServeMux

	// client is the Eloqua client being tested.
	client *Client

	// server is a test HTTP server used to provide mock API responses.
	server *httptest.Server
)

// setup creates a test server and client instance to test against.
func setup() {
	// Create test servers
	mux = http.NewServeMux()
	server = httptest.NewServer(mux)
	// Create Eloqua test client
	client = NewClient(server.URL, "TestCompany", "John.Smith", "mysecret")
}

func addRestHandlerFunc(endpoint string, handler func(http.ResponseWriter, *http.Request)) {
	mux.HandleFunc("/api/rest/2.0/"+strings.Trim(endpoint, " /"), handler)
}

// teardown does any cleanup operations, Specifically closes down the http server
func teardown() {
	server.Close()
}

// testURLParam is a helper to check url parameters are as expected
func testURLParam(t *testing.T, req *http.Request, name string, expectedVal string) {
	receivedVal := req.URL.Query().Get(name)
	if receivedVal != expectedVal {
		t.Errorf("URL parameter '%s' is %s, expected %s", name, receivedVal, expectedVal)
	}
}

// testMethod ensures the http method for a request is as expected
func testMethod(t *testing.T, req *http.Request, method string) {
	if req.Method != strings.ToUpper(method) {
		t.Errorf("HTTP method is not as expected\nExpected: %s\nReceived: %s", strings.ToUpper(method), req.Method)
	}
}

// testModels tests two structs against eachother
func testModels(t *testing.T, testDesc string, test interface{}, expected interface{}) {
	if !reflect.DeepEqual(test, expected) {
		t.Errorf("%s data is not as expected.\nReturned \n%+v,\nWanted \n%+v", testDesc, test, expected)
	}
}

func TestAuthHeader(t *testing.T) {
	setup()
	defer teardown()

	expectedString := "Basic VGVzdENvbXBhbnlcSm9obi5TbWl0aDpteXNlY3JldA=="

	if client.authHeader != expectedString {
		t.Errorf("Auth header is not as expected \nExpected: %s \nReceived: %s", expectedString, client.authHeader)
	}
}

func TestRestRequestErrorHandling(t *testing.T) {
	setup()
	defer teardown()

	resp, err := client.RestRequest("/%2///F a", "GET", "")

	if err == nil {
		t.Error("Invalid HTTP request error expected but no error was returned")
	}
	if resp != nil {
		t.Error("Response expected to be nil due to early errors but is not")
	}

	resp, err = client.RestRequest("/test/endpoint", "GET", "")
	if err != nil {
		t.Error("HTTP error expected but no error was returned")
	}
	if resp == nil {
		t.Error("Response expected from failed request but was found as nil")
	}
}

func TestRequestDecodeJSONErrorHandling(t *testing.T) {
	setup()
	defer teardown()

	tMap := make(chan int)
	_, err := client.requestDecode("/test/endpoint", "POST", tMap)

	if err.Error() != "json: unsupported type: chan int" {
		t.Error("Delete request with invalid postdata not returning an error as expected")
	}
}

func TestDeleteRequestErrorHandling(t *testing.T) {
	setup()
	defer teardown()

	user := User{Name: "Test User"}
	_, err := client.deleteRequest("/test/endpoint", user)

	if err == nil {
		t.Error("Request did not return an error but a 404 was expected")
	}
}

func TestDeleteRequestJSONErrorHandling(t *testing.T) {
	setup()
	defer teardown()

	tMap := make(chan int)
	_, err := client.deleteRequest("/test/endpoint", tMap)

	if err.Error() != "json: unsupported type: chan int" {
		t.Error("Delete request with invalid postdata not returning an error as expected")
	}
}

func TestEloquaErrorResponse(t *testing.T) {
	setup()
	defer teardown()

	responseMessage := "This is a test error message string response"

	addRestHandlerFunc("/assets/contact/lists", func(w http.ResponseWriter, req *http.Request) {
		w.WriteHeader(401)
		fmt.Fprint(w, responseMessage)
	})

	_, resp, err := client.ContactLists.List(nil)

	if resp.StatusCode != 401 {
		t.Errorf("Wrong response status code, Expected %d, Received %d", 401, resp.StatusCode)
	}

	if err.Error() != errorMessages[401] {
		t.Errorf("Wrong error message received, \nExpected: %s\nRecieved: %s", errorMessages[401], err.Error())
	}

	if resp.ErrorContent != responseMessage {
		t.Errorf("Failed request content not in request body as expected.\nExpected: %s\nRecieved:%s", responseMessage, resp.ErrorContent)
	}
}

func TestEloquaDefaultErrorResponse(t *testing.T) {
	setup()
	defer teardown()

	responseMessage := "There was an issue performing your request"

	addRestHandlerFunc("/assets/contact/lists", func(w http.ResponseWriter, req *http.Request) {
		w.WriteHeader(608)
		fmt.Fprint(w, responseMessage)
	})

	_, resp, _ := client.ContactLists.List(nil)

	if resp.ErrorContent != responseMessage {
		t.Errorf("Failed request content not in request body as expected.\nExpected: %s\nRecieved:%s", responseMessage, resp.ErrorContent)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"io/ioutil"
	"net/rpc"
	"os"
	"strings"
	"time"
)

const (
	mGocodeAddr = "127.0.0.1:57952"
)

type mGocode struct {
	Bin      string
	Env      map[string]string
	Home     string
	cmd      string
	Set      map[string]string
	Complete struct {
		Fn  string
		Src string
		Pos int
	}
}

func (m *mGocode) Call() (interface{}, string) {
	e := ""
	res := M{}
	c, err := rpc.Dial("tcp", mGocodeAddr)
	if err != nil {
		if serveErr := mGocodeServe(m); serveErr != nil {
			return res, "Error starting gocode server: " + serveErr.Error()
		}

		for i := 0; err != nil && i < 5; i += 1 {
			time.Sleep(20 * time.Millisecond)
			c, err = rpc.Dial("tcp", mGocodeAddr)
		}

		if err != nil {
			return res, "Error connecting to gocode server: " + err.Error()
		}
	}
	defer c.Close()

	switch m.cmd {
	case "set":
		for k, v := range m.Set {
			mGocodeCmdSet(c, k, v)
		}
		res, e = mGocodeCmdSet(c, "\x00", "\x00")
	case "complete":
		pos := 0
		if m.Complete.Src == "" {
			// this is here for testing, the client should always send the src
			s, _ := ioutil.ReadFile(m.Complete.Fn)
			m.Complete.Src = string(s)
		}

		for i, _ := range m.Complete.Src {
			pos += 1
			if pos >= m.Complete.Pos {
				pos = i
				break
			}
		}
		res, e = mGocodeCmdComplete(c, m.Complete.Fn, []byte(m.Complete.Src), pos)
	default:
		panic("Unsupported command: gocode: " + m.cmd)
	}

	return res, e
}

func init() {
	registry.Register("gocode_set", func(b *Broker) Caller {
		return &mGocode{cmd: "set"}
	})

	registry.Register("gocode_complete", func(b *Broker) Caller {
		return &mGocode{cmd: "complete"}
	})
}

func mGocodeServe(m *mGocode) error {
	argv := []string{os.Args[0], "-s", "-sock", "tcp", "-addr", mGocodeAddr}
	attr := os.ProcAttr{
		Dir:   m.Home,
		Env:   envSlice(m.Env),
		Files: []*os.File{nil, nil, nil},
	}

	p, err := os.StartProcess(m.Bin, argv, &attr)
	if err == nil {
		byeDefer(func() {
			p.Kill()
		})
		go func() {
			_, err := p.Wait()
			if err != nil {
				logger.Println("gocode failed", err)
			}
		}()
	}
	return err
}

func mGocodeCmdSet(c *rpc.Client, k, v string) (res M, e string) {
	args := struct{ Arg0, Arg1 string }{k, v}
	reply := struct{ Arg0 string }{}

	if err := c.Call("RPC.RPC_set", &args, &reply); err != nil {
		e = "RPC error: " + err.Error()
	}
	options := map[string]string{}
	for _, s := range strings.Split(reply.Arg0, "\n") {
		v := strings.SplitN(strings.TrimSpace(s), " ", 2)
		if len(v) == 2 {
			options[v[0]] = v[1]
		}
	}
	res = M{"options": options}
	return
}

func mGocodeCmdComplete(c *rpc.Client, fn string, src []byte, pos int) (res M, e string) {
	args := struct {
		Arg0 []byte
		Arg1 string
		Arg2 int
	}{src, fn, pos}

	reply := struct {
		Arg0 []candidate
		Arg1 int
	}{}

	if err := c.Call("RPC.RPC_auto_complete", &args, &reply); err != nil {
		e = "RPC error: " + err.Error()
	}

	completions := []M{}
	for _, d := range reply.Arg0 {
		completions = append(completions, M{
			"class": d.Class.String(),
			"type":  d.Type,
			"name":  d.Name,
		})
	}
	res = M{"completions": completions}

	return
}
<commit_msg>* pass correct file argv0 to startprocess<commit_after>package main

import (
	"io/ioutil"
	"net/rpc"
	"os"
	"strings"
	"time"
)

const (
	mGocodeAddr = "127.0.0.1:57952"
)

type mGocode struct {
	Bin      string
	Env      map[string]string
	Home     string
	cmd      string
	Set      map[string]string
	Complete struct {
		Fn  string
		Src string
		Pos int
	}
}

func (m *mGocode) Call() (interface{}, string) {
	e := ""
	res := M{}
	c, err := rpc.Dial("tcp", mGocodeAddr)
	if err != nil {
		if serveErr := mGocodeServe(m); serveErr != nil {
			return res, "Error starting gocode server: " + serveErr.Error()
		}

		for i := 0; err != nil && i < 5; i += 1 {
			time.Sleep(20 * time.Millisecond)
			c, err = rpc.Dial("tcp", mGocodeAddr)
		}

		if err != nil {
			return res, "Error connecting to gocode server: " + err.Error()
		}
	}
	defer c.Close()

	switch m.cmd {
	case "set":
		for k, v := range m.Set {
			mGocodeCmdSet(c, k, v)
		}
		res, e = mGocodeCmdSet(c, "\x00", "\x00")
	case "complete":
		pos := 0
		if m.Complete.Src == "" {
			// this is here for testing, the client should always send the src
			s, _ := ioutil.ReadFile(m.Complete.Fn)
			m.Complete.Src = string(s)
		}

		for i, _ := range m.Complete.Src {
			pos += 1
			if pos >= m.Complete.Pos {
				pos = i
				break
			}
		}
		res, e = mGocodeCmdComplete(c, m.Complete.Fn, []byte(m.Complete.Src), pos)
	default:
		panic("Unsupported command: gocode: " + m.cmd)
	}

	return res, e
}

func init() {
	registry.Register("gocode_set", func(b *Broker) Caller {
		return &mGocode{cmd: "set"}
	})

	registry.Register("gocode_complete", func(b *Broker) Caller {
		return &mGocode{cmd: "complete"}
	})
}

func mGocodeServe(m *mGocode) error {
	argv := []string{m.Bin, "-s", "-sock", "tcp", "-addr", mGocodeAddr}
	attr := os.ProcAttr{
		Dir:   m.Home,
		Env:   envSlice(m.Env),
		Files: []*os.File{nil, nil, nil},
	}

	p, err := os.StartProcess(m.Bin, argv, &attr)
	if err == nil {
		byeDefer(func() {
			p.Kill()
		})
		go func() {
			_, err := p.Wait()
			if err != nil {
				logger.Println("gocode failed", err)
			}
		}()
	}
	return err
}

func mGocodeCmdSet(c *rpc.Client, k, v string) (res M, e string) {
	args := struct{ Arg0, Arg1 string }{k, v}
	reply := struct{ Arg0 string }{}

	if err := c.Call("RPC.RPC_set", &args, &reply); err != nil {
		e = "RPC error: " + err.Error()
	}
	options := map[string]string{}
	for _, s := range strings.Split(reply.Arg0, "\n") {
		v := strings.SplitN(strings.TrimSpace(s), " ", 2)
		if len(v) == 2 {
			options[v[0]] = v[1]
		}
	}
	res = M{"options": options}
	return
}

func mGocodeCmdComplete(c *rpc.Client, fn string, src []byte, pos int) (res M, e string) {
	args := struct {
		Arg0 []byte
		Arg1 string
		Arg2 int
	}{src, fn, pos}

	reply := struct {
		Arg0 []candidate
		Arg1 int
	}{}

	if err := c.Call("RPC.RPC_auto_complete", &args, &reply); err != nil {
		e = "RPC error: " + err.Error()
	}

	completions := []M{}
	for _, d := range reply.Arg0 {
		completions = append(completions, M{
			"class": d.Class.String(),
			"type":  d.Type,
			"name":  d.Name,
		})
	}
	res = M{"completions": completions}

	return
}
<|endoftext|>


<commit_before>package mount

import "github.com/hanwen/go-fuse/fuse"

// https://github.com/libfuse/libfuse/blob/48ae2e72b39b6a31cb2194f6f11786b7ca06aac6/include/fuse.h#L778

/**
 * Copy a range of data from one file to anotherNiels de Vos, 4 years ago: • libfuse: add copy_file_range() support
 *
 * Performs an optimized copy between two file descriptors without the
 * additional cost of transferring data through the FUSE kernel module
 * to user space (glibc) and then back into the FUSE filesystem again.
 *
 * In case this method is not implemented, applications are expected to
 * fall back to a regular file copy.   (Some glibc versions did this
 * emulation automatically, but the emulation has been removed from all
 * glibc release branches.)
 */
func (wfs *WFS) CopyFileRange(cancel <-chan struct{}, in *fuse.CopyFileRangeIn) (written uint32, code fuse.Status) {
	return 0, fuse.ENOSYS
}

/**
 * Allocates space for an open file
 *
 * This function ensures that required space is allocated for specified
 * file.  If this function returns success then any subsequent write
 * request to specified range is guaranteed not to fail because of lack
 * of space on the file system media.
 */
func (wfs *WFS) Fallocate(cancel <-chan struct{}, in *fuse.FallocateIn) (code fuse.Status) {
	return fuse.ENOSYS
}

/**
 * Find next data or hole after the specified offset
 */
func (wfs *WFS) Lseek(cancel <-chan struct{}, in *fuse.LseekIn, out *fuse.LseekOut) fuse.Status {
	return fuse.ENOSYS
}

func (wfs *WFS) GetLk(cancel <-chan struct{}, in *fuse.LkIn, out *fuse.LkOut) (code fuse.Status) {
	return fuse.ENOSYS
}

func (wfs *WFS) SetLk(cancel <-chan struct{}, in *fuse.LkIn) (code fuse.Status) {
	return fuse.ENOSYS
}

func (wfs *WFS) SetLkw(cancel <-chan struct{}, in *fuse.LkIn) (code fuse.Status) {
	return fuse.ENOSYS
}

/**
 * Check file access permissions
 *
 * This will be called for the access() system call.  If the
 * 'default_permissions' mount option is given, this method is not
 * called.
 *
 * This method is not called under Linux kernel versions 2.4.x
 */
func (wfs *WFS) Access(cancel <-chan struct{}, input *fuse.AccessIn) (code fuse.Status) {
	return fuse.ENOSYS
}
<commit_msg>fix import<commit_after>package mount

import "github.com/hanwen/go-fuse/v2/fuse"

// https://github.com/libfuse/libfuse/blob/48ae2e72b39b6a31cb2194f6f11786b7ca06aac6/include/fuse.h#L778

/**
 * Copy a range of data from one file to anotherNiels de Vos, 4 years ago: • libfuse: add copy_file_range() support
 *
 * Performs an optimized copy between two file descriptors without the
 * additional cost of transferring data through the FUSE kernel module
 * to user space (glibc) and then back into the FUSE filesystem again.
 *
 * In case this method is not implemented, applications are expected to
 * fall back to a regular file copy.   (Some glibc versions did this
 * emulation automatically, but the emulation has been removed from all
 * glibc release branches.)
 */
func (wfs *WFS) CopyFileRange(cancel <-chan struct{}, in *fuse.CopyFileRangeIn) (written uint32, code fuse.Status) {
	return 0, fuse.ENOSYS
}

/**
 * Allocates space for an open file
 *
 * This function ensures that required space is allocated for specified
 * file.  If this function returns success then any subsequent write
 * request to specified range is guaranteed not to fail because of lack
 * of space on the file system media.
 */
func (wfs *WFS) Fallocate(cancel <-chan struct{}, in *fuse.FallocateIn) (code fuse.Status) {
	return fuse.ENOSYS
}

/**
 * Find next data or hole after the specified offset
 */
func (wfs *WFS) Lseek(cancel <-chan struct{}, in *fuse.LseekIn, out *fuse.LseekOut) fuse.Status {
	return fuse.ENOSYS
}

func (wfs *WFS) GetLk(cancel <-chan struct{}, in *fuse.LkIn, out *fuse.LkOut) (code fuse.Status) {
	return fuse.ENOSYS
}

func (wfs *WFS) SetLk(cancel <-chan struct{}, in *fuse.LkIn) (code fuse.Status) {
	return fuse.ENOSYS
}

func (wfs *WFS) SetLkw(cancel <-chan struct{}, in *fuse.LkIn) (code fuse.Status) {
	return fuse.ENOSYS
}

/**
 * Check file access permissions
 *
 * This will be called for the access() system call.  If the
 * 'default_permissions' mount option is given, this method is not
 * called.
 *
 * This method is not called under Linux kernel versions 2.4.x
 */
func (wfs *WFS) Access(cancel <-chan struct{}, input *fuse.AccessIn) (code fuse.Status) {
	return fuse.ENOSYS
}
<|endoftext|>


<commit_before>package buffalo

import (
	"encoding/json"
	"encoding/xml"
	"net/http"
	"sync"

	"github.com/monoculum/formam"
	"github.com/pkg/errors"
)

var binderLock = &sync.Mutex{}
var binders = map[string]BinderFunc{}
var decoder *formam.Decoder

// BinderFunc takes a request and binds it to an interface.
// If there is a problem it should return an error.
type BinderFunc func(*http.Request, interface{}) error

// RegisterBinder maps a request Content-Type (application/json)
// to a BinderFunc.
func RegisterBinder(contentType string, fn BinderFunc) {
	binderLock.Lock()
	defer binderLock.Unlock()
	binders[contentType] = fn
}

func init() {
	decoder = formam.NewDecoder(&formam.DecoderOptions{TagName: "schema"})
	sb := func(req *http.Request, i interface{}) error {
		err := req.ParseForm()
		if err != nil {
			return errors.WithStack(err)
		}

		if err := decoder.Decode(req.Form, i); err != nil {
			return errors.WithStack(err)
		}
		return nil
	}

	binders["application/html"] = sb
	binders["text/html"] = sb
	binders["application/x-www-form-urlencoded"] = sb
	binders["multipart/form-data"] = sb
}

func init() {
	jb := func(req *http.Request, value interface{}) error {
		return json.NewDecoder(req.Body).Decode(value)
	}
	binders["application/json"] = jb
	binders["text/json"] = jb
	binders["json"] = jb
}

func init() {
	xb := func(req *http.Request, value interface{}) error {
		return xml.NewDecoder(req.Body).Decode(value)
	}
	binders["application/xml"] = xb
	binders["text/xml"] = xb
	binders["xml"] = xb
}
<commit_msg>Setting formam to ignore unknown keys<commit_after>package buffalo

import (
	"encoding/json"
	"encoding/xml"
	"net/http"
	"sync"

	"github.com/monoculum/formam"
	"github.com/pkg/errors"
)

var binderLock = &sync.Mutex{}
var binders = map[string]BinderFunc{}
var decoder *formam.Decoder

// BinderFunc takes a request and binds it to an interface.
// If there is a problem it should return an error.
type BinderFunc func(*http.Request, interface{}) error

// RegisterBinder maps a request Content-Type (application/json)
// to a BinderFunc.
func RegisterBinder(contentType string, fn BinderFunc) {
	binderLock.Lock()
	defer binderLock.Unlock()
	binders[contentType] = fn
}

func init() {
	decoder = formam.NewDecoder(&formam.DecoderOptions{
		TagName:           "schema",
		IgnoreUnknownKeys: true,
	})

	sb := func(req *http.Request, i interface{}) error {
		err := req.ParseForm()
		if err != nil {
			return errors.WithStack(err)
		}

		if err := decoder.Decode(req.Form, i); err != nil {
			return errors.WithStack(err)
		}
		return nil
	}

	binders["application/html"] = sb
	binders["text/html"] = sb
	binders["application/x-www-form-urlencoded"] = sb
	binders["multipart/form-data"] = sb
}

func init() {
	jb := func(req *http.Request, value interface{}) error {
		return json.NewDecoder(req.Body).Decode(value)
	}
	binders["application/json"] = jb
	binders["text/json"] = jb
	binders["json"] = jb
}

func init() {
	xb := func(req *http.Request, value interface{}) error {
		return xml.NewDecoder(req.Body).Decode(value)
	}
	binders["application/xml"] = xb
	binders["text/xml"] = xb
	binders["xml"] = xb
}
<|endoftext|>


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

package behavior_tree

/*
 * BevRunningStatus
 */
const (
	k_BRS_ERROR_Transition = -1
	k_BRS_Executing        = iota
	k_BRS_Finish
)

/*
 * E_TerminalNodeStaus
 */
const (
	_ = iota
	k_TNS_Ready
	k_TNS_Running
	k_TNS_Finish
)

/*
 * Other const variables
 */
const (
	kInfiniteLoop                    int = -1
	k_BLimited_MaxChildNodeCnt       int = 16
	k_BLimited_InvalidChildNodeIndex int = 16
)

type BevRunningStatus int
type E_TerminalNodeStaus int

/*
 *
 */
type BevNode struct {
	mo_NodePrecondition BevNodePrecondition
	mo_ParentNode       *BevNode
	mo_ActiveNode       *BevNode
	mo_LastActiveNode   *BevNode
	mul_ChildNodeCount  int
	mz_DebugName        string
	mao_ChildNodeList   [k_BLimited_MaxChildNodeCnt]*BevNode
}

func NewBevNode(_o_ParentNode *BevNode, _o_NodeScript BevNodePrecondition) *BevNode {
	return &BevNode{mo_NodePrecondition: _o_NodeScript, mo_ParentNode: _o_ParentNode}
}

func (node *BevNode) AddChildNode(_o_ChildNode *BevNode) *BevNode {
	if node.mul_ChildNodeCount == k_BLimited_MaxChildNodeCnt {
		return node
	}

	node.mao_ChildNodeList[node.mul_ChildNodeCount] = _o_ChildNode
	node.mul_ChildNodeCount += 1
	return node
}

func (node *BevNode) SetNodePrecondition(_o_NodePrecondition BevNodePrecondition) *BevNode {
	if node.mo_NodePrecondition != _o_NodePrecondition {
		node.mo_NodePrecondition = _o_NodePrecondition
	}
	return node
}

func (node *BevNode) SetDebugName(_debugName string) *BevNode {
	node.mz_DebugName = _debugName
	return node
}

func (node *BevNode) GetLastActiveNode() *BevNode {
	return node.mo_LastActiveNode
}

func (node *BevNode) SetActiveNode(_o_Node *BevNode) {
	node.mo_LastActiveNode = node.mo_ActiveNode
	node.mo_ActiveNode = _o_Node

	if node.mo_ParentNode != nil {
		node.mo_ParentNode.SetActiveNode(_o_Node)
	}
}

func (node *BevNode) GetDebugName() string {
	return node.mz_DebugName
}

func (node *BevNode) Evaluate(input interface{}) bool {
	return (node.mo_NodePrecondition == nil || node.mo_NodePrecondition.ExternalCondition(input)) && node.doEvaluate(input)
}

func (node *BevNode) Transition(input interface{}) {
	node.doTransition(input)
}

func (node *BevNode) Tick(input interface{}, output interface{}) BevRunningStatus {
	return node.doTick(input, output)
}

func (node *BevNode) doEvaluate(input interface{}) bool {
	return true
}

func (node *BevNode) doTransition(input interface{}) {
}

func (node *BevNode) doTick(input interface{}, output interface{}) BevRunningStatus {
	return k_BRS_Finish
}

func (node *BevNode) setParentNode(_o_ParentNode *BevNode) {
	node.mo_ParentNode = _o_ParentNode
}

func (node *BevNode) checkIndex(_ui_Index int) bool {
	return _ui_Index >= 0 && _ui_Index < node.mul_ChildNodeCount
}

/*
 *
 */
type BevNodePrioritySelector struct {
	*BevNode
	mui_CurrentSelectIndex int
	mui_LastSelectIndex    int
}

func NewBevNodePrioritySelector(_o_ParentNode *BevNode, _o_NodePrecondition BevNodePrecondition) *BevNodePrioritySelector {
	return &BevNodePrioritySelector{NewBevNode(_o_ParentNode, _o_NodePrecondition), k_BLimited_InvalidChildNodeIndex, k_BLimited_InvalidChildNodeIndex}
}

func (node *BevNodePrioritySelector) doEvaluate(input interface{}) bool {
	return true
}

func (node *BevNodePrioritySelector) doTransition(input interface{}) {

}

func (node *BevNodePrioritySelector) doTick(input interface{}, output interface{}) BevRunningStatus {
	return k_BRS_Finish
}

/*
 *
 */
type BevNodeNonePrioritySelector struct {
	*BevNodePrioritySelector
}

func NewBevNodeNonePrioritySelector(_o_ParentNode *BevNode, _o_NodePrecondition BevNodePrecondition) *BevNodeNonePrioritySelector {
	return &BevNodeNonePrioritySelector{NewBevNodePrioritySelector(_o_ParentNode, _o_NodePrecondition)}
}

func (node *BevNodeNonePrioritySelector) doEvaluate(input interface{}) bool {
	return true
}

/*
 *
 */
type BevNodeSequence struct {
	*BevNode
	mui_CurrentNodeIndex int
}

func NewBevNodeSequence(_o_ParentNode *BevNode, _o_NodePrecondition BevNodePrecondition) *BevNodeSequence {
	return &BevNodeSequence{NewBevNode(_o_ParentNode, _o_NodePrecondition), k_BLimited_InvalidChildNodeIndex}
}

func (node *BevNodeSequence) doEvaluate(input interface{}) bool {
	return true
}

func (node *BevNodeSequence) doTransition(input interface{}) {

}

func (node *BevNodeSequence) doTick(input interface{}, output interface{}) BevRunningStatus {
	return k_BRS_Finish
}

/*
 *
 */
type BevNodeParallel struct {
	node                *BevNode
	mab_ChildNodeStatus [k_BLimited_MaxChildNodeCnt]BevRunningStatus
}

func NewBevNodeParallel(_o_ParentNode *BevNode, _o_NodePrecondition BevNodePrecondition) *BevNodeParallel {
	return &BevNodeParallel{node: NewBevNode(_o_ParentNode, _o_NodePrecondition)}
}

func (node *BevNodeParallel) doEvaluate(input interface{}) bool {
	return true
}

func (node *BevNodeParallel) doTransition(input interface{}) {

}

func (node *BevNodeParallel) doTick(input interface{}, output interface{}) BevRunningStatus {
	return k_BRS_Finish
}

/*
 *
 */
type BevNodeLoop struct {
	*BevNode
	mi_LoopCount    int
	mi_CurrentCount int
}

func NewBevNodeLoop(_o_ParentNode *BevNode, _o_NodePrecondition BevNodePrecondition, _i_LoopCnt int) *BevNodeLoop {
	return &BevNodeLoop{NewBevNode(_o_ParentNode, _o_NodePrecondition), _i_LoopCnt, 0}
}

func (node *BevNodeLoop) doEvaluate(input interface{}) bool {
	return true
}

func (node *BevNodeLoop) doTransition(input interface{}) {

}

func (node *BevNodeLoop) doTick(input interface{}, output interface{}) BevRunningStatus {
	return k_BRS_Finish
}

/*
 *
 */
type BevNodeTerminal struct {
	*BevNode
	me_Status   E_TerminalNodeStaus
	mb_NeedExit bool
}

func NewBevNodeTerminal(_o_ParentNode *BevNode, _o_NodePrecondition BevNodePrecondition) *BevNodeTerminal {
	return &BevNodeTerminal{NewBevNode(_o_ParentNode, _o_NodePrecondition), k_TNS_Ready, false}
}

func (node *BevNodeTerminal) doTransition(input interface{}) {

}

func (node *BevNodeTerminal) doTick(input interface{}, output interface{}) BevRunningStatus {
	return k_BRS_Finish
}

func doEnter(input interface{}) {

}

func doExecute(input interface{}, output interface{}) BevRunningStatus {
	return k_BRS_Finish
}

func doExit(input interface{}, _ui_ExitID BevRunningStatus) {

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

package behavior_tree

import (
	"math/rand"
)

/*
 * BevRunningStatus
 */
const (
	StateTransition = -1
	StateExecuting  = iota
	StateFinish
)

/*
 * E_TerminalNodeStaus
 */
const (
	_ = iota
	NodeReady
	NodeRunning
	NodeFinish
)

/*
 * Other const variables
 */
const (
	kInfiniteLoop                    int = -1
	k_BLimited_MaxChildNodeCnt       int = 16
	k_BLimited_InvalidChildNodeIndex int = 16
)

type BevRunningStatus int
type E_TerminalNodeStaus int

/*
 *
 */
type BevNode struct {
	nodePrecondition BevNodePrecondition
	parentNode       *BevNode // ? interface{}
	activeNode       *BevNode
	lastActiveNode   *BevNode
	childNodeCount   int
	debugName        string
	childNodeList    [k_BLimited_MaxChildNodeCnt]*BevNode
}

func NewBevNode(parentNode *BevNode, _o_NodeScript BevNodePrecondition) *BevNode {
	return &BevNode{nodePrecondition: _o_NodeScript, parentNode: parentNode}
}

func (node *BevNode) AddChildNode(childNode *BevNode) *BevNode {
	if node.childNodeCount == k_BLimited_MaxChildNodeCnt {
		return node
	}

	node.childNodeList[node.childNodeCount] = childNode
	node.childNodeCount += 1
	return node
}

func (node *BevNode) SetNodePrecondition(nodePrecondition BevNodePrecondition) *BevNode {
	if node.nodePrecondition != nodePrecondition {
		node.nodePrecondition = nodePrecondition
	}
	return node
}

func (node *BevNode) SetDebugName(_debugName string) *BevNode {
	node.debugName = _debugName
	return node
}

func (node *BevNode) GetLastActiveNode() *BevNode {
	return node.lastActiveNode
}

func (node *BevNode) setActiveNode(activeNode *BevNode) {
	node.lastActiveNode = node.activeNode
	node.activeNode = activeNode

	if node.parentNode != nil {
		node.parentNode.setActiveNode(activeNode)
	}
}

func (node *BevNode) GetDebugName() string {
	return node.debugName
}

func (node *BevNode) Evaluate(input interface{}) bool {
	return (node.nodePrecondition == nil || node.nodePrecondition.ExternalCondition(input)) && node.doEvaluate(input)
}

func (node *BevNode) Transition(input interface{}) {
	node.doTransition(input)
}

func (node *BevNode) Tick(input interface{}, output interface{}) BevRunningStatus {
	return node.doTick(input, output)
}

func (node *BevNode) doEvaluate(input interface{}) bool {
	return true
}

func (node *BevNode) doTransition(input interface{}) {
}

func (node *BevNode) doTick(input interface{}, output interface{}) BevRunningStatus {
	return StateFinish
}

func (node *BevNode) setParentNode(parentNode *BevNode) {
	node.parentNode = parentNode
}

func (node *BevNode) checkIndex(index int) bool {
	return index >= 0 && index < node.childNodeCount
}

/*
 *
 */
type BevNodePrioritySelector struct {
	*BevNode
	currentSelectIndex int
	lastSelectIndex    int
}

func NewBevNodePrioritySelector(parentNode *BevNode, nodePrecondition BevNodePrecondition) *BevNodePrioritySelector {
	return &BevNodePrioritySelector{NewBevNode(parentNode, nodePrecondition), k_BLimited_InvalidChildNodeIndex, k_BLimited_InvalidChildNodeIndex}
}

func (node *BevNodePrioritySelector) doEvaluate(input interface{}) bool {
	node.currentSelectIndex = k_BLimited_InvalidChildNodeIndex
	for i := 0; i < node.childNodeCount; i++ {
		if node.childNodeList[i].Evaluate(input) {
			node.currentSelectIndex = i
			return true
		}
	}
	return false
}

func (node *BevNodePrioritySelector) doTransition(input interface{}) {
	if node.checkIndex(node.lastSelectIndex) {
		node.childNodeList[node.lastSelectIndex].doTransition(input)
	}
	node.lastSelectIndex = k_BLimited_InvalidChildNodeIndex
}

func (node *BevNodePrioritySelector) doTick(input interface{}, output interface{}) BevRunningStatus {
	var isFinish BevRunningStatus = StateFinish

	if node.checkIndex(node.currentSelectIndex) {
		if node.lastSelectIndex != node.currentSelectIndex {
			if node.checkIndex(node.lastSelectIndex) {
				lastNode := node.childNodeList[node.lastSelectIndex]
				lastNode.Transition(input)
			}
			node.lastSelectIndex = node.currentSelectIndex
		}
	}

	if node.checkIndex(node.lastSelectIndex) {
		curNode := node.childNodeList[node.lastSelectIndex]
		isFinish = curNode.Tick(input, output)
		if isFinish == StateFinish {
			node.lastSelectIndex = k_BLimited_InvalidChildNodeIndex
		}
	}

	return isFinish
}

/*
 *
 */
type BevNodeNonePrioritySelector struct {
	*BevNodePrioritySelector
}

func NewBevNodeNonePrioritySelector(parentNode *BevNode, nodePrecondition BevNodePrecondition) *BevNodeNonePrioritySelector {
	return &BevNodeNonePrioritySelector{NewBevNodePrioritySelector(parentNode, nodePrecondition)}
}

func (node *BevNodeNonePrioritySelector) doEvaluate(input interface{}) bool {
	if node.checkIndex(node.currentSelectIndex) {
		curNode := node.childNodeList[node.currentSelectIndex]
		if curNode.Evaluate(input) {
			return true
		}
	}
	return node.Evaluate(input)
}

/*
 *
 */
type BevNodeRandomSelector struct {
	*BevNodePrioritySelector
}

func NewBevNodeRandomSelector(parentNode *BevNode, nodePrecondition BevNodePrecondition) *BevNodeRandomSelector {
	return &BevNodeRandomSelector{NewBevNodePrioritySelector(parentNode, nodePrecondition)}
}

func (node *BevNodeRandomSelector) doEvaluate(input interface{}) bool {
	if node.childNodeCount >= 1 {
		randomIndex := rand.Intn(node.childNodeCount)
		if node.childNodeList[randomIndex].Evaluate(input) == true {
			node.currentSelectIndex = randomIndex
			return true
		}
	}
	return false
}

/*
 *
 */
type BevNodeSequence struct {
	*BevNode
	currentSelectIndex int
}

func NewBevNodeSequence(parentNode *BevNode, nodePrecondition BevNodePrecondition) *BevNodeSequence {
	return &BevNodeSequence{NewBevNode(parentNode, nodePrecondition), k_BLimited_InvalidChildNodeIndex}
}

func (node *BevNodeSequence) doEvaluate(input interface{}) bool {
	Index := node.currentSelectIndex
	if !node.checkIndex(node.currentSelectIndex) && node.checkIndex(0) {
		Index = 0
	}
	if node.checkIndex(Index) {
		return node.childNodeList[Index].Evaluate(input)
	}
	return false
}

func (node *BevNodeSequence) doTransition(input interface{}) {
	if node.checkIndex(node.currentSelectIndex) {
		node.childNodeList[node.currentSelectIndex].Transition(input)
	}
	node.currentSelectIndex = k_BLimited_InvalidChildNodeIndex
}

func (node *BevNodeSequence) doTick(input interface{}, output interface{}) BevRunningStatus {
	var bIsFinish BevRunningStatus = StateFinish

	if !node.checkIndex(node.currentSelectIndex) && node.checkIndex(0) {
		node.currentSelectIndex = 0
	}

	if node.checkIndex(node.currentSelectIndex) {
		bIsFinish = node.childNodeList[node.currentSelectIndex].Tick(input, output)
		if bIsFinish == StateFinish {
			node.currentSelectIndex += 1
			if node.currentSelectIndex >= node.childNodeCount {
				bIsFinish = StateFinish
			} else {
				bIsFinish = StateExecuting
			}
		}
	}

	if bIsFinish < 0 {
		node.currentSelectIndex = k_BLimited_InvalidChildNodeIndex
	}

	return bIsFinish
}

/*
 *
 */
type BevNodeParallel struct {
	*BevNode
}

func NewBevNodeParallel(parentNode *BevNode, nodePrecondition BevNodePrecondition) *BevNodeParallel {
	return &BevNodeParallel{NewBevNode(parentNode, nodePrecondition)}
}

func (node *BevNodeParallel) doEvaluate(input interface{}) bool {
	for i := 0; i < node.childNodeCount; i++ {
		if !node.childNodeList[i].Evaluate(input) {
			return false
		}
	}
	return true
}

func (node *BevNodeParallel) doTransition(input interface{}) {
	for i := 0; i < node.childNodeCount; i++ {
		node.childNodeList[i].Transition(input)
	}
}

func (node *BevNodeParallel) doTick(input interface{}, output interface{}) BevRunningStatus {
	for i := 0; i < node.childNodeCount; i++ {
		if node.childNodeList[i].Tick(input, output) != StateFinish {
			return StateExecuting
		}
	}
	return StateFinish
}

/*
 *
 */
type BevNodeLoop struct {
	*BevNode
	loopCount    int
	currentCount int
}

func NewBevNodeLoop(parentNode *BevNode, nodePrecondition BevNodePrecondition, totalLoopCount int) *BevNodeLoop {
	return &BevNodeLoop{NewBevNode(parentNode, nodePrecondition), totalLoopCount, 0}
}

func (node *BevNodeLoop) doEvaluate(input interface{}) bool {
	checkLoop := node.loopCount != kInfiniteLoop && node.currentCount > node.loopCount

	if !checkLoop {
		return false
	} else if node.checkIndex(0) {
		return node.childNodeList[0].Evaluate(input)
	} else {
		return false
	}
}

func (node *BevNodeLoop) doTransition(input interface{}) {
	if node.checkIndex(0) {
		node.childNodeList[0].Transition(input)
	}
}

func (node *BevNodeLoop) doTick(input interface{}, output interface{}) BevRunningStatus {
	if node.checkIndex(0) && node.childNodeList[0].Tick(input, output) == StateFinish {
		node.currentCount = node.currentCount + 1
	}

	if node.loopCount != kInfiniteLoop && node.currentCount > node.loopCount {
		return StateFinish
	} else {
		return StateExecuting
	}
}

/*
 *
 */
type BevNodeTerminal struct {
	*BevNode
	nodeStatus E_TerminalNodeStaus
	needExit   bool
}

func NewBevNodeTerminal(parentNode *BevNode, nodePrecondition BevNodePrecondition) *BevNodeTerminal {
	return &BevNodeTerminal{NewBevNode(parentNode, nodePrecondition), NodeReady, false}
}

func (node *BevNodeTerminal) doTransition(input interface{}) {
	if node.needExit {
		node.doExit(input, StateTransition)
	}

	node.setActiveNode(nil)
	node.nodeStatus = NodeReady
	node.needExit = false
}

func (node *BevNodeTerminal) doTick(input interface{}, output interface{}) BevRunningStatus {
	var bIsFinish BevRunningStatus = StateFinish

	if node.nodeStatus == NodeReady {
		node.Enter(input)
		node.needExit = true
		node.nodeStatus = NodeRunning
		// node.setActiveNode(node)
	}

	if node.nodeStatus == NodeRunning {
		bIsFinish = node.Execute(input, output)
		// node.setActiveNode(node)
		if bIsFinish == StateFinish || bIsFinish < 0 {
			node.nodeStatus = NodeFinish
		}
	}

	if node.nodeStatus == NodeFinish {
		if node.needExit {
			node.Exit(input, bIsFinish)
		}

		node.nodeStatus = NodeReady
		node.needExit = false
		node.setActiveNode(nil)
	}

	return bIsFinish
}

func (node *BevNodeTerminal) Enter(input interface{}) {
	node.doEnter(input)
}

func (node *BevNodeTerminal) Execute(input interface{}, output interface{}) BevRunningStatus {
	return node.doExecute(input, output)
}

func (node *BevNodeTerminal) Exit(input interface{}, exitStatus BevRunningStatus) {
	node.doExit(input, exitStatus)
}

func (node *BevNodeTerminal) doEnter(input interface{}) {

}

func (node *BevNodeTerminal) doExecute(input interface{}, output interface{}) BevRunningStatus {
	return StateFinish
}

func (node *BevNodeTerminal) doExit(input interface{}, exitStatus BevRunningStatus) {

}
<|endoftext|>


<commit_before>package dirty

import (
	"log"
	"os"

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

type Dirty struct {
	*martini.Martini
	logger *log.Logger
}

func New() *Dirty {
	d := &Dirty{martini.New(), log.New(os.Stdout, "[dirty] ", 0)}
	d.Map(d.logger)
	return d
}

func (d *Dirty) SetLoggerPrefix(name string) {
	d.logger.SetPrefix(name)
}

type ClassicDirty struct {
	*Dirty
	Router
}

func Classic() *ClassicDirty {

	r := NewRouter()
	d := New()

	d.Use(martini.Logger())
	d.Use(martini.Recovery())
	d.Use(martini.Static("public"))

	d.Use(HelperMiddleware()) // Setup helper variables and methods for this request

	d.MapTo(r, (*martini.Routes)(nil))
	d.Action(r.Handle)

	return &ClassicDirty{d, r}

}
<commit_msg>Added DirtyClassicWiithFallback<commit_after>package dirty

import (
	"log"
	"os"

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

type Dirty struct {
	*martini.Martini
	logger *log.Logger
}

func New() *Dirty {
	d := &Dirty{martini.New(), log.New(os.Stdout, "[dirty] ", 0)}
	d.Map(d.logger)
	return d
}

func (d *Dirty) SetLoggerPrefix(name string) {
	d.logger.SetPrefix(name)
}

type ClassicDirty struct {
	*Dirty
	Router
}

func Classic() *ClassicDirty {

	r := NewRouter()
	d := New()

	d.Use(martini.Logger())
	d.Use(martini.Recovery())
	d.Use(martini.Static("public"))

	d.Use(HelperMiddleware()) // Setup helper variables and methods for this request

	d.MapTo(r, (*martini.Routes)(nil))
	d.Action(r.Handle)

	return &ClassicDirty{d, r}

}

func ClassicWithFallback(fallback, exclude string) *ClassicDirty {

	r := NewRouter()
	d := New()

	d.Use(martini.Logger())
	d.Use(martini.Recovery())
	d.Use(martini.Static("public", martini.StaticOptions{Fallback: fallback, Exclude: exclude}))

	d.Use(HelperMiddleware()) // Setup helper variables and methods for this request

	d.MapTo(r, (*martini.Routes)(nil))
	d.Action(r.Handle)

	return &ClassicDirty{d, r}

}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package simplepush

import (
	"fmt"
	"log"
	"os"
	"runtime"
	"strconv"
	"strings"
)

// Log levels
type LogLevel int32

const (
	CRITICAL LogLevel = iota
	ERROR
	WARNING
	INFO
	DEBUG
)

type LogFields map[string]string

type Logger interface {
	HasConfigStruct
	Log(level LogLevel, messageType, payload string, fields LogFields)
	ShouldLog(level LogLevel) bool
}

var AvailableLoggers = make(AvailableExtensions)

type SimpleLogger struct {
	Logger
}

// Error string helper that ignores nil errors
func ErrStr(err error) string {
	if err == nil {
		return ""
	} else {
		return err.Error()
	}
}

// Attempt to convert an interface to a string, ignore failures
func IStr(i interface{}) (reply string) {
	if i == nil {
		return ""
	}
	if reply, ok := i.(string); ok {
		return reply
	}
	return "Undefined"
}

// SimplePush Logger implementation, utilizes the passed in Logger
func NewLogger(log Logger) (*SimpleLogger, error) {
	return &SimpleLogger{log}, nil
}

// Default logging calls for convenience
func (sl *SimpleLogger) Info(mtype, msg string, fields LogFields) {
	sl.Logger.Log(INFO, mtype, msg, fields)
}

func (sl *SimpleLogger) Debug(mtype, msg string, fields LogFields) {
	sl.Logger.Log(DEBUG, mtype, msg, fields)
}

func (sl *SimpleLogger) Warn(mtype, msg string, fields LogFields) {
	sl.Logger.Log(WARNING, mtype, msg, fields)
}

func (sl *SimpleLogger) Error(mtype, msg string, fields LogFields) {
	sl.Logger.Log(ERROR, mtype, msg, fields)
}

func (sl *SimpleLogger) Critical(mtype, msg string, fields LogFields) {
	sl.Logger.Log(CRITICAL, mtype, msg, fields)
}

// Standard output logger implementation

type StdOutLoggerConfig struct {
	Filter int32
	Trace  bool
}

type StdOutLogger struct {
	logname  string
	pid      int32
	hostname string
	tracer   bool
	filter   LogLevel
}

func (ml *StdOutLogger) ConfigStruct() interface{} {
	return &StdOutLoggerConfig{
		Filter: 0,
		Trace:  false,
	}
}

func (ml *StdOutLogger) Init(app *Application, config interface{}) (err error) {
	conf := config.(*StdOutLoggerConfig)
	ml.pid = int32(os.Getpid())
	ml.hostname = app.Hostname()
	ml.tracer = conf.Trace
	ml.filter = LogLevel(conf.Filter)
	return
}

func (ml *StdOutLogger) ShouldLog(level LogLevel) bool {
	return level < ml.filter
}

func (ml *StdOutLogger) Log(level LogLevel, messageType, payload string, fields LogFields) {
	// Return ASAP if we shouldn't be logging
	if !ml.ShouldLog(level) {
		return
	}

	var caller LogFields
	// add in go language tracing. (Also CPU intensive, but REALLY helpful
	// when dev/debugging)
	if ml.tracer {
		if pc, file, line, ok := runtime.Caller(2); ok {
			funk := runtime.FuncForPC(pc)
			caller = LogFields{
				"file": file,
				// defaults don't appear to work.: file,
				"line": strconv.FormatInt(int64(line), 0),
				"name": funk.Name()}
		}
	}

	dump := fmt.Sprintf("[%d]% 7s: %s", level, messageType, payload)
	if len(fields) > 0 {
		var fld []string
		for key, val := range fields {
			fld = append(fld, key+": "+val)
		}
		dump += " {" + strings.Join(fld, ", ") + "}"
	}
	if len(caller) > 0 {
		dump += fmt.Sprintf(" [%s:%s %s]", caller["file"],
			caller["line"], caller["name"])
	}
	log.Printf(dump)
	return
}

func init() {
	AvailableLoggers["stdout"] = func() HasConfigStruct { return new(StdOutLogger) }
}
<commit_msg>sprintf is our friend.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package simplepush

import (
	"fmt"
	"log"
	"os"
	"runtime"
	"strconv"
	"strings"
)

// Log levels
type LogLevel int32

const (
	CRITICAL LogLevel = iota
	ERROR
	WARNING
	INFO
	DEBUG
)

type LogFields map[string]string

type Logger interface {
	HasConfigStruct
	Log(level LogLevel, messageType, payload string, fields LogFields)
	ShouldLog(level LogLevel) bool
}

var AvailableLoggers = make(AvailableExtensions)

type SimpleLogger struct {
	Logger
}

// Error string helper that ignores nil errors
func ErrStr(err error) string {
	if err == nil {
		return ""
	} else {
		return err.Error()
	}
}

// Attempt to convert an interface to a string, ignore failures
func IStr(i interface{}) (reply string) {
	if i == nil {
		return ""
	}
	if reply, ok := i.(string); ok {
		return reply
	}
	return "Undefined"
}

// SimplePush Logger implementation, utilizes the passed in Logger
func NewLogger(log Logger) (*SimpleLogger, error) {
	return &SimpleLogger{log}, nil
}

// Default logging calls for convenience
func (sl *SimpleLogger) Info(mtype, msg string, fields LogFields) {
	sl.Logger.Log(INFO, mtype, msg, fields)
}

func (sl *SimpleLogger) Debug(mtype, msg string, fields LogFields) {
	sl.Logger.Log(DEBUG, mtype, msg, fields)
}

func (sl *SimpleLogger) Warn(mtype, msg string, fields LogFields) {
	sl.Logger.Log(WARNING, mtype, msg, fields)
}

func (sl *SimpleLogger) Error(mtype, msg string, fields LogFields) {
	sl.Logger.Log(ERROR, mtype, msg, fields)
}

func (sl *SimpleLogger) Critical(mtype, msg string, fields LogFields) {
	sl.Logger.Log(CRITICAL, mtype, msg, fields)
}

// Standard output logger implementation

type StdOutLoggerConfig struct {
	Filter int32
	Trace  bool
}

type StdOutLogger struct {
	logname  string
	pid      int32
	hostname string
	tracer   bool
	filter   LogLevel
}

func (ml *StdOutLogger) ConfigStruct() interface{} {
	return &StdOutLoggerConfig{
		Filter: 0,
		Trace:  false,
	}
}

func (ml *StdOutLogger) Init(app *Application, config interface{}) (err error) {
	conf := config.(*StdOutLoggerConfig)
	ml.pid = int32(os.Getpid())
	ml.hostname = app.Hostname()
	ml.tracer = conf.Trace
	ml.filter = LogLevel(conf.Filter)
	return
}

func (ml *StdOutLogger) ShouldLog(level LogLevel) bool {
	return level < ml.filter
}

func (ml *StdOutLogger) Log(level LogLevel, messageType, payload string, fields LogFields) {
	// Return ASAP if we shouldn't be logging
	if !ml.ShouldLog(level) {
		return
	}

	var caller LogFields
	// add in go language tracing. (Also CPU intensive, but REALLY helpful
	// when dev/debugging)
	if ml.tracer {
		if pc, file, line, ok := runtime.Caller(2); ok {
			funk := runtime.FuncForPC(pc)
			caller = LogFields{
				"file": file,
				// defaults don't appear to work.: file,
				"line": strconv.FormatInt(int64(line), 0),
				"name": funk.Name()}
		}
	}

	dump := fmt.Sprintf("[%d]% 7s: %s", level, messageType, payload)
	if len(fields) > 0 {
		var fld []string
		for key, val := range fields {
			fld = append(fld, key+": "+val)
		}
		dump = fmt.Sprintf("%s {%s}", dump, strings.Join(fld, ", "))
	}
	if len(caller) > 0 {
		dump = fmt.Sprintf("%s [%s:%s %s]", dump, caller["file"],
			caller["line"], caller["name"])
	}
	log.Printf(dump)
	return
}

func init() {
	AvailableLoggers["stdout"] = func() HasConfigStruct { return new(StdOutLogger) }
}
<|endoftext|>