<commit_before>package main

import (
	"github.com/dmcbane/dierollergo/pathfinderpkg"
	"gopkg.in/alecthomas/kingpin.v2"
	"os"
)

func GetParameters() (pathfinderpkg.GenerationType, string, uint32, bool) {
	var (
		pathfinder = kingpin.New("pathfinder", "Generate Pathfinder character abilities.")
		classic    = pathfinder.Flag("classic", "The classic method: 3D6 per ability.").Default("false").Short('c').Bool()
		standard   = pathfinder.Flag("standard", "The standard method: 4D6 keep high 3 per ability. (this is the default)").Default("false").Short('s').Bool()
		heroic     = pathfinder.Flag("heroic", "The heroic method: 2D6 plus 6 per ability.").Default("false").Short('r').Bool()
		pool       = pathfinder.Flag("pool", "The pool method: 24D6 for all 6 abilities. The parameter specifies how many dice are assigned to each ability as follows: 3/3/3/3/3/9 with a minimum of 3 dice per ability.").Default("").Short('l').String()
		purchase   = pathfinder.Flag("purchase", "The purchase method: parameters are set according to cost. The parameter specifies the purchase type as follows: low, standard, high, and epic fantasy which provides 10, 15, 20, and 25 purchase points respectively.").Default("").Short('p').String()
		number     = pathfinder.Flag("number", "Number of characters to roll. Must be greater than 0.").Default("1").Short('n').Uint32()
		verbose    = pathfinder.Flag("verbose", "Display additional information.").Default("false").Short('v').Bool()
	)
	kingpin.MustParse(pathfinder.Parse(os.Args[1:]))
	if (*classic && *standard) ||
		(*classic && *heroic) ||
		(*classic && (*pool != "")) ||
		(*classic && (*purchase != "")) ||
		(*standard && *heroic) ||
		(*standard && (*pool != "")) ||
		(*standard && (*purchase != "")) ||
		(*heroic && (*pool != "")) ||
		(*heroic && (*purchase != "")) ||
		((*pool != "") && (*purchase != "")) {
		pathfinder.FatalUsage("multiple generation types cannot be defined.\n")
	}
	if *pool != "" && !pathfinderpkg.IsValidPoolSpecification(*pool) {
		pathfinder.FatalUsage("invalid pool specification.\n")
	}
	if *purchase != "" && !pathfinderpkg.IsValidPurchaseSpecification(*purchase) {
		pathfinder.FatalUsage("invalid purchase type specification.\n")
	}

	var gentype pathfinderpkg.GenerationType
	var options string

	switch {
	case *classic:
		gentype = pathfinderpkg.GenerationTypeClassic
		options = ""
	case *standard:
		gentype = pathfinderpkg.GenerationTypeStandard
		options = ""
	case *heroic:
		gentype = pathfinderpkg.GenerationTypeHeroic
		options = ""
	case *pool != "":
		gentype = pathfinderpkg.GenerationTypePool
		options = *pool
	case *purchase != "":
		gentype = pathfinderpkg.GenerationTypePurchase
		options = *purchase
	default:
		gentype = pathfinderpkg.GenerationTypeStandard
		options = ""
	}
	return gentype, options, *number, *verbose
}
<commit_msg>Missed number when changing from uint32 to int...<commit_after>package main

import (
	"github.com/dmcbane/dierollergo/pathfinderpkg"
	"gopkg.in/alecthomas/kingpin.v2"
	"os"
)

func GetParameters() (pathfinderpkg.GenerationType, string, int, bool) {
	var (
		pathfinder = kingpin.New("pathfinder", "Generate Pathfinder character abilities.")
		classic    = pathfinder.Flag("classic", "The classic method: 3D6 per ability.").Default("false").Short('c').Bool()
		standard   = pathfinder.Flag("standard", "The standard method: 4D6 keep high 3 per ability. (this is the default)").Default("false").Short('s').Bool()
		heroic     = pathfinder.Flag("heroic", "The heroic method: 2D6 plus 6 per ability.").Default("false").Short('r').Bool()
		pool       = pathfinder.Flag("pool", "The pool method: 24D6 for all 6 abilities. The parameter specifies how many dice are assigned to each ability as follows: 3/3/3/3/3/9 with a minimum of 3 dice per ability.").Default("").Short('l').String()
		purchase   = pathfinder.Flag("purchase", "The purchase method: parameters are set according to cost. The parameter specifies the purchase type as follows: low, standard, high, and epic fantasy which provides 10, 15, 20, and 25 purchase points respectively.").Default("").Short('p').String()
		number     = pathfinder.Flag("number", "Number of characters to roll. Must be greater than 0.").Default("1").Short('n').Int()
		verbose    = pathfinder.Flag("verbose", "Display additional information.").Default("false").Short('v').Bool()
	)
	kingpin.MustParse(pathfinder.Parse(os.Args[1:]))
	if (*classic && *standard) ||
		(*classic && *heroic) ||
		(*classic && (*pool != "")) ||
		(*classic && (*purchase != "")) ||
		(*standard && *heroic) ||
		(*standard && (*pool != "")) ||
		(*standard && (*purchase != "")) ||
		(*heroic && (*pool != "")) ||
		(*heroic && (*purchase != "")) ||
		((*pool != "") && (*purchase != "")) {
		pathfinder.FatalUsage("multiple generation types cannot be defined.\n")
	}
	if *pool != "" && !pathfinderpkg.IsValidPoolSpecification(*pool) {
		pathfinder.FatalUsage("invalid pool specification.\n")
	}
	if *purchase != "" && !pathfinderpkg.IsValidPurchaseSpecification(*purchase) {
		pathfinder.FatalUsage("invalid purchase type specification.\n")
	}

	var gentype pathfinderpkg.GenerationType
	var options string

	switch {
	case *classic:
		gentype = pathfinderpkg.GenerationTypeClassic
		options = ""
	case *standard:
		gentype = pathfinderpkg.GenerationTypeStandard
		options = ""
	case *heroic:
		gentype = pathfinderpkg.GenerationTypeHeroic
		options = ""
	case *pool != "":
		gentype = pathfinderpkg.GenerationTypePool
		options = *pool
	case *purchase != "":
		gentype = pathfinderpkg.GenerationTypePurchase
		options = *purchase
	default:
		gentype = pathfinderpkg.GenerationTypeStandard
		options = ""
	}
	return gentype, options, *number, *verbose
}
<|endoftext|>


<commit_before>package integration_test

