<commit_before>package cli

import (
	"bufio"
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"runtime"

	yaml "gopkg.in/yaml.v2"

	"github.com/synchro-food/filelint/config"
	"github.com/synchro-food/filelint/dispatcher"
	"github.com/synchro-food/filelint/lib"
	"github.com/synchro-food/filelint/lint"

	"github.com/spf13/cobra"
)

const Version = "0.1.0-beta.3"

var rootCmd = &cobra.Command{
	Use:           "filelint [files...]",
	Short:         "lint any text file following some file format",
	Long:          `Filelint is a CLI tool for linting any text file following some file format.`,
	RunE:          execute,
	SilenceUsage:  true,
	SilenceErrors: true,
}

var (
	showVersion      bool
	configFile       string
	useDefaultConfig bool
	printConfig      bool
	autofix          bool
	quiet            bool
	showTargets      bool
	useGitIgnore     bool
)

var (
	ErrNoSuchConfigFile = errors.New("no such config file")
)

func Execute() {
	if err := rootCmd.Execute(); err != nil {
		exitStatus := DefaultExitStatus

		if ee, ok := err.(ExitError); ok {
			exitStatus = ee.ExitStatus()
		}

		switch exitStatus {
		case LintFailedExitStatus:
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		case DefaultExitStatus:
			fmt.Fprintf(os.Stderr, "Error: %v\n\n", err)
			rootCmd.Usage()
		default:
			panic(err.Error())
		}

		os.Exit(exitStatus)
	}
}

func execute(cmd *cobra.Command, args []string) error {
	if showVersion {
		fmt.Printf("filelint v%s [%s %s-%s]\n", Version, runtime.Version(), runtime.GOOS, runtime.GOARCH)
		return nil
	}

	cfg, err := loadConfig(configFile, useDefaultConfig)
	if err != nil {
		return Raise(err)
	}

	if len(args) > 0 {
		cfg.File.Include = args
	}

	if showTargets {
		fs, err := cfg.File.FindTargets()
		if err != nil {
			return Raise(err)
		}
		buf := bufio.NewWriter(os.Stdout)
		for _, f := range fs {
			fmt.Fprintln(buf, f)
		}
		buf.Flush()
		return nil
	}

	if printConfig {
		yml, err := yaml.Marshal(cfg)
		if err != nil {
			return Raise(err)
		}
		fmt.Printf("%s", yml)
		return nil
	}

	buf := bufio.NewWriter(os.Stdout)

	linterResult := struct {
		numErrors      int
		numFixedErrors int
		numErrorFiles  int
		numFixedFiles  int
	}{}

	dp := dispatcher.NewDispatcher(cfg)
	if err := dp.Dispatch(useGitIgnore, func(file string, rules []lint.Rule) error {
		linter, err := lint.NewLinter(file, rules)
		if err != nil {
			return err
		}

		result, err := linter.Lint()
		if err != nil {
			return err
		}

		if num := len(result.Reports); num > 0 {
			linterResult.numErrors += num
			linterResult.numErrorFiles++

			for _, report := range result.Reports {
				if autofix {
					fmt.Fprintf(buf, "[autofixed]")
					linterResult.numFixedErrors++
				}
				fmt.Fprintf(buf, "%s:%s\n", file, report.String())
			}

			if autofix {
				if err := writeFile(file, result.Fixed); err != nil {
					return err
				}
				linterResult.numFixedFiles++
			}
		}

		return nil
	}); err != nil {
		return Raise(err)
	}

	if !quiet {
		buf.Flush()
	}

	if !autofix && linterResult.numErrors > 0 {
		fmt.Printf("%d lint error(s) detected in %d file(s)\n", linterResult.numErrors, linterResult.numErrorFiles)
		return Raise(errLintFailed)
	}

	if linterResult.numFixedFiles > 0 && !quiet {
		fmt.Printf("%d lint error(s) autofixed in %d file(s)\n", linterResult.numFixedErrors, linterResult.numFixedFiles)
	}

	return nil
}

func loadConfig(configFile string, useDefault bool) (*config.Config, error) {
	if useDefault {
		cfg, err := config.NewDefaultConfig()
		if err != nil {
			return nil, err
		}
		return cfg, err
	}

	if configFile != "" && !lib.IsExist(configFile) {
		return nil, ErrNoSuchConfigFile
	}

	if configFile == "" {
		var exist bool
		configFile, exist = config.SearchConfigFile()
		if !exist {
			return loadConfig("", true)
		}
	}

	cfg, err := config.NewConfig(configFile)
	if err != nil {
		return nil, err
	}
	return cfg, nil

}

func writeFile(filename string, src []byte) error {
	var fp *os.File
	var err error

	if lib.IsExist(filename) {
		fp, err = os.Open(filename)
	} else {
		fp, err = os.Create(filename)
	}
	if err != nil {
		return err
	}
	defer fp.Close()

	fi, err := fp.Stat()
	if err != nil {
		return err
	}
	perm := fi.Mode().Perm()

	err = ioutil.WriteFile(filename, src, perm)
	if err != nil {
		return err
	}

	return nil
}

func init() {
	rootCmd.Flags().BoolVarP(&showVersion, "version", "v", false, "print the version and quit")
	rootCmd.Flags().StringVarP(&configFile, "config", "c", "", "specify configuration file")
	rootCmd.Flags().BoolVarP(&printConfig, "print-config", "", false, "print the configuration")
	rootCmd.Flags().BoolVarP(&useDefaultConfig, "no-config", "", false, "don't use config file (use the application default config)")
	rootCmd.Flags().BoolVarP(&autofix, "fix", "", false, "automatically fix problems")
	rootCmd.Flags().BoolVarP(&quiet, "quiet", "q", false, "don't print lint errors or fixed files")
	rootCmd.Flags().BoolVarP(&showTargets, "print-targets", "", false, "print all lint target files and quit")
	rootCmd.Flags().BoolVarP(&useGitIgnore, "use-gitignore", "", true, "(experimental) read and use .gitignore file for excluding target files")
}
<commit_msg>Don't print an error message about failing lint<commit_after>package cli

import (
	"bufio"
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"runtime"

	yaml "gopkg.in/yaml.v2"

	"github.com/synchro-food/filelint/config"
	"github.com/synchro-food/filelint/dispatcher"
	"github.com/synchro-food/filelint/lib"
	"github.com/synchro-food/filelint/lint"

	"github.com/spf13/cobra"
)

const Version = "0.1.0-beta.3"

var rootCmd = &cobra.Command{
	Use:           "filelint [files...]",
	Short:         "lint any text file following some file format",
	Long:          `Filelint is a CLI tool for linting any text file following some file format.`,
	RunE:          execute,
	SilenceUsage:  true,
	SilenceErrors: true,
}

var (
	showVersion      bool
	configFile       string
	useDefaultConfig bool
	printConfig      bool
	autofix          bool
	quiet            bool
	showTargets      bool
	useGitIgnore     bool
)

var (
	ErrNoSuchConfigFile = errors.New("no such config file")
)

func Execute() {
	if err := rootCmd.Execute(); err != nil {
		exitStatus := DefaultExitStatus

		if ee, ok := err.(ExitError); ok {
			exitStatus = ee.ExitStatus()
		}

		switch exitStatus {
		case LintFailedExitStatus:
			break
		case DefaultExitStatus:
			fmt.Fprintf(os.Stderr, "Error: %v\n\n", err)
			rootCmd.Usage()
		default:
			panic(err.Error())
		}

		os.Exit(exitStatus)
	}
}

func execute(cmd *cobra.Command, args []string) error {
	if showVersion {
		fmt.Printf("filelint v%s [%s %s-%s]\n", Version, runtime.Version(), runtime.GOOS, runtime.GOARCH)
		return nil
	}

	cfg, err := loadConfig(configFile, useDefaultConfig)
	if err != nil {
		return Raise(err)
	}

	if len(args) > 0 {
		cfg.File.Include = args
	}

	if showTargets {
		fs, err := cfg.File.FindTargets()
		if err != nil {
			return Raise(err)
		}
		buf := bufio.NewWriter(os.Stdout)
		for _, f := range fs {
			fmt.Fprintln(buf, f)
		}
		buf.Flush()
		return nil
	}

	if printConfig {
		yml, err := yaml.Marshal(cfg)
		if err != nil {
			return Raise(err)
		}
		fmt.Printf("%s", yml)
		return nil
	}

	buf := bufio.NewWriter(os.Stdout)

	linterResult := struct {
		numErrors      int
		numFixedErrors int
		numErrorFiles  int
		numFixedFiles  int
	}{}

	dp := dispatcher.NewDispatcher(cfg)
	if err := dp.Dispatch(useGitIgnore, func(file string, rules []lint.Rule) error {
		linter, err := lint.NewLinter(file, rules)
		if err != nil {
			return err
		}

		result, err := linter.Lint()
		if err != nil {
			return err
		}

		if num := len(result.Reports); num > 0 {
			linterResult.numErrors += num
			linterResult.numErrorFiles++

			for _, report := range result.Reports {
				if autofix {
					fmt.Fprintf(buf, "[autofixed]")
					linterResult.numFixedErrors++
				}
				fmt.Fprintf(buf, "%s:%s\n", file, report.String())
			}

			if autofix {
				if err := writeFile(file, result.Fixed); err != nil {
					return err
				}
				linterResult.numFixedFiles++
			}
		}

		return nil
	}); err != nil {
		return Raise(err)
	}

	if !quiet {
		buf.Flush()
	}

	if !autofix && linterResult.numErrors > 0 {
		fmt.Printf("%d lint error(s) detected in %d file(s)\n", linterResult.numErrors, linterResult.numErrorFiles)
		return Raise(errLintFailed)
	}

	if linterResult.numFixedFiles > 0 && !quiet {
		fmt.Printf("%d lint error(s) autofixed in %d file(s)\n", linterResult.numFixedErrors, linterResult.numFixedFiles)
	}

	return nil
}

func loadConfig(configFile string, useDefault bool) (*config.Config, error) {
	if useDefault {
		cfg, err := config.NewDefaultConfig()
		if err != nil {
			return nil, err
		}
		return cfg, err
	}

	if configFile != "" && !lib.IsExist(configFile) {
		return nil, ErrNoSuchConfigFile
	}

	if configFile == "" {
		var exist bool
		configFile, exist = config.SearchConfigFile()
		if !exist {
			return loadConfig("", true)
		}
	}

	cfg, err := config.NewConfig(configFile)
	if err != nil {
		return nil, err
	}
	return cfg, nil

}

func writeFile(filename string, src []byte) error {
	var fp *os.File
	var err error

	if lib.IsExist(filename) {
		fp, err = os.Open(filename)
	} else {
		fp, err = os.Create(filename)
	}
	if err != nil {
		return err
	}
	defer fp.Close()

	fi, err := fp.Stat()
	if err != nil {
		return err
	}
	perm := fi.Mode().Perm()

	err = ioutil.WriteFile(filename, src, perm)
	if err != nil {
		return err
	}

	return nil
}

func init() {
	rootCmd.Flags().BoolVarP(&showVersion, "version", "v", false, "print the version and quit")
	rootCmd.Flags().StringVarP(&configFile, "config", "c", "", "specify configuration file")
	rootCmd.Flags().BoolVarP(&printConfig, "print-config", "", false, "print the configuration")
	rootCmd.Flags().BoolVarP(&useDefaultConfig, "no-config", "", false, "don't use config file (use the application default config)")
	rootCmd.Flags().BoolVarP(&autofix, "fix", "", false, "automatically fix problems")
	rootCmd.Flags().BoolVarP(&quiet, "quiet", "q", false, "don't print lint errors or fixed files")
	rootCmd.Flags().BoolVarP(&showTargets, "print-targets", "", false, "print all lint target files and quit")
	rootCmd.Flags().BoolVarP(&useGitIgnore, "use-gitignore", "", true, "(experimental) read and use .gitignore file for excluding target files")
}
<|endoftext|>


<commit_before>package compute

import (
	"fmt"
	"strings"
)

// Resources are an abstraction over the various types of entities in the DD compute API

// ResourceType represents a well-known DD compute resource type.
type ResourceType int

