<commit_before>package async

import (
	"sync"
	"sync/atomic"
)

type Result struct {
	Done  <-chan struct{}
	Error <-chan error
}

// All starts all functions concurrently
// if any error occurs it will be sent to the Error channel
// after all functions have terminated the Done channel will get a single value
func All(fns ...func() error) Result {
	done := make(chan struct{}, 1)
	errs := make(chan error, len(fns))

	waiting := int32(len(fns))

	for _, fn := range fns {
		go func(fn func() error) {
			if err := fn(); err != nil {
				errs <- err
			}

			if atomic.AddInt32(&waiting, -1) == 0 {
				done <- struct{}{}
				close(errs)
				close(done)
			}
		}(fn)
	}

	if len(fns) == 0 {
		done <- struct{}{}
		close(errs)
		close(done)
	}

	return Result{done, errs}
}

// Spawns N routines, after each completes runs all whendone functions
func Spawn(N int, fn func(id int), whendone ...func()) {
	waiting := int32(N)
	for k := 0; k < N; k += 1 {
		go func(k int) {
			fn(k)
			if atomic.AddInt32(&waiting, -1) == 0 {
				for _, fn := range whendone {
					fn()
				}
			}
		}(int(k))
	}
}

// Run N routines and wait for all to complete
func Run(N int, fn func(id int)) {
	var wg sync.WaitGroup
	wg.Add(N)
	for k := 0; k < N; k += 1 {
		go func(k int) {
			fn(k)
			wg.Done()
		}(int(k))
	}
	wg.Wait()
}

// Spawns N routines, iterating over [0..Count) items in increasing order
func Iter(Count int, N int, fn func(i int)) {
	var wg sync.WaitGroup
	wg.Add(N)
	i := int64(0)
	for k := 0; k < N; k += 1 {
		go func() {
			defer wg.Done()
			for {
				idx := int(atomic.AddInt64(&i, 1) - 1)
				if idx >= Count {
					break
				}
				fn(idx)
			}
		}()
	}
	wg.Wait()
}

// Spawns N routines, iterating over [0..Count] items by splitting
// them into blocks [start..limit), note that item "limit" shouldn't be
// processed.
func BlockIter(Count int, N int, fn func(start, limit int)) {
	var wg sync.WaitGroup

	start, left := 0, Count
	for k := 0; k < N; k += 1 {
		count := (left + (N - k - 1)) / (N - k)
		limit := start + count
		if limit >= Count {
			limit = Count
		}
		wg.Add(1)
		go func(start, limit int) {
			defer wg.Done()
			fn(start, limit)
		}(start, limit)
		start = start + count
		left -= count
		if left <= 0 {
			break
		}
	}
	wg.Wait()
}
<commit_msg>Add wait function.<commit_after>package async

import (
	"sync"
	"sync/atomic"
)

type Result struct {
	Done  <-chan struct{}
	Error <-chan error
}

func (r *Result) Wait() []error {
	select {
	case <-r.Done:
		var errs []error
		for err := range r.Error {
			errs = append(errs, err)
		}
		if len(errs) > 0 {
			return errs
		}
		return nil
	}
}

// All starts all functions concurrently
// if any error occurs it will be sent to the Error channel
// after all functions have terminated the Done channel will get a single value
func All(fns ...func() error) Result {
	done := make(chan struct{}, 1)
	errs := make(chan error, len(fns))

	waiting := int32(len(fns))

	for _, fn := range fns {
		go func(fn func() error) {
			if err := fn(); err != nil {
				errs <- err
			}

			if atomic.AddInt32(&waiting, -1) == 0 {
				done <- struct{}{}
				close(errs)
				close(done)
			}
		}(fn)
	}

	if len(fns) == 0 {
		done <- struct{}{}
		close(errs)
		close(done)
	}

	return Result{done, errs}
}

// Spawns N routines, after each completes runs all whendone functions
func Spawn(N int, fn func(id int), whendone ...func()) {
	waiting := int32(N)
	for k := 0; k < N; k += 1 {
		go func(k int) {
			fn(k)
			if atomic.AddInt32(&waiting, -1) == 0 {
				for _, fn := range whendone {
					fn()
				}
			}
		}(int(k))
	}
}

// Run N routines and wait for all to complete
func Run(N int, fn func(id int)) {
	var wg sync.WaitGroup
	wg.Add(N)
	for k := 0; k < N; k += 1 {
		go func(k int) {
			fn(k)
			wg.Done()
		}(int(k))
	}
	wg.Wait()
}

// Spawns N routines, iterating over [0..Count) items in increasing order
func Iter(Count int, N int, fn func(i int)) {
	var wg sync.WaitGroup
	wg.Add(N)
	i := int64(0)
	for k := 0; k < N; k += 1 {
		go func() {
			defer wg.Done()
			for {
				idx := int(atomic.AddInt64(&i, 1) - 1)
				if idx >= Count {
					break
				}
				fn(idx)
			}
		}()
	}
	wg.Wait()
}

// Spawns N routines, iterating over [0..Count] items by splitting
// them into blocks [start..limit), note that item "limit" shouldn't be
// processed.
func BlockIter(Count int, N int, fn func(start, limit int)) {
	var wg sync.WaitGroup

	start, left := 0, Count
	for k := 0; k < N; k += 1 {
		count := (left + (N - k - 1)) / (N - k)
		limit := start + count
		if limit >= Count {
			limit = Count
		}
		wg.Add(1)
		go func(start, limit int) {
			defer wg.Done()
			fn(start, limit)
		}(start, limit)
		start = start + count
		left -= count
		if left <= 0 {
			break
		}
	}
	wg.Wait()
}
<|endoftext|>