import (
	"crypto/tls"
	"crypto/x509"
	"fmt"
	"io/ioutil"
	"lib/testsupport"
	"math/rand"
	"net/http"
	"netmon/integration/fakes"
	"policy-server/config"
	"strings"

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

var _ = Describe("Internal API", func() {
	var (
		sessions     []*gexec.Session
		conf         config.Config
		address      string
		testDatabase *testsupport.TestDatabase
		tlsConfig    *tls.Config

		fakeMetron fakes.FakeMetron
	)

	BeforeEach(func() {
		fakeMetron = fakes.New()
		dbName := fmt.Sprintf("test_netman_database_%x", rand.Int())
		dbConnectionInfo := testsupport.GetDBConnectionInfo()
		testDatabase = dbConnectionInfo.CreateDatabase(dbName)
		cert, err := tls.LoadX509KeyPair("fixtures/client.crt", "fixtures/client.key")
		Expect(err).NotTo(HaveOccurred())

		clientCACert, err := ioutil.ReadFile("fixtures/netman-ca.crt")
		Expect(err).NotTo(HaveOccurred())

		clientCertPool := x509.NewCertPool()
		clientCertPool.AppendCertsFromPEM(clientCACert)

		tlsConfig = &tls.Config{
			Certificates: []tls.Certificate{cert},
			RootCAs:      clientCertPool,
		}
		tlsConfig.BuildNameToCertificate()

		template := DefaultTestConfig(testDatabase.DBConfig(), fakeMetron.Address())
		template.TagLength = 2
		policyServerConfs := configurePolicyServers(template, 1)
		sessions = startPolicyServers(policyServerConfs)
		conf = policyServerConfs[0]

		address = fmt.Sprintf("%s:%d", conf.ListenHost, conf.ListenPort)
	})

	AfterEach(func() {
		stopPolicyServers(sessions)

		if testDatabase != nil {
			testDatabase.Destroy()
		}

		Expect(fakeMetron.Close()).To(Succeed())
	})

	It("Lists policies and associated tags", func() {
		body := strings.NewReader(`{ "policies": [
				 {"source": { "id": "app1" }, "destination": { "id": "app2", "protocol": "tcp", "port": 8080 } },
				 {"source": { "id": "app3" }, "destination": { "id": "app1", "protocol": "tcp", "port": 9999 } },
				 {"source": { "id": "app3" }, "destination": { "id": "app4", "protocol": "tcp", "port": 3333 } }
				 ]}
				`)

		_ = makeAndDoRequest(
			"POST",
			fmt.Sprintf("http://%s:%d/networking/v0/external/policies", conf.ListenHost, conf.ListenPort),
			body,
		)

		resp := makeAndDoHTTPSRequest(
			"GET",
			fmt.Sprintf("https://%s:%d/networking/v0/internal/policies?id=app1,app2", conf.ListenHost, conf.InternalListenPort),
			nil,
			tlsConfig,
		)
		Expect(resp.StatusCode).To(Equal(http.StatusOK))
		responseString, err := ioutil.ReadAll(resp.Body)
		Expect(err).NotTo(HaveOccurred())
		Expect(responseString).To(MatchJSON(`{ "policies": [
				{"source": { "id": "app1", "tag": "0001" }, "destination": { "id": "app2", "tag": "0002", "protocol": "tcp", "port": 8080 } },
				{"source": { "id": "app3", "tag": "0003" }, "destination": { "id": "app1", "tag": "0001", "protocol": "tcp", "port": 9999 } }
			]}
		`))
	})

	It("emits metrics about durations", func() {
		resp := makeAndDoHTTPSRequest(
			"GET",
			fmt.Sprintf("https://%s:%d/networking/v0/internal/policies?id=app1,app2", conf.ListenHost, conf.InternalListenPort),
			nil,
			tlsConfig,
		)
		Expect(resp.StatusCode).To(Equal(http.StatusOK))
		Eventually(fakeMetron.AllEvents, "5s").Should(ContainElement(
			HaveName("InternalPoliciesRequestTime"),
		))
		Eventually(fakeMetron.AllEvents, "5s").Should(ContainElement(
			HaveName("InternalPoliciesQueryTime"),
		))
		Eventually(fakeMetron.AllEvents, "5s").Should(ContainElement(
			HaveName("StoreAllTime"),
		))
	})
})
<commit_msg>Remove check for InternalPoliciesQueryTime metric<commit_after>package integration_test

import (
	"crypto/tls"
	"crypto/x509"
	"fmt"
	"io/ioutil"
	"lib/testsupport"
	"math/rand"
	"net/http"
	"netmon/integration/fakes"
	"policy-server/config"
	"strings"

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

var _ = Describe("Internal API", func() {
	var (
		sessions     []*gexec.Session
		conf         config.Config
		address      string
		testDatabase *testsupport.TestDatabase
		tlsConfig    *tls.Config

		fakeMetron fakes.FakeMetron
	)

	BeforeEach(func() {
		fakeMetron = fakes.New()
		dbName := fmt.Sprintf("test_netman_database_%x", rand.Int())
		dbConnectionInfo := testsupport.GetDBConnectionInfo()
		testDatabase = dbConnectionInfo.CreateDatabase(dbName)
		cert, err := tls.LoadX509KeyPair("fixtures/client.crt", "fixtures/client.key")
		Expect(err).NotTo(HaveOccurred())

		clientCACert, err := ioutil.ReadFile("fixtures/netman-ca.crt")
		Expect(err).NotTo(HaveOccurred())

		clientCertPool := x509.NewCertPool()
		clientCertPool.AppendCertsFromPEM(clientCACert)

		tlsConfig = &tls.Config{
			Certificates: []tls.Certificate{cert},
			RootCAs:      clientCertPool,
		}
		tlsConfig.BuildNameToCertificate()

		template := DefaultTestConfig(testDatabase.DBConfig(), fakeMetron.Address())
		template.TagLength = 2
		policyServerConfs := configurePolicyServers(template, 1)
		sessions = startPolicyServers(policyServerConfs)
		conf = policyServerConfs[0]

		address = fmt.Sprintf("%s:%d", conf.ListenHost, conf.ListenPort)
	})

	AfterEach(func() {
		stopPolicyServers(sessions)

		if testDatabase != nil {
			testDatabase.Destroy()
		}

		Expect(fakeMetron.Close()).To(Succeed())
	})

	It("Lists policies and associated tags", func() {
		body := strings.NewReader(`{ "policies": [
				 {"source": { "id": "app1" }, "destination": { "id": "app2", "protocol": "tcp", "port": 8080 } },
				 {"source": { "id": "app3" }, "destination": { "id": "app1", "protocol": "tcp", "port": 9999 } },
				 {"source": { "id": "app3" }, "destination": { "id": "app4", "protocol": "tcp", "port": 3333 } }
				 ]}
				`)

		_ = makeAndDoRequest(
			"POST",
			fmt.Sprintf("http://%s:%d/networking/v0/external/policies", conf.ListenHost, conf.ListenPort),
			body,
		)

		resp := makeAndDoHTTPSRequest(
			"GET",
			fmt.Sprintf("https://%s:%d/networking/v0/internal/policies?id=app1,app2", conf.ListenHost, conf.InternalListenPort),
			nil,
			tlsConfig,
		)
		Expect(resp.StatusCode).To(Equal(http.StatusOK))
		responseString, err := ioutil.ReadAll(resp.Body)
		Expect(err).NotTo(HaveOccurred())
		Expect(responseString).To(MatchJSON(`{ "policies": [
				{"source": { "id": "app1", "tag": "0001" }, "destination": { "id": "app2", "tag": "0002", "protocol": "tcp", "port": 8080 } },
				{"source": { "id": "app3", "tag": "0003" }, "destination": { "id": "app1", "tag": "0001", "protocol": "tcp", "port": 9999 } }
			]}
		`))
	})

	It("emits metrics about durations", func() {
		resp := makeAndDoHTTPSRequest(
			"GET",
			fmt.Sprintf("https://%s:%d/networking/v0/internal/policies?id=app1,app2", conf.ListenHost, conf.InternalListenPort),
			nil,
			tlsConfig,
		)
		Expect(resp.StatusCode).To(Equal(http.StatusOK))
		Eventually(fakeMetron.AllEvents, "5s").Should(ContainElement(
			HaveName("InternalPoliciesRequestTime"),
		))
		Eventually(fakeMetron.AllEvents, "5s").Should(ContainElement(
			HaveName("StoreAllTime"),
		))
	})
})
<|endoftext|>


<commit_before>/*
Copyright 2013 The Camlistore Authors.

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

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

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

// This program runs the development appengine
// camlistore with dev_appserver.py.
package main

import (
	"errors"
	"flag"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"

	"camlistore.org/pkg/cmdmain"
	"camlistore.org/pkg/osutil"
)

type gaeCmd struct {
	// start of flag vars
	all  bool
	port string
	sdk  string
	wipe bool
	// end of flag vars

	camliSrcRoot   string // the camlistore source tree
	applicationDir string // App Engine application dir: camliSrcRoot/server/appengine
}

func init() {
	cmdmain.RegisterCommand("appengine", func(flags *flag.FlagSet) cmdmain.CommandRunner {
		cmd := new(gaeCmd)
		flags.BoolVar(&cmd.all, "all", false, "Listen on all interfaces.")
		flags.StringVar(&cmd.port, "port", "3179", "Port to listen on.")
		flags.StringVar(&cmd.sdk, "sdk", "", "The path to the App Engine Go SDK (or a symlink to it).")
		flags.BoolVar(&cmd.wipe, "wipe", false, "Wipe the blobs on disk and the indexer.")
		return cmd
	})
}

func (c *gaeCmd) Usage() {
	fmt.Fprintf(cmdmain.Stderr, "Usage: devcam [globalopts] appengine [cmdopts] [other_dev_appserver_opts] \n")
}

func (c *gaeCmd) Describe() string {
	return "run the App Engine camlistored in dev mode."
}

func (c *gaeCmd) RunCommand(args []string) error {
	err := c.checkFlags(args)
	if err != nil {
		return cmdmain.UsageError(fmt.Sprint(err))
	}
	c.camliSrcRoot, err = osutil.GoPackagePath("camlistore.org")
	if err != nil {
		return errors.New("Package camlistore.org not found in $GOPATH (or $GOPATH not defined).")
	}
	c.applicationDir = filepath.Join(c.camliSrcRoot, "server", "appengine")
	if _, err := os.Stat(c.applicationDir); err != nil {
		return fmt.Errorf("Appengine application dir not found at %s", c.applicationDir)
	}
	if err = c.checkSDK(); err != nil {
		return err
	}
	if err = c.mirrorSourceRoot(); err != nil {
		return err
	}

	devAppServerBin := filepath.Join(c.sdk, "dev_appserver.py")
	cmdArgs := []string{
		"--skip_sdk_update_check",
		fmt.Sprintf("--port=%s", c.port),
	}
	if c.all {
		cmdArgs = append(cmdArgs, "--host", "0.0.0.0")
	}
	if c.wipe {
		cmdArgs = append(cmdArgs, "--clear_datastore")
	}
	cmdArgs = append(cmdArgs, args...)
	cmdArgs = append(cmdArgs, c.applicationDir)
	return runExec(devAppServerBin, cmdArgs)
}

func (c *gaeCmd) checkFlags(args []string) error {
	if _, err := strconv.ParseInt(c.port, 0, 0); err != nil {
		return fmt.Errorf("Invalid -port value: %q", c.port)
	}
	return nil
}

func (c *gaeCmd) checkSDK() error {
	defaultSDK := filepath.Join(c.camliSrcRoot, "appengine-sdk")
	if c.sdk == "" {
		c.sdk = defaultSDK
	}
	if _, err := os.Stat(c.sdk); err != nil {
		return fmt.Errorf("App Engine SDK not found. Please specify it with --sdk or:\n$ ln -s /path/to/appengine-go-sdk %s\n\n", defaultSDK)
	}
	return nil
}

func (c *gaeCmd) mirrorSourceRoot() error {
	uiDirs := []string{"server/camlistored/ui", "third_party/closure/lib/closure", "pkg/server"}
	for _, dir := range uiDirs {
		oriPath := filepath.Join(c.camliSrcRoot, filepath.FromSlash(dir))
		dstPath := filepath.Join(c.applicationDir, "source_root", filepath.FromSlash(dir))
		if err := cpDir(oriPath, dstPath, []string{".go"}); err != nil {
			return fmt.Errorf("Error while mirroring %s to %s: %v", oriPath, dstPath, err)
		}
	}
	return nil
}
<commit_msg>devcam: fix build<commit_after>/*
Copyright 2013 The Camlistore Authors.

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

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

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

// This program runs the development appengine
// camlistore with dev_appserver.py.
package main

import (
	"errors"
	"flag"
	"fmt"
	"os"
	"path/filepath"
	"strconv"

	"camlistore.org/pkg/cmdmain"
	"camlistore.org/pkg/osutil"
)

type gaeCmd struct {
	// start of flag vars
	all  bool
	port string
	sdk  string
	wipe bool
	// end of flag vars

	camliSrcRoot   string // the camlistore source tree
	applicationDir string // App Engine application dir: camliSrcRoot/server/appengine
}

func init() {
	cmdmain.RegisterCommand("appengine", func(flags *flag.FlagSet) cmdmain.CommandRunner {
		cmd := new(gaeCmd)
		flags.BoolVar(&cmd.all, "all", false, "Listen on all interfaces.")
		flags.StringVar(&cmd.port, "port", "3179", "Port to listen on.")
		flags.StringVar(&cmd.sdk, "sdk", "", "The path to the App Engine Go SDK (or a symlink to it).")
		flags.BoolVar(&cmd.wipe, "wipe", false, "Wipe the blobs on disk and the indexer.")
		return cmd
	})
}

func (c *gaeCmd) Usage() {
	fmt.Fprintf(cmdmain.Stderr, "Usage: devcam [globalopts] appengine [cmdopts] [other_dev_appserver_opts] \n")
}

func (c *gaeCmd) Describe() string {
	return "run the App Engine camlistored in dev mode."
}

func (c *gaeCmd) RunCommand(args []string) error {
	err := c.checkFlags(args)
	if err != nil {
		return cmdmain.UsageError(fmt.Sprint(err))
	}
	c.camliSrcRoot, err = osutil.GoPackagePath("camlistore.org")
	if err != nil {
		return errors.New("Package camlistore.org not found in $GOPATH (or $GOPATH not defined).")
	}
	c.applicationDir = filepath.Join(c.camliSrcRoot, "server", "appengine")
	if _, err := os.Stat(c.applicationDir); err != nil {
		return fmt.Errorf("Appengine application dir not found at %s", c.applicationDir)
	}
	if err = c.checkSDK(); err != nil {
		return err
	}
	if err = c.mirrorSourceRoot(); err != nil {
		return err
	}

	devAppServerBin := filepath.Join(c.sdk, "dev_appserver.py")
	cmdArgs := []string{
		"--skip_sdk_update_check",
		fmt.Sprintf("--port=%s", c.port),
	}
	if c.all {
		cmdArgs = append(cmdArgs, "--host", "0.0.0.0")
	}
	if c.wipe {
		cmdArgs = append(cmdArgs, "--clear_datastore")
	}
	cmdArgs = append(cmdArgs, args...)
	cmdArgs = append(cmdArgs, c.applicationDir)
	return runExec(devAppServerBin, cmdArgs)
}

func (c *gaeCmd) checkFlags(args []string) error {
	if _, err := strconv.ParseInt(c.port, 0, 0); err != nil {
		return fmt.Errorf("Invalid -port value: %q", c.port)
	}
	return nil
}

func (c *gaeCmd) checkSDK() error {
	defaultSDK := filepath.Join(c.camliSrcRoot, "appengine-sdk")
	if c.sdk == "" {
		c.sdk = defaultSDK
	}
	if _, err := os.Stat(c.sdk); err != nil {
		return fmt.Errorf("App Engine SDK not found. Please specify it with --sdk or:\n$ ln -s /path/to/appengine-go-sdk %s\n\n", defaultSDK)
	}
	return nil
}

func (c *gaeCmd) mirrorSourceRoot() error {
	uiDirs := []string{"server/camlistored/ui", "third_party/closure/lib/closure", "pkg/server"}
	for _, dir := range uiDirs {
		oriPath := filepath.Join(c.camliSrcRoot, filepath.FromSlash(dir))
		dstPath := filepath.Join(c.applicationDir, "source_root", filepath.FromSlash(dir))
		if err := cpDir(oriPath, dstPath, []string{".go"}); err != nil {
			return fmt.Errorf("Error while mirroring %s to %s: %v", oriPath, dstPath, err)
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package process

import (
	"io"
	"os"
	"path/filepath"
	"reflect"
	"strings"

	"kego.io/json"
	"kego.io/kerr"
	"kego.io/system"
)

func Validate(root string, packagePath string, imports map[string]string) error {

	walker := func(filePath string, file os.FileInfo, err error) error {
		if err != nil {
			return kerr.New("GFBBIERGIY", err, "process.Validate", "walker (%s)", filePath)
		}
		if err := validateFile(filePath, packagePath, imports); err != nil {
			return kerr.New("QJGXAUKPTI", err, "process.Validate", "validateFile (%s)", filePath)
		}
		return nil
	}

	if err := filepath.Walk(root, walker); err != nil {
		return kerr.New("GCKFJQJUXK", err, "process.Validate", "filepath.Walk")
	}
	return nil
}

func validateFile(filePath string, packagePath string, imports map[string]string) error {

	if !strings.HasSuffix(filePath, ".json") {
		return nil
	}

	file, err := os.Open(filePath)
	if err != nil {
		return kerr.New("TIODJJGDCL", err, "process.validateFile", "os.Open (%s)", filePath)
	}
	defer file.Close()

	if err = validateReader(file, packagePath, imports); err != nil {
		return kerr.New("GFVGDBDTNQ", err, "process.validateFile", "validateReader (%s)", filePath)
	}
	return nil
}

func validateReader(file io.Reader, packagePath string, imports map[string]string) error {
	var i interface{}
	if err := json.NewDecoder(file, packagePath, imports).Decode(&i); err != nil {
		return kerr.New("QIVNOQKCQF", err, "process.validateReader", "json.NewDecoder.Decode")
	}
	if err := validateUnknown(i, packagePath, imports); err != nil {
		return kerr.New("RVKNMWKQHD", err, "process.validateReader", "validateUnknown")
	}
	return nil
}

func validateUnknown(data interface{}, path string, imports map[string]string) error {

	tp, ok := data.(system.Typer)
	if !ok {
		return kerr.New("RSSFIFHCOF", nil, "process.validateUnknown", "Input %T is not *system.Object", data)
	}
	t, ok := tp.GetType()
	if !ok {
		return kerr.New("BNQTCEDVGV", nil, "process.validateUnknown", "Type not found")
	}

	partialRuleHolder := system.NewMinimalRuleHolder(t, path, imports)

	return validateObject(partialRuleHolder, data, path, imports)

}

func validateObject(rule *system.RuleHolder, data interface{}, path string, imports map[string]string) error {

	// Validate the actual object
	if v, ok := data.(system.Validator); ok {
		ok, message, err := v.Validate(path, imports)
		if err != nil {
			return kerr.New("RUGJLUAFAN", err, "process.validateObject", "v.Validate")
		}
		if !ok {
			return kerr.New("DCIARXKRXN", nil, "process.validateObject", "Invalid data. %s. %#v", message, data)
		}
	}

	// TODO: Get selectors working
	/*
		for selector, rule := range rules {
			if selector == "doesnt apply to the current object" {
				continue
			}
			if e, ok := rule.(system.Enforcer); ok {
				ok, message, err := e.Enforce(data, path, imports)
				if err != nil {
					kerr.New("MGHHDYTXVV", err, "process.validateObject", "e.Enforce")
				}
				if !ok {
					return kerr.New("FRXEXSTARP", nil, "process.validateObject", "Broken rule. %s. %#v", message, data)
				}
			}
		}
	*/

	// Validate the children
	switch rule.ParentType.Native.Value {
	case "object":
		return validateObjectChildren(rule, data, path, imports)
	case "array":
		items, err := rule.ItemsRule()
		if err != nil {
			return kerr.New("YFNERJIKWF", err, "process.validateObject", "rule.ItemsRule (array)")
		}
		return validateArrayChildren(items, data, path, imports)
	case "map":
		items, err := rule.ItemsRule()
		if err != nil {
			return kerr.New("PRPQQJKIKF", err, "process.validateObject", "rule.ItemsRule (map)")
		}
		return validateMapChildren(items, data, path, imports)
	}

	return nil
}

// TODO: Generate some code to remove the reflection from this
func validateObjectChildren(itemsRule *system.RuleHolder, data interface{}, path string, imports map[string]string) error {

	if data == nil {
		return nil
	}

	value := reflect.Indirect(reflect.ValueOf(data))
	if value.Kind() != reflect.Struct {
		return kerr.New("FJBEEDBLOK", nil, "process.validateObjectChildren", "value.Kind %s (%T) must be Struct", value.Kind(), data)
	}

	for name, property := range itemsRule.ParentType.Properties {
		child, _, _, found, _, err := system.GetObjectField(value, system.IdToGoName(name))
		if err != nil {
			return kerr.New("XTUKWWRDHH", err, "process.validateObjectChildren", "system.GetField (%s)", name)
		}
		if !property.Optional && !found {
			return kerr.New("ETODESNSET", nil, "process.validateObjectChildren", "Field %s is missing and not optional", name)
		}
		childRule, err := system.NewRuleHolder(property.Item, path, imports)
		if err != nil {
			return kerr.New("IQOXVXBLRO", err, "process.validateObjectChildren", "system.NewRuleHolder (%s)", name)
		}
		if err = validateObject(childRule, child, path, imports); err != nil {
			return kerr.New("YJYSAOQWSJ", err, "process.validateObjectChildren", "validateObject (%s)", name)
		}
	}
	return nil
}

// TODO: Generate some code to remove the reflection from this
func validateArrayChildren(itemsRule *system.RuleHolder, data interface{}, path string, imports map[string]string) error {

	value := reflect.Indirect(reflect.ValueOf(data))
	if value.Kind() != reflect.Slice {
		return kerr.New("HQOKLQABIA", nil, "process.validateArrayChildren", "value.Kind %s must be Slice", value.Kind())
	}

	for i := 0; i < value.Len(); i++ {
		child := value.Index(i).Interface()
		if err := validateObject(itemsRule, child, path, imports); err != nil {
			return kerr.New("DKVEPIWTPI", err, "process.validateArrayChildren", "validateObject")
		}
	}
	return nil
}

// TODO: Generate some code to remove the reflection from this
func validateMapChildren(itemsRule *system.RuleHolder, data interface{}, path string, imports map[string]string) error {

	value := reflect.Indirect(reflect.ValueOf(data))
	if value.Kind() != reflect.Map {
		return kerr.New("GMEQUWCFBQ", nil, "process.validateMapChildren", "value.Kind %s must be Map", value.Kind())
	}
	if value.Type().Key() != reflect.TypeOf("") {
		return kerr.New("BPEHPQWUSG", nil, "process.validateMapChildren", "Map key %s must be string", value.Type().Key())
	}

	for _, key := range value.MapKeys() {
		child := value.MapIndex(key).Interface()
		if err := validateObject(itemsRule, child, path, imports); err != nil {
			return kerr.New("YLONAMFUAG", err, "process.validateMapChildren", "validateObject")
		}
	}
	return nil
}
<commit_msg>validators, enforcers and rules<commit_after>package process

import (
	"io"
	"os"
	"path/filepath"
	"reflect"
	"strings"

	"kego.io/json"
	"kego.io/jsonselect"
	"kego.io/kerr"
	"kego.io/system"
)

func Validate(root string, packagePath string, imports map[string]string) error {

	walker := func(filePath string, file os.FileInfo, err error) error {
		if err != nil {
			return kerr.New("GFBBIERGIY", err, "process.Validate", "walker (%s)", filePath)
		}
		if err := validateFile(filePath, packagePath, imports); err != nil {
			return kerr.New("QJGXAUKPTI", err, "process.Validate", "validateFile (%s)", filePath)
		}
		return nil
	}

	if err := filepath.Walk(root, walker); err != nil {
		return kerr.New("GCKFJQJUXK", err, "process.Validate", "filepath.Walk")
	}
	return nil
}

func validateFile(filePath string, packagePath string, imports map[string]string) error {

	if !strings.HasSuffix(filePath, ".json") {
		return nil
	}

	file, err := os.Open(filePath)
	if err != nil {
		return kerr.New("TIODJJGDCL", err, "process.validateFile", "os.Open (%s)", filePath)
	}
	defer file.Close()

	if err = validateReader(file, packagePath, imports); err != nil {
		return kerr.New("GFVGDBDTNQ", err, "process.validateFile", "validateReader (%s)", filePath)
	}
	return nil
}

func validateReader(file io.Reader, packagePath string, imports map[string]string) error {
	var i interface{}
	if err := json.NewDecoder(file, packagePath, imports).Decode(&i); err != nil {
		return kerr.New("QIVNOQKCQF", err, "process.validateReader", "json.NewDecoder.Decode")
	}
	if err := validateUnknown(i, packagePath, imports); err != nil {
		return kerr.New("RVKNMWKQHD", err, "process.validateReader", "validateUnknown")
	}
	return nil
}

func validateUnknown(data interface{}, path string, imports map[string]string) error {

	tp, ok := data.(system.Typer)
	if !ok {
		return kerr.New("RSSFIFHCOF", nil, "process.validateUnknown", "data %T does not implement system.Typer", data)
	}
	t, ok := tp.GetType()
	if !ok {
		return kerr.New("BNQTCEDVGV", nil, "process.validateUnknown", "tp.GetType not found")
	}

	partialRuleHolder := system.NewMinimalRuleHolder(t, path, imports)

	return validateObject(partialRuleHolder, nil, data, path, imports)

}

func validateObject(rule *system.RuleHolder, rules map[string]system.Rule, data interface{}, path string, imports map[string]string) error {

	// Validate the actual object
	if v, ok := data.(system.Validator); ok {
		ok, message, err := v.Validate(path, imports)
		if err != nil {
			return kerr.New("RUGJLUAFAN", err, "process.validateObject", "v.Validate")
		}
		if !ok {
			return kerr.New("DCIARXKRXN", nil, "process.validateObject", "Invalid data. %s. %#v", message, data)
		}
	}

	if rule.Rule != nil {
		e, ok := rule.Rule.(system.Enforcer)
		if ok {
			ok, message, err := e.Enforce(data, path, imports)
			if err != nil {
				return kerr.New("EBEMISLGDX", err, "process.validateObject", "e.Enforce (main)")
			}
			if !ok {
				return kerr.New("KKOFBHILXM", nil, "process.validateObject", "Broken rule. %s. %#v", message, data)
			}
		}
	}

	if rules != nil && len(rules) > 0 {

		j := &jsonselect.Json{Data: data, Value: reflect.ValueOf(data), Rule: rule}
		p, err := jsonselect.CreateParser(j, path, imports)
		if err != nil {
			return kerr.New("AIWLGYGGAY", err, "process.validateObject", "jsonselect.CreateParser")
		}

		for selector, rule := range rules {
			e, ok := rule.(system.Enforcer)
			if !ok {
				return kerr.New("ABVWHMMXGG", nil, "process.validateObject", "rule %T does not implement system.Enforcer", rule)
			}
			matches, err := p.GetJsonElements(selector)
			if err != nil {
				return kerr.New("UKOCCFJWAB", err, "process.validateObject", "p.GetJsonElements (%s)", selector)
			}
			for _, match := range matches {
				ok, message, err := e.Enforce(match.Data, path, imports)
				if err != nil {
					kerr.New("MGHHDYTXVV", err, "process.validateObject", "e.Enforce")
				}
				if !ok {
					return kerr.New("FRXEXSTARP", nil, "process.validateObject", "Broken rule. %s. %#v", message, data)
				}

			}
		}
	}

	// Validate the children
	switch rule.ParentType.Native.Value {
	case "object":
		return validateObjectChildren(rule, data, path, imports)
	case "array":
		items, err := rule.ItemsRule()
		if err != nil {
			return kerr.New("YFNERJIKWF", err, "process.validateObject", "rule.ItemsRule (array)")
		}
		rules := rule.Rule.(system.Ruler).GetRules()
		return validateArrayChildren(items, rules, data, path, imports)
	case "map":
		items, err := rule.ItemsRule()
		if err != nil {
			return kerr.New("PRPQQJKIKF", err, "process.validateObject", "rule.ItemsRule (map)")
		}
		rules := rule.Rule.(system.Ruler).GetRules()
		return validateMapChildren(items, rules, data, path, imports)
	}

	return nil
}

// TODO: Generate some code to remove the reflection from this
func validateObjectChildren(itemsRule *system.RuleHolder, data interface{}, path string, imports map[string]string) error {

	if data == nil {
		return nil
	}

	value := reflect.Indirect(reflect.ValueOf(data))
	if value.Kind() != reflect.Struct {
		return kerr.New("FJBEEDBLOK", nil, "process.validateObjectChildren", "value.Kind %s (%T) must be Struct", value.Kind(), data)
	}

	for name, property := range itemsRule.ParentType.Properties {
		child, _, _, found, _, err := system.GetObjectField(value, system.IdToGoName(name))
		if err != nil {
			return kerr.New("XTUKWWRDHH", err, "process.validateObjectChildren", "system.GetField (%s)", name)
		}
		if !property.Optional && !found {
			return kerr.New("ETODESNSET", nil, "process.validateObjectChildren", "Field %s is missing and not optional", name)
		}
		childRule, err := system.NewRuleHolder(property.Item, path, imports)
		if err != nil {
			return kerr.New("IQOXVXBLRO", err, "process.validateObjectChildren", "system.NewRuleHolder (%s)", name)
		}
		if err = validateObject(childRule, property.Rules, child, path, imports); err != nil {
			return kerr.New("YJYSAOQWSJ", err, "process.validateObjectChildren", "validateObject (%s)", name)
		}
	}
	return nil
}

// TODO: Generate some code to remove the reflection from this
func validateArrayChildren(itemsRule *system.RuleHolder, rules map[string]system.Rule, data interface{}, path string, imports map[string]string) error {

	value := reflect.Indirect(reflect.ValueOf(data))
	if value.Kind() != reflect.Slice {
		return kerr.New("HQOKLQABIA", nil, "process.validateArrayChildren", "value.Kind %s must be Slice", value.Kind())
	}

	for i := 0; i < value.Len(); i++ {
		child := value.Index(i).Interface()
		if err := validateObject(itemsRule, rules, child, path, imports); err != nil {
			return kerr.New("DKVEPIWTPI", err, "process.validateArrayChildren", "validateObject")
		}
	}
	return nil
}

// TODO: Generate some code to remove the reflection from this
func validateMapChildren(itemsRule *system.RuleHolder, rules map[string]system.Rule, data interface{}, path string, imports map[string]string) error {

	value := reflect.Indirect(reflect.ValueOf(data))
	if value.Kind() != reflect.Map {
		return kerr.New("GMEQUWCFBQ", nil, "process.validateMapChildren", "value.Kind %s must be Map", value.Kind())
	}
	if value.Type().Key() != reflect.TypeOf("") {
		return kerr.New("BPEHPQWUSG", nil, "process.validateMapChildren", "Map key %s must be string", value.Type().Key())
	}

	for _, key := range value.MapKeys() {
		child := value.MapIndex(key).Interface()
		if err := validateObject(itemsRule, rules, child, path, imports); err != nil {
			return kerr.New("YLONAMFUAG", err, "process.validateMapChildren", "validateObject")
		}
	}
	return nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 SEkiSoft
// See License.txt

package store

import (
	"testing"

	"github.com/SEkiSoft/gogogo/model"
)

func TestMoveStoreSave(t *testing.T) {
	TestSetUp()

	move := model.Move{
		Id:       model.NewId(),
		PlayerId: model.NewId(),
		GameId:   model.NewId(),
		X:        1,
		Y:        1,
	}

	if result := <-store.Move().Save(&move); result.Err != nil {
		t.Fatal("save move failed")
	}

	if result := <-store.Move().Delete(move.Id); result.Err != nil {
		t.Fatal("save move failed, delete")
	}
}

func TestMoveStoreDelete(t *testing.T) {
	TestSetUp()

	move := model.Move{
		Id:       model.NewId(),
		PlayerId: model.NewId(),
		GameId:   model.NewId(),
		X:        1,
		Y:        1,
	}

	if result := <-store.Move().Save(&move); result.Err != nil {
		t.Fatal("delete move failed, save")
	}

	if result := <-store.Move().Delete(move.Id); result.Err != nil {
		t.Fatal("delete move failed")
	}
}

func TestMoveStoreGet(t *testing.T) {
	TestSetUp()

	move := model.Move{
		Id:       model.NewId(),
		PlayerId: model.NewId(),
		GameId:   model.NewId(),
		X:        1,
		Y:        1,
	}

	if result := <-store.Move().Save(&move); result.Err != nil {
		t.Fatal("get move failed, save")
	}

	if result := <-store.Move().Get(move.Id); result.Err != nil {
		t.Fatal("get move failed, store")
	} else if result.Data.(*model.Move).GameId != move.GameId {
		t.Fatal("get move failed, not equal")
	}

	if result := <-store.Move().Delete(move.Id); result.Err != nil {
		t.Fatal("get move failed, delete")
	}
}

func TestMoveStoreGetByGame(t *testing.T) {
	TestSetUp()

	move := model.Move{
		Id:       model.NewId(),
		PlayerId: model.NewId(),
		GameId:   model.NewId(),
		X:        1,
		Y:        1,
	}

	if result := <-store.Move().Save(&move); result.Err != nil {
		t.Fatal("get move failed, save")
	}

	if result := <-store.Move().GetByGame(move.GameId); result.Err != nil {
		t.Fatal("get move failed, store")
	} else if result.Data.(*model.Move).GameId != move.GameId {
		t.Fatal("get move failed, not equal")
	}

	if result := <-store.Move().Delete(move.Id); result.Err != nil {
		t.Fatal("get move failed, delete")
	}
}

func TestMoveStoreGetByPlayer(t *testing.T) {
	TestSetUp()

	move := model.Move{
		Id:       model.NewId(),
		PlayerId: model.NewId(),
		GameId:   model.NewId(),
		X:        1,
		Y:        1,
	}

	if result := <-store.Move().Save(&move); result.Err != nil {
		t.Fatal("get move failed, save")
	}

	if result := <-store.Move().GetByPlayer(move.PlayerId); result.Err != nil {
		t.Fatal("get move failed, store")
	} else if result.Data.(*model.Move).GameId != move.GameId {
		t.Fatal("get move failed, not equal")
	}

	if result := <-store.Move().Delete(move.Id); result.Err != nil {
		t.Fatal("get move failed, delete")
	}
}

func TestMoveStoreGetAll(t *testing.T) {
	TestSetUp()

	move1 := model.Move{
		Id:       model.NewId(),
		PlayerId: model.NewId(),
		GameId:   model.NewId(),
		X:        1,
		Y:        1,
	}

	move2 := model.Move{
		Id:       model.NewId(),
		PlayerId: model.NewId(),
		GameId:   model.NewId(),
		X:        1,
		Y:        1,
	}

	if result := <-store.Move().Save(&move1); result.Err != nil {
		t.Fatal("get all moves failed, save")
	}

	if result := <-store.Move().Save(&move2); result.Err != nil {
		t.Fatal("get all moves failed, save")
	}

	if result := <-store.Move().GetAll(); result.Err != nil {
		t.Fatal("get all moves failed, store")
	} else if len(result.Data.([]*model.Move)) != 2 {
		t.Fatal("get all moves failed, wrong size")
	}

	if result := <-store.Move().Delete(move1.Id); result.Err != nil {
		t.Fatal("get all moves failed, delete")
	}

	if result := <-store.Move().Delete(move2.Id); result.Err != nil {
		t.Fatal("get all moves failed, delete")
	}
}

func TestMoveStoreGetTotalMovesCount(t *testing.T) {
	TestSetUp()

	move1 := model.Move{
		Id:       model.NewId(),
		PlayerId: model.NewId(),
		GameId:   model.NewId(),
		X:        1,
		Y:        1,
	}

	move2 := model.Move{
		Id:       model.NewId(),
		PlayerId: model.NewId(),
		GameId:   model.NewId(),
		X:        1,
		Y:        1,
	}

	if result := <-store.Move().Save(&move1); result.Err != nil {
		t.Fatal("get all moves count failed, save")
	}

	if result := <-store.Move().Save(&move2); result.Err != nil {
		t.Fatal("get all moves count failed, save")
	}

	if result := <-store.Move().GetTotalMovesCount(); result.Err != nil {
		t.Fatal("get all moves count failed, store")
	} else if result.Data.(int64) != 2 {
		t.Fatal("get all moves count failed, wrong size")
	}

	if result := <-store.Move().Delete(move1.Id); result.Err != nil {
		t.Fatal("get all moves count failed, delete")
	}

	if result := <-store.Move().Delete(move2.Id); result.Err != nil {
		t.Fatal("get all moves count failed, delete")
	}
}
<commit_msg>Update move_store_test.go<commit_after>// Copyright (c) 2016 SEkiSoft
// See License.txt

package store

import (
	"testing"

	"github.com/SEkiSoft/gogogo/model"
)

func TestMoveStoreSave(t *testing.T) {
	Setup()

	move := model.Move{
		Id:       model.NewId(),
		PlayerId: model.NewId(),
		GameId:   model.NewId(),
		X:        1,
		Y:        1,
	}

	if result := <-store.Move().Save(&move); result.Err != nil {
		t.Fatal("save move failed")
	}

	if result := <-store.Move().Delete(move.Id); result.Err != nil {
		t.Fatal("save move failed, delete")
	}
}

func TestMoveStoreDelete(t *testing.T) {
	Setup()

	move := model.Move{
		Id:       model.NewId(),
		PlayerId: model.NewId(),
		GameId:   model.NewId(),
		X:        1,
		Y:        1,
	}

	if result := <-store.Move().Save(&move); result.Err != nil {
		t.Fatal("delete move failed, save")
	}

	if result := <-store.Move().Delete(move.Id); result.Err != nil {
		t.Fatal("delete move failed")
	}
}

func TestMoveStoreGet(t *testing.T) {
	Setup()

	move := model.Move{
		Id:       model.NewId(),
		PlayerId: model.NewId(),
		GameId:   model.NewId(),
		X:        1,
		Y:        1,
	}

	if result := <-store.Move().Save(&move); result.Err != nil {
		t.Fatal("get move failed, save")
	}

	if result := <-store.Move().Get(move.Id); result.Err != nil {
		t.Fatal("get move failed, store")
	} else if result.Data.(*model.Move).GameId != move.GameId {
		t.Fatal("get move failed, not equal")
	}

	if result := <-store.Move().Delete(move.Id); result.Err != nil {
		t.Fatal("get move failed, delete")
	}
}

func TestMoveStoreGetByGame(t *testing.T) {
	Setup()

	move := model.Move{
		Id:       model.NewId(),
		PlayerId: model.NewId(),
		GameId:   model.NewId(),
		X:        1,
		Y:        1,
	}

	if result := <-store.Move().Save(&move); result.Err != nil {
		t.Fatal("get move failed, save")
	}

	if result := <-store.Move().GetByGame(move.GameId); result.Err != nil {
		t.Fatal("get move failed, store")
	} else if result.Data.(*model.Move).GameId != move.GameId {
		t.Fatal("get move failed, not equal")
	}

	if result := <-store.Move().Delete(move.Id); result.Err != nil {
		t.Fatal("get move failed, delete")
	}
}

func TestMoveStoreGetByPlayer(t *testing.T) {
	Setup()

	move := model.Move{
		Id:       model.NewId(),
		PlayerId: model.NewId(),
		GameId:   model.NewId(),
		X:        1,
		Y:        1,
	}

	if result := <-store.Move().Save(&move); result.Err != nil {
		t.Fatal("get move failed, save")
	}

	if result := <-store.Move().GetByPlayer(move.PlayerId); result.Err != nil {
		t.Fatal("get move failed, store")
	} else if result.Data.(*model.Move).GameId != move.GameId {
		t.Fatal("get move failed, not equal")
	}

	if result := <-store.Move().Delete(move.Id); result.Err != nil {
		t.Fatal("get move failed, delete")
	}
}

func TestMoveStoreGetAll(t *testing.T) {
	Setup()

	move1 := model.Move{
		Id:       model.NewId(),
		PlayerId: model.NewId(),
		GameId:   model.NewId(),
		X:        1,
		Y:        1,
	}

	move2 := model.Move{
		Id:       model.NewId(),
		PlayerId: model.NewId(),
		GameId:   model.NewId(),
		X:        1,
		Y:        1,
	}

	if result := <-store.Move().Save(&move1); result.Err != nil {
		t.Fatal("get all moves failed, save")
	}

	if result := <-store.Move().Save(&move2); result.Err != nil {
		t.Fatal("get all moves failed, save")
	}

	if result := <-store.Move().GetAll(); result.Err != nil {
		t.Fatal("get all moves failed, store")
	} else if len(result.Data.([]*model.Move)) != 2 {
		t.Fatal("get all moves failed, wrong size")
	}

	if result := <-store.Move().Delete(move1.Id); result.Err != nil {
		t.Fatal("get all moves failed, delete")
	}

	if result := <-store.Move().Delete(move2.Id); result.Err != nil {
		t.Fatal("get all moves failed, delete")
	}
}

func TestMoveStoreGetTotalMovesCount(t *testing.T) {
	Setup()

	move1 := model.Move{
		Id:       model.NewId(),
		PlayerId: model.NewId(),
		GameId:   model.NewId(),
		X:        1,
		Y:        1,
	}

	move2 := model.Move{
		Id:       model.NewId(),
		PlayerId: model.NewId(),
		GameId:   model.NewId(),
		X:        1,
		Y:        1,
	}

	if result := <-store.Move().Save(&move1); result.Err != nil {
		t.Fatal("get all moves count failed, save")
	}

	if result := <-store.Move().Save(&move2); result.Err != nil {
		t.Fatal("get all moves count failed, save")
	}

	if result := <-store.Move().GetTotalMovesCount(); result.Err != nil {
		t.Fatal("get all moves count failed, store")
	} else if result.Data.(int64) != 2 {
		t.Fatal("get all moves count failed, wrong size")
	}

	if result := <-store.Move().Delete(move1.Id); result.Err != nil {
		t.Fatal("get all moves count failed, delete")
	}

	if result := <-store.Move().Delete(move2.Id); result.Err != nil {
		t.Fatal("get all moves count failed, delete")
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net/http"
	"net/http/httputil"
	"net/url"
	"io/ioutil"
	"log"
	"time"
	"github.com/BurntSushi/toml"
)

type Config struct {
	Upstream string
	ReqFanFactor int
	TimeoutMS int
}

func snd (c chan string, s string) {
	go func () { c <- s }()
}

// start starts Charm up and returns a done channel for the done message
func start(confPath string) (chan string) {
	done := make(chan string)

	// print a welcome message
	log.Print("Charm is starting up.")
	// read the config file
	log.Printf(".   . Reading %s", confPath)
	tomlData, err := ioutil.ReadFile(confPath)
	if err != nil {
		snd(done, fmt.Sprintf("Could not read file at %s", confPath))
		return done
	}
	// populate the config struct
	log.Print(".   . Loading config")
	var conf Config
	_, err = toml.Decode(string(tomlData), &conf)
	if err != nil {
		snd(done, "Could not decode config")
		return done
	}
	// report on the configuration
	log.Print("Charm is configured!")
	log.Printf(".   . Stabilizing %v", conf.Upstream)
	log.Printf(".   . with %v duplicate requests", conf.ReqFanFactor)
	log.Printf(".   . and a %v milisecond timeout.", conf.TimeoutMS)
	go run(conf, done)
	return done
}

func First() {}

type stableTransport struct {
	wrappedTransport http.RoundTripper
	reqFanFactor int
}

// stableTransport.RoundTrip makes many round trips and returns the first
// response
func (t *stableTransport) RoundTrip(r *http.Request) (*http.Response, error) {
	c := make(chan *http.Response)
	if t.wrappedTransport == nil {
		t.wrappedTransport = http.DefaultTransport
	}
	// fan out requests, send responses to the channel, log errors
	for i := 0; i < t.reqFanFactor; i++ {
		time.Sleep(5)
		go func () {
			resp, err := t.wrappedTransport.RoundTrip(r)
			if err != nil {
				// TODO: figure out how much logging we want
			} else {
				c <- resp
			}
		}()
	}

	// return the first good response
	return <-c, nil
}

type Stabilizer struct {
	upstreamURL *url.URL
	reqFanFactor int
}

// Stabilizer.ServeHTTP proxies with a stable transport
func (st *Stabilizer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	proxy := httputil.NewSingleHostReverseProxy(st.upstreamURL)
	proxy.Transport = &stableTransport{proxy.Transport, st.reqFanFactor}
	proxy.ServeHTTP(w, r)
}

// run
func run(conf Config, done chan string) {
	// make a stabilizer
	upstreamURL, err := url.Parse(conf.Upstream)
	if err != nil {
		log.Fatal("error parsing Upstream URL", conf.Upstream)
	}
	stabilizer := &Stabilizer{upstreamURL, conf.ReqFanFactor}

	// serve that stabilizer under a timeout
	timeout := time.Duration(conf.TimeoutMS) * time.Millisecond
	log.Fatal(http.ListenAndServe(
		":8000",
		http.TimeoutHandler(stabilizer, timeout, "upstream timeout"),
	))
}

func main() {
	// start Charm,
	done := start("/secret/charm.conf")
	// when Charm is done, log the message and quit.
        log.Print(<-done)
}
<commit_msg>Removes test function<commit_after>package main

import (
	"fmt"
	"net/http"
	"net/http/httputil"
	"net/url"
	"io/ioutil"
	"log"
	"time"
	"github.com/BurntSushi/toml"
)

type Config struct {
	Upstream string
	ReqFanFactor int
	TimeoutMS int
}

func snd (c chan string, s string) {
	go func () { c <- s }()
}

// start starts Charm up and returns a done channel for the done message
func start(confPath string) (chan string) {
	done := make(chan string)

	// print a welcome message
	log.Print("Charm is starting up.")
	// read the config file
	log.Printf(".   . Reading %s", confPath)
	tomlData, err := ioutil.ReadFile(confPath)
	if err != nil {
		snd(done, fmt.Sprintf("Could not read file at %s", confPath))
		return done
	}
	// populate the config struct
	log.Print(".   . Loading config")
	var conf Config
	_, err = toml.Decode(string(tomlData), &conf)
	if err != nil {
		snd(done, "Could not decode config")
		return done
	}
	// report on the configuration
	log.Print("Charm is configured!")
	log.Printf(".   . Stabilizing %v", conf.Upstream)
	log.Printf(".   . with %v duplicate requests", conf.ReqFanFactor)
	log.Printf(".   . and a %v milisecond timeout.", conf.TimeoutMS)
	go run(conf, done)
	return done
}

type stableTransport struct {
	wrappedTransport http.RoundTripper
	reqFanFactor int
}

// stableTransport.RoundTrip makes many round trips and returns the first
// response
func (t *stableTransport) RoundTrip(r *http.Request) (*http.Response, error) {
	c := make(chan *http.Response)
	if t.wrappedTransport == nil {
		t.wrappedTransport = http.DefaultTransport
	}
	// fan out requests, send responses to the channel, log errors
	for i := 0; i < t.reqFanFactor; i++ {
		time.Sleep(5)
		go func () {
			resp, err := t.wrappedTransport.RoundTrip(r)
			if err != nil {
				// TODO: figure out how much logging we want
			} else {
				c <- resp
			}
		}()
	}

	// return the first good response
	return <-c, nil
}

type Stabilizer struct {
	upstreamURL *url.URL
	reqFanFactor int
}

// Stabilizer.ServeHTTP proxies with a stable transport
func (st *Stabilizer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	proxy := httputil.NewSingleHostReverseProxy(st.upstreamURL)
	proxy.Transport = &stableTransport{proxy.Transport, st.reqFanFactor}
	proxy.ServeHTTP(w, r)
}

// run
func run(conf Config, done chan string) {
	// make a stabilizer
	upstreamURL, err := url.Parse(conf.Upstream)
	if err != nil {
		log.Fatal("error parsing Upstream URL", conf.Upstream)
	}
	stabilizer := &Stabilizer{upstreamURL, conf.ReqFanFactor}

	// serve that stabilizer under a timeout
	timeout := time.Duration(conf.TimeoutMS) * time.Millisecond
	log.Fatal(http.ListenAndServe(
		":8000",
		http.TimeoutHandler(stabilizer, timeout, "upstream timeout"),
	))
}

func main() {
	// start Charm,
	done := start("/secret/charm.conf")
	// when Charm is done, log the message and quit.
        log.Print(<-done)
}
<|endoftext|>


<commit_before>/*
 Copyright 2016 Padduck, LLC

 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 programs

import (
	"container/list"
	"sync"
	"time"
	"github.com/pufferpanel/pufferd/environments"
)

type Program interface {
	//Starts the program.
	//This includes starting the environment if it is not running.
	Start() (err error)

	//Stops the program.
	//This will also stop the environment it is ran in.
	Stop() (err error)

	//Kills the program.
	//This will also stop the environment it is ran in.
	Kill() (err error)

	//Creates any files needed for the program.
	//This includes creating the environment.
	Create() (err error)

	//Destroys the server.
	//This will delete the server, environment, and any files related to it.
	Destroy() (err error)

	Install() (err error)

	//Determines if the server is running.
	IsRunning() (isRunning bool, err error)

	//Sends a command to the process
	//If the program supports input, this will send the arguments to that.
	Execute(command string) (err error)

	SetEnabled(isEnabled bool) (err error)

	IsEnabled() (isEnabled bool)

	SetAutoStart(isAutoStart bool) (err error)

	IsAutoStart() (isAutoStart bool)

	SetEnvironment(environment environments.Environment) (err error)

	Id() string

	GetEnvironment() environments.Environment

	Save(file string) (err error)

	Edit(data map[string]interface{}) (err error)

	GetData() map[string]DataObject

	GetNetwork() string
}

var queue *list.List
var lock = sync.Mutex{}
var ticker *time.Ticker
var running = false

func InitService() {
	queue = list.New()
	ticker = time.NewTicker(10 * time.Second)
	running = true
	go func() {
		for range ticker.C {
			lock.Lock()
			next := queue.Front()
			lock.Unlock()
			if next == nil {
				continue
			}
			program := next.Value.(Program)
			if run, _ := program.IsRunning(); !run {
				program.Start()
			}
		}
	}()
}

func StartViaService (p Program) {
	lock.Lock()
	defer func() {
		lock.Unlock()
	}()

	if running {
		queue.PushBack(p)
	}
}

func ShutdownService() {
	lock.Lock()
	defer func() {
		lock.Unlock()
	}()

	running = false
	ticker.Stop()
}<commit_msg>Decrease timer for server starts<commit_after>/*
 Copyright 2016 Padduck, LLC

 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 programs

import (
	"container/list"
	"sync"
	"time"
	"github.com/pufferpanel/pufferd/environments"
)

type Program interface {
	//Starts the program.
	//This includes starting the environment if it is not running.
	Start() (err error)

	//Stops the program.
	//This will also stop the environment it is ran in.
	Stop() (err error)

	//Kills the program.
	//This will also stop the environment it is ran in.
	Kill() (err error)

	//Creates any files needed for the program.
	//This includes creating the environment.
	Create() (err error)

	//Destroys the server.
	//This will delete the server, environment, and any files related to it.
	Destroy() (err error)

	Install() (err error)

	//Determines if the server is running.
	IsRunning() (isRunning bool, err error)

	//Sends a command to the process
	//If the program supports input, this will send the arguments to that.
	Execute(command string) (err error)

	SetEnabled(isEnabled bool) (err error)

	IsEnabled() (isEnabled bool)

	SetAutoStart(isAutoStart bool) (err error)

	IsAutoStart() (isAutoStart bool)

	SetEnvironment(environment environments.Environment) (err error)

	Id() string

	GetEnvironment() environments.Environment

	Save(file string) (err error)

	Edit(data map[string]interface{}) (err error)

	GetData() map[string]DataObject

	GetNetwork() string
}

var queue *list.List
var lock = sync.Mutex{}
var ticker *time.Ticker
var running = false

func InitService() {
	queue = list.New()
	ticker = time.NewTicker(1 * time.Second)
	running = true
	go func() {
		for range ticker.C {
			lock.Lock()
			next := queue.Front()
			lock.Unlock()
			if next == nil {
				continue
			}
			program := next.Value.(Program)
			if run, _ := program.IsRunning(); !run {
				program.Start()
			}
		}
	}()
}

func StartViaService (p Program) {
	lock.Lock()
	defer func() {
		lock.Unlock()
	}()

	if running {
		queue.PushBack(p)
	}
}

func ShutdownService() {
	lock.Lock()
	defer func() {
		lock.Unlock()
	}()

	running = false
	ticker.Stop()
}<|endoftext|>


<commit_before>package layer

// Priority represents the middleware priority.
type Priority int

const (
	// Head priority defines the middleware handlers
	// in the head of the middleware stack.
	Head Priority = iota

	// Normal priority defines the middleware handlers
	// in the last middleware stack available.
	Normal

	// Tail priority defines the middleware handlers
	// in the tail of the middleware stack.
	Tail
)

// Stack stores the data to show.
type Stack struct {
	// memo stores the memorized pre-computed merged stack for better performance.
	memo []MiddlewareFunc

	// Head stores the head priority handlers.
	Head []MiddlewareFunc

	// Stack stores the middleware normal priority handlers.
	Stack []MiddlewareFunc

	// Tail stores the middleware tail priority handlers.
	Tail []MiddlewareFunc
}

// Push pushes a new middleware handler to the stack based on the given priority.
func (s *Stack) Push(order Priority, h MiddlewareFunc) {
	s.memo = nil // flush the memoized stack
	if order == Head {
		s.Head = append(s.Head, h)
	} else if order == Tail {
		s.Tail = append(s.Tail, h)
	} else {
		s.Stack = append(s.Stack, h)
	}
}

// Join joins the middleware functions into a unique slice.
func (s *Stack) Join() []MiddlewareFunc {
	if s.memo != nil {
		return s.memo
	}
	s.memo = append(append(s.Head, s.Stack...), s.Tail...)
	return s.memo
}

// Len returns the middleware stack length.
func (s *Stack) Len() int {
	return len(s.Stack) + len(s.Tail) + len(s.Head)
}
<commit_msg>refactor(stack): add top priority for better ordering<commit_after>package layer

// Priority represents the middleware priority.
type Priority int

const (
	// TopHead priority defines the middleware handler
	// as first element of the stack head.
	TopHead Priority = iota

	// Head priority stores the middleware handler
	// in the head of the stack.
	Head

	// Normal priority defines the middleware handler
	// in the last stack available.
	Normal

	// TopTail priority defines the middleware handler
	// as fist element of the stack tail.
	TopTail

	// Tail priority defines the middleware handler
	// in the tail of the stack.
	Tail
)

// Stack stores the data to show.
type Stack struct {
	// memo stores the memorized pre-computed merged stack for better performance.
	memo []MiddlewareFunc

	// Head stores the head priority handlers.
	Head []MiddlewareFunc

	// Stack stores the middleware normal priority handlers.
	Stack []MiddlewareFunc

	// Tail stores the middleware tail priority handlers.
	Tail []MiddlewareFunc
}

// Push pushes a new middleware handler to the stack based on the given priority.
func (s *Stack) Push(order Priority, h MiddlewareFunc) {
	s.memo = nil // flush the memoized stack
	if order == TopHead {
		s.Head = append([]MiddlewareFunc{h}, s.Head...)
	}
	if order == Head {
		s.Head = append(s.Head, h)
	}
	if order == Tail {
		s.Tail = append(s.Tail, h)
	}
	if order == TopTail {
		s.Tail = append([]MiddlewareFunc{h}, s.Tail...)
	}
	if order == Normal {
		s.Stack = append(s.Stack, h)
	}
}

// Join joins the middleware functions into a unique slice.
func (s *Stack) Join() []MiddlewareFunc {
	if s.memo != nil {
		return s.memo
	}
	s.memo = append(append(s.Head, s.Stack...), s.Tail...)
	return s.memo
}

// Len returns the middleware stack length.
func (s *Stack) Len() int {
	return len(s.Stack) + len(s.Tail) + len(s.Head)
}
<|endoftext|>


<commit_before>package digests

import (
	"fmt"

	"github.com/ion-channel/ionic/scanner"
	"github.com/ion-channel/ionic/scans"
)

type dfilter func(*scans.Dependency) bool

func nv(d *scans.Dependency) bool {
	if d.Requirement == "" {
		return true
	}
	return false
}

func od(d *scans.Dependency) bool {
	if d.Version < d.LatestVersion {
		return true
	}
	return false
}

func giveem(d *scans.Dependency) bool {
	return true
}

func filterDependencies(data interface{}, unique bool, f dfilter) ([]scans.Dependency, error) {
	b, ok := data.(scans.DependencyResults)
	if !ok {
		return nil, fmt.Errorf("error coercing evaluation translated results into dep")
	}
	ds := []scans.Dependency{}
	for _, dr := range b.Dependencies {
		if f(&dr) {
			ds = append(ds, dr)
		}
	}
	return ds, nil
}

func dependencyDigests(status *scanner.ScanStatus, eval *scans.Evaluation) ([]Digest, error) {
	digests := make([]Digest, 0)
	var data interface{}

	var updateAvailable, noVersions, directDeps, transDeps int
	if eval != nil && !status.Errored() {
		data = eval.TranslatedResults.Data
		b, ok := data.(scans.DependencyResults)
		if !ok {
			return nil, fmt.Errorf("error coercing evaluation translated results into dependency bytes")
		}
		updateAvailable = b.Meta.UpdateAvailableCount
		noVersions = b.Meta.NoVersionCount
		directDeps = b.Meta.FirstDegreeCount
		transDeps = b.Meta.TotalUniqueCount - b.Meta.FirstDegreeCount
	}

	d := NewDigest(status, dependencyOutdatedIndex, "dependency outdated", "dependencies outdated")

	if eval != nil && !status.Errored() {
		filtered, err := filterDependencies(data, false, od)
		if err != nil {
			return nil, fmt.Errorf("failed to add evaluation data to no version dependency digest: %v", err.Error())
		}

		err = d.AppendEval(eval, "count", updateAvailable)
		if err != nil {
			return nil, fmt.Errorf("failed to create dependencies outdated digest: %v", err.Error())
		}

		d.MarshalSourceData(filtered, "dependency")
		d.Evaluated = false // As of now there's no rule to evaluate this against so it's set to not evaluated.
	}

	digests = append(digests, *d)

	// No version specified
	d = NewDigest(status, noVersionIndex, "dependency no version specified", "dependencies no version specified")

	if eval != nil && !status.Errored() {
		filtered, err := filterDependencies(data, false, nv)
		if err != nil {
			return nil, fmt.Errorf("failed to add evaluation data to no version dependency digest: %v", err.Error())
		}
		d.MarshalSourceData(filtered, "dependency")
		err = d.AppendEval(eval, "count", noVersions)
		if err != nil {
			return nil, fmt.Errorf("failed to create dependencies no version digest: %v", err.Error())
		}

		if noVersions > 0 {
			d.Warning = true
			d.WarningMessage = "dependencies with no version specified"

			if noVersions == 1 {
				d.WarningMessage = "dependency with no version specified"
			}
		}
	}

	digests = append(digests, *d)

	d = NewDigest(status, directDependencyIndex, "direct dependency", "direct dependencies")

	if eval != nil && !status.Errored() {
		filtered, err := filterDependencies(data, false, giveem)
		if err != nil {
			return nil, fmt.Errorf("failed to add evaluation data to direct dependency digest: %v", err.Error())
		}
		d.MarshalSourceData(filtered, "dependency")
		err = d.AppendEval(eval, "count", directDeps)
		if err != nil {
			return nil, fmt.Errorf("failed to create direct dependencies digeest: %v", err.Error())
		}

		d.Evaluated = false // As of now there's no rule to evaluate this against so it's set to not evaluated.

		if directDeps < 1 {
			d.Warning = true
			d.WarningMessage = "no direct dependencies found"
		}
	}

	digests = append(digests, *d)

	d = NewDigest(status, transitiveDependencyIndex, "transitive dependency", "transitive dependencies")

	if eval != nil && !status.Errored() {
		filtered, err := filterDependencies(data, false, giveem)
		if err != nil {
			return nil, fmt.Errorf("failed to add evaluation data to transitive dependency digest: %v", err.Error())
		}
		d.MarshalSourceData(filtered, "dependency")
		err = d.AppendEval(eval, "count", transDeps)
		if err != nil {
			return nil, fmt.Errorf("failed to create transitive dependencies digeest: %v", err.Error())
		}

		d.Evaluated = false // As of now there's no rule to evaluate this against so it's set to not evaluated.

		if transDeps < 1 {
			d.Warning = true
			d.WarningMessage = "no transitive dependencies found"
		}
	}

	digests = append(digests, *d)

	return digests, nil
}
<commit_msg>Only the top level need apply<commit_after>package digests

import (
	"fmt"
	"reflect"
	"runtime"

	"github.com/ion-channel/ionic/scanner"
	"github.com/ion-channel/ionic/scans"
)

type dfilter func(*scans.Dependency) *scans.Dependency

func nv(d *scans.Dependency) *scans.Dependency {
	if d.Requirement == "" {
		return d
	}
	return nil
}

func od(d *scans.Dependency) *scans.Dependency {
	if d.Version < d.LatestVersion {
		return d
	}
	return nil
}

func giveem(d *scans.Dependency) *scans.Dependency {
	return d
}

func direct(d *scans.Dependency) *scans.Dependency {
	ff := d
	ff.Dependencies = nil
	return ff
}

func filterDependencies(data interface{}, unique bool, f dfilter) ([]scans.Dependency, error) {
	b, ok := data.(scans.DependencyResults)
	if !ok {
		return nil, fmt.Errorf("error coercing evaluation translated results into dep")
	}
	ds := []scans.Dependency{}
	for _, dr := range b.Dependencies {
		fmt.Printf("Filter: %v\n", runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name())
		fmt.Printf("Before: %v\n", dr.Dependencies)
		filtered := f(&dr)
		if filtered != nil {
			fmt.Printf("After: %v\n", filtered.Dependencies)
			ds = append(ds, *filtered)
		}
	}
	return ds, nil
}

func dependencyDigests(status *scanner.ScanStatus, eval *scans.Evaluation) ([]Digest, error) {
	digests := make([]Digest, 0)
	var data interface{}

	var updateAvailable, noVersions, directDeps, transDeps int
	if eval != nil && !status.Errored() {
		data = eval.TranslatedResults.Data
		b, ok := data.(scans.DependencyResults)
		if !ok {
			return nil, fmt.Errorf("error coercing evaluation translated results into dependency bytes")
		}
		updateAvailable = b.Meta.UpdateAvailableCount
		noVersions = b.Meta.NoVersionCount
		directDeps = b.Meta.FirstDegreeCount
		transDeps = b.Meta.TotalUniqueCount - b.Meta.FirstDegreeCount
	}

	d := NewDigest(status, dependencyOutdatedIndex, "dependency outdated", "dependencies outdated")

	if eval != nil && !status.Errored() {
		filtered, err := filterDependencies(data, false, od)
		if err != nil {
			return nil, fmt.Errorf("failed to add evaluation data to no version dependency digest: %v", err.Error())
		}

		err = d.AppendEval(eval, "count", updateAvailable)
		if err != nil {
			return nil, fmt.Errorf("failed to create dependencies outdated digest: %v", err.Error())
		}

		d.MarshalSourceData(filtered, "dependency")
		d.Evaluated = false // As of now there's no rule to evaluate this against so it's set to not evaluated.
	}

	digests = append(digests, *d)

	// No version specified
	d = NewDigest(status, noVersionIndex, "dependency no version specified", "dependencies no version specified")

	if eval != nil && !status.Errored() {
		filtered, err := filterDependencies(data, false, nv)
		if err != nil {
			return nil, fmt.Errorf("failed to add evaluation data to no version dependency digest: %v", err.Error())
		}
		d.MarshalSourceData(filtered, "dependency")
		err = d.AppendEval(eval, "count", noVersions)
		if err != nil {
			return nil, fmt.Errorf("failed to create dependencies no version digest: %v", err.Error())
		}

		if noVersions > 0 {
			d.Warning = true
			d.WarningMessage = "dependencies with no version specified"

			if noVersions == 1 {
				d.WarningMessage = "dependency with no version specified"
			}
		}
	}

	digests = append(digests, *d)

	d = NewDigest(status, directDependencyIndex, "direct dependency", "direct dependencies")

	if eval != nil && !status.Errored() {
		fmt.Printf("data: %v\n", data)
		filtered, err := filterDependencies(data, false, direct)
		fmt.Printf("Filtered: %v\n", filtered)
		if err != nil {
			return nil, fmt.Errorf("failed to add evaluation data to direct dependency digest: %v", err.Error())
		}
		d.MarshalSourceData(filtered, "dependency")
		err = d.AppendEval(eval, "count", directDeps)
		if err != nil {
			return nil, fmt.Errorf("failed to create direct dependencies digeest: %v", err.Error())
		}

		d.Evaluated = false // As of now there's no rule to evaluate this against so it's set to not evaluated.

		if directDeps < 1 {
			d.Warning = true
			d.WarningMessage = "no direct dependencies found"
		}
	}

	digests = append(digests, *d)

	d = NewDigest(status, transitiveDependencyIndex, "transitive dependency", "transitive dependencies")

	if eval != nil && !status.Errored() {
		filtered, err := filterDependencies(data, false, giveem)
		if err != nil {
			return nil, fmt.Errorf("failed to add evaluation data to transitive dependency digest: %v", err.Error())
		}
		d.MarshalSourceData(filtered, "dependency")
		err = d.AppendEval(eval, "count", transDeps)
		if err != nil {
			return nil, fmt.Errorf("failed to create transitive dependencies digeest: %v", err.Error())
		}

		d.Evaluated = false // As of now there's no rule to evaluate this against so it's set to not evaluated.

		if transDeps < 1 {
			d.Warning = true
			d.WarningMessage = "no transitive dependencies found"
		}
	}

	digests = append(digests, *d)

	return digests, nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2015, Daniel Martí <mvdan@mvdan.cc>
// See LICENSE for licensing information

package interfacer

import (
	"fmt"
	"go/ast"
	"go/token"
	"io"
	"os"
	"path/filepath"
	"sort"
	"strings"

	"golang.org/x/tools/go/loader"
	"golang.org/x/tools/go/types"
)

func (v *visitor) implementsIface(sign *types.Signature) bool {
	s := signString(sign)
	return v.funcOf(s) != ""
}

func doMethoderType(t types.Type) map[string]string {
	switch x := t.(type) {
	case *types.Pointer:
		return doMethoderType(x.Elem())
	case *types.Named:
		if u, ok := x.Underlying().(*types.Interface); ok {
			return doMethoderType(u)
		}
		return namedMethodMap(x)
	case *types.Interface:
		return ifaceFuncMap(x)
	default:
		return nil
	}
}

func assignable(s, t string, called, want map[string]string) bool {
	if s == t {
		return true
	}
	if len(t) >= len(s) {
		return false
	}
	for fname, ftype := range want {
		s, e := called[fname]
		if !e || s != ftype {
			return false
		}
	}
	return true
}

func (v *visitor) interfaceMatching(obj types.Object, vr *variable) (string, string) {
	for to := range vr.assigned {
		if to.discard {
			return "", ""
		}
	}
	allFuncs := doMethoderType(obj.Type())
	called := make(map[string]string, len(vr.calls))
	for fname := range vr.calls {
		called[fname] = allFuncs[fname]
	}
	s := funcMapString(called)
	name := v.ifaceOf(s)
	if name == "" {
		return "", ""
	}
	for t := range vr.usedAs {
		iface, ok := t.(*types.Interface)
		if !ok {
			return "", ""
		}
		asMethods := ifaceFuncMap(iface)
		as := funcMapString(asMethods)
		if !assignable(s, as, called, asMethods) {
			return "", ""
		}
	}
	return name, s
}

func orderedPkgs(prog *loader.Program) ([]*types.Package, error) {
	// TODO: InitialPackages() is not in the order that we passed to
	// it via Import() calls.
	// For now, make it deterministic by sorting by import path.
	unordered := prog.InitialPackages()
	paths := make([]string, 0, len(unordered))
	byPath := make(map[string]*types.Package, len(unordered))
	for _, info := range unordered {
		if info.Errors != nil {
			return nil, info.Errors[0]
		}
		path := info.Pkg.Path()
		paths = append(paths, path)
		byPath[path] = info.Pkg
	}
	sort.Sort(ByAlph(paths))
	pkgs := make([]*types.Package, 0, len(unordered))
	for _, path := range paths {
		pkgs = append(pkgs, byPath[path])
	}
	return pkgs, nil
}

// relPathErr makes converts errors by go/types and go/loader that use
// absolute paths into errors with relative paths
func relPathErr(err error) error {
	errStr := fmt.Sprintf("%v", err)
	if !strings.HasPrefix(errStr, "/") {
		return err
	}
	wd, err := os.Getwd()
	if err != nil {
		return err
	}
	if strings.HasPrefix(errStr, wd) {
		return fmt.Errorf(errStr[len(wd)+1:])
	}
	return err
}

func CheckArgs(args []string, w io.Writer, verbose bool) error {
	paths, err := recurse(args)
	if err != nil {
		return err
	}
	c := newCache()
	if _, err := c.FromArgs(paths, false); err != nil {
		return err
	}
	prog, err := c.Load()
	if err != nil {
		return err
	}
	pkgs, err := orderedPkgs(prog)
	if err != nil {
		return relPathErr(err)
	}
	c.typesGet(pkgs)
	for _, pkg := range pkgs {
		info := prog.AllPackages[pkg]
		if verbose {
			fmt.Fprintln(w, info.Pkg.Path())
		}
		checkPkg(c, info, prog.Fset, w)
	}
	return nil
}

func checkPkg(c *cache, info *loader.PackageInfo, fset *token.FileSet, w io.Writer) {
	v := &visitor{
		cache:       c,
		PackageInfo: info,
		w:           w,
		fset:        fset,
		vars:        make(map[types.Object]*variable),
	}
	for _, f := range info.Files {
		ast.Walk(v, f)
	}
}

type variable struct {
	calls   map[string]struct{}
	usedAs  map[types.Type]struct{}
	discard bool

	assigned map[*variable]struct{}
}

type visitor struct {
	*cache
	*loader.PackageInfo

	w     io.Writer
	fset  *token.FileSet
	signs []*types.Signature

	vars map[types.Object]*variable

	skipNext bool
}

func (v *visitor) addParams(t *types.Tuple) {
	for i := 0; i < t.Len(); i++ {
		obj := t.At(i)
		v.vars[obj] = &variable{
			calls:    make(map[string]struct{}),
			usedAs:   make(map[types.Type]struct{}),
			assigned: make(map[*variable]struct{}),
		}
	}
}

func paramType(sign *types.Signature, i int) types.Type {
	params := sign.Params()
	extra := sign.Variadic() && i >= params.Len()-1
	if !extra {
		if i >= params.Len() {
			// builtins with multiple signatures
			return nil
		}
		return params.At(i).Type()
	}
	last := params.At(params.Len() - 1)
	switch x := last.Type().(type) {
	case *types.Slice:
		return x.Elem()
	default:
		return x
	}
}

func (v *visitor) variable(id *ast.Ident) *variable {
	obj := v.ObjectOf(id)
	if vr, e := v.vars[obj]; e {
		return vr
	}
	vr := &variable{
		calls:    make(map[string]struct{}),
		usedAs:   make(map[types.Type]struct{}),
		assigned: make(map[*variable]struct{}),
	}
	v.vars[obj] = vr
	return vr
}

func (v *visitor) addUsed(id *ast.Ident, as types.Type) {
	if as == nil {
		return
	}
	vr := v.variable(id)
	vr.usedAs[as.Underlying()] = struct{}{}
}

func (v *visitor) addAssign(to, from *ast.Ident) {
	pto := v.variable(to)
	pfrom := v.variable(from)
	pfrom.assigned[pto] = struct{}{}
}

func (v *visitor) discard(e ast.Expr) {
	id, ok := e.(*ast.Ident)
	if !ok {
		return
	}
	vr := v.variable(id)
	vr.discard = true
}

func (v *visitor) Visit(node ast.Node) ast.Visitor {
	if v.skipNext {
		v.skipNext = false
		return nil
	}
	var sign *types.Signature
	switch x := node.(type) {
	case *ast.FuncLit:
		sign = v.Types[x].Type.(*types.Signature)
		if v.implementsIface(sign) {
			return nil
		}
		v.addParams(sign.Params())
	case *ast.FuncDecl:
		sign = v.Defs[x.Name].Type().(*types.Signature)
		if v.implementsIface(sign) {
			return nil
		}
		v.addParams(sign.Params())
	case *ast.SelectorExpr:
		v.discard(x.X)
	case *ast.UnaryExpr:
		v.discard(x.X)
	case *ast.BinaryExpr:
		v.discard(x.X)
		v.discard(x.Y)
	case *ast.IndexExpr:
		v.discard(x.X)
	case *ast.IncDecStmt:
		v.discard(x.X)
	case *ast.AssignStmt:
		v.onAssign(x)
	case *ast.CallExpr:
		v.onCall(x)
	case nil:
		top := v.signs[len(v.signs)-1]
		if top != nil {
			v.funcEnded(top)
		}
		v.signs = v.signs[:len(v.signs)-1]
	}
	if node != nil {
		v.signs = append(v.signs, sign)
	}
	return v
}

func funcSignature(t types.Type) *types.Signature {
	switch x := t.(type) {
	case *types.Signature:
		return x
	case *types.Named:
		return funcSignature(x.Underlying())
	default:
		return nil
	}
}

func (v *visitor) onAssign(as *ast.AssignStmt) {
	for i, e := range as.Rhs {
		id, ok := e.(*ast.Ident)
		if !ok {
			continue
		}
		left := as.Lhs[i]
		v.addUsed(id, v.Types[left].Type)
		if lid, ok := left.(*ast.Ident); ok {
			v.addAssign(lid, id)
		}
	}
}

func (v *visitor) onCall(ce *ast.CallExpr) {
	switch y := ce.Fun.(type) {
	case *ast.Ident:
		v.skipNext = true
	case *ast.SelectorExpr:
		if _, ok := y.X.(*ast.Ident); ok {
			v.skipNext = true
		}
	}
	sign := funcSignature(v.Types[ce.Fun].Type)
	if sign == nil {
		return
	}
	for i, e := range ce.Args {
		if id, ok := e.(*ast.Ident); ok {
			v.addUsed(id, paramType(sign, i))
		}
	}
	sel, ok := ce.Fun.(*ast.SelectorExpr)
	if !ok {
		return
	}
	left, ok := sel.X.(*ast.Ident)
	if !ok {
		return
	}
	vr := v.variable(left)
	vr.calls[sel.Sel.Name] = struct{}{}
	return
}

func (v *visitor) funcEnded(sign *types.Signature) {
	params := sign.Params()
	for i := 0; i < params.Len(); i++ {
		obj := params.At(i)
		vr := v.vars[obj]
		v.evalParam(obj, vr)
	}
}

func (v *visitor) evalParam(obj types.Object, vr *variable) {
	if vr.discard {
		return
	}
	ifname, iftype := v.interfaceMatching(obj, vr)
	if ifname == "" {
		return
	}
	t := obj.Type()
	if _, haveIface := t.Underlying().(*types.Interface); haveIface {
		if ifname == t.String() {
			return
		}
		have := funcMapString(doMethoderType(t))
		if have == iftype {
			return
		}
	}
	pos := v.fset.Position(obj.Pos())
	fname := pos.Filename
	if fname[0] == '/' {
		fname = filepath.Join(v.Pkg.Path(), filepath.Base(fname))
	}
	pname := v.Pkg.Name()
	if strings.HasPrefix(ifname, pname+".") {
		ifname = ifname[len(pname)+1:]
	}
	fmt.Fprintf(v.w, "%s:%d:%d: %s can be %s\n",
		fname, pos.Line, pos.Column, obj.Name(), ifname)
}
<commit_msg>Check if a param is to be discarded properly<commit_after>// Copyright (c) 2015, Daniel Martí <mvdan@mvdan.cc>
// See LICENSE for licensing information

package interfacer

import (
	"fmt"
	"go/ast"
	"go/token"
	"io"
	"os"
	"path/filepath"
	"sort"
	"strings"

	"golang.org/x/tools/go/loader"
	"golang.org/x/tools/go/types"
)

func (v *visitor) implementsIface(sign *types.Signature) bool {
	s := signString(sign)
	return v.funcOf(s) != ""
}

func doMethoderType(t types.Type) map[string]string {
	switch x := t.(type) {
	case *types.Pointer:
		return doMethoderType(x.Elem())
	case *types.Named:
		if u, ok := x.Underlying().(*types.Interface); ok {
			return doMethoderType(u)
		}
		return namedMethodMap(x)
	case *types.Interface:
		return ifaceFuncMap(x)
	default:
		return nil
	}
}

func assignable(s, t string, called, want map[string]string) bool {
	if s == t {
		return true
	}
	if len(t) >= len(s) {
		return false
	}
	for fname, ftype := range want {
		s, e := called[fname]
		if !e || s != ftype {
			return false
		}
	}
	return true
}

func toDiscard(vr *variable) bool {
	if vr.discard {
		return true
	}
	for to := range vr.assigned {
		if toDiscard(to) {
			return true
		}
	}
	return false
}

func (v *visitor) interfaceMatching(obj types.Object, vr *variable) (string, string) {
	if toDiscard(vr) {
		return "", ""
	}
	allFuncs := doMethoderType(obj.Type())
	called := make(map[string]string, len(vr.calls))
	for fname := range vr.calls {
		called[fname] = allFuncs[fname]
	}
	s := funcMapString(called)
	name := v.ifaceOf(s)
	if name == "" {
		return "", ""
	}
	for t := range vr.usedAs {
		iface, ok := t.(*types.Interface)
		if !ok {
			return "", ""
		}
		asMethods := ifaceFuncMap(iface)
		as := funcMapString(asMethods)
		if !assignable(s, as, called, asMethods) {
			return "", ""
		}
	}
	return name, s
}

func orderedPkgs(prog *loader.Program) ([]*types.Package, error) {
	// TODO: InitialPackages() is not in the order that we passed to
	// it via Import() calls.
	// For now, make it deterministic by sorting by import path.
	unordered := prog.InitialPackages()
	paths := make([]string, 0, len(unordered))
	byPath := make(map[string]*types.Package, len(unordered))
	for _, info := range unordered {
		if info.Errors != nil {
			return nil, info.Errors[0]
		}
		path := info.Pkg.Path()
		paths = append(paths, path)
		byPath[path] = info.Pkg
	}
	sort.Sort(ByAlph(paths))
	pkgs := make([]*types.Package, 0, len(unordered))
	for _, path := range paths {
		pkgs = append(pkgs, byPath[path])
	}
	return pkgs, nil
}

// relPathErr makes converts errors by go/types and go/loader that use
// absolute paths into errors with relative paths
func relPathErr(err error) error {
	errStr := fmt.Sprintf("%v", err)
	if !strings.HasPrefix(errStr, "/") {
		return err
	}
	wd, err := os.Getwd()
	if err != nil {
		return err
	}
	if strings.HasPrefix(errStr, wd) {
		return fmt.Errorf(errStr[len(wd)+1:])
	}
	return err
}

func CheckArgs(args []string, w io.Writer, verbose bool) error {
	paths, err := recurse(args)
	if err != nil {
		return err
	}
	c := newCache()
	if _, err := c.FromArgs(paths, false); err != nil {
		return err
	}
	prog, err := c.Load()
	if err != nil {
		return err
	}
	pkgs, err := orderedPkgs(prog)
	if err != nil {
		return relPathErr(err)
	}
	c.typesGet(pkgs)
	for _, pkg := range pkgs {
		info := prog.AllPackages[pkg]
		if verbose {
			fmt.Fprintln(w, info.Pkg.Path())
		}
		checkPkg(c, info, prog.Fset, w)
	}
	return nil
}

func checkPkg(c *cache, info *loader.PackageInfo, fset *token.FileSet, w io.Writer) {
	v := &visitor{
		cache:       c,
		PackageInfo: info,
		w:           w,
		fset:        fset,
		vars:        make(map[types.Object]*variable),
	}
	for _, f := range info.Files {
		ast.Walk(v, f)
	}
}

type variable struct {
	calls   map[string]struct{}
	usedAs  map[types.Type]struct{}
	discard bool

	assigned map[*variable]struct{}
}

type visitor struct {
	*cache
	*loader.PackageInfo

	w     io.Writer
	fset  *token.FileSet
	signs []*types.Signature

	vars map[types.Object]*variable

	skipNext bool
}

func (v *visitor) addParams(t *types.Tuple) {
	for i := 0; i < t.Len(); i++ {
		obj := t.At(i)
		v.vars[obj] = &variable{
			calls:    make(map[string]struct{}),
			usedAs:   make(map[types.Type]struct{}),
			assigned: make(map[*variable]struct{}),
		}
	}
}

func paramType(sign *types.Signature, i int) types.Type {
	params := sign.Params()
	extra := sign.Variadic() && i >= params.Len()-1
	if !extra {
		if i >= params.Len() {
			// builtins with multiple signatures
			return nil
		}
		return params.At(i).Type()
	}
	last := params.At(params.Len() - 1)
	switch x := last.Type().(type) {
	case *types.Slice:
		return x.Elem()
	default:
		return x
	}
}

func (v *visitor) variable(id *ast.Ident) *variable {
	obj := v.ObjectOf(id)
	if vr, e := v.vars[obj]; e {
		return vr
	}
	vr := &variable{
		calls:    make(map[string]struct{}),
		usedAs:   make(map[types.Type]struct{}),
		assigned: make(map[*variable]struct{}),
	}
	v.vars[obj] = vr
	return vr
}

func (v *visitor) addUsed(id *ast.Ident, as types.Type) {
	if as == nil {
		return
	}
	vr := v.variable(id)
	vr.usedAs[as.Underlying()] = struct{}{}
}

func (v *visitor) addAssign(to, from *ast.Ident) {
	pto := v.variable(to)
	pfrom := v.variable(from)
	pfrom.assigned[pto] = struct{}{}
}

func (v *visitor) discard(e ast.Expr) {
	id, ok := e.(*ast.Ident)
	if !ok {
		return
	}
	vr := v.variable(id)
	vr.discard = true
}

func (v *visitor) Visit(node ast.Node) ast.Visitor {
	if v.skipNext {
		v.skipNext = false
		return nil
	}
	var sign *types.Signature
	switch x := node.(type) {
	case *ast.FuncLit:
		sign = v.Types[x].Type.(*types.Signature)
		if v.implementsIface(sign) {
			return nil
		}
		v.addParams(sign.Params())
	case *ast.FuncDecl:
		sign = v.Defs[x.Name].Type().(*types.Signature)
		if v.implementsIface(sign) {
			return nil
		}
		v.addParams(sign.Params())
	case *ast.SelectorExpr:
		v.discard(x.X)
	case *ast.UnaryExpr:
		v.discard(x.X)
	case *ast.BinaryExpr:
		v.discard(x.X)
		v.discard(x.Y)
	case *ast.IndexExpr:
		v.discard(x.X)
	case *ast.IncDecStmt:
		v.discard(x.X)
	case *ast.AssignStmt:
		v.onAssign(x)
	case *ast.CallExpr:
		v.onCall(x)
	case nil:
		top := v.signs[len(v.signs)-1]
		if top != nil {
			v.funcEnded(top)
		}
		v.signs = v.signs[:len(v.signs)-1]
	}
	if node != nil {
		v.signs = append(v.signs, sign)
	}
	return v
}

func funcSignature(t types.Type) *types.Signature {
	switch x := t.(type) {
	case *types.Signature:
		return x
	case *types.Named:
		return funcSignature(x.Underlying())
	default:
		return nil
	}
}

func (v *visitor) onAssign(as *ast.AssignStmt) {
	for i, e := range as.Rhs {
		id, ok := e.(*ast.Ident)
		if !ok {
			continue
		}
		left := as.Lhs[i]
		v.addUsed(id, v.Types[left].Type)
		if lid, ok := left.(*ast.Ident); ok {
			v.addAssign(lid, id)
		}
	}
}

func (v *visitor) onCall(ce *ast.CallExpr) {
	switch y := ce.Fun.(type) {
	case *ast.Ident:
		v.skipNext = true
	case *ast.SelectorExpr:
		if _, ok := y.X.(*ast.Ident); ok {
			v.skipNext = true
		}
	}
	sign := funcSignature(v.Types[ce.Fun].Type)
	if sign == nil {
		return
	}
	for i, e := range ce.Args {
		if id, ok := e.(*ast.Ident); ok {
			v.addUsed(id, paramType(sign, i))
		}
	}
	sel, ok := ce.Fun.(*ast.SelectorExpr)
	if !ok {
		return
	}
	left, ok := sel.X.(*ast.Ident)
	if !ok {
		return
	}
	vr := v.variable(left)
	vr.calls[sel.Sel.Name] = struct{}{}
	return
}

func (v *visitor) funcEnded(sign *types.Signature) {
	params := sign.Params()
	for i := 0; i < params.Len(); i++ {
		obj := params.At(i)
		vr := v.vars[obj]
		v.evalParam(obj, vr)
	}
}

func (v *visitor) evalParam(obj types.Object, vr *variable) {
	ifname, iftype := v.interfaceMatching(obj, vr)
	if ifname == "" {
		return
	}
	t := obj.Type()
	if _, haveIface := t.Underlying().(*types.Interface); haveIface {
		if ifname == t.String() {
			return
		}
		have := funcMapString(doMethoderType(t))
		if have == iftype {
			return
		}
	}
	pos := v.fset.Position(obj.Pos())
	fname := pos.Filename
	if fname[0] == '/' {
		fname = filepath.Join(v.Pkg.Path(), filepath.Base(fname))
	}
	pname := v.Pkg.Name()
	if strings.HasPrefix(ifname, pname+".") {
		ifname = ifname[len(pname)+1:]
	}
	fmt.Fprintf(v.w, "%s:%d:%d: %s can be %s\n",
		fname, pos.Line, pos.Column, obj.Name(), ifname)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
)

// Processing statistics.
type stats struct {
	examined   int32 // Total number of files examined.
	withCamera int32 // Number of files with camera details in Exif.
	warnings   int32 // Number of files with a warning printed to output
	inCat      int32 // Number of files already in a relevant category.
	populated  int32 // Number of files skipped because of catFileLimit.
	edited     int32 // Number of files with attempt to edit.
}

func (s stats) print() {
	fmt.Println("Total files examined: ", s.examined)
	fmt.Println("Files with camera details in Exif: ", s.withCamera)
	fmt.Println("Files with warnings printed: ", s.warnings)
	fmt.Println("Files already categorised: ", s.inCat)
	fmt.Println("Files skipped due to CatFileLimit: ", s.populated)
	fmt.Println("Files attempted to edit: ", s.edited)
}
<commit_msg>change printed stats order<commit_after>package main

import (
	"fmt"
)

// Processing statistics.
type stats struct {
	examined   int32 // Total number of files examined.
	withCamera int32 // Number of files with camera details in Exif.
	warnings   int32 // Number of files with a warning printed to output
	inCat      int32 // Number of files already in a relevant category.
	populated  int32 // Number of files skipped because of catFileLimit.
	edited     int32 // Number of files with attempt to edit.
}

func (s stats) print() {
	fmt.Println("Total files examined: ", s.examined)
	fmt.Println("Files with camera details in Exif: ", s.withCamera)
	fmt.Println("Files skipped due to CatFileLimit: ", s.populated)
	fmt.Println("Files with warnings printed: ", s.warnings)
	fmt.Println("Files already categorised: ", s.inCat)
	fmt.Println("Files attempted to edit: ", s.edited)
}
<|endoftext|>