const (
	// ResourceTypeNetworkDomain represents a network domain.
	ResourceTypeNetworkDomain ResourceType = iota

	// ResourceTypeVLAN represents a VLAN.
	ResourceTypeVLAN

	// ResourceTypeServer represents a virtual machine.
	ResourceTypeServer

	// ResourceTypeServerAntiAffinityRule represents a server anti-affinity rule.
	ResourceTypeServerAntiAffinityRule

	// ResourceTypeServerBackup represents the backup configuration for a virtual machine.
	ResourceTypeServerBackup

	// ResourceTypeNetworkAdapter represents a network adapter in a virtual machine.
	// Note that when calling methods such as WaitForChange, the Id must be of the form 'serverId/networkAdapterId'.
	ResourceTypeNetworkAdapter

	// ResourceTypePublicIPBlock represents a block of public IP addresses.
	ResourceTypePublicIPBlock

	// ResourceTypeFirewallRule represents a firewall rule.
	ResourceTypeFirewallRule

	// ResourceTypeVIPNode represents a VIP node.
	ResourceTypeVIPNode

	// ResourceTypeVIPPool represents a VIP pool.
	ResourceTypeVIPPool

	// ResourceTypeVirtualListener represents a virtual listener.
	ResourceTypeVirtualListener

	// ResourceTypeOSImage represents an OS image.
	ResourceTypeOSImage

	// ResourceTypeCustomerImage represents a customer image.
	ResourceTypeCustomerImage

	// ResourceTypeSSLDomainCertificate represents an SSL certificate for a domain name.
	ResourceTypeSSLDomainCertificate

	// ResourceTypeSSLCertificateChain represents an SSL certificate chain
	ResourceTypeSSLCertificateChain

	// ResourceTypeSSLOffloadProfile represents an SSL-offload profile
	ResourceTypeSSLOffloadProfile
)

// Resource represents a compute resource.
type Resource interface {
	NamedEntity

	// The resource type.
	GetResourceType() ResourceType

	// The resource's current state (e.g. ResourceStatusNormal, etc).
	GetState() string

	// Has the resource been deleted (i.e. the underlying struct is nil)?
	IsDeleted() bool
}

// GetResourceDescription retrieves a textual description of the specified resource type.
func GetResourceDescription(resourceType ResourceType) (string, error) {
	switch resourceType {
	case ResourceTypeNetworkDomain:
		return "Network domain", nil

	case ResourceTypeVLAN:
		return "VLAN", nil

	case ResourceTypeServer:
		return "Server", nil

	case ResourceTypeServerAntiAffinityRule:
		return "Server anti-affinity rule", nil

	case ResourceTypeNetworkAdapter:
		return "Network adapter", nil

	case ResourceTypePublicIPBlock:
		return "Public IPv4 address block", nil

	case ResourceTypeFirewallRule:
		return "Firewall rule", nil

	case ResourceTypeVIPNode:
		return "VIP node", nil

	case ResourceTypeVIPPool:
		return "VIP pool", nil

	case ResourceTypeVirtualListener:
		return "virtual listener", nil

	case ResourceTypeOSImage:
		return "OS image", nil

	case ResourceTypeCustomerImage:
		return "customer image", nil

	case ResourceTypeSSLDomainCertificate:
		return "SSL domain certificate", nil

	case ResourceTypeSSLCertificateChain:
		return "SSL certificate chain", nil

	case ResourceTypeSSLOffloadProfile:
		return "SSL-offload profile", nil

	default:
		return "", fmt.Errorf("unrecognised resource type (value = %d)", resourceType)
	}
}

// GetResource retrieves a compute resource of the specified type by Id.
// id is the resource Id.
// resourceType is the resource type (e.g. ResourceTypeNetworkDomain, ResourceTypeVLAN, etc).
func (client *Client) GetResource(id string, resourceType ResourceType) (Resource, error) {
	switch resourceType {
	case ResourceTypeNetworkDomain:
		return client.GetNetworkDomain(id)

	case ResourceTypeVLAN:
		return client.GetVLAN(id)

	case ResourceTypeServer:
		return client.GetServer(id)

	case ResourceTypeServerAntiAffinityRule:
		return client.getServerAntiAffinityRuleByQualifiedID(id)

	case ResourceTypeNetworkAdapter:
		return client.getNetworkAdapterByID(id)

	case ResourceTypePublicIPBlock:
		return client.GetPublicIPBlock(id)

	case ResourceTypeFirewallRule:
		return client.GetFirewallRule(id)

	case ResourceTypeVIPNode:
		return client.GetVIPNode(id)

	case ResourceTypeVIPPool:
		return client.GetVIPPool(id)

	case ResourceTypeVirtualListener:
		return client.GetVirtualListener(id)

	case ResourceTypeOSImage:
		return client.GetCustomerImage(id)

	case ResourceTypeCustomerImage:
		return client.GetCustomerImage(id)

	case ResourceTypeSSLDomainCertificate:
		return client.GetSSLDomainCertificate(id)

	case ResourceTypeSSLCertificateChain:
		return client.GetSSLCertificateChain(id)

	case ResourceTypeSSLOffloadProfile:
		return client.GetSSLOffloadProfile(id)
	}

	return nil, fmt.Errorf("unrecognised resource type (value = %d)", resourceType)
}

func (client *Client) getNetworkAdapterByID(id string) (Resource, error) {
	compositeIDComponents := strings.Split(id, "/")
	if len(compositeIDComponents) != 2 {
		return nil, fmt.Errorf("'%s' is not a valid network adapter Id (when loading as a resource, the Id must be of the form 'serverId/networkAdapterId')", id)
	}

	server, err := client.GetServer(compositeIDComponents[0])
	if err != nil {
		return nil, err
	}
	if server == nil {
		return nil, fmt.Errorf("No server found with Id '%s.'", compositeIDComponents[0])
	}

	var targetAdapterID = compositeIDComponents[1]
	if *server.Network.PrimaryAdapter.ID == targetAdapterID {
		return &server.Network.PrimaryAdapter, nil
	}

	for _, adapter := range server.Network.AdditionalNetworkAdapters {
		if *adapter.ID == targetAdapterID {
			return &adapter, nil
		}
	}

	return nil, nil
}

// Retrieve a server anti-affinity rule by qualified ID ("networkDomainId/ruleId").
func (client *Client) getServerAntiAffinityRuleByQualifiedID(id string) (Resource, error) {
	compositeIDComponents := strings.Split(id, "/")
	if len(compositeIDComponents) != 2 {
		return nil, fmt.Errorf("'%s' is not a valid network adapter Id (when loading as a resource, the Id must be of the form 'serverId/networkAdapterId')", id)
	}

	networkDomainID := compositeIDComponents[0]
	ruleID := compositeIDComponents[1]

	rule, err := client.GetServerAntiAffinityRule(ruleID, networkDomainID)
	if err != nil {
		return nil, err
	}

	return rule, nil
}

func getPublicIPBlockByID(client *Client, id string) (Resource, error) {
	return client.GetPublicIPBlock(id)
}

func getFirewallRuleByID(client *Client, id string) (Resource, error) {
	return client.GetFirewallRule(id)
}
<commit_msg>Remove unused resource type.<commit_after>package compute

import (
	"fmt"
	"strings"
)

// Resources are an abstraction over the various types of entities in the DD compute API

// ResourceType represents a well-known DD compute resource type.
type ResourceType int

const (
	// ResourceTypeNetworkDomain represents a network domain.
	ResourceTypeNetworkDomain ResourceType = iota

	// ResourceTypeVLAN represents a VLAN.
	ResourceTypeVLAN

	// ResourceTypeServer represents a virtual machine.
	ResourceTypeServer

	// ResourceTypeServerAntiAffinityRule represents a server anti-affinity rule.
	ResourceTypeServerAntiAffinityRule

	// ResourceTypeNetworkAdapter represents a network adapter in a virtual machine.
	// Note that when calling methods such as WaitForChange, the Id must be of the form 'serverId/networkAdapterId'.
	ResourceTypeNetworkAdapter

	// ResourceTypePublicIPBlock represents a block of public IP addresses.
	ResourceTypePublicIPBlock

	// ResourceTypeFirewallRule represents a firewall rule.
	ResourceTypeFirewallRule

	// ResourceTypeVIPNode represents a VIP node.
	ResourceTypeVIPNode

	// ResourceTypeVIPPool represents a VIP pool.
	ResourceTypeVIPPool

	// ResourceTypeVirtualListener represents a virtual listener.
	ResourceTypeVirtualListener

	// ResourceTypeOSImage represents an OS image.
	ResourceTypeOSImage

	// ResourceTypeCustomerImage represents a customer image.
	ResourceTypeCustomerImage

	// ResourceTypeSSLDomainCertificate represents an SSL certificate for a domain name.
	ResourceTypeSSLDomainCertificate

	// ResourceTypeSSLCertificateChain represents an SSL certificate chain
	ResourceTypeSSLCertificateChain

	// ResourceTypeSSLOffloadProfile represents an SSL-offload profile
	ResourceTypeSSLOffloadProfile
)

// Resource represents a compute resource.
type Resource interface {
	NamedEntity

	// The resource type.
	GetResourceType() ResourceType

	// The resource's current state (e.g. ResourceStatusNormal, etc).
	GetState() string

	// Has the resource been deleted (i.e. the underlying struct is nil)?
	IsDeleted() bool
}

// GetResourceDescription retrieves a textual description of the specified resource type.
func GetResourceDescription(resourceType ResourceType) (string, error) {
	switch resourceType {
	case ResourceTypeNetworkDomain:
		return "network domain", nil

	case ResourceTypeVLAN:
		return "VLAN", nil

	case ResourceTypeServer:
		return "server", nil

	case ResourceTypeServerAntiAffinityRule:
		return "server anti-affinity rule", nil

	case ResourceTypeNetworkAdapter:
		return "network adapter", nil

	case ResourceTypePublicIPBlock:
		return "public IPv4 address block", nil

	case ResourceTypeFirewallRule:
		return "Firewall rule", nil

	case ResourceTypeVIPNode:
		return "VIP node", nil

	case ResourceTypeVIPPool:
		return "VIP pool", nil

	case ResourceTypeVirtualListener:
		return "virtual listener", nil

	case ResourceTypeOSImage:
		return "OS image", nil

	case ResourceTypeCustomerImage:
		return "customer image", nil

	case ResourceTypeSSLDomainCertificate:
		return "SSL domain certificate", nil

	case ResourceTypeSSLCertificateChain:
		return "SSL certificate chain", nil

	case ResourceTypeSSLOffloadProfile:
		return "SSL-offload profile", nil

	default:
		return "", fmt.Errorf("unrecognised resource type (value = %d)", resourceType)
	}
}

// GetResource retrieves a compute resource of the specified type by Id.
// id is the resource Id.
// resourceType is the resource type (e.g. ResourceTypeNetworkDomain, ResourceTypeVLAN, etc).
func (client *Client) GetResource(id string, resourceType ResourceType) (Resource, error) {
	switch resourceType {
	case ResourceTypeNetworkDomain:
		return client.GetNetworkDomain(id)

	case ResourceTypeVLAN:
		return client.GetVLAN(id)

	case ResourceTypeServer:
		return client.GetServer(id)

	case ResourceTypeServerAntiAffinityRule:
		return client.getServerAntiAffinityRuleByQualifiedID(id)

	case ResourceTypeNetworkAdapter:
		return client.getNetworkAdapterByID(id)

	case ResourceTypePublicIPBlock:
		return client.GetPublicIPBlock(id)

	case ResourceTypeFirewallRule:
		return client.GetFirewallRule(id)

	case ResourceTypeVIPNode:
		return client.GetVIPNode(id)

	case ResourceTypeVIPPool:
		return client.GetVIPPool(id)

	case ResourceTypeVirtualListener:
		return client.GetVirtualListener(id)

	case ResourceTypeOSImage:
		return client.GetCustomerImage(id)

	case ResourceTypeCustomerImage:
		return client.GetCustomerImage(id)

	case ResourceTypeSSLDomainCertificate:
		return client.GetSSLDomainCertificate(id)

	case ResourceTypeSSLCertificateChain:
		return client.GetSSLCertificateChain(id)

	case ResourceTypeSSLOffloadProfile:
		return client.GetSSLOffloadProfile(id)
	}

	return nil, fmt.Errorf("unrecognised resource type (value = %d)", resourceType)
}

func (client *Client) getNetworkAdapterByID(id string) (Resource, error) {
	compositeIDComponents := strings.Split(id, "/")
	if len(compositeIDComponents) != 2 {
		return nil, fmt.Errorf("'%s' is not a valid network adapter Id (when loading as a resource, the Id must be of the form 'serverId/networkAdapterId')", id)
	}

	server, err := client.GetServer(compositeIDComponents[0])
	if err != nil {
		return nil, err
	}
	if server == nil {
		return nil, fmt.Errorf("No server found with Id '%s.'", compositeIDComponents[0])
	}

	var targetAdapterID = compositeIDComponents[1]
	if *server.Network.PrimaryAdapter.ID == targetAdapterID {
		return &server.Network.PrimaryAdapter, nil
	}

	for _, adapter := range server.Network.AdditionalNetworkAdapters {
		if *adapter.ID == targetAdapterID {
			return &adapter, nil
		}
	}

	return nil, nil
}