<commit_before>/*
Copyright 2014 The Kubernetes Authors All rights reserved.

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 scheduler

// Note: if you change code in this file, you might need to change code in
// contrib/mesos/pkg/scheduler/.

import (
	"time"

	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/client/record"
	"k8s.io/kubernetes/pkg/util/wait"
	"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm"
	"k8s.io/kubernetes/plugin/pkg/scheduler/metrics"
	"k8s.io/kubernetes/plugin/pkg/scheduler/schedulercache"

	"github.com/golang/glog"
)

// Binder knows how to write a binding.
type Binder interface {
	Bind(binding *api.Binding) error
}

type PodConditionUpdater interface {
	Update(pod *api.Pod, podCondition *api.PodCondition) error
}

// Scheduler watches for new unscheduled pods. It attempts to find
// nodes that they fit on and writes bindings back to the api server.
type Scheduler struct {
	config *Config
}

type Config struct {
	// It is expected that changes made via SchedulerCache will be observed
	// by NodeLister and Algorithm.
	SchedulerCache schedulercache.Cache
	NodeLister     algorithm.NodeLister
	Algorithm      algorithm.ScheduleAlgorithm
	Binder         Binder
	// PodConditionUpdater is used only in case of scheduling errors. If we succeed
	// with scheduling, PodScheduled condition will be updated in apiserver in /bind
	// handler so that binding and setting PodCondition it is atomic.
	PodConditionUpdater PodConditionUpdater

	// NextPod should be a function that blocks until the next pod
	// is available. We don't use a channel for this, because scheduling
	// a pod may take some amount of time and we don't want pods to get
	// stale while they sit in a channel.
	NextPod func() *api.Pod

	// Error is called if there is an error. It is passed the pod in
	// question, and the error
	Error func(*api.Pod, error)

	// Recorder is the EventRecorder to use
	Recorder record.EventRecorder

	// Close this to shut down the scheduler.
	StopEverything chan struct{}
}

// New returns a new scheduler.
func New(c *Config) *Scheduler {
	s := &Scheduler{
		config: c,
	}
	metrics.Register()
	return s
}

// Run begins watching and scheduling. It starts a goroutine and returns immediately.
func (s *Scheduler) Run() {
	go wait.Until(s.scheduleOne, 0, s.config.StopEverything)
}

func (s *Scheduler) scheduleOne() {
	pod := s.config.NextPod()

	glog.V(3).Infof("Attempting to schedule: %+v", pod)
	start := time.Now()
	dest, err := s.config.Algorithm.Schedule(pod, s.config.NodeLister)
	if err != nil {
		glog.V(1).Infof("Failed to schedule: %+v", pod)
		s.config.Error(pod, err)
		s.config.Recorder.Eventf(pod, api.EventTypeWarning, "FailedScheduling", "%v", err)
		s.config.PodConditionUpdater.Update(pod, &api.PodCondition{
			Type:   api.PodScheduled,
			Status: api.ConditionFalse,
			Reason: "Unschedulable",
		})
		return
	}
	metrics.SchedulingAlgorithmLatency.Observe(metrics.SinceInMicroseconds(start))

	// Optimistically assume that the binding will succeed and send it to apiserver
	// in the background.
	// The only risk in this approach is that if the binding fails because of some
	// reason, scheduler will be assuming that it succeeded while scheduling next
	// pods, until the assumption in the internal cache expire (expiration is
	// defined as "didn't read the binding via watch within a given timeout",
	// timeout is currently set to 30s). However, after this timeout, the situation
	// will self-repair.
	assumed := *pod
	assumed.Spec.NodeName = dest
	s.config.SchedulerCache.AssumePod(&assumed)

	go func() {
		defer metrics.E2eSchedulingLatency.Observe(metrics.SinceInMicroseconds(start))

		b := &api.Binding{
			ObjectMeta: api.ObjectMeta{Namespace: pod.Namespace, Name: pod.Name},
			Target: api.ObjectReference{
				Kind: "Node",
				Name: dest,
			},
		}

		bindingStart := time.Now()
		// If binding succeded then PodScheduled condition will be updated in apiserver so that
		// it's atomic with setting host.
		err := s.config.Binder.Bind(b)
		if err != nil {
			glog.V(1).Infof("Failed to bind pod: %+v", err)
			s.config.Error(pod, err)
			s.config.Recorder.Eventf(pod, api.EventTypeNormal, "FailedScheduling", "Binding rejected: %v", err)
			s.config.PodConditionUpdater.Update(pod, &api.PodCondition{
				Type:   api.PodScheduled,
				Status: api.ConditionFalse,
				Reason: "BindingRejected",
			})
			return
		}
		metrics.BindingLatency.Observe(metrics.SinceInMicroseconds(bindingStart))
		s.config.Recorder.Eventf(pod, api.EventTypeNormal, "Scheduled", "Successfully assigned %v to %v", pod.Name, dest)
	}()
}
<commit_msg>Fix useless error message in scheduler log<commit_after>/*
Copyright 2014 The Kubernetes Authors All rights reserved.

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 scheduler

// Note: if you change code in this file, you might need to change code in
// contrib/mesos/pkg/scheduler/.

import (
	"time"

	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/client/record"
	"k8s.io/kubernetes/pkg/util/wait"
	"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm"
	"k8s.io/kubernetes/plugin/pkg/scheduler/metrics"
	"k8s.io/kubernetes/plugin/pkg/scheduler/schedulercache"

	"github.com/golang/glog"
)

// Binder knows how to write a binding.
type Binder interface {
	Bind(binding *api.Binding) error
}

type PodConditionUpdater interface {
	Update(pod *api.Pod, podCondition *api.PodCondition) error
}

// Scheduler watches for new unscheduled pods. It attempts to find
// nodes that they fit on and writes bindings back to the api server.
type Scheduler struct {
	config *Config
}

type Config struct {
	// It is expected that changes made via SchedulerCache will be observed
	// by NodeLister and Algorithm.
	SchedulerCache schedulercache.Cache
	NodeLister     algorithm.NodeLister
	Algorithm      algorithm.ScheduleAlgorithm
	Binder         Binder
	// PodConditionUpdater is used only in case of scheduling errors. If we succeed
	// with scheduling, PodScheduled condition will be updated in apiserver in /bind
	// handler so that binding and setting PodCondition it is atomic.
	PodConditionUpdater PodConditionUpdater

	// NextPod should be a function that blocks until the next pod
	// is available. We don't use a channel for this, because scheduling
	// a pod may take some amount of time and we don't want pods to get
	// stale while they sit in a channel.
	NextPod func() *api.Pod

	// Error is called if there is an error. It is passed the pod in
	// question, and the error
	Error func(*api.Pod, error)

	// Recorder is the EventRecorder to use
	Recorder record.EventRecorder

	// Close this to shut down the scheduler.
	StopEverything chan struct{}
}

// New returns a new scheduler.
func New(c *Config) *Scheduler {
	s := &Scheduler{
		config: c,
	}
	metrics.Register()
	return s
}

// Run begins watching and scheduling. It starts a goroutine and returns immediately.
func (s *Scheduler) Run() {
	go wait.Until(s.scheduleOne, 0, s.config.StopEverything)
}

func (s *Scheduler) scheduleOne() {
	pod := s.config.NextPod()

	glog.V(3).Infof("Attempting to schedule: %+v", pod)
	start := time.Now()
	dest, err := s.config.Algorithm.Schedule(pod, s.config.NodeLister)
	if err != nil {
		glog.V(1).Infof("Failed to schedule: %+v", pod)
		s.config.Error(pod, err)
		s.config.Recorder.Eventf(pod, api.EventTypeWarning, "FailedScheduling", "%v", err)
		s.config.PodConditionUpdater.Update(pod, &api.PodCondition{
			Type:   api.PodScheduled,
			Status: api.ConditionFalse,
			Reason: "Unschedulable",
		})
		return
	}
	metrics.SchedulingAlgorithmLatency.Observe(metrics.SinceInMicroseconds(start))

	// Optimistically assume that the binding will succeed and send it to apiserver
	// in the background.
	// The only risk in this approach is that if the binding fails because of some
	// reason, scheduler will be assuming that it succeeded while scheduling next
	// pods, until the assumption in the internal cache expire (expiration is
	// defined as "didn't read the binding via watch within a given timeout",
	// timeout is currently set to 30s). However, after this timeout, the situation
	// will self-repair.
	assumed := *pod
	assumed.Spec.NodeName = dest
	s.config.SchedulerCache.AssumePod(&assumed)

	go func() {
		defer metrics.E2eSchedulingLatency.Observe(metrics.SinceInMicroseconds(start))

		b := &api.Binding{
			ObjectMeta: api.ObjectMeta{Namespace: pod.Namespace, Name: pod.Name},
			Target: api.ObjectReference{
				Kind: "Node",
				Name: dest,
			},
		}

		bindingStart := time.Now()
		// If binding succeded then PodScheduled condition will be updated in apiserver so that
		// it's atomic with setting host.
		err := s.config.Binder.Bind(b)
		if err != nil {
			glog.V(1).Infof("Failed to bind pod: %v/%v", pod.Namespace, pod.Name)
			s.config.Error(pod, err)
			s.config.Recorder.Eventf(pod, api.EventTypeNormal, "FailedScheduling", "Binding rejected: %v", err)
			s.config.PodConditionUpdater.Update(pod, &api.PodCondition{
				Type:   api.PodScheduled,
				Status: api.ConditionFalse,
				Reason: "BindingRejected",
			})
			return
		}
		metrics.BindingLatency.Observe(metrics.SinceInMicroseconds(bindingStart))
		s.config.Recorder.Eventf(pod, api.EventTypeNormal, "Scheduled", "Successfully assigned %v to %v", pod.Name, dest)
	}()
}
<|endoftext|>


<commit_before>package auth

import (
	"encoding/base64"
	"net/http"
	"strings"
)

// Realm is used when setting the WWW-Authenticate response header.
var Realm = "Authorization Required"

// Basic returns a Handler that authenticates via Basic Auth. Writes a http.StatusUnauthorized
// if authentication fails.
func Basic(username string, password string) http.HandlerFunc {
	var siteAuth = base64.StdEncoding.EncodeToString([]byte(username + ":" + password))
	return func(res http.ResponseWriter, req *http.Request) {
		auth := req.Header.Get("Authorization")
		if !SecureCompare(auth, "Basic "+siteAuth) {
			unauthorized(res)
		}
	}
}

// BasicFunc returns a Handler that authenticates via Basic Auth using the provided function.
// The function should return true for a valid username/password combination.
func BasicFunc(authfn func(string, string) bool) http.HandlerFunc {
	return func(res http.ResponseWriter, req *http.Request) {
		auth := req.Header.Get("Authorization")
		if len(auth) < 6 || auth[:6] != "Basic " {
			unauthorized(res)
			return
		}
		b, err := base64.StdEncoding.DecodeString(auth[6:])
		if err != nil {
			unauthorized(res)
			return
		}
		tokens := strings.SplitN(string(b), ":", 2)
		if len(tokens) != 2 || !authfn(tokens[0], tokens[1]) {
			unauthorized(res)
		}
	}
}

func unauthorized(res http.ResponseWriter) {
	res.Header().Set("WWW-Authenticate", "Basic realm=\"" + Realm + "\"")
	http.Error(res, "Not Authorized", http.StatusUnauthorized)
}
<commit_msg>rename Realm to BasicRealm<commit_after>package auth

import (
	"encoding/base64"
	"net/http"
	"strings"
)

// BasicRealm is used when setting the WWW-Authenticate response header.
var BasicRealm = "Authorization Required"

// Basic returns a Handler that authenticates via Basic Auth. Writes a http.StatusUnauthorized
// if authentication fails.
func Basic(username string, password string) http.HandlerFunc {
	var siteAuth = base64.StdEncoding.EncodeToString([]byte(username + ":" + password))
	return func(res http.ResponseWriter, req *http.Request) {
		auth := req.Header.Get("Authorization")
		if !SecureCompare(auth, "Basic "+siteAuth) {
			unauthorized(res)
		}
	}
}

// BasicFunc returns a Handler that authenticates via Basic Auth using the provided function.
// The function should return true for a valid username/password combination.
func BasicFunc(authfn func(string, string) bool) http.HandlerFunc {
	return func(res http.ResponseWriter, req *http.Request) {
		auth := req.Header.Get("Authorization")
		if len(auth) < 6 || auth[:6] != "Basic " {
			unauthorized(res)
			return
		}
		b, err := base64.StdEncoding.DecodeString(auth[6:])
		if err != nil {
			unauthorized(res)
			return
		}
		tokens := strings.SplitN(string(b), ":", 2)
		if len(tokens) != 2 || !authfn(tokens[0], tokens[1]) {
			unauthorized(res)
		}
	}
}

func unauthorized(res http.ResponseWriter) {
	res.Header().Set("WWW-Authenticate", "Basic realm=\"" + BasicRealm + "\"")
	http.Error(res, "Not Authorized", http.StatusUnauthorized)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"time"

	log "github.com/sirupsen/logrus"
	"github.com/yuin/gopher-lua"
)

func exportBasicSystemFunctions(L *lua.LState) {

	// Return the version string
	L.SetGlobal("version", L.NewFunction(func(L *lua.LState) int {
		L.Push(lua.LString(versionString))
		return 1 // number of results
	}))

	// Log text with the "Info" log type
	L.SetGlobal("log", L.NewFunction(func(L *lua.LState) int {
		buf := arguments2buffer(L, false)
		// Log the combined text
		log.Info(buf.String())
		return 0 // number of results
	}))

	// Log text with the "Warn" log type
	L.SetGlobal("warn", L.NewFunction(func(L *lua.LState) int {
		buf := arguments2buffer(L, false)
		// Log the combined text
		log.Warn(buf.String())
		return 0 // number of results
	}))

	// Log text with the "Error" log type
	L.SetGlobal("error", L.NewFunction(func(L *lua.LState) int {
		buf := arguments2buffer(L, false)
		// Log the combined text
		log.Error(buf.String())
		return 0 // number of results
	}))

	// Sleep for the given number of seconds (can be a float)
	L.SetGlobal("sleep", L.NewFunction(func(L *lua.LState) int {
		// Extract the correct number of nanoseconds
		duration := time.Duration(float64(L.ToNumber(1)) * 1000000000.0)
		// Wait and block the current thread of execution.
		time.Sleep(duration)
		return 0
	}))

}

// Make functions related to HTTP requests and responses available to Lua scripts.
// Filename can be an empty string.
// realW is only used for flushing the buffer in debug mode, and is the underlying ResponseWriter.
func exportBasicWeb(w http.ResponseWriter, req *http.Request, L *lua.LState, filename string, flushFunc func()) {

	// Print text to the webpage that is being served. Add a newline.
	L.SetGlobal("print", L.NewFunction(func(L *lua.LState) int {
		var buf bytes.Buffer
		top := L.GetTop()
		for i := 1; i <= top; i++ {
			buf.WriteString(L.Get(i).String())
			if i != top {
				buf.WriteString("\t")
			}
		}
		// Final newline
		buf.WriteString("\n")

		// Write the combined text to the http.ResponseWriter
		w.Write(buf.Bytes())

		return 0 // number of results
	}))

	// Flush the ResponseWriter.
	// Needed in debug mode, where ResponseWriter is buffered.
	L.SetGlobal("flush", L.NewFunction(func(L *lua.LState) int {
		if flushFunc != nil {
			flushFunc()
		}
		return 0 // number of results
	}))

	// Set the Content-Type for the page
	L.SetGlobal("content", L.NewFunction(func(L *lua.LState) int {
		lv := L.ToString(1)
		w.Header().Add("Content-Type", lv)
		return 0 // number of results
	}))

	// Return the current URL Path
	L.SetGlobal("urlpath", L.NewFunction(func(L *lua.LState) int {
		L.Push(lua.LString(req.URL.Path))
		return 1 // number of results
	}))

	// Return the current HTTP method (GET, POST etc)
	L.SetGlobal("method", L.NewFunction(func(L *lua.LState) int {
		L.Push(lua.LString(req.Method))
		return 1 // number of results
	}))

	// Return the HTTP headers as a table
	L.SetGlobal("headers", L.NewFunction(func(L *lua.LState) int {
		luaTable := L.NewTable()
		for key := range req.Header {
			L.RawSet(luaTable, lua.LString(key), lua.LString(req.Header.Get(key)))
		}
		L.Push(luaTable)
		return 1 // number of results
	}))

	// Return the HTTP header in the request, for a given key/string
	L.SetGlobal("header", L.NewFunction(func(L *lua.LState) int {
		key := L.ToString(1)
		value := req.Header.Get(key)
		L.Push(lua.LString(value))
		return 1 // number of results
	}))

	// Set the HTTP header in the request, for a given key and value
	L.SetGlobal("setheader", L.NewFunction(func(L *lua.LState) int {
		key := L.ToString(1)
		value := L.ToString(2)
		w.Header().Set(key, value)
		return 0 // number of results
	}))

	// Return the HTTP body in the request
	L.SetGlobal("body", L.NewFunction(func(L *lua.LState) int {
		body, err := ioutil.ReadAll(req.Body)
		var result lua.LString
		if err != nil {
			result = lua.LString("")
		} else {
			result = lua.LString(string(body))
		}
		L.Push(result)
		return 1 // number of results
	}))

	// Set the HTTP status code (must come before print)
	L.SetGlobal("status", L.NewFunction(func(L *lua.LState) int {
		code := int(L.ToNumber(1))
		w.WriteHeader(code)
		return 0 // number of results
	}))

	// Print a message and set the HTTP status code
	L.SetGlobal("error", L.NewFunction(func(L *lua.LState) int {
		message := L.ToString(1)
		code := int(L.ToNumber(2))
		w.WriteHeader(code)
		fmt.Fprint(w, message)
		return 0 // number of results
	}))

	// Get the full filename of a given file that is in the directory
	// of the script that is about to be run. If no filename is given,
	// the directory of the script is returned.
	L.SetGlobal("scriptdir", L.NewFunction(func(L *lua.LState) int {
		scriptpath, err := filepath.Abs(filename)
		if err != nil {
			scriptpath = filename
		}
		scriptdir := filepath.Dir(scriptpath)
		scriptpath = scriptdir
		top := L.GetTop()
		if top == 1 {
			// Also include a separator and a filename
			fn := L.ToString(1)
			scriptpath = filepath.Join(scriptdir, fn)
		}
		// Now have the correct absolute scriptpath
		L.Push(lua.LString(scriptpath))
		return 1 // number of results
	}))

	// Given a filename, return the URL path
	L.SetGlobal("file2url", L.NewFunction(func(L *lua.LState) int {
		fn := L.ToString(1)
		targetpath := filepath.Join(filepath.Dir(filename), fn)
		if strings.HasPrefix(targetpath, serverDir) {
			targetpath = targetpath[len(serverDir):]
		}
		if pathsep != "/" {
			// For operating systems that use another path separator for files than for URLs
			targetpath = strings.Replace(targetpath, pathsep, "/", everyInstance)
		}
		L.Push(lua.LString(targetpath))
		return 1 // number of results
	}))

	// Get the full filename of a given file that is in the directory
	// where the server is running (root directory for the server).
	// If no filename is given, the directory where the server is
	// currently running is returned.
	L.SetGlobal("serverdir", L.NewFunction(func(L *lua.LState) int {
		serverdir, err := os.Getwd()
		if err != nil {
			// Could not retrieve a directory
			serverdir = ""
		} else if L.GetTop() == 1 {
			// Also include a separator and a filename
			fn := L.ToString(1)
			serverdir = filepath.Join(serverdir, fn)
		}
		L.Push(lua.LString(serverdir))
		return 1 // number of results
	}))

	// Retrieve a table with keys and values from the form in the request
	L.SetGlobal("formdata", L.NewFunction(func(L *lua.LState) int {
		// Place the form data in a map
		m := make(map[string]string)
		req.ParseForm()
		for k, v := range req.Form {
			m[k] = v[0]
		}
		// Convert the map to a table and return it
		L.Push(map2table(L, m))
		return 1 // number of results
	}))

}
<commit_msg>Fixed file2url<commit_after>package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"path"
	"path/filepath"
	"strings"
	"time"

	log "github.com/sirupsen/logrus"
	"github.com/yuin/gopher-lua"
)

func exportBasicSystemFunctions(L *lua.LState) {

	// Return the version string
	L.SetGlobal("version", L.NewFunction(func(L *lua.LState) int {
		L.Push(lua.LString(versionString))
		return 1 // number of results
	}))

	// Log text with the "Info" log type
	L.SetGlobal("log", L.NewFunction(func(L *lua.LState) int {
		buf := arguments2buffer(L, false)
		// Log the combined text
		log.Info(buf.String())
		return 0 // number of results
	}))

	// Log text with the "Warn" log type
	L.SetGlobal("warn", L.NewFunction(func(L *lua.LState) int {
		buf := arguments2buffer(L, false)
		// Log the combined text
		log.Warn(buf.String())
		return 0 // number of results
	}))

	// Log text with the "Error" log type
	L.SetGlobal("error", L.NewFunction(func(L *lua.LState) int {
		buf := arguments2buffer(L, false)
		// Log the combined text
		log.Error(buf.String())
		return 0 // number of results
	}))

	// Sleep for the given number of seconds (can be a float)
	L.SetGlobal("sleep", L.NewFunction(func(L *lua.LState) int {
		// Extract the correct number of nanoseconds
		duration := time.Duration(float64(L.ToNumber(1)) * 1000000000.0)
		// Wait and block the current thread of execution.
		time.Sleep(duration)
		return 0
	}))

}

// Make functions related to HTTP requests and responses available to Lua scripts.
// Filename can be an empty string.
// realW is only used for flushing the buffer in debug mode, and is the underlying ResponseWriter.
func exportBasicWeb(w http.ResponseWriter, req *http.Request, L *lua.LState, filename string, flushFunc func()) {

	// Print text to the webpage that is being served. Add a newline.
	L.SetGlobal("print", L.NewFunction(func(L *lua.LState) int {
		var buf bytes.Buffer
		top := L.GetTop()
		for i := 1; i <= top; i++ {
			buf.WriteString(L.Get(i).String())
			if i != top {
				buf.WriteString("\t")
			}
		}
		// Final newline
		buf.WriteString("\n")

		// Write the combined text to the http.ResponseWriter
		w.Write(buf.Bytes())

		return 0 // number of results
	}))

	// Flush the ResponseWriter.
	// Needed in debug mode, where ResponseWriter is buffered.
	L.SetGlobal("flush", L.NewFunction(func(L *lua.LState) int {
		if flushFunc != nil {
			flushFunc()
		}
		return 0 // number of results
	}))

	// Set the Content-Type for the page
	L.SetGlobal("content", L.NewFunction(func(L *lua.LState) int {
		lv := L.ToString(1)
		w.Header().Add("Content-Type", lv)
		return 0 // number of results
	}))

	// Return the current URL Path
	L.SetGlobal("urlpath", L.NewFunction(func(L *lua.LState) int {
		L.Push(lua.LString(req.URL.Path))
		return 1 // number of results
	}))

	// Return the current HTTP method (GET, POST etc)
	L.SetGlobal("method", L.NewFunction(func(L *lua.LState) int {
		L.Push(lua.LString(req.Method))
		return 1 // number of results
	}))

	// Return the HTTP headers as a table
	L.SetGlobal("headers", L.NewFunction(func(L *lua.LState) int {
		luaTable := L.NewTable()
		for key := range req.Header {
			L.RawSet(luaTable, lua.LString(key), lua.LString(req.Header.Get(key)))
		}
		L.Push(luaTable)
		return 1 // number of results
	}))

	// Return the HTTP header in the request, for a given key/string
	L.SetGlobal("header", L.NewFunction(func(L *lua.LState) int {
		key := L.ToString(1)
		value := req.Header.Get(key)
		L.Push(lua.LString(value))
		return 1 // number of results
	}))

	// Set the HTTP header in the request, for a given key and value
	L.SetGlobal("setheader", L.NewFunction(func(L *lua.LState) int {
		key := L.ToString(1)
		value := L.ToString(2)
		w.Header().Set(key, value)
		return 0 // number of results
	}))

	// Return the HTTP body in the request
	L.SetGlobal("body", L.NewFunction(func(L *lua.LState) int {
		body, err := ioutil.ReadAll(req.Body)
		var result lua.LString
		if err != nil {
			result = lua.LString("")
		} else {
			result = lua.LString(string(body))
		}
		L.Push(result)
		return 1 // number of results
	}))

	// Set the HTTP status code (must come before print)
	L.SetGlobal("status", L.NewFunction(func(L *lua.LState) int {
		code := int(L.ToNumber(1))
		w.WriteHeader(code)
		return 0 // number of results
	}))

	// Print a message and set the HTTP status code
	L.SetGlobal("error", L.NewFunction(func(L *lua.LState) int {
		message := L.ToString(1)
		code := int(L.ToNumber(2))
		w.WriteHeader(code)
		fmt.Fprint(w, message)
		return 0 // number of results
	}))

	// Get the full filename of a given file that is in the directory
	// of the script that is about to be run. If no filename is given,
	// the directory of the script is returned.
	L.SetGlobal("scriptdir", L.NewFunction(func(L *lua.LState) int {
		scriptpath, err := filepath.Abs(filename)
		if err != nil {
			scriptpath = filename
		}
		scriptdir := filepath.Dir(scriptpath)
		scriptpath = scriptdir
		top := L.GetTop()
		if top == 1 {
			// Also include a separator and a filename
			fn := L.ToString(1)
			scriptpath = filepath.Join(scriptdir, fn)
		}
		// Now have the correct absolute scriptpath
		L.Push(lua.LString(scriptpath))
		return 1 // number of results
	}))

	// Given a filename, return the URL path
	L.SetGlobal("file2url", L.NewFunction(func(L *lua.LState) int {
		fn := L.ToString(1)
		targetpath := filepath.Join(filepath.Dir(filename), fn)
		if strings.HasPrefix(targetpath, serverDir) {
			targetpath = targetpath[len(serverDir):]
		}
		if pathsep != "/" {
			// For operating systems that use another path separator for files than for URLs
			targetpath = strings.Replace(targetpath, pathsep, "/", everyInstance)
		}
		withSlashPrefix := path.Join("/", targetpath)
		L.Push(lua.LString(withSlashPrefix))
		return 1 // number of results
	}))

	// Get the full filename of a given file that is in the directory
	// where the server is running (root directory for the server).
	// If no filename is given, the directory where the server is
	// currently running is returned.
	L.SetGlobal("serverdir", L.NewFunction(func(L *lua.LState) int {
		serverdir, err := os.Getwd()
		if err != nil {
			// Could not retrieve a directory
			serverdir = ""
		} else if L.GetTop() == 1 {
			// Also include a separator and a filename
			fn := L.ToString(1)
			serverdir = filepath.Join(serverdir, fn)
		}
		L.Push(lua.LString(serverdir))
		return 1 // number of results
	}))

	// Retrieve a table with keys and values from the form in the request
	L.SetGlobal("formdata", L.NewFunction(func(L *lua.LState) int {
		// Place the form data in a map
		m := make(map[string]string)
		req.ParseForm()
		for k, v := range req.Form {
			m[k] = v[0]
		}
		// Convert the map to a table and return it
		L.Push(map2table(L, m))
		return 1 // number of results
	}))

}
<|endoftext|>


<commit_before>package pixel

import (
	"image/color"

	"github.com/go-gl/mathgl/mgl32"
)

// Batch is a Target that allows for efficient drawing of many objects with the same Picture (but
// different slices of the same Picture are allowed).
//
// To put an object into a Batch, just draw it onto it:
//   object.Draw(batch)
type Batch struct {
	cont TrianglesDrawer

	pic *Picture
	mat mgl32.Mat3
	col NRGBA
}

// NewBatch creates an empty Batch with the specified Picture and container.
//
// The container is where objects get accumulated. Batch will support precisely those vertex
// properties, that the supplied container supports.
//
// Note, that if the container does not support TrianglesColor, color masking will not work.
func NewBatch(pic *Picture, container Triangles) *Batch {
	return &Batch{
		cont: TrianglesDrawer{Triangles: container},
		pic:  pic,
	}
}

// Clear removes all objects from the Batch.
func (b *Batch) Clear() {
	b.cont.Update(&TrianglesData{})
}

// Draw draws all objects that are currently in the Batch onto another Target.
func (b *Batch) Draw(t Target) {
	t.SetPicture(b.pic)
	b.cont.Draw(t)
}

// MakeTriangles returns a specialized copy of the provided Triangles, that draws onto this Batch.
func (b *Batch) MakeTriangles(t Triangles) Triangles {
	return &batchTriangles{
		Triangles: t.Copy(),
		trans:     t.Copy(),
		batch:     b,
	}
}

// SetPicture only checks, whether the supplied Picture has the same underlying Picture as the fixed
// Picture of this Batch. If that is not true, this method panics.
func (b *Batch) SetPicture(p *Picture) {
	if p == nil {
		return
	}
	if p.Texture() != b.pic.Texture() {
		panic("batch: attempted to draw with a different Picture")
	}
}

// SetTransform sets transforms used in the following draws onto the Batch.
func (b *Batch) SetTransform(t ...Transform) {
	b.mat = transformToMat(t...)
}

// SetMaskColor sets a mask color used in the following draws onto the Batch.
func (b *Batch) SetMaskColor(c color.Color) {
	if c == nil {
		b.col = NRGBA{1, 1, 1, 1}
		return
	}
	b.col = NRGBAModel.Convert(c).(NRGBA)
}

type batchTriangles struct {
	Triangles
	trans Triangles

	batch *Batch
}

func (bt *batchTriangles) Draw() {
	// need to apply transforms and mask color and picture bounds
	trans := make(TrianglesData, bt.Len())
	trans.Update(bt.Triangles)
	for i := range trans {
		transPos := bt.batch.mat.Mul3x1(mgl32.Vec3{
			float32(trans[i].Position.X()),
			float32(trans[i].Position.Y()),
			1,
		})
		trans[i].Position = V(float64(transPos.X()), float64(transPos.Y()))
		trans[i].Color = trans[i].Color.Mul(bt.batch.col)
		//TODO: texture
	}
	bt.trans.Update(&trans)
	bt.batch.cont.Append(bt.trans)
}
<commit_msg>optimize batch draw (reduce allocations)<commit_after>package pixel

import (
	"image/color"

	"github.com/go-gl/mathgl/mgl32"
)

// Batch is a Target that allows for efficient drawing of many objects with the same Picture (but
// different slices of the same Picture are allowed).
//
// To put an object into a Batch, just draw it onto it:
//   object.Draw(batch)
type Batch struct {
	cont TrianglesDrawer

	pic *Picture
	mat mgl32.Mat3
	col NRGBA
}

// NewBatch creates an empty Batch with the specified Picture and container.
//
// The container is where objects get accumulated. Batch will support precisely those vertex
// properties, that the supplied container supports.
//
// Note, that if the container does not support TrianglesColor, color masking will not work.
func NewBatch(pic *Picture, container Triangles) *Batch {
	return &Batch{
		cont: TrianglesDrawer{Triangles: container},
		pic:  pic,
	}
}

// Clear removes all objects from the Batch.
func (b *Batch) Clear() {
	b.cont.Update(&TrianglesData{})
}

// Draw draws all objects that are currently in the Batch onto another Target.
func (b *Batch) Draw(t Target) {
	t.SetPicture(b.pic)
	b.cont.Draw(t)
}

// MakeTriangles returns a specialized copy of the provided Triangles, that draws onto this Batch.
func (b *Batch) MakeTriangles(t Triangles) Triangles {
	return &batchTriangles{
		Triangles: t.Copy(),
		trans:     t.Copy(),
		batch:     b,
	}
}

// SetPicture only checks, whether the supplied Picture has the same underlying Picture as the fixed
// Picture of this Batch. If that is not true, this method panics.
func (b *Batch) SetPicture(p *Picture) {
	if p == nil {
		return
	}
	if p.Texture() != b.pic.Texture() {
		panic("batch: attempted to draw with a different Picture")
	}
}

// SetTransform sets transforms used in the following draws onto the Batch.
func (b *Batch) SetTransform(t ...Transform) {
	b.mat = transformToMat(t...)
}

// SetMaskColor sets a mask color used in the following draws onto the Batch.
func (b *Batch) SetMaskColor(c color.Color) {
	if c == nil {
		b.col = NRGBA{1, 1, 1, 1}
		return
	}
	b.col = NRGBAModel.Convert(c).(NRGBA)
}

type batchTriangles struct {
	Triangles
	trans Triangles
	data  TrianglesData

	batch *Batch
}

func (bt *batchTriangles) Draw() {
	// need to apply transforms and mask color and picture bounds
	bt.data.Update(bt.Triangles)
	for i := range bt.data {
		transPos := bt.batch.mat.Mul3x1(mgl32.Vec3{
			float32(bt.data[i].Position.X()),
			float32(bt.data[i].Position.Y()),
			1,
		})
		bt.data[i].Position = V(float64(transPos.X()), float64(transPos.Y()))
		bt.data[i].Color = bt.data[i].Color.Mul(bt.batch.col)
		//TODO: texture
	}
	bt.trans.Update(&bt.data)
	bt.batch.cont.Append(bt.trans)
}
<|endoftext|>


<commit_before>package models

import (
	"testing"

	"bitbucket.org/mundipagg/boletoapi/test"
	. "github.com/smartystreets/goconvey/convey"
)

func TestShouldReturnValidCpfOnDocumentType(t *testing.T) {
	document := Document{Number: "12345678901", Type: "CPF"}
	if document.IsCPF() == false {
		t.Fail()
	}
}

func TestShouldValidateDocumentNumber(t *testing.T) {
	h := Title{DocumentNumber: "1234567891011"}
	h.ValidateDocumentNumber()
	test.ExpectTrue(len(h.DocumentNumber) == 10, t)

	h.DocumentNumber = "123x"
	h.ValidateDocumentNumber()
	test.ExpectTrue(len(h.DocumentNumber) == 10, t)

	h.DocumentNumber = "xx"
	h.ValidateDocumentNumber()
	test.ExpectTrue(h.DocumentNumber == "", t)
}

func TestShouldReturnInvalidCpfOnDocumentType(t *testing.T) {
	document := Document{Number: "1234567890132", Type: "CNPJ"}
	if document.IsCNPJ() == false {
		t.Fail()
	}
}

func TestShouldReturnValidCnpjOnDocumentType(t *testing.T) {
	document := Document{Number: "1234567890132", Type: "CnpJ"}
	if document.IsCNPJ() == false {
		t.Fail()
	}
}

func TestShouldReturnInvalidCnpjOnDocumentType(t *testing.T) {
	document := Document{Number: "12345678901", Type: "CPF"}
	if document.IsCNPJ() {
		t.Fail()
	}
}

func TestShouldReturnValidCnpjOnDocumentNumber(t *testing.T) {
	document := Document{Number: "12345678901564fas", Type: "CNPJ"}
	if err := document.ValidateCNPJ(); err != nil {
		t.Fail()
	}
}

func TestShouldReturnInvalidCnpjOnDocumentNumber(t *testing.T) {
	document := Document{Number: "12345678901564asdf22", Type: "CNPJ"}
	if err := document.ValidateCNPJ(); err == nil {
		t.Fail()
	}
}

func TestShouldReturnBankNumberIsValid(t *testing.T) {
	var b BankNumber = 237

	if b.IsBankNumberValid() == false {
		t.Fail()
	}
}

func TestShouldAppendCollectionOfErrrors(t *testing.T) {
	e := NewErrorCollection(ErrorResponse{Code: "200", Message: "Hue2"})
	e.Append("100", "Hue")
	test.ExpectTrue(len(e) == 2, t)
}

func TestShouldCreateNewSingleErrorCollection(t *testing.T) {
	e := NewSingleErrorCollection("200", "Hue2")
	test.ExpectTrue(len(e) == 1, t)
}

func TestIsAgencyValid(t *testing.T) {
	Convey("Deve retornar um erro para a agência inválida", t, func() {
		a := Agreement{
			Agency: "234-2222a",
		}
		err := a.IsAgencyValid()
		So(err, ShouldNotBeNil)

		Convey("Deve ajustar a agência para ter a quantidade certa de dígitos", func() {
			a.Agency = "321"
			err := a.IsAgencyValid()
			So(a.Agency, ShouldEqual, "0321")
			So(err, ShouldBeNil)
		})
	})
}

func TestCalculateAgencyDigit(t *testing.T) {
	Convey("Deve ajustar o dígito da Agência quando ela tiver caracteres inválidos", t, func() {
		a := new(Agreement)
		a.AgencyDigit = "2sssss"
		c := func(s string) string {
			return "1"
		}
		a.CalculateAgencyDigit(c)
		So(a.AgencyDigit, ShouldEqual, "2")
		Convey("Deve calcular o dígito da Agência quando o fornecido for errado", func() {
			a.AgencyDigit = "332sssss"
			a.CalculateAgencyDigit(c)
			So(a.AgencyDigit, ShouldEqual, "1")
		})
	})
}

func TestCalculateAccountDigit(t *testing.T) {
	Convey("Deve ajustar o dígito da Conta quando ela tiver caracteres inválidos", t, func() {
		a := new(Agreement)
		a.AccountDigit = "2sssss"
		c := func(s, y string) string {
			return "1"
		}
		a.CalculateAccountDigit(c)
		So(a.AccountDigit, ShouldEqual, "2")
		Convey("Deve calcular o dígito da Conta quando o fornecido for errado", func() {
			a.AccountDigit = "332sssss"
			a.CalculateAccountDigit(c)
			So(a.AccountDigit, ShouldEqual, "1")
		})
	})
}

func TestIsAccountValid(t *testing.T) {
	Convey("Verifica se a conta é valida e formata para o tamanho correto", t, func() {
		a := Agreement{
			Account: "1234fff",
		}
		err := a.IsAccountValid(8)
		So(err, ShouldBeNil)
		So(a.Account, ShouldEqual, "00001234")
		Convey("Verifica se a conta é valida e retorna um erro", func() {
			a.Account = "654654654654654654654654654564"
			err := a.IsAccountValid(8)
			So(err, ShouldNotBeNil)
		})
	})
}
<commit_msg>:white_check_mark: Bota em 100% o coverage do Document e começa testes do Titel<commit_after>package models

import (
	"testing"

	"bitbucket.org/mundipagg/boletoapi/test"
	. "github.com/smartystreets/goconvey/convey"
)

func TestDocument(t *testing.T) {
	Convey("Espera que o tipo de documento passado seja um CPF", t, func() {
		document := Document{Number: "13245678901ssa", Type: "CPF"}
		So(document.IsCPF(), ShouldBeTrue)
		document.Type = "cPf"
		So(document.IsCPF(), ShouldBeTrue)
		Convey("Espera que o CPF seja válido", func() {
			err := document.ValidateCPF()
			So(err, ShouldBeNil)
			So(len(document.Number), ShouldEqual, 11)
		})
		Convey("Espera que o CPF seja inválido", func() {
			document.Number = "lasjdlf019239098adjal9390jflsadjf9309jfsl"
			err := document.ValidateCPF()
			So(err, ShouldNotBeNil)
		})
	})
	Convey("Espera que o tipo de documento seja um CNPJ", t, func() {
		document := Document{Number: "12345678901326asdfad", Type: "CNPJ"}
		So(document.IsCNPJ(), ShouldBeTrue)
		document.Type = "cnPj"
		So(document.IsCNPJ(), ShouldBeTrue)
		Convey("Espera que o CNPJ seja válido", func() {
			err := document.ValidateCNPJ()
			So(err, ShouldBeNil)
			So(len(document.Number), ShouldEqual, 14)
		})
		Convey("Espera que o CNPJ seja inválido", func() {
			document.Number = "lasjdlf019239098adjal9390jflsadjf9309jfsl"
			err := document.ValidateCNPJ()
			So(err, ShouldNotBeNil)
		})
	})
}

func TestTitle(t *testing.T) {
	Convey("O DocumentNumber deve conter 10 dígitos", t, func() {
		h := Title{DocumentNumber: "1234567891011"}
		err := h.ValidateDocumentNumber()
		So(err, ShouldBeNil)
		So(len(h.DocumentNumber), ShouldEqual, 10)

		Convey("O DocumentNumber mesmo com menos de 10 dígitos deve possuir 10 dígitos após ser validado com 0 a esquerda", func() {
			h.DocumentNumber = "123x"
			h.ValidateDocumentNumber()
			So(len(h.DocumentNumber), ShouldEqual, 10)
		})

		Convey("O DocumentNumber quando não possuir dígitos deve ser vazio", func() {
			h.DocumentNumber = "xx"
			h.ValidateDocumentNumber()
			So(h.DocumentNumber, ShouldBeEmpty)
		})

		Convey("O DocumentNumber quando for vazio deve permanecer vazio", func() {
			h.DocumentNumber = ""
			h.ValidateDocumentNumber()
			So(h.DocumentNumber, ShouldBeEmpty)
		})
	})

	Convey("As instruções devem ser válidas", t, func() {
		h := Title{Instructions: "Some instructions"}
		err := h.ValidateInstructionsLength(100)
		So(err, ShouldBeNil)
		Convey("As instruções devem ser inválidas", func() {
			err = h.ValidateInstructionsLength(1)
			So(err, ShouldNotBeNil)
		})

	})
}

func TestShouldReturnBankNumberIsValid(t *testing.T) {
	var b BankNumber = 237

	if b.IsBankNumberValid() == false {
		t.Fail()
	}
}

func TestShouldAppendCollectionOfErrrors(t *testing.T) {
	e := NewErrorCollection(ErrorResponse{Code: "200", Message: "Hue2"})
	e.Append("100", "Hue")
	test.ExpectTrue(len(e) == 2, t)
}

func TestShouldCreateNewSingleErrorCollection(t *testing.T) {
	e := NewSingleErrorCollection("200", "Hue2")
	test.ExpectTrue(len(e) == 1, t)
}

func TestIsAgencyValid(t *testing.T) {
	Convey("Deve retornar um erro para a agência inválida", t, func() {
		a := Agreement{
			Agency: "234-2222a",
		}
		err := a.IsAgencyValid()
		So(err, ShouldNotBeNil)

		Convey("Deve ajustar a agência para ter a quantidade certa de dígitos", func() {
			a.Agency = "321"
			err := a.IsAgencyValid()
			So(a.Agency, ShouldEqual, "0321")
			So(err, ShouldBeNil)
		})
	})
}

func TestCalculateAgencyDigit(t *testing.T) {
	Convey("Deve ajustar o dígito da Agência quando ela tiver caracteres inválidos", t, func() {
		a := new(Agreement)
		a.AgencyDigit = "2sssss"
		c := func(s string) string {
			return "1"
		}
		a.CalculateAgencyDigit(c)
		So(a.AgencyDigit, ShouldEqual, "2")
		Convey("Deve calcular o dígito da Agência quando o fornecido for errado", func() {
			a.AgencyDigit = "332sssss"
			a.CalculateAgencyDigit(c)
			So(a.AgencyDigit, ShouldEqual, "1")
		})
	})
}

func TestCalculateAccountDigit(t *testing.T) {
	Convey("Deve ajustar o dígito da Conta quando ela tiver caracteres inválidos", t, func() {
		a := new(Agreement)
		a.AccountDigit = "2sssss"
		c := func(s, y string) string {
			return "1"
		}
		a.CalculateAccountDigit(c)
		So(a.AccountDigit, ShouldEqual, "2")
		Convey("Deve calcular o dígito da Conta quando o fornecido for errado", func() {
			a.AccountDigit = "332sssss"
			a.CalculateAccountDigit(c)
			So(a.AccountDigit, ShouldEqual, "1")
		})
	})
}

func TestIsAccountValid(t *testing.T) {
	Convey("Verifica se a conta é valida e formata para o tamanho correto", t, func() {
		a := Agreement{
			Account: "1234fff",
		}
		err := a.IsAccountValid(8)
		So(err, ShouldBeNil)
		So(a.Account, ShouldEqual, "00001234")
		Convey("Verifica se a conta é valida e retorna um erro", func() {
			a.Account = "654654654654654654654654654564"
			err := a.IsAccountValid(8)
			So(err, ShouldNotBeNil)
		})
	})
}
<|endoftext|>


<commit_before>package core

import (
	"fmt"
	"time"
)

// Bootstrap the daemon
func Bootstrap() {
	loadConfigFromFile()
	deliveryServersConnectionTests()
	config.DirectoryPickup.start()
	initSendCampaignsCommands()

	ticker := time.NewTicker(time.Second * 60)
	for _ = range ticker.C {
	}
}
<commit_msg>remove unused fmt<commit_after>package core

import (
	"time"
)

// Bootstrap the daemon
func Bootstrap() {
	loadConfigFromFile()
	deliveryServersConnectionTests()
	config.DirectoryPickup.start()
	initSendCampaignsCommands()

	ticker := time.NewTicker(time.Second * 60)
	for _ = range ticker.C {
	}
}
<|endoftext|>


<commit_before>package api

import (
	"fmt"
	"os"
	"os/exec"
	"strings"
	"syscall"

	"github.com/zenoss/glog"
	docker "github.com/zenoss/go-dockerclient"
	"github.com/zenoss/serviced/domain/service"
	"github.com/zenoss/serviced/shell"
)

// ShellConfig is the deserialized object from the command-line
type ShellConfig struct {
	ServiceID string
	Command   string
	Args      []string
	SaveAs    string
	IsTTY     bool
}

// StartShell runs a command for a given service
func (a *api) StartShell(config ShellConfig) error {
	dockerClient, err := a.connectDocker()
	if err != nil {
		return err
	}
	dockerRegistry, err := a.connectDockerRegistry()
	if err != nil {
		return err
	}
	command := []string{config.Command}
	command = append(command, config.Args...)

	cfg := shell.ProcessConfig{
		ServiceID: config.ServiceID,
		IsTTY:     config.IsTTY,
		SaveAs:    config.SaveAs,
		Command:   strings.Join(command, " "),
	}

	// TODO: change me to use sockets
	cmd, err := shell.StartDocker(dockerRegistry, dockerClient, &cfg, options.Endpoint)
	if err != nil {
		return fmt.Errorf("failed to connect to service: %s", err)
	}

	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	cmd.Run()

	return nil
}

// RunShell runs a predefined service shell command via the service definition
func (a *api) RunShell(config ShellConfig) error {
	client, err := a.connectDAO()
	if err != nil {
		return err
	}
	dockerClient, err := a.connectDocker()
	if err != nil {
		return err
	}
	dockerRegistry, err := a.connectDockerRegistry()
	if err != nil {
		return err
	}

	svc, err := a.GetService(config.ServiceID)
	if err != nil {
		return err
	}

	getSvc := func(svcID string) (service.Service, error) {
		s := service.Service{}
		err := client.GetService(svcID, &s)
		return s, err
	}
	if err := svc.EvaluateRunsTemplate(getSvc); err != nil {
		fmt.Errorf("error evaluating service:%s Runs:%+v  error:%s", svc.Id, svc.Runs, err)
	}
	command, ok := svc.Runs[config.Command]
	if !ok {
		return fmt.Errorf("command not found for service")
	}
	command = strings.Join(append([]string{command}, config.Args...), " ")

	cfg := shell.ProcessConfig{
		ServiceID: config.ServiceID,
		IsTTY:     config.IsTTY,
		SaveAs:    config.SaveAs,
		Command:   fmt.Sprintf("su - zenoss -c \"%s\"", command),
	}

	// TODO: change me to use sockets
	cmd, err := shell.StartDocker(dockerRegistry, dockerClient, &cfg, options.Endpoint)
	if err != nil {
		return fmt.Errorf("failed to connect to service: %s", err)
	}

	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	err = cmd.Run()
	if isAbnormalTermination(err) {
		glog.Fatalf("abnormal termination from shell command: %s", err)
	}

	dockercli, err := a.connectDocker()
	if err != nil {
		glog.Fatalf("unable to connect to the docker service: %s", err)
	}
	exitcode, err := dockercli.WaitContainer(config.SaveAs)
	if err != nil {
		glog.Fatalf("failure waiting for container: %s", err)
	}
	container, err := dockercli.InspectContainer(config.SaveAs)
	if err != nil {
		glog.Fatalf("cannot acquire information about container: %s (%s)", config.SaveAs, err)
	}
	glog.V(2).Infof("Container ID: %s", container.ID)

	switch exitcode {
	case 0:
		// Commit the container
		label := ""
		glog.V(0).Infof("Committing container")
		if err := client.Commit(container.ID, &label); err != nil {
			glog.Fatalf("Error committing container: %s (%s)", container.ID, err)
		}
	default:
		// Delete the container
		glog.V(0).Infof("Command failed (exit code %d)", exitcode)
		if err := dockercli.StopContainer(container.ID, 10); err != nil {
			glog.Fatalf("failed to stop container: %s (%s)", container.ID, err)
		} else if err := dockercli.RemoveContainer(docker.RemoveContainerOptions{ID: container.ID}); err != nil {
			glog.Fatalf("failed to remove container: %s (%s)", container.ID, err)
		}
	}

	return nil
}

// isAbnormalTermination checks for unexpected errors in running a command.  An
// unexpected error is any error other than a non-zero status code.
func isAbnormalTermination(err error) bool {
	if err == nil {
		return false
	}
	if exitError, ok := err.(*exec.ExitError); ok {
		if exitStatus, ok := exitError.Sys().(syscall.WaitStatus); ok {
			if exitStatus.ExitStatus() != 0 {
				return false
			}
		}
	}
	return true
}
<commit_msg>Quote argmuents to 'service run' commands<commit_after>package api

import (
	"fmt"
	"os"
	"os/exec"
	"strings"
	"syscall"

	"github.com/zenoss/glog"
	docker "github.com/zenoss/go-dockerclient"
	"github.com/zenoss/serviced/domain/service"
	"github.com/zenoss/serviced/shell"
)

// ShellConfig is the deserialized object from the command-line
type ShellConfig struct {
	ServiceID string
	Command   string
	Args      []string
	SaveAs    string
	IsTTY     bool
}

// StartShell runs a command for a given service
func (a *api) StartShell(config ShellConfig) error {
	dockerClient, err := a.connectDocker()
	if err != nil {
		return err
	}
	dockerRegistry, err := a.connectDockerRegistry()
	if err != nil {
		return err
	}
	command := []string{config.Command}
	command = append(command, config.Args...)

	cfg := shell.ProcessConfig{
		ServiceID: config.ServiceID,
		IsTTY:     config.IsTTY,
		SaveAs:    config.SaveAs,
		Command:   strings.Join(command, " "),
	}

	// TODO: change me to use sockets
	cmd, err := shell.StartDocker(dockerRegistry, dockerClient, &cfg, options.Endpoint)
	if err != nil {
		return fmt.Errorf("failed to connect to service: %s", err)
	}

	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	cmd.Run()

	return nil
}

// RunShell runs a predefined service shell command via the service definition
func (a *api) RunShell(config ShellConfig) error {
	client, err := a.connectDAO()
	if err != nil {
		return err
	}
	dockerClient, err := a.connectDocker()
	if err != nil {
		return err
	}
	dockerRegistry, err := a.connectDockerRegistry()
	if err != nil {
		return err
	}

	svc, err := a.GetService(config.ServiceID)
	if err != nil {
		return err
	}

	getSvc := func(svcID string) (service.Service, error) {
		s := service.Service{}
		err := client.GetService(svcID, &s)
		return s, err
	}
	if err := svc.EvaluateRunsTemplate(getSvc); err != nil {
		fmt.Errorf("error evaluating service:%s Runs:%+v  error:%s", svc.Id, svc.Runs, err)
	}
	command, ok := svc.Runs[config.Command]
	if !ok {
		return fmt.Errorf("command not found for service")
	}

	quotedArgs := []string{}
	for _, arg := range config.Args {
		quotedArgs = append(quotedArgs, fmt.Sprintf("\\\"%s\\\"", arg))
	}
	command = strings.Join(append([]string{command}, quotedArgs...), " ")

	cfg := shell.ProcessConfig{
		ServiceID: config.ServiceID,
		IsTTY:     config.IsTTY,
		SaveAs:    config.SaveAs,
		Command:   fmt.Sprintf("su - zenoss -c \"%s\"", command),
	}

	// TODO: change me to use sockets
	cmd, err := shell.StartDocker(dockerRegistry, dockerClient, &cfg, options.Endpoint)
	if err != nil {
		return fmt.Errorf("failed to connect to service: %s", err)
	}

	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	err = cmd.Run()
	if isAbnormalTermination(err) {
		glog.Fatalf("abnormal termination from shell command: %s", err)
	}

	dockercli, err := a.connectDocker()
	if err != nil {
		glog.Fatalf("unable to connect to the docker service: %s", err)
	}
	exitcode, err := dockercli.WaitContainer(config.SaveAs)
	if err != nil {
		glog.Fatalf("failure waiting for container: %s", err)
	}
	container, err := dockercli.InspectContainer(config.SaveAs)
	if err != nil {
		glog.Fatalf("cannot acquire information about container: %s (%s)", config.SaveAs, err)
	}
	glog.V(2).Infof("Container ID: %s", container.ID)

	switch exitcode {
	case 0:
		// Commit the container
		label := ""
		glog.V(0).Infof("Committing container")
		if err := client.Commit(container.ID, &label); err != nil {
			glog.Fatalf("Error committing container: %s (%s)", container.ID, err)
		}
	default:
		// Delete the container
		glog.V(0).Infof("Command failed (exit code %d)", exitcode)
		if err := dockercli.StopContainer(container.ID, 10); err != nil {
			glog.Fatalf("failed to stop container: %s (%s)", container.ID, err)
		} else if err := dockercli.RemoveContainer(docker.RemoveContainerOptions{ID: container.ID}); err != nil {
			glog.Fatalf("failed to remove container: %s (%s)", container.ID, err)
		}
	}

	return nil
}

// isAbnormalTermination checks for unexpected errors in running a command.  An
// unexpected error is any error other than a non-zero status code.
func isAbnormalTermination(err error) bool {
	if err == nil {
		return false
	}
	if exitError, ok := err.(*exec.ExitError); ok {
		if exitStatus, ok := exitError.Sys().(syscall.WaitStatus); ok {
			if exitStatus.ExitStatus() != 0 {
				return false
			}
		}
	}
	return true
}
<|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 cli

import (
	"fmt"
	"sort"
	"strings"
	"unicode"

	"github.com/apache/cloudstack-cloudmonkey/cmd"
	"github.com/apache/cloudstack-cloudmonkey/config"
)

func buildAPICacheMap(apiMap map[string][]*config.API) map[string][]*config.API {
	for _, cmd := range cmd.AllCommands() {
		verb := cmd.Name
		if cmd.SubCommands != nil && len(cmd.SubCommands) > 0 {
			for command, opts := range cmd.SubCommands {
				var args []*config.APIArg
				options := opts
				if command == "profile" {
					options = config.GetProfiles()
				}
				for _, opt := range options {
					args = append(args, &config.APIArg{
						Name: opt,
					})
				}
				apiMap[verb] = append(apiMap[verb], &config.API{
					Name: command,
					Verb: verb,
					Noun: command,
					Args: args,
				})
			}
		} else {
			dummyAPI := &config.API{
				Name: "",
				Verb: verb,
			}
			apiMap[verb] = append(apiMap[verb], dummyAPI)
		}
	}
	return apiMap
}

func trimSpaceLeft(in []rune) []rune {
	firstIndex := len(in)
	for i, r := range in {
		if unicode.IsSpace(r) == false {
			firstIndex = i
			break
		}
	}
	return in[firstIndex:]
}

func equal(a, b []rune) bool {
	if len(a) != len(b) {
		return false
	}
	for i := 0; i < len(a); i++ {
		if a[i] != b[i] {
			return false
		}
	}
	return true
}

func hasPrefix(r, prefix []rune) bool {
	if len(r) < len(prefix) {
		return false
	}
	return equal(r[:len(prefix)], prefix)
}

func inArray(s string, array []string) bool {
	for _, item := range array {
		if s == item {
			return true
		}
	}
	return false
}

func lastString(array []string) string {
	return array[len(array)-1]
}

type argOption struct {
	Value  string
	Detail string
}

func buildArgOptions(response map[string]interface{}, hasID bool) []argOption {
	argOptions := []argOption{}
	for _, v := range response {
		switch obj := v.(type) {
		case []interface{}:
			if obj == nil {
				break
			}
			for _, item := range obj {
				resource, ok := item.(map[string]interface{})
				if !ok {
					continue
				}
				var id, name, detail string
				if resource["id"] != nil {
					id = resource["id"].(string)
				}
				if resource["name"] != nil {
					name = resource["name"].(string)
				} else if resource["username"] != nil {
					name = resource["username"].(string)
				}
				if resource["displaytext"] != nil {
					detail = resource["displaytext"].(string)
				}
				if len(detail) == 0 && resource["description"] != nil {
					detail = resource["description"].(string)
				}
				if len(detail) == 0 && resource["ipaddress"] != nil {
					detail = resource["ipaddress"].(string)
				}
				var opt argOption
				if hasID {
					opt.Value = id
					opt.Detail = name
					if len(name) == 0 {
						opt.Detail = detail
					}
				} else {
					opt.Value = name
					opt.Detail = detail
				}
				argOptions = append(argOptions, opt)
			}
			break
		}
	}
	return argOptions
}

func doInternal(line []rune, pos int, lineLen int, argName []rune) (newLine [][]rune, offset int) {
	offset = lineLen
	if lineLen >= len(argName) {
		if hasPrefix(line, argName) {
			if lineLen == len(argName) {
				newLine = append(newLine, []rune{' '})
			} else {
				newLine = append(newLine, argName)
			}
			offset = offset - len(argName) - 1
		}
	} else {
		if hasPrefix(argName, line) {
			newLine = append(newLine, argName[offset:])
		}
	}
	return
}

type autoCompleter struct {
	Config *config.Config
}

func (t *autoCompleter) Do(line []rune, pos int) (options [][]rune, offset int) {
	apiMap := buildAPICacheMap(t.Config.GetAPIVerbMap())

	var verbs []string
	for verb := range apiMap {
		verbs = append(verbs, verb)
		sort.Slice(apiMap[verb], func(i, j int) bool {
			return apiMap[verb][i].Name < apiMap[verb][j].Name
		})
	}
	sort.Strings(verbs)

	line = trimSpaceLeft(line[:pos])

	// Auto-complete verb
	var verbFound string
	for _, verb := range verbs {
		search := verb + " "
		if !hasPrefix(line, []rune(search)) {
			sLine, sOffset := doInternal(line, pos, len(line), []rune(search))
			options = append(options, sLine...)
			offset = sOffset
		} else {
			verbFound = verb
			break
		}
	}
	if len(verbFound) == 0 {
		return
	}

	// Auto-complete noun
	var nounFound string
	line = trimSpaceLeft(line[len(verbFound):])
	for _, api := range apiMap[verbFound] {
		search := api.Noun + " "
		if !hasPrefix(line, []rune(search)) {
			sLine, sOffset := doInternal(line, pos, len(line), []rune(search))
			options = append(options, sLine...)
			offset = sOffset
		} else {
			nounFound = api.Noun
			break
		}
	}
	if len(nounFound) == 0 {
		return
	}

	// Find API
	var apiFound *config.API
	for _, api := range apiMap[verbFound] {
		if api.Noun == nounFound {
			apiFound = api
			break
		}
	}
	if apiFound == nil {
		return
	}

	// Auto-complete API arg
	splitLine := strings.Split(string(line), " ")
	line = trimSpaceLeft([]rune(splitLine[len(splitLine)-1]))
	for _, arg := range apiFound.Args {
		search := arg.Name
		if !hasPrefix(line, []rune(search)) {
			sLine, sOffset := doInternal(line, pos, len(line), []rune(search))
			options = append(options, sLine...)
			offset = sOffset
		} else {
			words := strings.Split(string(line), "=")
			argInput := lastString(words)
			if arg.Type == "boolean" {
				for _, search := range []string{"true ", "false "} {
					offset = 0
					if strings.HasPrefix(search, argInput) {
						options = append(options, []rune(search[len(argInput):]))
						offset = len(argInput)
					}
				}
				return
			}
			if arg.Type == config.FAKE && arg.Name == "filter=" {
				offset = 0
				filterInputs := strings.Split(strings.Replace(argInput, ",", ",|", -1), "|")
				lastFilterInput := lastString(filterInputs)
				for _, key := range apiFound.ResponseKeys {
					if inArray(key, filterInputs) {
						continue
					}
					if strings.HasPrefix(key, lastFilterInput) {
						options = append(options, []rune(key[len(lastFilterInput):]))
						offset = len(lastFilterInput)
					}
				}
				return
			}

			argName := strings.Replace(arg.Name, "=", "", -1)
			var autocompleteAPI *config.API
			var relatedNoun string
			if argName == "id" || argName == "ids" {
				relatedNoun = apiFound.Noun
				if apiFound.Verb != "list" {
					relatedNoun += "s"
				}
			} else if argName == "account" {
				relatedNoun = "accounts"
			} else {
				relatedNoun = strings.Replace(strings.Replace(argName, "ids", "", -1), "id", "", -1) + "s"
			}

			for _, listAPI := range apiMap["list"] {
				if relatedNoun == listAPI.Noun {
					autocompleteAPI = listAPI
					break
				}
			}

			if autocompleteAPI == nil {
				relatedAPIName := ""
				for _, name := range arg.Related {
					if strings.HasPrefix(name, "list") {
						if len(relatedAPIName) == 0 {
							relatedAPIName = name
						}
						if len(name) < len(relatedAPIName) {
							relatedAPIName = name
						}
					}
				}
				if len(relatedAPIName) > 0 {
					for _, listAPI := range apiMap["list"] {
						if relatedAPIName == listAPI.Name {
							autocompleteAPI = listAPI
							break
						}
					}
				}
			}

			if autocompleteAPI == nil {
				return nil, 0
			}

			autocompleteAPIArgs := []string{"listall=true"}
			if autocompleteAPI.Noun == "templates" {
				autocompleteAPIArgs = append(autocompleteAPIArgs, "templatefilter=executable")
			}

			spinner := t.Config.StartSpinner("fetching options, please wait...")
			request := cmd.NewRequest(nil, completer.Config, nil)
			response, _ := cmd.NewAPIRequest(request, autocompleteAPI.Name, autocompleteAPIArgs, false)
			t.Config.StopSpinner(spinner)

			hasID := strings.HasSuffix(arg.Name, "id=") || strings.HasSuffix(arg.Name, "ids=")
			argOptions := buildArgOptions(response, hasID)

			filteredOptions := []argOption{}
			if len(argOptions) > 0 {
				sort.Slice(argOptions, func(i, j int) bool {
					return argOptions[i].Value < argOptions[j].Value
				})
				for _, item := range argOptions {
					if strings.HasPrefix(item.Value, argInput) {
						filteredOptions = append(filteredOptions, item)
					}
				}
			}
			offset = 0
			if len(filteredOptions) == 0 {
				options = [][]rune{[]rune("")}
			}
			for _, item := range filteredOptions {
				option := item.Value + " "
				if len(filteredOptions) > 1 && len(item.Detail) > 0 {
					option += fmt.Sprintf("(%v)", item.Detail)
				}
				if strings.HasPrefix(option, argInput) {
					options = append(options, []rune(option[len(argInput):]))
					offset = len(argInput)
				}
			}
			return
		}
	}

	return options, offset
}
<commit_msg>cli: fix auto-completion bug<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 cli

import (
	"fmt"
	"sort"
	"strings"
	"unicode"

	"github.com/apache/cloudstack-cloudmonkey/cmd"
	"github.com/apache/cloudstack-cloudmonkey/config"
)

func buildAPICacheMap(apiMap map[string][]*config.API) map[string][]*config.API {
	for _, cmd := range cmd.AllCommands() {
		verb := cmd.Name
		if cmd.SubCommands != nil && len(cmd.SubCommands) > 0 {
			for command, opts := range cmd.SubCommands {
				var args []*config.APIArg
				options := opts
				if command == "profile" {
					options = config.GetProfiles()
				}
				for _, opt := range options {
					args = append(args, &config.APIArg{
						Name: opt,
					})
				}
				apiMap[verb] = append(apiMap[verb], &config.API{
					Name: command,
					Verb: verb,
					Noun: command,
					Args: args,
				})
			}
		} else {
			dummyAPI := &config.API{
				Name: "",
				Verb: verb,
			}
			apiMap[verb] = append(apiMap[verb], dummyAPI)
		}
	}
	return apiMap
}

func trimSpaceLeft(in []rune) []rune {
	firstIndex := len(in)
	for i, r := range in {
		if unicode.IsSpace(r) == false {
			firstIndex = i
			break
		}
	}
	return in[firstIndex:]
}

func equal(a, b []rune) bool {
	if len(a) != len(b) {
		return false
	}
	for i := 0; i < len(a); i++ {
		if a[i] != b[i] {
			return false
		}
	}
	return true
}

func hasPrefix(r, prefix []rune) bool {
	if len(r) < len(prefix) {
		return false
	}
	return equal(r[:len(prefix)], prefix)
}

func inArray(s string, array []string) bool {
	for _, item := range array {
		if s == item {
			return true
		}
	}
	return false
}

func lastString(array []string) string {
	return array[len(array)-1]
}

type argOption struct {
	Value  string
	Detail string
}

func buildArgOptions(response map[string]interface{}, hasID bool) []argOption {
	argOptions := []argOption{}
	for _, v := range response {
		switch obj := v.(type) {
		case []interface{}:
			if obj == nil {
				break
			}
			for _, item := range obj {
				resource, ok := item.(map[string]interface{})
				if !ok {
					continue
				}
				var id, name, detail string
				if resource["id"] != nil {
					id = resource["id"].(string)
				}
				if resource["name"] != nil {
					name = resource["name"].(string)
				} else if resource["username"] != nil {
					name = resource["username"].(string)
				}
				if resource["displaytext"] != nil {
					detail = resource["displaytext"].(string)
				}
				if len(detail) == 0 && resource["description"] != nil {
					detail = resource["description"].(string)
				}
				if len(detail) == 0 && resource["ipaddress"] != nil {
					detail = resource["ipaddress"].(string)
				}
				var opt argOption
				if hasID {
					opt.Value = id
					opt.Detail = name
					if len(name) == 0 {
						opt.Detail = detail
					}
				} else {
					opt.Value = name
					opt.Detail = detail
					if len(name) == 0 {
						opt.Value = detail
					}
				}
				argOptions = append(argOptions, opt)
			}
			break
		}
	}
	return argOptions
}

func doInternal(line []rune, pos int, lineLen int, argName []rune) (newLine [][]rune, offset int) {
	offset = lineLen
	if lineLen >= len(argName) {
		if hasPrefix(line, argName) {
			if lineLen == len(argName) {
				newLine = append(newLine, []rune{' '})
			} else {
				newLine = append(newLine, argName)
			}
			offset = offset - len(argName) - 1
		}
	} else {
		if hasPrefix(argName, line) {
			newLine = append(newLine, argName[offset:])
		}
	}
	return
}

func findAutocompleteAPI(arg *config.APIArg, apiFound *config.API, apiMap map[string][]*config.API) *config.API {
	if arg.Type == "map" {
		return nil
	}

	var autocompleteAPI *config.API
	argName := strings.Replace(arg.Name, "=", "", -1)
	relatedNoun := argName
	if argName == "id" || argName == "ids" {
		// Heuristic: user is trying to autocomplete for id/ids arg for a list API
		relatedNoun = apiFound.Noun
		if apiFound.Verb != "list" {
			relatedNoun += "s"
		}
	} else if argName == "account" {
		// Heuristic: user is trying to autocomplete for accounts
		relatedNoun = "accounts"
	} else if argName == "ipaddressid" {
		// Heuristic: user is trying to autocomplete for ip addresses
		relatedNoun = "publicipaddresses"
	} else {
		// Heuristic: autocomplete for the arg for which a list<Arg without id/ids>s API exists
		// For example, for zoneid arg, listZones API exists
		cutIdx := len(argName)
		if strings.HasSuffix(argName, "id") {
			cutIdx -= 2
		} else if strings.HasSuffix(argName, "ids") {
			cutIdx -= 3
		} else {
		}
		relatedNoun = argName[:cutIdx] + "s"
	}

	config.Debug("Possible related noun for the arg: ", relatedNoun, " and type: ", arg.Type)
	for _, listAPI := range apiMap["list"] {
		if relatedNoun == listAPI.Noun {
			autocompleteAPI = listAPI
			break
		}
	}

	if autocompleteAPI != nil {
		config.Debug("Autocomplete: API found using heuristics: ", autocompleteAPI.Name)
	}

	if strings.HasSuffix(relatedNoun, "s") {
		relatedNoun = relatedNoun[:len(relatedNoun)-1]
	}

	// Heuristic: find any list API that contains the arg name
	if autocompleteAPI == nil {
		config.Debug("Finding possible API that have: ", argName, " related APIs: ", arg.Related)
		possibleAPIs := []*config.API{}
		for _, listAPI := range apiMap["list"] {
			if strings.Contains(listAPI.Noun, argName) {
				config.Debug("Found possible API: ", listAPI.Name)
				possibleAPIs = append(possibleAPIs, listAPI)
			}
		}
		if len(possibleAPIs) == 1 {
			autocompleteAPI = possibleAPIs[0]
		}
	}

	return autocompleteAPI
}

type autoCompleter struct {
	Config *config.Config
}

func (t *autoCompleter) Do(line []rune, pos int) (options [][]rune, offset int) {
	apiMap := buildAPICacheMap(t.Config.GetAPIVerbMap())

	var verbs []string
	for verb := range apiMap {
		verbs = append(verbs, verb)
		sort.Slice(apiMap[verb], func(i, j int) bool {
			return apiMap[verb][i].Name < apiMap[verb][j].Name
		})
	}
	sort.Strings(verbs)

	line = trimSpaceLeft(line[:pos])

	// Auto-complete verb
	var verbFound string
	for _, verb := range verbs {
		search := verb + " "
		if !hasPrefix(line, []rune(search)) {
			sLine, sOffset := doInternal(line, pos, len(line), []rune(search))
			options = append(options, sLine...)
			offset = sOffset
		} else {
			verbFound = verb
			break
		}
	}
	if len(verbFound) == 0 {
		return
	}

	// Auto-complete noun
	var nounFound string
	line = trimSpaceLeft(line[len(verbFound):])
	for _, api := range apiMap[verbFound] {
		search := api.Noun + " "
		if !hasPrefix(line, []rune(search)) {
			sLine, sOffset := doInternal(line, pos, len(line), []rune(search))
			options = append(options, sLine...)
			offset = sOffset
		} else {
			nounFound = api.Noun
			break
		}
	}
	if len(nounFound) == 0 {
		return
	}

	// Find API
	var apiFound *config.API
	for _, api := range apiMap[verbFound] {
		if api.Noun == nounFound {
			apiFound = api
			break
		}
	}
	if apiFound == nil {
		return
	}

	// Auto-complete API arg
	splitLine := strings.Split(string(line), " ")
	line = trimSpaceLeft([]rune(splitLine[len(splitLine)-1]))
	for _, arg := range apiFound.Args {
		search := arg.Name
		if !hasPrefix(line, []rune(search)) {
			sLine, sOffset := doInternal(line, pos, len(line), []rune(search))
			options = append(options, sLine...)
			offset = sOffset
		} else {
			words := strings.Split(string(line), "=")
			argInput := lastString(words)
			if arg.Type == "boolean" {
				for _, search := range []string{"true ", "false "} {
					offset = 0
					if strings.HasPrefix(search, argInput) {
						options = append(options, []rune(search[len(argInput):]))
						offset = len(argInput)
					}
				}
				return
			}
			if arg.Type == config.FAKE && arg.Name == "filter=" {
				offset = 0
				filterInputs := strings.Split(strings.Replace(argInput, ",", ",|", -1), "|")
				lastFilterInput := lastString(filterInputs)
				for _, key := range apiFound.ResponseKeys {
					if inArray(key, filterInputs) {
						continue
					}
					if strings.HasPrefix(key, lastFilterInput) {
						options = append(options, []rune(key[len(lastFilterInput):]))
						offset = len(lastFilterInput)
					}
				}
				return
			}

			autocompleteAPI := findAutocompleteAPI(arg, apiFound, apiMap)
			if autocompleteAPI == nil {
				return nil, 0
			}

			autocompleteAPIArgs := []string{"listall=true"}
			if autocompleteAPI.Noun == "templates" {
				autocompleteAPIArgs = append(autocompleteAPIArgs, "templatefilter=executable")
			}

			spinner := t.Config.StartSpinner("fetching options, please wait...")
			request := cmd.NewRequest(nil, completer.Config, nil)
			response, _ := cmd.NewAPIRequest(request, autocompleteAPI.Name, autocompleteAPIArgs, false)
			t.Config.StopSpinner(spinner)

			hasID := strings.HasSuffix(arg.Name, "id=") || strings.HasSuffix(arg.Name, "ids=")
			argOptions := buildArgOptions(response, hasID)

			filteredOptions := []argOption{}
			if len(argOptions) > 0 {
				sort.Slice(argOptions, func(i, j int) bool {
					return argOptions[i].Value < argOptions[j].Value
				})
				for _, item := range argOptions {
					if strings.HasPrefix(item.Value, argInput) {
						filteredOptions = append(filteredOptions, item)
					}
				}
			}
			offset = 0
			if len(filteredOptions) == 0 {
				options = [][]rune{[]rune("")}
			}
			for _, item := range filteredOptions {
				option := item.Value + " "
				if len(filteredOptions) > 1 && len(item.Detail) > 0 {
					option += fmt.Sprintf("(%v)", item.Detail)
				}
				if strings.HasPrefix(option, argInput) {
					options = append(options, []rune(option[len(argInput):]))
					offset = len(argInput)
				}
			}
			return
		}
	}

	return options, offset
}
<|endoftext|>


<commit_before>package decoder

import (
	"time"
)

type Message interface{}
type MessageDecoded interface{}

type DecoderFunc func(Message interface{}) error
type DoneCallback func(string, int, time.Time, time.Time)
type ErrorCallback func(string, int, time.Time, time.Time, error)

// Worker structure
type Worker struct {
	Id            int
	DecoderParams DecoderParams
	WorkerPool    chan chan Message
	Name          string
	InMsg         chan Message
	Quit          chan bool
}

// Create a worker and add it to the pool.
func CreateWorker(workerPool chan chan Message, decoderParams DecoderParams, id int, name string) Worker {
	return Worker{
		Id:            id,
		DecoderParams: decoderParams,
		WorkerPool:    workerPool,
		Name:          name,
		InMsg:         make(chan Message),
		Quit:          make(chan bool),
	}
}

// Start the worker. Launches a goroutine to process NFv9 messages.
// The worker will add its input channel of NFv9 messages to decode to the pool.
func (w Worker) Start() {
	go func() {
		//log.Debugf("Worker %v started", w.Id)
		for {
			w.WorkerPool <- w.InMsg
			select {
			case <-w.Quit:
				break
			case msg := <-w.InMsg:
				timeTrackStart := time.Now()
				err := w.DecoderParams.DecoderFunc(msg)
				timeTrackStop := time.Now()

				if err != nil && w.DecoderParams.ErrorCallback != nil {
					w.DecoderParams.ErrorCallback(w.Name, w.Id, timeTrackStart, timeTrackStop, err)
				} else if err == nil && w.DecoderParams.DoneCallback != nil {
					w.DecoderParams.DoneCallback(w.Name, w.Id, timeTrackStart, timeTrackStop)
				}
			}
		}
		//log.Debugf("Worker %v done", w.Id)
	}()
}

// Stop the worker.
func (w Worker) Stop() {
	//log.Debugf("Stopping worker %v", w.Id)
	w.Quit <- true
}

// Processor structure
type Processor struct {
	workerpool    chan chan Message
	workerlist    []Worker
	DecoderParams DecoderParams
	Name          string
}

// Decoder structure. Define the function to call and the config specific to the type of packets.
type DecoderParams struct {
	DecoderFunc   DecoderFunc
	DoneCallback  DoneCallback
	ErrorCallback ErrorCallback
}

// Create a message processor which is going to create all the workers and set-up the pool.
func CreateProcessor(numWorkers int, decoderParams DecoderParams, name string) Processor {
	processor := Processor{
		workerpool:    make(chan chan Message),
		workerlist:    make([]Worker, numWorkers),
		DecoderParams: decoderParams,
		Name:          name,
	}
	for i := 0; i < numWorkers; i++ {
		worker := CreateWorker(processor.workerpool, decoderParams, i, name)
		processor.workerlist[i] = worker
	}
	return processor
}

// Start message processor
func (p Processor) Start() {
	for _, worker := range p.workerlist {
		worker.Start()
	}
}

func (p Processor) Stop() {
	for _, worker := range p.workerlist {
		worker.Stop()
	}
}

// Send a message to be decoded to the pool.
func (p Processor) ProcessMessage(msg Message) {
	sendChannel := <-p.workerpool
	sendChannel <- msg
}
<commit_msg>Fix for #40: change the position of the channel<commit_after>package decoder

import (
	"time"
)

type Message interface{}
type MessageDecoded interface{}

type DecoderFunc func(Message interface{}) error
type DoneCallback func(string, int, time.Time, time.Time)
type ErrorCallback func(string, int, time.Time, time.Time, error)

// Worker structure
type Worker struct {
	Id            int
	DecoderParams DecoderParams
	WorkerPool    chan chan Message
	Name          string
	InMsg         chan Message
	Quit          chan bool
}

// Create a worker and add it to the pool.
func CreateWorker(workerPool chan chan Message, decoderParams DecoderParams, id int, name string) Worker {
	return Worker{
		Id:            id,
		DecoderParams: decoderParams,
		WorkerPool:    workerPool,
		Name:          name,
		InMsg:         make(chan Message),
		Quit:          make(chan bool),
	}
}

// Start the worker. Launches a goroutine to process NFv9 messages.
// The worker will add its input channel of NFv9 messages to decode to the pool.
func (w Worker) Start() {
	go func() {
		//log.Debugf("Worker %v started", w.Id)
		for {
			select {
			case <-w.Quit:
				break
			case w.WorkerPool <- w.InMsg:
				msg := <-w.InMsg
				timeTrackStart := time.Now()
				err := w.DecoderParams.DecoderFunc(msg)
				timeTrackStop := time.Now()

				if err != nil && w.DecoderParams.ErrorCallback != nil {
					w.DecoderParams.ErrorCallback(w.Name, w.Id, timeTrackStart, timeTrackStop, err)
				} else if err == nil && w.DecoderParams.DoneCallback != nil {
					w.DecoderParams.DoneCallback(w.Name, w.Id, timeTrackStart, timeTrackStop)
				}
			}
		}
		//log.Debugf("Worker %v done", w.Id)
	}()
}

// Stop the worker.
func (w Worker) Stop() {
	//log.Debugf("Stopping worker %v", w.Id)
	w.Quit <- true
}

// Processor structure
type Processor struct {
	workerpool    chan chan Message
	workerlist    []Worker
	DecoderParams DecoderParams
	Name          string
}

// Decoder structure. Define the function to call and the config specific to the type of packets.
type DecoderParams struct {
	DecoderFunc   DecoderFunc
	DoneCallback  DoneCallback
	ErrorCallback ErrorCallback
}

// Create a message processor which is going to create all the workers and set-up the pool.
func CreateProcessor(numWorkers int, decoderParams DecoderParams, name string) Processor {
	processor := Processor{
		workerpool:    make(chan chan Message),
		workerlist:    make([]Worker, numWorkers),
		DecoderParams: decoderParams,
		Name:          name,
	}
	for i := 0; i < numWorkers; i++ {
		worker := CreateWorker(processor.workerpool, decoderParams, i, name)
		processor.workerlist[i] = worker
	}
	return processor
}

// Start message processor
func (p Processor) Start() {
	for _, worker := range p.workerlist {
		worker.Start()
	}
}

func (p Processor) Stop() {
	for _, worker := range p.workerlist {
		worker.Stop()
	}
}

// Send a message to be decoded to the pool.
func (p Processor) ProcessMessage(msg Message) {
	sendChannel := <-p.workerpool
	sendChannel <- msg
}
<|endoftext|>


<commit_before>package module

import (
	"github.com/v4lproik/no-name/data"
	"github.com/PuerkitoBio/goquery"
	"strings"
	"github.com/v4lproik/no-name/util"
)

type formModule struct {
	name string
	htmlTagsNames *data.HtmlTagsNames

	next Module
}

func NewFindFormModule(name string, htmlTagsNames *data.HtmlTagsNames) *formModule {
	return &formModule{name, htmlTagsNames, nil}
}

func (m *formModule) Request(flag bool, wi *data.WebInterface) {

	if wi.Doc != nil {
		form := wi.Form
		formHtml := wi.Doc.Find("form")

		if len(formHtml.Nodes) < 1 {
			logger.Infof("No form has been found for url " + wi.ClientWeb.GetUrl().String())
		} else {
			// set the url of the form
			wi.Form.UrlForm = wi.ClientWeb.GetUrl().RequestURI()

			// find arguments to submit the form
			wi.Doc.Find("form").Each(func(i int, s *goquery.Selection) {
				action, exists := s.Attr("action")
				if exists {
					form.UrlToSubmit = action
					logger.Debugf("SubmitUrl has been found with action <" + action + ">")
				}

				method, exists := s.Attr("method")
				if exists {
					form.MethodSubmitArg = strings.ToUpper(method)
					logger.Debugf("MethodSubmit has been found with method <" + method + ">")
				} else {
					form.MethodSubmitArg = "GET"
				}
			})

			// find mandatory inputs to submit the form
			wi.Doc.Find("form input").Each(func(i int, s *goquery.Selection) {
				// find by name
				names, exists := s.Attr("name")
				if exists {
					//try to find if the input is a username or a password field
					switch {
					case util.Contains(m.htmlTagsNames.UsernameNames, names):
						logger.Debugf("Username input has been found with name <" + names + ">")
						form.UsernameArg = names
					case util.Contains(m.htmlTagsNames.PasswordNames, names):
						logger.Debugf("Password has been found with name <" + names + ">")
						form.PasswordArg = names
					case util.ContainsRegex(m.htmlTagsNames.CsrfNames, names):
						logger.Debugf("Csrf has been found with name <" + names + ">")
						form.CsrfArg = names
					}
				}

				// find by type
				types, exists := s.Attr("type")
				if exists {
					//try to find if the input is a username or a password field
					switch {
					case strings.Contains(types, "submit"):
						logger.Debugf("Submit input has been found with type <" + types + ">")
						form.SubmitArg = types

					case strings.Contains(types, "password"):
						logger.Debugf("Password input has been found with type <" + types + ">")
						form.PasswordArg = types
					}
				}

				// find by value and if this value is not already contained as a username, password etc
				value, existsValue := s.Attr("value")
				if existsValue {
					name, existsName := s.Attr("name")
					if existsName && name != form.UsernameArg && name != form.PasswordArg && name != form.CsrfArg {
						form.OtherArgWithValue[name] = value
						logger.Debugf("Couple name=value has been found <" + name + "=" + value + ">")
					}
				}

				//default values for non found input
				if form.UrlToSubmit == "" {
					form.UrlToSubmit = form.UrlForm
				}
			})

		}
	}

	if flag && m.next != nil{
		m.next.Request(flag, wi)
	}
}

func (m *formModule) SetNextModule(next Module){
	m.next = next
}<commit_msg>Fix bug when password input is found with password input type<commit_after>package module

import (
	"github.com/v4lproik/no-name/data"
	"github.com/PuerkitoBio/goquery"
	"strings"
	"github.com/v4lproik/no-name/util"
)

type formModule struct {
	name string
	htmlTagsNames *data.HtmlTagsNames

	next Module
}

func NewFindFormModule(name string, htmlTagsNames *data.HtmlTagsNames) *formModule {
	return &formModule{name, htmlTagsNames, nil}
}

func (m *formModule) Request(flag bool, wi *data.WebInterface) {

	if wi.Doc != nil {
		form := wi.Form
		formHtml := wi.Doc.Find("form")

		if len(formHtml.Nodes) < 1 {
			logger.Infof("No form has been found for url " + wi.ClientWeb.GetUrl().String())
		} else {
			// set the url of the form
			wi.Form.UrlForm = wi.ClientWeb.GetUrl().RequestURI()

			// find arguments to submit the form
			wi.Doc.Find("form").Each(func(i int, s *goquery.Selection) {
				action, exists := s.Attr("action")
				if exists {
					form.UrlToSubmit = action
					logger.Debugf("SubmitUrl has been found with action <" + action + ">")
				}

				method, exists := s.Attr("method")
				if exists {
					form.MethodSubmitArg = strings.ToUpper(method)
					logger.Debugf("MethodSubmit has been found with method <" + method + ">")
				} else {
					form.MethodSubmitArg = "GET"
				}
			})

			// find mandatory inputs to submit the form
			wi.Doc.Find("form input").Each(func(i int, s *goquery.Selection) {
				// find by name
				names, exists := s.Attr("name")
				if exists {
					//try to find if the input is a username or a password field
					switch {
					case util.Contains(m.htmlTagsNames.UsernameNames, names):
						logger.Debugf("Username input has been found with name <" + names + ">")
						form.UsernameArg = names
					case util.Contains(m.htmlTagsNames.PasswordNames, names):
						logger.Debugf("Password has been found with name <" + names + ">")
						form.PasswordArg = names
					case util.ContainsRegex(m.htmlTagsNames.CsrfNames, names):
						logger.Debugf("Csrf has been found with name <" + names + ">")
						form.CsrfArg = names
					}
				}

				// find by type
				types, exists := s.Attr("type")
				if exists {
					//try to find if the input is a username or a password field
					switch {
					case strings.Contains(types, "submit"):
						logger.Debugf("Submit input has been found with type <" + types + ">")
						form.SubmitArg = types

					case strings.Contains(types, "password"):
						logger.Debugf("Password input has been found with type <" + types + ">")

						names, exists := s.Attr("name")
						if exists {
							form.PasswordArg = names
						}

					}
				}

				// find by value and if this value is not already contained as a username, password etc
				value, existsValue := s.Attr("value")
				if existsValue {
					name, existsName := s.Attr("name")
					if existsName && name != form.UsernameArg && name != form.PasswordArg && name != form.CsrfArg {
						form.OtherArgWithValue[name] = value
						logger.Debugf("Couple name=value has been found <" + name + "=" + value + ">")
					}
				}

				//default values for non found input
				if form.UrlToSubmit == "" {
					form.UrlToSubmit = form.UrlForm
				}
			})

		}
	}

	if flag && m.next != nil{
		m.next.Request(flag, wi)
	}
}

func (m *formModule) SetNextModule(next Module){
	m.next = next
}<|endoftext|>