// Retrieve a server anti-affinity rule by qualified ID ("networkDomainId/ruleId").
func (client *Client) getServerAntiAffinityRuleByQualifiedID(id string) (Resource, error) {
	compositeIDComponents := strings.Split(id, "/")
	if len(compositeIDComponents) != 2 {
		return nil, fmt.Errorf("'%s' is not a valid network adapter Id (when loading as a resource, the Id must be of the form 'serverId/networkAdapterId')", id)
	}

	networkDomainID := compositeIDComponents[0]
	ruleID := compositeIDComponents[1]

	rule, err := client.GetServerAntiAffinityRule(ruleID, networkDomainID)
	if err != nil {
		return nil, err
	}

	return rule, nil
}

func getPublicIPBlockByID(client *Client, id string) (Resource, error) {
	return client.GetPublicIPBlock(id)
}

func getFirewallRuleByID(client *Client, id string) (Resource, error) {
	return client.GetFirewallRule(id)
}
<|endoftext|>


<commit_before>package compute

import (
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
)

const (
	// VIPNodeStatusEnabled represents a VIP node that is currently enabled.
	VIPNodeStatusEnabled = "ENABLED"

	// VIPNodeStatusDisabled represents a VIP node that is currently disabled.
	VIPNodeStatusDisabled = "DISABLED"

	// VIPNodeStatusForcedOffline represents a VIP node that has been forced offline.
	VIPNodeStatusForcedOffline = "FORCED_OFFLINE"
)

// VIPNodeReference represents a reference to a VIP node.
type VIPNodeReference struct {
	EntityReference

	IPAddress string `json:"ipAddress"`
	Status    string `json:"status"`
}

// VIPNode represents a VIP node.
type VIPNode struct {
	// The node Id.
	ID string `json:"id"`

	// The node name.
	Name string `json:"name"`

	// The node description.
	Description string `json:"description"`

	// VIPNode's IPv4 address (either IPv4 or IPv6 address must be specified).
	IPv4Address string `json:"ipv4Address,omitempty"`

	// VIPNode's IPv6 address (either IPv4 or IPv6 address must be specified).
	IPv6Address string `json:"ipv6Address,omitempty"`

	// The node status (VIPNodeStatusEnabled, VIPNodeStatusDisabled, or VIPNodeStatusForcedOffline).
	Status string `json:"status"`

	// The Id of the node's associated health monitor (if any).
	HealthMonitorID string `json:"healthMonitorId,omitempty"`

	// The node's connection limit (must be greater than 0).
	ConnectionLimit int `json:"connectionLimit"`

	// The node's connection rate limit (must be greater than 0).
	ConnectionRateLimit int `json:"connectionRateLimit"`

	// The Id of the network domain where the node is located.
	NetworkDomainID string `json:"networkDomainId"`

	// The Id of the data centre where the node is located.
	DataCenterID string `json:"datacenterId"`

	// The node's creation timestamp.
	CreateTime string `json:"createTime"`

	// The node's current state.
	State string `json:"state"`

	// The node's current progress (if any).
	Progress string `json:"progress"`
}

// GetID returns the node's Id.
func (node *VIPNode) GetID() string {
	return node.ID
}

// GetResourceType returns the node's resource type.
func (node *VIPNode) GetResourceType() ResourceType {
	return ResourceTypeVIPNode
}

// GetName returns the node's name.
func (node *VIPNode) GetName() string {
	return node.Name
}

// GetState returns the node's current state.
func (node *VIPNode) GetState() string {
	return node.State
}

// IsDeleted determines whether the node has been deleted (is nil).
func (node *VIPNode) IsDeleted() bool {
	return node == nil
}

var _ Resource = &VIPNode{}

// ToEntityReference creates an EntityReference representing the VIPNode.
func (node *VIPNode) ToEntityReference() EntityReference {
	return EntityReference{
		ID:   node.ID,
		Name: node.Name,
	}
}

var _ NamedEntity = &VIPNode{}

// VIPNodes represents a page of VIPNode results.
type VIPNodes struct {
	// The current page of node results.
	Items []VIPNode `json:"node"`

	PagedResult
}

// NewVIPNodeConfiguration represents the configuration for a new VIP node.
type NewVIPNodeConfiguration struct {
	// The VIP node name.
	Name string `json:"name"`

	// The VIP node description.
	Description string `json:"description"`

	// The node's IPv4 address (either IPv4 or IPv6 address must be specified).
	IPv4Address string `json:"ipv4Address,omitempty"`

	// The node's IPv6 address (either IPv4 or IPv6 address must be specified).
	IPv6Address string `json:"ipv6Address,omitempty"`

	// The node status (VIPNodeStatusEnabled, VIPNodeStatusDisabled, or VIPNodeStatusForcedOffline).
	Status string `json:"status"`

	// The Id of the node's associated health monitor (if any).
	HealthMonitorID string `json:"healthMonitorId,omitempty"`

	// The node's connection limit (must be greater than 0).
	ConnectionLimit int `json:"connectionLimit"`

	// The node's connection rate limit (must be greater than 0).
	ConnectionRateLimit int `json:"connectionRateLimit"`

	// The Id of the network domain where the node is located.
	NetworkDomainID string `json:"networkDomainId"`
}

// EditVIPNodeConfiguration represents the request body when editing a VIP node.
type EditVIPNodeConfiguration struct {
	// The VIP node Id.
	ID string `json:"id"`

	// The VIP node description.
	Description *string `json:"description,omitempty"`

	// The node status (VIPNodeStatusEnabled, VIPNodeStatusDisabled, or VIPNodeStatusForcedOffline).
	Status *string `json:"status,omitempty"`

	// The Id of the node's associated health monitor (if any).
	HealthMonitorID *string `json:"healthMonitorId,omitempty"`

	// The node's connection limit (must be greater than 0).
	ConnectionLimit *int `json:"connectionLimit,omitempty"`

	// The node's connection rate limit (must be greater than 0).
	ConnectionRateLimit *int `json:"connectionRateLimit,omitempty"`
}

// Request body for deleting a VIP node.
type deleteVIPNode struct {
	// The VIP node ID.
	ID string `json:"id"`
}

// ListVIPNodesInNetworkDomain retrieves a list of all VIP nodes in the specified network domain.
func (client *Client) ListVIPNodesInNetworkDomain(networkDomainID string, paging *Paging) (nodes *VIPNodes, err error) {
	organizationID, err := client.getOrganizationID()
	if err != nil {
		return nil, err
	}

	requestURI := fmt.Sprintf("%s/networkDomainVip/node?networkDomainId=%s&%s",
		url.QueryEscape(organizationID),
		url.QueryEscape(networkDomainID),
		paging.EnsurePaging().toQueryParameters(),
	)
	request, err := client.newRequestV22(requestURI, http.MethodGet, nil)
	if err != nil {
		return nil, err
	}

	responseBody, statusCode, err := client.executeRequest(request)
	if err != nil {
		return nil, err
	}

	if statusCode != http.StatusOK {
		var apiResponse *APIResponseV2

		apiResponse, err = readAPIResponseAsJSON(responseBody, statusCode)
		if err != nil {
			return nil, err
		}

		return nil, apiResponse.ToError("Request to list VIP nodes in network domain '%s' failed with status code %d (%s): %s", networkDomainID, statusCode, apiResponse.ResponseCode, apiResponse.Message)
	}

	nodes = &VIPNodes{}
	err = json.Unmarshal(responseBody, nodes)
	if err != nil {
		return nil, err
	}

	return nodes, nil
}

// GetVIPNode retrieves the VIP node with the specified Id.
// Returns nil if no VIP node is found with the specified Id.
func (client *Client) GetVIPNode(id string) (node *VIPNode, err error) {
	organizationID, err := client.getOrganizationID()
	if err != nil {
		return nil, err
	}

	requestURI := fmt.Sprintf("%s/networkDomainVip/node/%s",
		url.QueryEscape(organizationID),
		url.QueryEscape(id),
	)
	request, err := client.newRequestV22(requestURI, http.MethodGet, nil)
	if err != nil {
		return nil, err
	}
	responseBody, statusCode, err := client.executeRequest(request)
	if err != nil {
		return nil, err
	}

	if statusCode != http.StatusOK {
		var apiResponse *APIResponseV2

		apiResponse, err = readAPIResponseAsJSON(responseBody, statusCode)
		if err != nil {
			return nil, err
		}

		if apiResponse.ResponseCode == ResponseCodeResourceNotFound {
			return nil, nil // Not an error, but was not found.
		}

		return nil, apiResponse.ToError("Request to retrieve VIP node with Id '%s' failed with status code %d (%s): %s", id, statusCode, apiResponse.ResponseCode, apiResponse.Message)
	}

	node = &VIPNode{}
	err = json.Unmarshal(responseBody, node)
	if err != nil {
		return nil, err
	}

	return node, nil
}

// CreateVIPNode creates a new VIP node.
// Returns the Id of the new node.
func (client *Client) CreateVIPNode(nodeConfiguration NewVIPNodeConfiguration) (nodeID string, err error) {
	organizationID, err := client.getOrganizationID()
	if err != nil {
		return "", err
	}

	requestURI := fmt.Sprintf("%s/networkDomainVip/createNode",
		url.QueryEscape(organizationID),
	)
	request, err := client.newRequestV22(requestURI, http.MethodPost, &nodeConfiguration)
	responseBody, statusCode, err := client.executeRequest(request)
	if err != nil {
		return "", err
	}

	apiResponse, err := readAPIResponseAsJSON(responseBody, statusCode)
	if err != nil {
		return "", err
	}

	if apiResponse.ResponseCode != ResponseCodeOK {
		return "", apiResponse.ToError("Request to create VIP node '%s' failed with status code %d (%s): %s", nodeConfiguration.Name, statusCode, apiResponse.ResponseCode, apiResponse.Message)
	}

	// Expected: "info" { "name": "nodeId", "value": "the-Id-of-the-new-node" }
	nodeIDMessage := apiResponse.GetFieldMessage("nodeId")
	if nodeIDMessage == nil {
		return "", apiResponse.ToError("Received an unexpected response (missing 'nodeId') with status code %d (%s): %s", statusCode, apiResponse.ResponseCode, apiResponse.Message)
	}

	return *nodeIDMessage, nil
}

// EditVIPNode updates an existing VIP node.
func (client *Client) EditVIPNode(id string, nodeConfiguration EditVIPNodeConfiguration) error {
	organizationID, err := client.getOrganizationID()
	if err != nil {
		return err
	}

	editNodeConfiguration := &nodeConfiguration
	editNodeConfiguration.ID = id

	requestURI := fmt.Sprintf("%s/networkDomainVip/editNode",
		url.QueryEscape(organizationID),
	)
	request, err := client.newRequestV22(requestURI, http.MethodPost, editNodeConfiguration)
	responseBody, statusCode, err := client.executeRequest(request)
	if err != nil {
		return err
	}

	apiResponse, err := readAPIResponseAsJSON(responseBody, statusCode)
	if err != nil {
		return err
	}

	if statusCode != http.StatusOK {
		return apiResponse.ToError("Request to edit VIP node '%s' failed with status code %d (%s): %s", nodeConfiguration.ID, statusCode, apiResponse.ResponseCode, apiResponse.Message)
	}

	return nil
}

// DeleteVIPNode deletes an existing VIP node.
// Returns an error if the operation was not successful.
func (client *Client) DeleteVIPNode(id string) (err error) {
	organizationID, err := client.getOrganizationID()
	if err != nil {
		return err
	}

	requestURI := fmt.Sprintf("%s/networkDomainVip/deleteNode",
		url.QueryEscape(organizationID),
	)
	request, err := client.newRequestV22(requestURI, http.MethodPost, &deleteVIPNode{id})
	responseBody, statusCode, err := client.executeRequest(request)
	if err != nil {
		return err
	}

	apiResponse, err := readAPIResponseAsJSON(responseBody, statusCode)
	if err != nil {
		return err
	}

	if apiResponse.ResponseCode != ResponseCodeOK {
		return apiResponse.ToError("Request to delete VIP node '%s' failed with unexpected status code %d (%s): %s", id, statusCode, apiResponse.ResponseCode, apiResponse.Message)
	}

	return nil
}
<commit_msg>changes to set the haelth montior by name for the vip node<commit_after>package compute

import (
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
)

const (
	// VIPNodeStatusEnabled represents a VIP node that is currently enabled.
	VIPNodeStatusEnabled = "ENABLED"

	// VIPNodeStatusDisabled represents a VIP node that is currently disabled.
	VIPNodeStatusDisabled = "DISABLED"

	// VIPNodeStatusForcedOffline represents a VIP node that has been forced offline.
	VIPNodeStatusForcedOffline = "FORCED_OFFLINE"
)

// VIPNodeReference represents a reference to a VIP node.
type VIPNodeReference struct {
	EntityReference

	IPAddress string `json:"ipAddress"`
	Status    string `json:"status"`
}

// VIPNodeHealthMonitor represents a health Monitor to a VIP node.
type VIPNodeHealthMonitor struct {
	ID   string `json:"id"`
	Name string `json:"name"`
}

// VIPNode represents a VIP node.
type VIPNode struct {
	// The node Id.
	ID string `json:"id"`

	// The node name.
	Name string `json:"name"`

	// The node description.
	Description string `json:"description"`

	// VIPNode's IPv4 address (either IPv4 or IPv6 address must be specified).
	IPv4Address string `json:"ipv4Address,omitempty"`

	// VIPNode's IPv6 address (either IPv4 or IPv6 address must be specified).
	IPv6Address string `json:"ipv6Address,omitempty"`

	// The node status (VIPNodeStatusEnabled, VIPNodeStatusDisabled, or VIPNodeStatusForcedOffline).
	Status string `json:"status"`

	// The Id of the node's associated health monitor (if any).
	HealthMonitor VIPNodeHealthMonitor `json:"healthMonitor,omitempty"`

	// The node's connection limit (must be greater than 0).
	ConnectionLimit int `json:"connectionLimit"`

	// The node's connection rate limit (must be greater than 0).
	ConnectionRateLimit int `json:"connectionRateLimit"`

	// The Id of the network domain where the node is located.
	NetworkDomainID string `json:"networkDomainId"`

	// The Id of the data centre where the node is located.
	DataCenterID string `json:"datacenterId"`

	// The node's creation timestamp.
	CreateTime string `json:"createTime"`

	// The node's current state.
	State string `json:"state"`

	// The node's current progress (if any).
	Progress string `json:"progress"`
}

// GetID returns the node's Id.
func (node *VIPNode) GetID() string {
	return node.ID
}

// GetResourceType returns the node's resource type.
func (node *VIPNode) GetResourceType() ResourceType {
	return ResourceTypeVIPNode
}

// GetName returns the node's name.
func (node *VIPNode) GetName() string {
	return node.Name
}

// GetState returns the node's current state.
func (node *VIPNode) GetState() string {
	return node.State
}

// IsDeleted determines whether the node has been deleted (is nil).
func (node *VIPNode) IsDeleted() bool {
	return node == nil
}

var _ Resource = &VIPNode{}

// ToEntityReference creates an EntityReference representing the VIPNode.
func (node *VIPNode) ToEntityReference() EntityReference {
	return EntityReference{
		ID:   node.ID,
		Name: node.Name,
	}
}

var _ NamedEntity = &VIPNode{}

// VIPNodes represents a page of VIPNode results.
type VIPNodes struct {
	// The current page of node results.
	Items []VIPNode `json:"node"`

	PagedResult
}

// NewVIPNodeConfiguration represents the configuration for a new VIP node.
type NewVIPNodeConfiguration struct {
	// The VIP node name.
	Name string `json:"name"`

	// The VIP node description.
	Description string `json:"description"`

	// The node's IPv4 address (either IPv4 or IPv6 address must be specified).
	IPv4Address string `json:"ipv4Address,omitempty"`

	// The node's IPv6 address (either IPv4 or IPv6 address must be specified).
	IPv6Address string `json:"ipv6Address,omitempty"`

	// The node status (VIPNodeStatusEnabled, VIPNodeStatusDisabled, or VIPNodeStatusForcedOffline).
	Status string `json:"status"`

	// The Id of the node's associated health monitor (if any).
	HealthMonitorID string `json:"healthMonitorId,omitempty"`

	// The node's connection limit (must be greater than 0).
	ConnectionLimit int `json:"connectionLimit"`

	// The node's connection rate limit (must be greater than 0).
	ConnectionRateLimit int `json:"connectionRateLimit"`

	// The Id of the network domain where the node is located.
	NetworkDomainID string `json:"networkDomainId"`
}

// EditVIPNodeConfiguration represents the request body when editing a VIP node.
type EditVIPNodeConfiguration struct {
	// The VIP node Id.
	ID string `json:"id"`

	// The VIP node description.
	Description *string `json:"description,omitempty"`

	// The node status (VIPNodeStatusEnabled, VIPNodeStatusDisabled, or VIPNodeStatusForcedOffline).
	Status *string `json:"status,omitempty"`

	// The Id of the node's associated health monitor (if any).
	HealthMonitorID *string `json:"healthMonitorId,omitempty"`

	// The node's connection limit (must be greater than 0).
	ConnectionLimit *int `json:"connectionLimit,omitempty"`

	// The node's connection rate limit (must be greater than 0).
	ConnectionRateLimit *int `json:"connectionRateLimit,omitempty"`
}

// Request body for deleting a VIP node.
type deleteVIPNode struct {
	// The VIP node ID.
	ID string `json:"id"`
}

// ListVIPNodesInNetworkDomain retrieves a list of all VIP nodes in the specified network domain.
func (client *Client) ListVIPNodesInNetworkDomain(networkDomainID string, paging *Paging) (nodes *VIPNodes, err error) {
	organizationID, err := client.getOrganizationID()
	if err != nil {
		return nil, err
	}

	requestURI := fmt.Sprintf("%s/networkDomainVip/node?networkDomainId=%s&%s",
		url.QueryEscape(organizationID),
		url.QueryEscape(networkDomainID),
		paging.EnsurePaging().toQueryParameters(),
	)
	request, err := client.newRequestV22(requestURI, http.MethodGet, nil)
	if err != nil {
		return nil, err
	}

	responseBody, statusCode, err := client.executeRequest(request)
	if err != nil {
		return nil, err
	}

	if statusCode != http.StatusOK {
		var apiResponse *APIResponseV2

		apiResponse, err = readAPIResponseAsJSON(responseBody, statusCode)
		if err != nil {
			return nil, err
		}

		return nil, apiResponse.ToError("Request to list VIP nodes in network domain '%s' failed with status code %d (%s): %s", networkDomainID, statusCode, apiResponse.ResponseCode, apiResponse.Message)
	}

	nodes = &VIPNodes{}
	err = json.Unmarshal(responseBody, nodes)
	if err != nil {
		return nil, err
	}

	return nodes, nil
}

// GetVIPNode retrieves the VIP node with the specified Id.
// Returns nil if no VIP node is found with the specified Id.
func (client *Client) GetVIPNode(id string) (node *VIPNode, err error) {
	organizationID, err := client.getOrganizationID()
	if err != nil {
		return nil, err
	}

	requestURI := fmt.Sprintf("%s/networkDomainVip/node/%s",
		url.QueryEscape(organizationID),
		url.QueryEscape(id),
	)
	request, err := client.newRequestV22(requestURI, http.MethodGet, nil)
	if err != nil {
		return nil, err
	}
	responseBody, statusCode, err := client.executeRequest(request)
	if err != nil {
		return nil, err
	}

	if statusCode != http.StatusOK {
		var apiResponse *APIResponseV2

		apiResponse, err = readAPIResponseAsJSON(responseBody, statusCode)
		if err != nil {
			return nil, err
		}

		if apiResponse.ResponseCode == ResponseCodeResourceNotFound {
			return nil, nil // Not an error, but was not found.
		}

		return nil, apiResponse.ToError("Request to retrieve VIP node with Id '%s' failed with status code %d (%s): %s", id, statusCode, apiResponse.ResponseCode, apiResponse.Message)
	}

	node = &VIPNode{}
	err = json.Unmarshal(responseBody, node)
	if err != nil {
		return nil, err
	}

	return node, nil
}

// CreateVIPNode creates a new VIP node.
// Returns the Id of the new node.
func (client *Client) CreateVIPNode(nodeConfiguration NewVIPNodeConfiguration) (nodeID string, err error) {
	organizationID, err := client.getOrganizationID()
	if err != nil {
		return "", err
	}

	requestURI := fmt.Sprintf("%s/networkDomainVip/createNode",
		url.QueryEscape(organizationID),
	)
	request, err := client.newRequestV22(requestURI, http.MethodPost, &nodeConfiguration)
	responseBody, statusCode, err := client.executeRequest(request)
	if err != nil {
		return "", err
	}

	apiResponse, err := readAPIResponseAsJSON(responseBody, statusCode)
	if err != nil {
		return "", err
	}

	if apiResponse.ResponseCode != ResponseCodeOK {
		return "", apiResponse.ToError("Request to create VIP node '%s' failed with status code %d (%s): %s", nodeConfiguration.Name, statusCode, apiResponse.ResponseCode, apiResponse.Message)
	}

	// Expected: "info" { "name": "nodeId", "value": "the-Id-of-the-new-node" }
	nodeIDMessage := apiResponse.GetFieldMessage("nodeId")
	if nodeIDMessage == nil {
		return "", apiResponse.ToError("Received an unexpected response (missing 'nodeId') with status code %d (%s): %s", statusCode, apiResponse.ResponseCode, apiResponse.Message)
	}

	return *nodeIDMessage, nil
}

// EditVIPNode updates an existing VIP node.
func (client *Client) EditVIPNode(id string, nodeConfiguration EditVIPNodeConfiguration) error {
	organizationID, err := client.getOrganizationID()
	if err != nil {
		return err
	}

	editNodeConfiguration := &nodeConfiguration
	editNodeConfiguration.ID = id

	requestURI := fmt.Sprintf("%s/networkDomainVip/editNode",
		url.QueryEscape(organizationID),
	)
	request, err := client.newRequestV22(requestURI, http.MethodPost, editNodeConfiguration)
	responseBody, statusCode, err := client.executeRequest(request)
	if err != nil {
		return err
	}

	apiResponse, err := readAPIResponseAsJSON(responseBody, statusCode)
	if err != nil {
		return err
	}

	if statusCode != http.StatusOK {
		return apiResponse.ToError("Request to edit VIP node '%s' failed with status code %d (%s): %s", nodeConfiguration.ID, statusCode, apiResponse.ResponseCode, apiResponse.Message)
	}

	return nil
}

// DeleteVIPNode deletes an existing VIP node.
// Returns an error if the operation was not successful.
func (client *Client) DeleteVIPNode(id string) (err error) {
	organizationID, err := client.getOrganizationID()
	if err != nil {
		return err
	}

	requestURI := fmt.Sprintf("%s/networkDomainVip/deleteNode",
		url.QueryEscape(organizationID),
	)
	request, err := client.newRequestV22(requestURI, http.MethodPost, &deleteVIPNode{id})
	responseBody, statusCode, err := client.executeRequest(request)
	if err != nil {
		return err
	}

	apiResponse, err := readAPIResponseAsJSON(responseBody, statusCode)
	if err != nil {
		return err
	}

	if apiResponse.ResponseCode != ResponseCodeOK {
		return apiResponse.ToError("Request to delete VIP node '%s' failed with unexpected status code %d (%s): %s", id, statusCode, apiResponse.ResponseCode, apiResponse.Message)
	}

	return nil
}
<|endoftext|>


<commit_before>package router

import (
	"math"
	"net"
	"time"

	"github.com/weaveworks/weave/common"
	"github.com/weaveworks/weave/mesh"
)

const (
	ChannelSize         = 16
	MaxUDPPacketSize    = 65535
	FastHeartbeat       = 500 * time.Millisecond
	SlowHeartbeat       = 10 * time.Second
	MaxMissedHeartbeats = 6
	HeartbeatTimeout    = MaxMissedHeartbeats * SlowHeartbeat
	MaxDuration         = time.Duration(math.MaxInt64)
	NameSize            = mesh.NameSize
	// should be greater than typical ARP cache expiries, i.e. > 3/2 *
	// /proc/sys/net/ipv4_neigh/*/base_reachable_time_ms on Linux
	macMaxAge = 10 * time.Minute
)

var (
	log        = common.Log
	checkFatal = common.CheckFatal
	checkWarn  = common.CheckWarn
)

type NetworkConfig struct {
	BufSz         int
	PacketLogging PacketLogging
	Bridge        Bridge
}

type PacketLogging interface {
	LogPacket(string, PacketKey)
	LogForwardPacket(string, ForwardPacketKey)
}

type NetworkRouter struct {
	*mesh.Router
	NetworkConfig
	Macs *MacCache
}

func NewNetworkRouter(config mesh.Config, networkConfig NetworkConfig, name mesh.PeerName, nickName string, overlay NetworkOverlay) *NetworkRouter {
	if overlay == nil {
		overlay = NullNetworkOverlay{}
	}
	if networkConfig.Bridge == nil {
		networkConfig.Bridge = NullBridge{}
	}

	router := &NetworkRouter{Router: mesh.NewRouter(config, name, nickName, overlay), NetworkConfig: networkConfig}
	router.Peers.OnInvalidateShortIDs(overlay.InvalidateShortIDs)
	router.Routes.OnChange(overlay.InvalidateRoutes)
	router.Macs = NewMacCache(macMaxAge,
		func(mac net.HardwareAddr, peer *mesh.Peer) {
			log.Println("Expired MAC", mac, "at", peer)
		})
	router.Peers.OnGC(func(peer *mesh.Peer) { router.Macs.Delete(peer) })
	return router
}

// Start listening for TCP connections, locally captured packets, and
// forwarded packets.
func (router *NetworkRouter) Start() {
	log.Println("Sniffing traffic on", router.Bridge)
	checkFatal(router.Bridge.StartConsumingPackets(router.handleCapturedPacket))
	checkFatal(router.Overlay.(NetworkOverlay).StartConsumingPackets(router.Ourself.Peer, router.Peers, router.handleForwardedPacket))
	router.Router.Start()
}

func (router *NetworkRouter) handleCapturedPacket(key PacketKey) FlowOp {
	router.PacketLogging.LogPacket("Captured", key)
	srcMac := net.HardwareAddr(key.SrcMAC[:])

	switch newSrcMac, conflictPeer := router.Macs.Add(srcMac, router.Ourself.Peer); {
	case newSrcMac:
		log.Println("Discovered local MAC", srcMac)

	case conflictPeer != nil:
		// The MAC cache has an entry for the source MAC
		// associated with another peer.  This probably means
		// we are seeing a frame we injected ourself.  That
		// shouldn't happen, but discard it just in case.
		log.Error("Captured frame from MAC (", srcMac, ") associated with another peer ", conflictPeer)
		return DiscardingFlowOp{}
	}

	// Discard STP broadcasts
	if key.DstMAC == [...]byte{0x01, 0x80, 0xC2, 0x00, 0x00, 0x00} {
		return DiscardingFlowOp{}
	}

	dstMac := net.HardwareAddr(key.DstMAC[:])
	switch dstPeer := router.Macs.Lookup(dstMac); dstPeer {
	case router.Ourself.Peer:
		// The packet is destined for a local MAC.  The bridge
		// won't normally send us such packets, and if it does
		// it's likely to be broadcasting the packet to all
		// ports.  So if it happens, just drop the packet to
		// avoid warnings if we try to forward it.
		return DiscardingFlowOp{}
	case nil:
		// If we don't know which peer corresponds to the dest
		// MAC, broadcast it.
		router.PacketLogging.LogPacket("Broadcasting", key)
		return router.relayBroadcast(router.Ourself.Peer, key)
	default:
		router.PacketLogging.LogPacket("Forwarding", key)
		return router.relay(ForwardPacketKey{
			PacketKey: key,
			SrcPeer:   router.Ourself.Peer,
			DstPeer:   dstPeer})
	}
}

func (router *NetworkRouter) handleForwardedPacket(key ForwardPacketKey) FlowOp {
	if key.DstPeer != router.Ourself.Peer {
		// it's not for us, we're just relaying it
		router.PacketLogging.LogForwardPacket("Relaying", key)
		return router.relay(key)
	}

	// At this point, it's either unicast to us, or a broadcast
	// (because the DstPeer on a forwarded broadcast packet is
	// always set to the peer being forwarded to)

	srcMac := net.HardwareAddr(key.SrcMAC[:])
	dstMac := net.HardwareAddr(key.DstMAC[:])

	switch newSrcMac, conflictPeer := router.Macs.AddForced(srcMac, key.SrcPeer); {
	case newSrcMac:
		log.Print("Discovered remote MAC ", srcMac, " at ", key.SrcPeer)

	case conflictPeer != nil:
		log.Print("Discovered remote MAC ", srcMac, " at ", key.SrcPeer, " (was at ", conflictPeer, ")")

		// We need to clear out any flows destined to the MAC
		// that forward to the old peer.
		router.Overlay.(NetworkOverlay).InvalidateRoutes()
	}

	router.PacketLogging.LogForwardPacket("Injecting", key)
	injectFop := router.Bridge.InjectPacket(key.PacketKey)
	dstPeer := router.Macs.Lookup(dstMac)
	if dstPeer == router.Ourself.Peer {
		return injectFop
	}

	router.PacketLogging.LogForwardPacket("Relaying broadcast", key)
	relayFop := router.relayBroadcast(key.SrcPeer, key.PacketKey)
	switch {
	case injectFop == nil:
		return relayFop

	case relayFop == nil:
		return injectFop

	default:
		mfop := NewMultiFlowOp(false)
		mfop.Add(injectFop)
		mfop.Add(relayFop)
		return mfop
	}
}

// Routing

func (router *NetworkRouter) relay(key ForwardPacketKey) FlowOp {
	relayPeerName, found := router.Routes.Unicast(key.DstPeer.Name)
	if !found {
		// Not necessarily an error as there could be a race with the
		// dst disappearing whilst the frame is in flight
		log.Println("Received packet for unknown destination:", key.DstPeer)
		return DiscardingFlowOp{}
	}

	conn, found := router.Ourself.ConnectionTo(relayPeerName)
	if !found {
		// Again, could just be a race, not necessarily an error
		log.Println("Unable to find connection to relay peer", relayPeerName)
		return DiscardingFlowOp{}
	}

	return conn.(*mesh.LocalConnection).OverlayConn.(OverlayForwarder).Forward(key)
}

func (router *NetworkRouter) relayBroadcast(srcPeer *mesh.Peer, key PacketKey) FlowOp {
	nextHops := router.Routes.Broadcast(srcPeer.Name)
	if len(nextHops) == 0 {
		return DiscardingFlowOp{}
	}

	op := NewMultiFlowOp(true)

	for _, conn := range router.Ourself.ConnectionsTo(nextHops) {
		op.Add(conn.(*mesh.LocalConnection).OverlayConn.(OverlayForwarder).Forward(ForwardPacketKey{
			PacketKey: key,
			SrcPeer:   srcPeer,
			DstPeer:   conn.Remote()}))
	}

	return op
}
<commit_msg>cosmetic: whitespace<commit_after>package router

import (
	"math"
	"net"
	"time"

	"github.com/weaveworks/weave/common"
	"github.com/weaveworks/weave/mesh"
)

const (
	ChannelSize         = 16
	MaxUDPPacketSize    = 65535
	FastHeartbeat       = 500 * time.Millisecond
	SlowHeartbeat       = 10 * time.Second
	MaxMissedHeartbeats = 6
	HeartbeatTimeout    = MaxMissedHeartbeats * SlowHeartbeat
	MaxDuration         = time.Duration(math.MaxInt64)
	NameSize            = mesh.NameSize
	// should be greater than typical ARP cache expiries, i.e. > 3/2 *
	// /proc/sys/net/ipv4_neigh/*/base_reachable_time_ms on Linux
	macMaxAge = 10 * time.Minute
)

var (
	log        = common.Log
	checkFatal = common.CheckFatal
	checkWarn  = common.CheckWarn
)

type NetworkConfig struct {
	BufSz         int
	PacketLogging PacketLogging
	Bridge        Bridge
}

type PacketLogging interface {
	LogPacket(string, PacketKey)
	LogForwardPacket(string, ForwardPacketKey)
}

type NetworkRouter struct {
	*mesh.Router
	NetworkConfig
	Macs *MacCache
}

func NewNetworkRouter(config mesh.Config, networkConfig NetworkConfig, name mesh.PeerName, nickName string, overlay NetworkOverlay) *NetworkRouter {
	if overlay == nil {
		overlay = NullNetworkOverlay{}
	}
	if networkConfig.Bridge == nil {
		networkConfig.Bridge = NullBridge{}
	}

	router := &NetworkRouter{Router: mesh.NewRouter(config, name, nickName, overlay), NetworkConfig: networkConfig}
	router.Peers.OnInvalidateShortIDs(overlay.InvalidateShortIDs)
	router.Routes.OnChange(overlay.InvalidateRoutes)
	router.Macs = NewMacCache(macMaxAge,
		func(mac net.HardwareAddr, peer *mesh.Peer) {
			log.Println("Expired MAC", mac, "at", peer)
		})
	router.Peers.OnGC(func(peer *mesh.Peer) { router.Macs.Delete(peer) })
	return router
}

// Start listening for TCP connections, locally captured packets, and
// forwarded packets.
func (router *NetworkRouter) Start() {
	log.Println("Sniffing traffic on", router.Bridge)
	checkFatal(router.Bridge.StartConsumingPackets(router.handleCapturedPacket))
	checkFatal(router.Overlay.(NetworkOverlay).StartConsumingPackets(router.Ourself.Peer, router.Peers, router.handleForwardedPacket))
	router.Router.Start()
}

func (router *NetworkRouter) handleCapturedPacket(key PacketKey) FlowOp {
	router.PacketLogging.LogPacket("Captured", key)
	srcMac := net.HardwareAddr(key.SrcMAC[:])

	switch newSrcMac, conflictPeer := router.Macs.Add(srcMac, router.Ourself.Peer); {
	case newSrcMac:
		log.Println("Discovered local MAC", srcMac)

	case conflictPeer != nil:
		// The MAC cache has an entry for the source MAC
		// associated with another peer.  This probably means
		// we are seeing a frame we injected ourself.  That
		// shouldn't happen, but discard it just in case.
		log.Error("Captured frame from MAC (", srcMac, ") associated with another peer ", conflictPeer)
		return DiscardingFlowOp{}
	}

	// Discard STP broadcasts
	if key.DstMAC == [...]byte{0x01, 0x80, 0xC2, 0x00, 0x00, 0x00} {
		return DiscardingFlowOp{}
	}

	dstMac := net.HardwareAddr(key.DstMAC[:])
	switch dstPeer := router.Macs.Lookup(dstMac); dstPeer {
	case router.Ourself.Peer:
		// The packet is destined for a local MAC.  The bridge
		// won't normally send us such packets, and if it does
		// it's likely to be broadcasting the packet to all
		// ports.  So if it happens, just drop the packet to
		// avoid warnings if we try to forward it.
		return DiscardingFlowOp{}
	case nil:
		// If we don't know which peer corresponds to the dest
		// MAC, broadcast it.
		router.PacketLogging.LogPacket("Broadcasting", key)
		return router.relayBroadcast(router.Ourself.Peer, key)
	default:
		router.PacketLogging.LogPacket("Forwarding", key)
		return router.relay(ForwardPacketKey{
			PacketKey: key,
			SrcPeer:   router.Ourself.Peer,
			DstPeer:   dstPeer})
	}
}

func (router *NetworkRouter) handleForwardedPacket(key ForwardPacketKey) FlowOp {
	if key.DstPeer != router.Ourself.Peer {
		// it's not for us, we're just relaying it
		router.PacketLogging.LogForwardPacket("Relaying", key)
		return router.relay(key)
	}

	// At this point, it's either unicast to us, or a broadcast
	// (because the DstPeer on a forwarded broadcast packet is
	// always set to the peer being forwarded to)

	srcMac := net.HardwareAddr(key.SrcMAC[:])
	dstMac := net.HardwareAddr(key.DstMAC[:])

	switch newSrcMac, conflictPeer := router.Macs.AddForced(srcMac, key.SrcPeer); {
	case newSrcMac:
		log.Print("Discovered remote MAC ", srcMac, " at ", key.SrcPeer)
	case conflictPeer != nil:
		log.Print("Discovered remote MAC ", srcMac, " at ", key.SrcPeer, " (was at ", conflictPeer, ")")
		// We need to clear out any flows destined to the MAC
		// that forward to the old peer.
		router.Overlay.(NetworkOverlay).InvalidateRoutes()
	}

	router.PacketLogging.LogForwardPacket("Injecting", key)
	injectFop := router.Bridge.InjectPacket(key.PacketKey)
	dstPeer := router.Macs.Lookup(dstMac)
	if dstPeer == router.Ourself.Peer {
		return injectFop
	}

	router.PacketLogging.LogForwardPacket("Relaying broadcast", key)
	relayFop := router.relayBroadcast(key.SrcPeer, key.PacketKey)
	switch {
	case injectFop == nil:
		return relayFop
	case relayFop == nil:
		return injectFop
	default:
		mfop := NewMultiFlowOp(false)
		mfop.Add(injectFop)
		mfop.Add(relayFop)
		return mfop
	}
}

// Routing

func (router *NetworkRouter) relay(key ForwardPacketKey) FlowOp {
	relayPeerName, found := router.Routes.Unicast(key.DstPeer.Name)
	if !found {
		// Not necessarily an error as there could be a race with the
		// dst disappearing whilst the frame is in flight
		log.Println("Received packet for unknown destination:", key.DstPeer)
		return DiscardingFlowOp{}
	}

	conn, found := router.Ourself.ConnectionTo(relayPeerName)
	if !found {
		// Again, could just be a race, not necessarily an error
		log.Println("Unable to find connection to relay peer", relayPeerName)
		return DiscardingFlowOp{}
	}

	return conn.(*mesh.LocalConnection).OverlayConn.(OverlayForwarder).Forward(key)
}

func (router *NetworkRouter) relayBroadcast(srcPeer *mesh.Peer, key PacketKey) FlowOp {
	nextHops := router.Routes.Broadcast(srcPeer.Name)
	if len(nextHops) == 0 {
		return DiscardingFlowOp{}
	}

	op := NewMultiFlowOp(true)

	for _, conn := range router.Ourself.ConnectionsTo(nextHops) {
		op.Add(conn.(*mesh.LocalConnection).OverlayConn.(OverlayForwarder).Forward(ForwardPacketKey{
			PacketKey: key,
			SrcPeer:   srcPeer,
			DstPeer:   conn.Remote()}))
	}

	return op
}
<|endoftext|>


<commit_before>/**********************************************************\
|                                                          |
|                          hprose                          |
|                                                          |
| Official WebSite: http://www.hprose.com/                 |
|                   http://www.hprose.org/                 |
|                                                          |
\**********************************************************/
/**********************************************************\
 *                                                        *
 * rpc/fasthttp_service.go                                *
 *                                                        *
 * hprose fasthttp service for Go.                        *
 *                                                        *
 * LastModified: Sep 23, 2016                             *
 * Author: Ma Bingyao <andot@hprose.com>                  *
 *                                                        *
\**********************************************************/

package rpc

import (
	"reflect"
	"strings"
	"unsafe"

	"github.com/hprose/hprose-golang/util"
	"github.com/valyala/fasthttp"
)

// FastHTTPContext is the hprose fasthttp context
type FastHTTPContext struct {
	*ServiceContext
	RequestCtx *fasthttp.RequestCtx
}

// NewFastHTTPContext is the constructor of FastHTTPContext
func NewFastHTTPContext(
	clients Clients, ctx *fasthttp.RequestCtx) (context *FastHTTPContext) {
	context = new(FastHTTPContext)
	context.ServiceContext = NewServiceContext(clients)
	context.ServiceContext.TransportContext = context
	context.RequestCtx = ctx
	return
}

// FastHTTPService is the hprose fasthttp service
type FastHTTPService struct {
	baseHTTPService
}

type fastSendHeaderEvent interface {
	OnSendHeader(context *FastHTTPContext)
}

type fastSendHeaderEvent2 interface {
	OnSendHeader(context *FastHTTPContext) error
}

func fasthttpFixArguments(args []reflect.Value, context *ServiceContext) {
	i := len(args) - 1
	switch args[i].Type() {
	case fasthttpContextType:
		if c, ok := context.TransportContext.(*FastHTTPContext); ok {
			args[i] = reflect.ValueOf(c)
		}
	case fasthttpRequestCtxType:
		if c, ok := context.TransportContext.(*FastHTTPContext); ok {
			args[i] = reflect.ValueOf(c.RequestCtx)
		}
	default:
		DefaultFixArguments(args, context)
	}
}

// NewFastHTTPService is the constructor of FastHTTPService
func NewFastHTTPService() (service *FastHTTPService) {
	service = (*FastHTTPService)(unsafe.Pointer(newBaseHTTPService()))
	service.FixArguments = fasthttpFixArguments
	return
}

func (service *FastHTTPService) xmlFileHandler(
	ctx *fasthttp.RequestCtx, path string, context []byte) bool {
	requestPath := util.ByteString(ctx.Path())
	if context == nil || strings.ToLower(requestPath) != path {
		return false
	}
	ifModifiedSince := util.ByteString(ctx.Request.Header.Peek("if-modified-since"))
	ifNoneMatch := util.ByteString(ctx.Request.Header.Peek("if-none-match"))
	if ifModifiedSince == service.lastModified && ifNoneMatch == service.etag {
		ctx.SetStatusCode(304)
	} else {
		contentLength := len(context)
		ctx.Response.Header.Set("Last-Modified", service.lastModified)
		ctx.Response.Header.Set("Etag", service.etag)
		ctx.Response.Header.SetContentType("text/xml")
		ctx.Response.Header.Set("Content-Length", util.Itoa(contentLength))
		ctx.SetBody(context)
	}
	return true
}

func (service *FastHTTPService) crossDomainXMLHandler(
	ctx *fasthttp.RequestCtx) bool {
	path := "/crossdomain.xml"
	context := service.crossDomainXMLContent
	return service.xmlFileHandler(ctx, path, context)
}

func (service *FastHTTPService) clientAccessPolicyXMLHandler(
	ctx *fasthttp.RequestCtx) bool {
	path := "/clientaccesspolicy.xml"
	context := service.clientAccessPolicyXMLContent
	return service.xmlFileHandler(ctx, path, context)
}

func (service *FastHTTPService) fireSendHeaderEvent(
	context *FastHTTPContext) (err error) {
	defer func() {
		if e := recover(); e != nil {
			err = NewPanicError(e)
		}
	}()
	switch event := service.Event.(type) {
	case fastSendHeaderEvent:
		event.OnSendHeader(context)
	case fastSendHeaderEvent2:
		err = event.OnSendHeader(context)
	}
	return err
}

func (service *FastHTTPService) sendHeader(
	context *FastHTTPContext) (err error) {
	if err = service.fireSendHeaderEvent(context); err != nil {
		return err
	}
	ctx := context.RequestCtx
	ctx.Response.Header.Set("Content-Type", "text/plain")
	if service.P3P {
		ctx.Response.Header.Set("P3P",
			`CP="CAO DSP COR CUR ADM DEV TAI PSA PSD IVAi IVDi `+
				`CONi TELo OTPi OUR DELi SAMi OTRi UNRi PUBi IND PHY ONL `+
				`UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE GOV"`)
	}
	if service.CrossDomain {
		origin := util.ByteString(ctx.Request.Header.Peek("origin"))
		if origin != "" && origin != "null" {
			if len(service.accessControlAllowOrigins) == 0 ||
				service.accessControlAllowOrigins[origin] {
				ctx.Response.Header.Set("Access-Control-Allow-Origin", origin)
				ctx.Response.Header.Set("Access-Control-Allow-Credentials", "true")
			}
		} else {
			ctx.Response.Header.Set("Access-Control-Allow-Origin", "*")
		}
	}
	return nil
}

// ServeFastHTTP is the hprose fasthttp handler method
func (service *FastHTTPService) ServeFastHTTP(ctx *fasthttp.RequestCtx) {
	if service.clientAccessPolicyXMLHandler(ctx) ||
		service.crossDomainXMLHandler(ctx) {
		return
	}
	context := NewFastHTTPContext(service, ctx)
	var resp []byte
	if err := service.sendHeader(context); err == nil {
		switch util.ByteString(ctx.Method()) {
		case "GET":
			if service.GET {
				resp = service.doFunctionList(context.ServiceContext)
			} else {
				ctx.SetStatusCode(403)
			}
		case "POST":
			resp = service.Handle(ctx.Request.Body(), context.ServiceContext)
		}
	} else {
		resp = service.endError(err, context.ServiceContext)
	}
	context.RequestCtx = nil
	ctx.Response.Header.Set("Content-Length", util.Itoa(len(resp)))
	ctx.SetBody(resp)
}
<commit_msg>Improved FastHTTPService<commit_after>/**********************************************************\
|                                                          |
|                          hprose                          |
|                                                          |
| Official WebSite: http://www.hprose.com/                 |
|                   http://www.hprose.org/                 |
|                                                          |
\**********************************************************/
/**********************************************************\
 *                                                        *
 * rpc/fasthttp_service.go                                *
 *                                                        *
 * hprose fasthttp service for Go.                        *
 *                                                        *
 * LastModified: Sep 27, 2016                             *
 * Author: Ma Bingyao <andot@hprose.com>                  *
 *                                                        *
\**********************************************************/

package rpc

import (
	"reflect"
	"strings"
	"unsafe"

	"github.com/hprose/hprose-golang/util"
	"github.com/valyala/fasthttp"
)

// FastHTTPContext is the hprose fasthttp context
type FastHTTPContext struct {
	*ServiceContext
	RequestCtx *fasthttp.RequestCtx
}

// NewFastHTTPContext is the constructor of FastHTTPContext
func NewFastHTTPContext(
	clients Clients, ctx *fasthttp.RequestCtx) (context *FastHTTPContext) {
	context = new(FastHTTPContext)
	context.ServiceContext = NewServiceContext(clients)
	context.ServiceContext.TransportContext = context
	context.RequestCtx = ctx
	return
}

// FastHTTPService is the hprose fasthttp service
type FastHTTPService struct {
	baseHTTPService
}

type fastSendHeaderEvent interface {
	OnSendHeader(context *FastHTTPContext)
}

type fastSendHeaderEvent2 interface {
	OnSendHeader(context *FastHTTPContext) error
}

func fasthttpFixArguments(args []reflect.Value, context *ServiceContext) {
	i := len(args) - 1
	switch args[i].Type() {
	case fasthttpContextType:
		if c, ok := context.TransportContext.(*FastHTTPContext); ok {
			args[i] = reflect.ValueOf(c)
		}
	case fasthttpRequestCtxType:
		if c, ok := context.TransportContext.(*FastHTTPContext); ok {
			args[i] = reflect.ValueOf(c.RequestCtx)
		}
	default:
		DefaultFixArguments(args, context)
	}
}

// NewFastHTTPService is the constructor of FastHTTPService
func NewFastHTTPService() (service *FastHTTPService) {
	service = (*FastHTTPService)(unsafe.Pointer(newBaseHTTPService()))
	service.FixArguments = fasthttpFixArguments
	return
}

func (service *FastHTTPService) xmlFileHandler(
	ctx *fasthttp.RequestCtx, path string, context []byte) bool {
	requestPath := util.ByteString(ctx.Path())
	if context == nil || strings.ToLower(requestPath) != path {
		return false
	}
	ifModifiedSince := util.ByteString(ctx.Request.Header.Peek("if-modified-since"))
	ifNoneMatch := util.ByteString(ctx.Request.Header.Peek("if-none-match"))
	if ifModifiedSince == service.lastModified && ifNoneMatch == service.etag {
		ctx.SetStatusCode(304)
	} else {
		contentLength := len(context)
		ctx.Response.Header.Set("Last-Modified", service.lastModified)
		ctx.Response.Header.Set("Etag", service.etag)
		ctx.Response.Header.SetContentType("text/xml")
		ctx.Response.Header.Set("Content-Length", util.Itoa(contentLength))
		ctx.SetBody(context)
	}
	return true
}

func (service *FastHTTPService) crossDomainXMLHandler(
	ctx *fasthttp.RequestCtx) bool {
	path := "/crossdomain.xml"
	context := service.crossDomainXMLContent
	return service.xmlFileHandler(ctx, path, context)
}

func (service *FastHTTPService) clientAccessPolicyXMLHandler(
	ctx *fasthttp.RequestCtx) bool {
	path := "/clientaccesspolicy.xml"
	context := service.clientAccessPolicyXMLContent
	return service.xmlFileHandler(ctx, path, context)
}

func (service *FastHTTPService) fireSendHeaderEvent(
	context *FastHTTPContext) (err error) {
	defer func() {
		if e := recover(); e != nil {
			err = NewPanicError(e)
		}
	}()
	switch event := service.Event.(type) {
	case fastSendHeaderEvent:
		event.OnSendHeader(context)
	case fastSendHeaderEvent2:
		err = event.OnSendHeader(context)
	}
	return err
}

func (service *FastHTTPService) sendHeader(
	context *FastHTTPContext) (err error) {
	if err = service.fireSendHeaderEvent(context); err != nil {
		return err
	}
	ctx := context.RequestCtx
	ctx.Response.Header.Set("Content-Type", "text/plain")
	if service.P3P {
		ctx.Response.Header.Set("P3P",
			`CP="CAO DSP COR CUR ADM DEV TAI PSA PSD IVAi IVDi `+
				`CONi TELo OTPi OUR DELi SAMi OTRi UNRi PUBi IND PHY ONL `+
				`UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE GOV"`)
	}
	if service.CrossDomain {
		origin := util.ByteString(ctx.Request.Header.Peek("origin"))
		if origin != "" && origin != "null" {
			if len(service.accessControlAllowOrigins) == 0 ||
				service.accessControlAllowOrigins[origin] {
				ctx.Response.Header.Set("Access-Control-Allow-Origin", origin)
				ctx.Response.Header.Set("Access-Control-Allow-Credentials", "true")
			}
		} else {
			ctx.Response.Header.Set("Access-Control-Allow-Origin", "*")
		}
	}
	return nil
}

// ServeFastHTTP is the hprose fasthttp handler method
func (service *FastHTTPService) ServeFastHTTP(ctx *fasthttp.RequestCtx) {
	if service.clientAccessPolicyXMLHandler(ctx) ||
		service.crossDomainXMLHandler(ctx) {
		return
	}
	context := NewFastHTTPContext(service, ctx)
	var resp []byte
	if err := service.sendHeader(context); err == nil {
		switch util.ByteString(ctx.Method()) {
		case "GET":
			if service.GET {
				resp = service.doFunctionList(context.ServiceContext)
			} else {
				ctx.SetStatusCode(403)
			}
		case "POST":
			resp = service.Handle(ctx.PostBody(), context.ServiceContext)
		}
	} else {
		resp = service.endError(err, context.ServiceContext)
	}
	context.RequestCtx = nil
	ctx.Response.Header.Set("Content-Length", util.Itoa(len(resp)))
	ctx.SetBody(resp)
}
<|endoftext|>


<commit_before>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"go/doc"
	"go/parser"
	"go/token"
	"log"
	"os"
	"path/filepath"
	"strings"
)

const MaxCommentLength = 500 // App Engine won't store more in a StringProperty.

func (b *Builder) buildPackages(workpath string, hash string) os.Error {
	pkgs, err := packages()
	if err != nil {
		return err
	}
	for _, p := range pkgs {
		goroot := filepath.Join(workpath, "go")
		gobin := filepath.Join(goroot, "bin")
		goinstall := filepath.Join(gobin, "goinstall")
		envv := append(b.envv(), "GOROOT="+goroot)

		// add GOBIN to path
		for i, v := range envv {
			if strings.HasPrefix(v, "PATH=") {
				p := filepath.SplitList(v[5:])
				p = append([]string{gobin}, p...)
				s := strings.Join(p, string(filepath.ListSeparator))
				envv[i] = "PATH=" + s
			}
		}

		// goinstall
		buildLog, code, err := runLog(envv, "", goroot, goinstall, "-log=false", p)
		if err != nil {
			log.Printf("goinstall %v: %v", p, err)
		}

		// get doc comment from package source
		info, err := packageComment(p, filepath.Join(goroot, "src", "pkg", p))
		if err != nil {
			log.Printf("packageComment %v: %v", p, err)
		}

		// update dashboard with build state + info
		err = b.updatePackage(p, code == 0, buildLog, info)
		if err != nil {
			log.Printf("updatePackage %v: %v", p, err)
		}
	}
	return nil
}

func isGoFile(fi *os.FileInfo) bool {
	return fi.IsRegular() && // exclude directories
		!strings.HasPrefix(fi.Name, ".") && // ignore .files
		filepath.Ext(fi.Name) == ".go"
}

func packageComment(pkg, pkgpath string) (info string, err os.Error) {
	fset := token.NewFileSet()
	pkgs, err := parser.ParseDir(fset, pkgpath, isGoFile, parser.PackageClauseOnly|parser.ParseComments)
	if err != nil {
		return
	}
	for name := range pkgs {
		if name == "main" {
			continue
		}
		if info != "" {
			return "", os.NewError("multiple non-main package docs")
		}
		pdoc := doc.NewPackageDoc(pkgs[name], pkg)
		info = pdoc.Doc
	}
	// grab only first paragraph
	if parts := strings.SplitN(info, "\n\n", 2); len(parts) > 1 {
		info = parts[0]
	}
	// replace newlines with spaces
	info = strings.Replace(info, "\n", " ", -1)
	// truncate
	if len(info) > MaxCommentLength {
		info = info[:MaxCommentLength]
	}
	return
}
<commit_msg>gobuilder: goinstall with -dashboard=false instead of -log=false<commit_after>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"go/doc"
	"go/parser"
	"go/token"
	"log"
	"os"
	"path/filepath"
	"strings"
)

const MaxCommentLength = 500 // App Engine won't store more in a StringProperty.

func (b *Builder) buildPackages(workpath string, hash string) os.Error {
	pkgs, err := packages()
	if err != nil {
		return err
	}
	for _, p := range pkgs {
		goroot := filepath.Join(workpath, "go")
		gobin := filepath.Join(goroot, "bin")
		goinstall := filepath.Join(gobin, "goinstall")
		envv := append(b.envv(), "GOROOT="+goroot)

		// add GOBIN to path
		for i, v := range envv {
			if strings.HasPrefix(v, "PATH=") {
				p := filepath.SplitList(v[5:])
				p = append([]string{gobin}, p...)
				s := strings.Join(p, string(filepath.ListSeparator))
				envv[i] = "PATH=" + s
			}
		}

		// goinstall
		buildLog, code, err := runLog(envv, "", goroot, goinstall, "-dashboard=false", p)
		if err != nil {
			log.Printf("goinstall %v: %v", p, err)
		}

		// get doc comment from package source
		info, err := packageComment(p, filepath.Join(goroot, "src", "pkg", p))
		if err != nil {
			log.Printf("packageComment %v: %v", p, err)
		}

		// update dashboard with build state + info
		err = b.updatePackage(p, code == 0, buildLog, info)
		if err != nil {
			log.Printf("updatePackage %v: %v", p, err)
		}
	}
	return nil
}

func isGoFile(fi *os.FileInfo) bool {
	return fi.IsRegular() && // exclude directories
		!strings.HasPrefix(fi.Name, ".") && // ignore .files
		filepath.Ext(fi.Name) == ".go"
}

func packageComment(pkg, pkgpath string) (info string, err os.Error) {
	fset := token.NewFileSet()
	pkgs, err := parser.ParseDir(fset, pkgpath, isGoFile, parser.PackageClauseOnly|parser.ParseComments)
	if err != nil {
		return
	}
	for name := range pkgs {
		if name == "main" {
			continue
		}
		if info != "" {
			return "", os.NewError("multiple non-main package docs")
		}
		pdoc := doc.NewPackageDoc(pkgs[name], pkg)
		info = pdoc.Doc
	}
	// grab only first paragraph
	if parts := strings.SplitN(info, "\n\n", 2); len(parts) > 1 {
		info = parts[0]
	}
	// replace newlines with spaces
	info = strings.Replace(info, "\n", " ", -1)
	// truncate
	if len(info) > MaxCommentLength {
		info = info[:MaxCommentLength]
	}
	return
}
<|endoftext|>


<commit_before>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"go/doc"
	"go/parser"
	"go/token"
	"log"
	"os"
	"path"
)

func (b *Builder) buildPackages(workpath string, hash string) os.Error {
	pkgs, err := packages()
	if err != nil {
		return err
	}
	for _, p := range pkgs {
		goroot := path.Join(workpath, "go")
		goinstall := path.Join(goroot, "bin", "goinstall")
		envv := append(b.envv(), "GOROOT="+goroot)

		// goinstall
		buildLog, code, err := runLog(envv, "", goroot, goinstall, p)
		if err != nil {
			log.Printf("goinstall %v: %v", p, err)
			continue
		}
		built := code != 0

		// get doc comment from package source
		info, err := packageComment(p, path.Join(goroot, "pkg", p))
		if err != nil {
			log.Printf("goinstall %v: %v", p, err)
		}

		// update dashboard with build state + info
		err = b.updatePackage(p, built, buildLog, info, hash)
		if err != nil {
			log.Printf("updatePackage %v: %v", p, err)
		}
	}
	return nil
}

func packageComment(pkg, pkgpath string) (info string, err os.Error) {
	fset := token.NewFileSet()
	pkgs, err := parser.ParseDir(fset, pkgpath, nil, parser.PackageClauseOnly|parser.ParseComments)
	if err != nil {
		return
	}
	for name := range pkgs {
		if name == "main" {
			continue
		}
		if info != "" {
			return "", os.NewError("multiple non-main package docs")
		}
		pdoc := doc.NewPackageDoc(pkgs[name], pkg)
		info = pdoc.Doc
	}
	return
}
<commit_msg>builder: minor fixes<commit_after>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"go/doc"
	"go/parser"
	"go/token"
	"log"
	"os"
	"path/filepath"
	"strings"
)

func (b *Builder) buildPackages(workpath string, hash string) os.Error {
	pkgs, err := packages()
	if err != nil {
		return err
	}
	for _, p := range pkgs {
		goroot := filepath.Join(workpath, "go")
		goinstall := filepath.Join(goroot, "bin", "goinstall")
		envv := append(b.envv(), "GOROOT="+goroot)

		// goinstall
		buildLog, code, err := runLog(envv, "", goroot, goinstall, p)
		if err != nil {
			log.Printf("goinstall %v: %v", p, err)
			continue
		}
		built := code == 0

		// get doc comment from package source
		info, err := packageComment(p, filepath.Join(goroot, "pkg", p))
		if err != nil {
			log.Printf("goinstall %v: %v", p, err)
		}

		// update dashboard with build state + info
		err = b.updatePackage(p, built, buildLog, info, hash)
		if err != nil {
			log.Printf("updatePackage %v: %v", p, err)
		}
	}
	return nil
}

func isGoFile(fi *os.FileInfo) bool {
	return fi.IsRegular() && // exclude directories
		!strings.HasPrefix(fi.Name, ".") && // ignore .files
		filepath.Ext(fi.Name) == ".go"
}

func packageComment(pkg, pkgpath string) (info string, err os.Error) {
	fset := token.NewFileSet()
	pkgs, err := parser.ParseDir(fset, pkgpath, isGoFile, parser.PackageClauseOnly|parser.ParseComments)
	if err != nil {
		return
	}
	for name := range pkgs {
		if name == "main" {
			continue
		}
		if info != "" {
			return "", os.NewError("multiple non-main package docs")
		}
		pdoc := doc.NewPackageDoc(pkgs[name], pkg)
		info = pdoc.Doc
	}
	return
}
<|endoftext|>


<commit_before>package version

const (
	Version = "0.1.1+git"
)
<commit_msg>bump(version): v0.1.2<commit_after>package version

const (
	Version = "0.1.2"
)
<|endoftext|>


<commit_before>package version

import (
	"bytes"
	"fmt"
)

// Version is the version of the app
const Version = "1.1.1"

// VersionPrerelease is the state of the app
const VersionPrerelease = "dev"

// FormattedVersion is used to format the full version of the app
func FormattedVersion() string {
	var versionString bytes.Buffer
	fmt.Fprintf(&versionString, "%s", Version)

	if VersionPrerelease != "" {
		fmt.Fprintf(&versionString, "-%s", VersionPrerelease)
	}

	return versionString.String()
}
<commit_msg>Prepare 1.2.0 release<commit_after>package version

import (
	"bytes"
	"fmt"
)

// Version is the version of the app
const Version = "1.2.0"

// VersionPrerelease is the state of the app
const VersionPrerelease = ""

// FormattedVersion is used to format the full version of the app
func FormattedVersion() string {
	var versionString bytes.Buffer
	fmt.Fprintf(&versionString, "%s", Version)

	if VersionPrerelease != "" {
		fmt.Fprintf(&versionString, "-%s", VersionPrerelease)
	}

	return versionString.String()
}
<|endoftext|>


<commit_before>package version

import (
	"bytes"
	"fmt"
)

// The git commit that was compiled. This will be filled in by the compiler.
var GitCommit string

// The main version number that is being run at the moment.
const Version = "0.12.1"

// A pre-release marker for the version. If this is "" (empty string)
// then it means that it is a final release. Otherwise, this is a pre-release
// such as "dev" (in development), "beta", "rc1", etc.
const VersionPrerelease = ""

func FormattedVersion() string {
	var versionString bytes.Buffer
	fmt.Fprintf(&versionString, "%s", Version)
	if VersionPrerelease != "" {
		fmt.Fprintf(&versionString, ".%s", VersionPrerelease)

		if GitCommit != "" {
			fmt.Fprintf(&versionString, " (%s)", GitCommit)
		}
	}

	return versionString.String()
}
<commit_msg>prep for next version<commit_after>package version

import (
	"bytes"
	"fmt"
)

// The git commit that was compiled. This will be filled in by the compiler.
var GitCommit string

// The main version number that is being run at the moment.
const Version = "0.12.2"

// A pre-release marker for the version. If this is "" (empty string)
// then it means that it is a final release. Otherwise, this is a pre-release
// such as "dev" (in development), "beta", "rc1", etc.
const VersionPrerelease = "dev"

func FormattedVersion() string {
	var versionString bytes.Buffer
	fmt.Fprintf(&versionString, "%s", Version)
	if VersionPrerelease != "" {
		fmt.Fprintf(&versionString, ".%s", VersionPrerelease)

		if GitCommit != "" {
			fmt.Fprintf(&versionString, " (%s)", GitCommit)
		}
	}

	return versionString.String()
}
<|endoftext|>


<commit_before>// +build darwin linux windows

package main

import (
	"log"
	"time"

	"golang.org/x/mobile/app"
	"golang.org/x/mobile/event/lifecycle"
	"golang.org/x/mobile/event/mouse"
	"golang.org/x/mobile/event/paint"
	"golang.org/x/mobile/event/size"
	"golang.org/x/mobile/event/touch"
	"golang.org/x/mobile/gl"
)

type gameState struct {
	width  int
	height int
	gl     gl.Context
}

func main() {
	log.Print("main begin")

	game := &gameState{}
	var frames int
	var paints int
	sec := time.Now().Second()
	slowPaint := true

	app.Main(func(a app.App) {
		log.Print("app.Main begin")

	LOOP:
		for e := range a.Events() {
			switch t := a.Filter(e).(type) {
			case lifecycle.Event:
				log.Printf("Lifecycle: %v", t)

				if t.From > t.To && t.To == lifecycle.StageDead {
					log.Printf("lifecycle down to dead")
					break LOOP
				}

				if t.Crosses(lifecycle.StageAlive) == lifecycle.CrossOff {
					log.Printf("lifecycle cross down alive")
					break LOOP
				}

				switch t.Crosses(lifecycle.StageVisible) {
				case lifecycle.CrossOn:
					glc, isGL := t.DrawContext.(gl.Context)
					if !isGL {
						log.Printf("Lifecycle: visible: bad GL context")
						continue LOOP
					}
					game.start(glc)
					a.Send(paint.Event{}) // start drawing
				case lifecycle.CrossOff:
					game.stop()
				}

			case paint.Event:
				if t.External || game.gl == nil {
					// As we are actively painting as fast as
					// we can (usually 60 FPS), skip any paint
					// events sent by the system.
					continue
				}

				paints++ // events

				if now := time.Now().Second(); now != sec {
					log.Printf("fps: %d, paints: %d", frames, paints)
					frames = 0
					paints = 0
					sec = now
				}

				if !slowPaint || frames == 0 {
					frames++ // draws
					game.paint()
					a.Publish()
				}

				if slowPaint {
					time.Sleep(500 * time.Millisecond)
				}

				// we request next paint event
				// in order to draw as fast as possible
				a.Send(paint.Event{})
			case mouse.Event:
				game.input(t.X, t.Y)
			case touch.Event:
				game.input(t.X, t.Y)
			case size.Event:
				game.resize(t.WidthPx, t.HeightPx)
			}
		}

		log.Print("app.Main end")
	})

	log.Print("main end")
}

func (game *gameState) resize(w, h int) {
	if game.width != w || game.height != h {
		log.Printf("resize: %d,%d", w, h)
	}
	game.width = w
	game.height = h
}

func (game *gameState) input(x, y float32) {
	log.Printf("input: %f,%f (%d x %d)", x, y, game.width, game.height)
}

func (game *gameState) start(glc gl.Context) {
	log.Printf("start")
	game.gl = glc
}

func (game *gameState) stop() {
	log.Printf("stop")
	game.gl = nil
}

func (game *gameState) paint() {
	//log.Printf("paint: call OpenGL here")
}
<commit_msg>Enable slow paint from command line.<commit_after>// +build darwin linux windows

package main

import (
	"log"
	"os"
	"time"

	"golang.org/x/mobile/app"
	"golang.org/x/mobile/event/lifecycle"
	"golang.org/x/mobile/event/mouse"
	"golang.org/x/mobile/event/paint"
	"golang.org/x/mobile/event/size"
	"golang.org/x/mobile/event/touch"
	"golang.org/x/mobile/gl"
)

type gameState struct {
	width  int
	height int
	gl     gl.Context
}

func main() {
	log.Print("main begin")

	slowPaint := len(os.Args) > 1
	log.Printf("slowPaint: %v", slowPaint)

	game := &gameState{}
	var frames int
	var paints int
	sec := time.Now().Second()

	app.Main(func(a app.App) {
		log.Print("app.Main begin")

	LOOP:
		for e := range a.Events() {
			switch t := a.Filter(e).(type) {
			case lifecycle.Event:
				log.Printf("Lifecycle: %v", t)

				if t.From > t.To && t.To == lifecycle.StageDead {
					log.Printf("lifecycle down to dead")
					break LOOP
				}

				if t.Crosses(lifecycle.StageAlive) == lifecycle.CrossOff {
					log.Printf("lifecycle cross down alive")
					break LOOP
				}

				switch t.Crosses(lifecycle.StageVisible) {
				case lifecycle.CrossOn:
					glc, isGL := t.DrawContext.(gl.Context)
					if !isGL {
						log.Printf("Lifecycle: visible: bad GL context")
						continue LOOP
					}
					game.start(glc)
					a.Send(paint.Event{}) // start drawing
				case lifecycle.CrossOff:
					game.stop()
				}

			case paint.Event:
				if t.External || game.gl == nil {
					// As we are actively painting as fast as
					// we can (usually 60 FPS), skip any paint
					// events sent by the system.
					continue
				}

				paints++ // events

				if now := time.Now().Second(); now != sec {
					log.Printf("fps: %d, paints: %d", frames, paints)
					frames = 0
					paints = 0
					sec = now
				}

				if !slowPaint || frames == 0 {
					frames++ // draws
					game.paint()
					a.Publish()
				}

				if slowPaint {
					time.Sleep(500 * time.Millisecond)
				}

				// we request next paint event
				// in order to draw as fast as possible
				a.Send(paint.Event{})
			case mouse.Event:
				game.input(t.X, t.Y)
			case touch.Event:
				game.input(t.X, t.Y)
			case size.Event:
				game.resize(t.WidthPx, t.HeightPx)
			}
		}

		log.Print("app.Main end")
	})

	log.Print("main end")
}

func (game *gameState) resize(w, h int) {
	if game.width != w || game.height != h {
		log.Printf("resize: %d,%d", w, h)
	}
	game.width = w
	game.height = h
}

func (game *gameState) input(x, y float32) {
	log.Printf("input: %f,%f (%d x %d)", x, y, game.width, game.height)
}

func (game *gameState) start(glc gl.Context) {
	log.Printf("start")
	game.gl = glc
}

func (game *gameState) stop() {
	log.Printf("stop")
	game.gl = nil
}

func (game *gameState) paint() {
	//log.Printf("paint: call OpenGL here")
}
<|endoftext|>


<commit_before>package telegraph

import "testing"

const (
	invalidAuthorURL = "lolwat"
	invalidPageURL   = "sukablyat'"
	invalidContent   = 42
)

var invalidAccount = &Account{}

func TestInvalidContentFormat(t *testing.T) {
	if _, err := ContentFormat(invalidContent); err != ErrInvalidDataType {
		t.Error()
	}
}

func TestInvalidCreateAccount(t *testing.T) {
	if _, err := CreateAccount(invalidAccount); err == nil {
		t.Error()
	}

	t.Run("invalidCreatePage", testInvalidCreatePage)
	t.Run("invalidEditAccountInfo", testInvalidEditAccountInfo)
	t.Run("invalidEditPage", testInvalidEditPage)
	t.Run("invalidGetAccountInfo", testInvalidGetAccountInfo)
	t.Run("invalidGetPageList", testInvalidGetPageList)
	t.Run("invalidRevokeAccessToken", testInvalidRevokeAccessToken)
}

func testInvalidCreatePage(t *testing.T) {
	if _, err := invalidAccount.CreatePage(&Page{
		AuthorURL: invalidAuthorURL,
	}, false); err == nil {
		t.Error()
	}
}

func testInvalidEditAccountInfo(t *testing.T) {
	if _, err := invalidAccount.EditAccountInfo(&Account{
		AuthorURL: invalidAuthorURL,
	}); err == nil {
		t.Error()
	}
}

func testInvalidEditPage(t *testing.T) {
	if _, err := invalidAccount.EditPage(&Page{
		AuthorURL: invalidAuthorURL,
	}, false); err == nil {
		t.Error()
	}
}

func testInvalidGetAccountInfo(t *testing.T) {
	if _, err := invalidAccount.GetAccountInfo(FieldShortName, FieldPageCount); err == nil {
		t.Error()
	}
}

func testInvalidGetPageList(t *testing.T) {
	if _, err := invalidAccount.GetPageList(0, 3); err == nil {
		t.Error()
	}
}

func testInvalidGetPageListByOffset(t *testing.T) {
	if _, err := invalidAccount.GetPageList(-42, 3); err == nil {
		t.Error()
	}
}

func testInvalidGetPageListByLimit(t *testing.T) {
	if _, err := invalidAccount.GetPageList(0, 9000); err == nil {
		t.Error()
	}
}

func TestInvalidGetPage(t *testing.T) {
	if _, err := GetPage(invalidPageURL, true); err == nil {
		t.Error()
	}
}

func TestInvalidGetViewsByPage(t *testing.T) {
	if _, err := GetViews(validPageURL, 2016, 12, 0, -1); err == nil {
		t.Error()
	}
}

func TestInvalidGetViewsByHour(t *testing.T) {
	if _, err := GetViews(validPageURL, 42, 0, 0, 0); err == nil {
		t.Error()
	}
}

func TestInvalidGetViewsByDay(t *testing.T) {
	if _, err := GetViews(validPageURL, 23, 42, 0, 0); err == nil {
		t.Error()
	}
}

func TestInvalidGetViewsByMonth(t *testing.T) {
	if _, err := GetViews(validPageURL, 23, 24, 22, 0); err == nil {
		t.Error()
	}
}

func TestInvalidGetViewsByYear(t *testing.T) {
	if _, err := GetViews(validPageURL, 23, 24, 12, 1980); err == nil {
		t.Error()
	}
}

func testInvalidRevokeAccessToken(t *testing.T) {
	if _, err := invalidAccount.RevokeAccessToken(); err == nil {
		t.Error()
	}
}
<commit_msg>:white_check_mark: Added unused invalid tests<commit_after>package telegraph

import "testing"

const (
	invalidAuthorURL = "lolwat"
	invalidPageURL   = "sukablyat'"
	invalidContent   = 42
)

var invalidAccount = &Account{}

func TestInvalidContentFormat(t *testing.T) {
	if _, err := ContentFormat(invalidContent); err != ErrInvalidDataType {
		t.Error()
	}
}

func TestInvalidCreateAccount(t *testing.T) {
	if _, err := CreateAccount(invalidAccount); err == nil {
		t.Error()
	}

	t.Run("invalidCreatePage", testInvalidCreatePage)
	t.Run("invalidEditAccountInfo", testInvalidEditAccountInfo)
	t.Run("invalidEditPage", testInvalidEditPage)
	t.Run("invalidGetAccountInfo", testInvalidGetAccountInfo)
	t.Run("invalidGetPageList", testInvalidGetPageList)
	t.Run("invalidGetPageListByLimit", testInvalidGetPageListByLimit)
	t.Run("invalidGetPageListByOffset", testInvalidGetPageListByOffset)
	t.Run("invalidRevokeAccessToken", testInvalidRevokeAccessToken)
}

func testInvalidCreatePage(t *testing.T) {
	if _, err := invalidAccount.CreatePage(&Page{
		AuthorURL: invalidAuthorURL,
	}, false); err == nil {
		t.Error()
	}
}

func testInvalidEditAccountInfo(t *testing.T) {
	if _, err := invalidAccount.EditAccountInfo(&Account{
		AuthorURL: invalidAuthorURL,
	}); err == nil {
		t.Error()
	}
}

func testInvalidEditPage(t *testing.T) {
	if _, err := invalidAccount.EditPage(&Page{
		AuthorURL: invalidAuthorURL,
	}, false); err == nil {
		t.Error()
	}
}

func testInvalidGetAccountInfo(t *testing.T) {
	if _, err := invalidAccount.GetAccountInfo(FieldShortName, FieldPageCount); err == nil {
		t.Error()
	}
}

func testInvalidGetPageList(t *testing.T) {
	if _, err := invalidAccount.GetPageList(0, 3); err == nil {
		t.Error()
	}
}

func testInvalidGetPageListByOffset(t *testing.T) {
	if _, err := invalidAccount.GetPageList(-42, 3); err == nil {
		t.Error()
	}
}

func testInvalidGetPageListByLimit(t *testing.T) {
	if _, err := invalidAccount.GetPageList(0, 9000); err == nil {
		t.Error()
	}
}

func TestInvalidGetPage(t *testing.T) {
	if _, err := GetPage(invalidPageURL, true); err == nil {
		t.Error()
	}
}

func TestInvalidGetViewsByPage(t *testing.T) {
	if _, err := GetViews(validPageURL, 2016, 12, 0, -1); err == nil {
		t.Error()
	}
}

func TestInvalidGetViewsByHour(t *testing.T) {
	if _, err := GetViews(validPageURL, 42, 0, 0, 0); err == nil {
		t.Error()
	}
}

func TestInvalidGetViewsByDay(t *testing.T) {
	if _, err := GetViews(validPageURL, 23, 42, 0, 0); err == nil {
		t.Error()
	}
}

func TestInvalidGetViewsByMonth(t *testing.T) {
	if _, err := GetViews(validPageURL, 23, 24, 22, 0); err == nil {
		t.Error()
	}
}

func TestInvalidGetViewsByYear(t *testing.T) {
	if _, err := GetViews(validPageURL, 23, 24, 12, 1980); err == nil {
		t.Error()
	}
}

func testInvalidRevokeAccessToken(t *testing.T) {
	if _, err := invalidAccount.RevokeAccessToken(); err == nil {
		t.Error()
	}
}
<|endoftext|>