<commit_before>package aws

import (
	"fmt"
	"testing"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/hashicorp/terraform/helper/acctest"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func TestAccAWSAMICopy_basic(t *testing.T) {
	var image ec2.Image
	resourceName := "aws_ami_copy.test"

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSAMICopyDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSAMICopyConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSAMICopyExists(resourceName, &image),
					testAccCheckAWSAMICopyAttributes(&image),
				),
			},
		},
	})
}

func TestAccAWSAMICopy_EnaSupport(t *testing.T) {
	var image ec2.Image
	rName := acctest.RandomWithPrefix("tf-acc-test")
	resourceName := "aws_ami_copy.test"

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSAMICopyDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSAMICopyConfig_ENASupport(rName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSAMICopyExists(resourceName, &image),
					resource.TestCheckResourceAttr(resourceName, "ena_support", "true"),
				),
			},
		},
	})
}

func testAccCheckAWSAMICopyExists(resourceName string, image *ec2.Image) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[resourceName]
		if !ok {
			return fmt.Errorf("Not found: %s", resourceName)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No ID set for %s", resourceName)
		}

		conn := testAccProvider.Meta().(*AWSClient).ec2conn

		input := &ec2.DescribeImagesInput{
			ImageIds: []*string{aws.String(rs.Primary.ID)},
		}
		output, err := conn.DescribeImages(input)
		if err != nil {
			return err
		}

		if len(output.Images) == 0 || aws.StringValue(output.Images[0].ImageId) != rs.Primary.ID {
			return fmt.Errorf("AMI %q not found", rs.Primary.ID)
		}

		*image = *output.Images[0]

		return nil
	}
}

func testAccCheckAWSAMICopyDestroy(s *terraform.State) error {
	conn := testAccProvider.Meta().(*AWSClient).ec2conn

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "aws_ami_copy" {
			continue
		}

		input := &ec2.DescribeImagesInput{
			ImageIds: []*string{aws.String(rs.Primary.ID)},
		}
		output, err := conn.DescribeImages(input)
		if err != nil {
			return err
		}

		if output != nil && len(output.Images) > 0 && aws.StringValue(output.Images[0].ImageId) == rs.Primary.ID {
			return fmt.Errorf("AMI %q still exists in state: %s", rs.Primary.ID, aws.StringValue(output.Images[0].State))
		}
	}

	// Check for managed EBS snapshots
	return testAccCheckAWSEbsSnapshotDestroy(s)
}

func testAccCheckAWSAMICopyAttributes(image *ec2.Image) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		if expected := "available"; aws.StringValue(image.State) != expected {
			return fmt.Errorf("invalid image state; expected %s, got %s", expected, aws.StringValue(image.State))
		}
		if expected := "machine"; aws.StringValue(image.ImageType) != expected {
			return fmt.Errorf("wrong image type; expected %s, got %s", expected, aws.StringValue(image.ImageType))
		}
		if expected := "terraform-acc-ami-copy"; aws.StringValue(image.Name) != expected {
			return fmt.Errorf("wrong name; expected %s, got %s", expected, aws.StringValue(image.Name))
		}

		snapshots := []string{}
		for _, bdm := range image.BlockDeviceMappings {
			// The snapshot ID might not be set,
			// even for a block device that is an
			// EBS volume.
			if bdm.Ebs != nil && bdm.Ebs.SnapshotId != nil {
				snapshots = append(snapshots, aws.StringValue(bdm.Ebs.SnapshotId))
			}
		}

		if expected := 1; len(snapshots) != expected {
			return fmt.Errorf("wrong number of snapshots; expected %v, got %v", expected, len(snapshots))
		}

		return nil
	}
}

var testAccAWSAMICopyConfig = `
provider "aws" {
	region = "us-east-1"
}

// An AMI can't be directly copied from one account to another, and
// we can't rely on any particular AMI being available since anyone
// can run this test in whatever account they like.
// Therefore we jump through some hoops here:
//  - Spin up an EC2 instance based on a public AMI
//  - Create an AMI by snapshotting that EC2 instance, using
//    aws_ami_from_instance .
//  - Copy the new AMI using aws_ami_copy .
//
// Thus this test can only succeed if the aws_ami_from_instance resource
// is working. If it's misbehaving it will likely cause this test to fail too.

// Since we're booting a t2.micro HVM instance we need a VPC for it to boot
// up into.

resource "aws_vpc" "foo" {
	cidr_block = "10.1.0.0/16"
	tags = {
		Name = "terraform-testacc-ami-copy"
	}
}

resource "aws_subnet" "foo" {
	cidr_block = "10.1.1.0/24"
	vpc_id = "${aws_vpc.foo.id}"
	tags = {
		Name = "tf-acc-ami-copy"
	}
}

resource "aws_instance" "test" {
    // This AMI has one block device mapping, so we expect to have
    // one snapshot in our created AMI.
    // This is an Ubuntu Linux HVM AMI. A public HVM AMI is required
    // because paravirtual images cannot be copied between accounts.
    ami = "ami-0f8bce65"
    instance_type = "t2.micro"
  tags = {
        Name = "terraform-acc-ami-copy-victim"
    }

    subnet_id = "${aws_subnet.foo.id}"
}

resource "aws_ami_from_instance" "test" {
    name = "terraform-acc-ami-copy-victim"
    description = "Testing Terraform aws_ami_from_instance resource"
    source_instance_id = "${aws_instance.test.id}"
}

resource "aws_ami_copy" "test" {
    name = "terraform-acc-ami-copy"
    description = "Testing Terraform aws_ami_copy resource"
    source_ami_id = "${aws_ami_from_instance.test.id}"
    source_ami_region = "us-east-1"
}
`

func testAccAWSAMICopyConfig_ENASupport(rName string) string {
	return fmt.Sprintf(`
data "aws_availability_zones" "available" {}
data "aws_region" "current" {}

resource "aws_ebs_volume" "test" {
  availability_zone = "${data.aws_availability_zones.available.names[0]}"
  size              = 1

  tags = {
    Name = %q
  }
}

resource "aws_ebs_snapshot" "test" {
  volume_id = "${aws_ebs_volume.test.id}"

  tags = {
    Name = %q
  }
}

resource "aws_ami" "test" {
  ena_support         = true
  name                = "%s-source"
  virtualization_type = "hvm"
  root_device_name    = "/dev/sda1"

  ebs_block_device {
    device_name = "/dev/sda1"
    snapshot_id = "${aws_ebs_snapshot.test.id}"
  }
}

resource "aws_ami_copy" "test" {
    name              = "%s-copy"
    source_ami_id     = "${aws_ami.test.id}"
    source_ami_region = "${data.aws_region.current.name}"
}
`, rName, rName, rName, rName)
}
<commit_msg>tests/resource/aws_ami_copy: Simplify basic test and add description test<commit_after>package aws

import (
	"fmt"
	"testing"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/hashicorp/terraform/helper/acctest"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func TestAccAWSAMICopy_basic(t *testing.T) {
	var image ec2.Image
	rName := acctest.RandomWithPrefix("tf-acc-test")
	resourceName := "aws_ami_copy.test"

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSAMICopyDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSAMICopyConfig(rName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSAMICopyExists(resourceName, &image),
					testAccCheckAWSAMICopyAttributes(&image, rName),
				),
			},
		},
	})
}

func TestAccAWSAMICopy_Description(t *testing.T) {
	var image ec2.Image
	rName := acctest.RandomWithPrefix("tf-acc-test")
	resourceName := "aws_ami_copy.test"

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSAMICopyDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSAMICopyConfigDescription(rName, "description1"),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSAMICopyExists(resourceName, &image),
					resource.TestCheckResourceAttr(resourceName, "description", "description1"),
				),
			},
			{
				Config: testAccAWSAMICopyConfigDescription(rName, "description2"),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSAMICopyExists(resourceName, &image),
					resource.TestCheckResourceAttr(resourceName, "description", "description2"),
				),
			},
		},
	})
}

func TestAccAWSAMICopy_EnaSupport(t *testing.T) {
	var image ec2.Image
	rName := acctest.RandomWithPrefix("tf-acc-test")
	resourceName := "aws_ami_copy.test"

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSAMICopyDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSAMICopyConfigENASupport(rName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSAMICopyExists(resourceName, &image),
					resource.TestCheckResourceAttr(resourceName, "ena_support", "true"),
				),
			},
		},
	})
}

func testAccCheckAWSAMICopyExists(resourceName string, image *ec2.Image) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[resourceName]
		if !ok {
			return fmt.Errorf("Not found: %s", resourceName)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No ID set for %s", resourceName)
		}

		conn := testAccProvider.Meta().(*AWSClient).ec2conn

		input := &ec2.DescribeImagesInput{
			ImageIds: []*string{aws.String(rs.Primary.ID)},
		}
		output, err := conn.DescribeImages(input)
		if err != nil {
			return err
		}

		if len(output.Images) == 0 || aws.StringValue(output.Images[0].ImageId) != rs.Primary.ID {
			return fmt.Errorf("AMI %q not found", rs.Primary.ID)
		}

		*image = *output.Images[0]

		return nil
	}
}

func testAccCheckAWSAMICopyDestroy(s *terraform.State) error {
	conn := testAccProvider.Meta().(*AWSClient).ec2conn

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "aws_ami_copy" {
			continue
		}

		input := &ec2.DescribeImagesInput{
			ImageIds: []*string{aws.String(rs.Primary.ID)},
		}
		output, err := conn.DescribeImages(input)
		if err != nil {
			return err
		}

		if output != nil && len(output.Images) > 0 && aws.StringValue(output.Images[0].ImageId) == rs.Primary.ID {
			return fmt.Errorf("AMI %q still exists in state: %s", rs.Primary.ID, aws.StringValue(output.Images[0].State))
		}
	}

	// Check for managed EBS snapshots
	return testAccCheckAWSEbsSnapshotDestroy(s)
}

func testAccCheckAWSAMICopyAttributes(image *ec2.Image, expectedName string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		if expected := "available"; aws.StringValue(image.State) != expected {
			return fmt.Errorf("invalid image state; expected %s, got %s", expected, aws.StringValue(image.State))
		}
		if expected := "machine"; aws.StringValue(image.ImageType) != expected {
			return fmt.Errorf("wrong image type; expected %s, got %s", expected, aws.StringValue(image.ImageType))
		}
		if expected := expectedName; aws.StringValue(image.Name) != expected {
			return fmt.Errorf("wrong name; expected %s, got %s", expected, aws.StringValue(image.Name))
		}

		snapshots := []string{}
		for _, bdm := range image.BlockDeviceMappings {
			// The snapshot ID might not be set,
			// even for a block device that is an
			// EBS volume.
			if bdm.Ebs != nil && bdm.Ebs.SnapshotId != nil {
				snapshots = append(snapshots, aws.StringValue(bdm.Ebs.SnapshotId))
			}
		}

		if expected := 1; len(snapshots) != expected {
			return fmt.Errorf("wrong number of snapshots; expected %v, got %v", expected, len(snapshots))
		}

		return nil
	}
}

func testAccAWSAMICopyConfigBase() string {
	return fmt.Sprintf(`
data "aws_availability_zones" "available" {}
data "aws_region" "current" {}

resource "aws_ebs_volume" "test" {
  availability_zone = "${data.aws_availability_zones.available.names[0]}"
  size              = 1

  tags = {
    Name = "tf-acc-test-ami-copy"
  }
}

resource "aws_ebs_snapshot" "test" {
  volume_id = "${aws_ebs_volume.test.id}"

  tags = {
    Name = "tf-acc-test-ami-copy"
  }
}
`)
}

func testAccAWSAMICopyConfig(rName string) string {
	return testAccAWSAMICopyConfigBase() + fmt.Sprintf(`
resource "aws_ami" "test" {
  name                = "%s-source"
  virtualization_type = "hvm"
  root_device_name    = "/dev/sda1"

  ebs_block_device {
    device_name = "/dev/sda1"
    snapshot_id = "${aws_ebs_snapshot.test.id}"
  }
}

resource "aws_ami_copy" "test" {
  name              = %q
  source_ami_id     = "${aws_ami.test.id}"
  source_ami_region = "${data.aws_region.current.name}"
}
`, rName, rName)
}

func testAccAWSAMICopyConfigDescription(rName, description string) string {
	return testAccAWSAMICopyConfigBase() + fmt.Sprintf(`
resource "aws_ami" "test" {
  name                = "%s-source"
  virtualization_type = "hvm"
  root_device_name    = "/dev/sda1"

  ebs_block_device {
    device_name = "/dev/sda1"
    snapshot_id = "${aws_ebs_snapshot.test.id}"
  }
}

resource "aws_ami_copy" "test" {
  description       = %q
  name              = %q
  source_ami_id     = "${aws_ami.test.id}"
  source_ami_region = "${data.aws_region.current.name}"
}
`, rName, description, rName)
}

func testAccAWSAMICopyConfigENASupport(rName string) string {
	return testAccAWSAMICopyConfigBase() + fmt.Sprintf(`
resource "aws_ami" "test" {
  ena_support         = true
  name                = "%s-source"
  virtualization_type = "hvm"
  root_device_name    = "/dev/sda1"

  ebs_block_device {
    device_name = "/dev/sda1"
    snapshot_id = "${aws_ebs_snapshot.test.id}"
  }
}

resource "aws_ami_copy" "test" {
    name              = "%s-copy"
    source_ami_id     = "${aws_ami.test.id}"
    source_ami_region = "${data.aws_region.current.name}"
}
`, rName, rName)
}
<|endoftext|>


<commit_before>/*
Copyright 2018 The Kubernetes Authors.

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

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

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

package common

import (
	"context"
	"fmt"
	"sync"
	"time"

	goerrors "github.com/go-errors/errors"
	rbacv1 "k8s.io/api/rbac/v1"
	apierrs "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	clientset "k8s.io/client-go/kubernetes"
	"k8s.io/klog"
	"k8s.io/perf-tests/clusterloader2/pkg/framework/client"
	"k8s.io/perf-tests/clusterloader2/pkg/measurement"
	measurementutil "k8s.io/perf-tests/clusterloader2/pkg/measurement/util"
	"k8s.io/perf-tests/clusterloader2/pkg/provider"
	"k8s.io/perf-tests/clusterloader2/pkg/util"
)

const (
	cpuProfileName    = "CPUProfile"
	memoryProfileName = "MemoryProfile"
	mutexProfileName  = "MutexProfile"
)

func init() {
	if err := measurement.Register(cpuProfileName, createProfileMeasurementFactory(cpuProfileName, "profile")); err != nil {
		klog.Fatalf("Cannot register %s: %v", cpuProfileName, err)
	}
	if err := measurement.Register(memoryProfileName, createProfileMeasurementFactory(memoryProfileName, "heap")); err != nil {
		klog.Fatalf("Cannot register %s: %v", memoryProfileName, err)
	}
	if err := measurement.Register(mutexProfileName, createProfileMeasurementFactory(mutexProfileName, "mutex")); err != nil {
		klog.Fatalf("Cannot register %s: %v", mutexProfileName, err)
	}
}

type profileConfig struct {
	componentName string
	provider      provider.Provider
	hosts         []string
	kind          string
}

func (p *profileMeasurement) populateProfileConfig(config *measurement.Config) error {
	var err error
	if p.config.componentName, err = util.GetString(config.Params, "componentName"); err != nil {
		return err
	}
	p.config.provider = config.ClusterFramework.GetClusterConfig().Provider
	p.config.hosts = config.ClusterFramework.GetClusterConfig().MasterIPs
	return nil
}

type profileMeasurement struct {
	name      string
	config    *profileConfig
	summaries []measurement.Summary
	isRunning bool
	stopCh    chan struct{}
	wg        sync.WaitGroup
}

func createProfileMeasurementFactory(name, kind string) func() measurement.Measurement {
	return func() measurement.Measurement {
		return &profileMeasurement{
			name:   name,
			config: &profileConfig{kind: kind},
		}
	}
}

func (p *profileMeasurement) start(config *measurement.Config, SSHToMasterSupported bool) error {
	if err := p.populateProfileConfig(config); err != nil {
		return err
	}
	if len(p.config.hosts) < 1 {
		klog.Warning("Profile measurements will be disabled due to no MasterIps")
		return nil
	}
	k8sClient := config.ClusterFramework.GetClientSets().GetClient()
	if p.shouldExposeAPIServerDebugEndpoint() {
		if err := exposeAPIServerDebugEndpoint(k8sClient); err != nil {
			klog.Warningf("error while exposing kube-apiserver /debug endpoint: %v", err)
		}
	}

	p.summaries = make([]measurement.Summary, 0)
	p.isRunning = true
	p.stopCh = make(chan struct{})
	p.wg.Add(1)

	// Currently length of the test is proportional to the cluster size.
	// So for now we make the profiling frequency proportional to the cluster size.
	// We may want to revisit ot adjust it in the future.
	numNodes := config.ClusterFramework.GetClusterConfig().Nodes
	profileFrequency := time.Duration(5+numNodes/250) * time.Minute
	go func() {
		defer p.wg.Done()
		for {
			select {
			case <-p.stopCh:
				return
			case <-time.After(profileFrequency):
				profileSummaries, err := p.gatherProfile(k8sClient, SSHToMasterSupported, config)
				if err != nil {
					klog.Errorf("failed to gather profile for %#v: %v", *p.config, err)
					continue
				}
				if profileSummaries != nil {
					p.summaries = append(p.summaries, profileSummaries...)
				}
			}
		}
	}()
	return nil
}

func (p *profileMeasurement) stop() {
	if !p.isRunning {
		return
	}
	close(p.stopCh)
	p.wg.Wait()
}

// Execute gathers memory profile of a given component.
func (p *profileMeasurement) Execute(config *measurement.Config) ([]measurement.Summary, error) {
	provider := config.ClusterFramework.GetClusterConfig().Provider
	SSHToMasterSupported := provider.Features().SupportSSHToMaster
	APIServerPprofEnabled := config.ClusterFramework.GetClusterConfig().APIServerPprofByClientEnabled

	if !SSHToMasterSupported && APIServerPprofEnabled {
		klog.Warningf("fetching profile data from is not possible from provider: %s", provider.Name())
		return nil, nil
	}

	action, err := util.GetString(config.Params, "action")
	if err != nil {
		return nil, err
	}

	switch action {
	case "start":
		if p.isRunning {
			klog.V(2).Infof("%s: measurement already running", p)
			return nil, nil
		}
		return nil, p.start(config, SSHToMasterSupported)
	case "gather":
		p.stop()
		return p.summaries, nil
	default:
		return nil, fmt.Errorf("unknown action %v", action)
	}
}

// Dispose cleans up after the measurement.
func (*profileMeasurement) Dispose() {}

// String returns string representation of this measurement.
func (p *profileMeasurement) String() string {
	return p.name
}

func (p *profileMeasurement) gatherProfile(c clientset.Interface, SSHToMasterSupported bool, config *measurement.Config) ([]measurement.Summary, error) {
	getCommand, err := p.getProfileCommand(config)
	if err != nil {
		return nil, goerrors.Errorf("profile gathering failed during retrieving profile command: %v", err)
	}

	var summaries []measurement.Summary
	for _, host := range p.config.hosts {
		profilePrefix := fmt.Sprintf("%s_%s_%s", host, p.config.componentName, p.name)

		// Get the profile data over SSH.
		// Start by checking that the provider allows us to do so.
		if !SSHToMasterSupported {
			// SSH to master for this provider is not possible.
			// For kube-apiserver, we can still fetch the profile using a RESTClient and pprof.
			// TODO(#246): This will connect to a random master in HA (multi-master) clusters, fix it.
			if p.config.componentName == "kube-apiserver" {
				body, err := c.CoreV1().RESTClient().Get().AbsPath("/debug/pprof/" + p.config.kind).DoRaw(context.TODO())
				if err != nil {
					return nil, err
				}
				summary := measurement.CreateSummary(profilePrefix, "pprof", string(body))
				summaries = append(summaries, summary)
				break
			}
			// Only logging error for gke. SSHing to gke master is not supported.
			klog.Warningf("%s: failed to execute curl command on master through SSH", p.name)
			return nil, nil
		}

		sshResult, err := measurementutil.SSH(getCommand, host+":22", p.config.provider)
		if err != nil {
			return nil, fmt.Errorf("failed to execute curl command on master node %s through SSH: %v", host, err)
		}
		summaries = append(summaries, measurement.CreateSummary(profilePrefix, "pprof", sshResult.Stdout))
	}

	return summaries, nil
}

func (p *profileMeasurement) shouldExposeAPIServerDebugEndpoint() bool {
	return p.config.componentName == "kube-apiserver"
}

func (p *profileMeasurement) getProfileCommand(config *measurement.Config) (string, error) {
	profileProtocol, profilePort, err := config.ClusterFramework.GetClusterConfig().Provider.GetComponentProtocolAndPort(p.config.componentName)
	if err != nil {
		return "", goerrors.Errorf("get profile command failed finding component protocol/port: %v", err)
	}

	var command string
	if p.config.componentName == "etcd" {
		etcdCert := config.ClusterFramework.GetClusterConfig().EtcdCertificatePath
		etcdKey := config.ClusterFramework.GetClusterConfig().EtcdKeyPath
		command = fmt.Sprintf("curl -s -k --cert %s --key %s %slocalhost:%v/debug/pprof/%s", etcdCert, etcdKey, profileProtocol, profilePort, p.config.kind)
	} else {
		command = fmt.Sprintf("curl -s -k %slocalhost:%v/debug/pprof/%s", profileProtocol, profilePort, p.config.kind)
	}

	return command, nil
}

func exposeAPIServerDebugEndpoint(c clientset.Interface) error {
	klog.V(2).Info("Exposing kube-apiserver debug endpoint for anonymous access")
	createClusterRole := func() error {
		_, err := c.RbacV1().ClusterRoles().Create(context.TODO(), &rbacv1.ClusterRole{
			ObjectMeta: metav1.ObjectMeta{Name: "apiserver-debug-viewer"},
			Rules: []rbacv1.PolicyRule{
				{Verbs: []string{"get"}, NonResourceURLs: []string{"/debug/*"}},
			},
		}, metav1.CreateOptions{})
		return err
	}
	createClusterRoleBinding := func() error {
		_, err := c.RbacV1().ClusterRoleBindings().Create(context.TODO(), &rbacv1.ClusterRoleBinding{
			ObjectMeta: metav1.ObjectMeta{Name: "anonymous:apiserver-debug-viewer"},
			RoleRef:    rbacv1.RoleRef{Kind: "ClusterRole", Name: "apiserver-debug-viewer"},
			Subjects: []rbacv1.Subject{
				{Kind: "User", Name: "system:anonymous"},
			},
		}, metav1.CreateOptions{})
		return err
	}
	if err := retryCreateFunction(createClusterRole); err != nil {
		return err
	}
	if err := retryCreateFunction(createClusterRoleBinding); err != nil {
		return err
	}
	return nil
}

func retryCreateFunction(f func() error) error {
	return client.RetryWithExponentialBackOff(
		client.RetryFunction(f, client.Allow(apierrs.IsAlreadyExists)))
}
<commit_msg>Change profile frequency to 5m<commit_after>/*
Copyright 2018 The Kubernetes Authors.

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

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

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

package common

import (
	"context"
	"fmt"
	"sync"
	"time"

	goerrors "github.com/go-errors/errors"
	rbacv1 "k8s.io/api/rbac/v1"
	apierrs "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	clientset "k8s.io/client-go/kubernetes"
	"k8s.io/klog"
	"k8s.io/perf-tests/clusterloader2/pkg/framework/client"
	"k8s.io/perf-tests/clusterloader2/pkg/measurement"
	measurementutil "k8s.io/perf-tests/clusterloader2/pkg/measurement/util"
	"k8s.io/perf-tests/clusterloader2/pkg/provider"
	"k8s.io/perf-tests/clusterloader2/pkg/util"
)

const (
	cpuProfileName    = "CPUProfile"
	memoryProfileName = "MemoryProfile"
	mutexProfileName  = "MutexProfile"
)

func init() {
	if err := measurement.Register(cpuProfileName, createProfileMeasurementFactory(cpuProfileName, "profile")); err != nil {
		klog.Fatalf("Cannot register %s: %v", cpuProfileName, err)
	}
	if err := measurement.Register(memoryProfileName, createProfileMeasurementFactory(memoryProfileName, "heap")); err != nil {
		klog.Fatalf("Cannot register %s: %v", memoryProfileName, err)
	}
	if err := measurement.Register(mutexProfileName, createProfileMeasurementFactory(mutexProfileName, "mutex")); err != nil {
		klog.Fatalf("Cannot register %s: %v", mutexProfileName, err)
	}
}

type profileConfig struct {
	componentName string
	provider      provider.Provider
	hosts         []string
	kind          string
}

func (p *profileMeasurement) populateProfileConfig(config *measurement.Config) error {
	var err error
	if p.config.componentName, err = util.GetString(config.Params, "componentName"); err != nil {
		return err
	}
	p.config.provider = config.ClusterFramework.GetClusterConfig().Provider
	p.config.hosts = config.ClusterFramework.GetClusterConfig().MasterIPs
	return nil
}

type profileMeasurement struct {
	name      string
	config    *profileConfig
	summaries []measurement.Summary
	isRunning bool
	stopCh    chan struct{}
	wg        sync.WaitGroup
}

func createProfileMeasurementFactory(name, kind string) func() measurement.Measurement {
	return func() measurement.Measurement {
		return &profileMeasurement{
			name:   name,
			config: &profileConfig{kind: kind},
		}
	}
}

func (p *profileMeasurement) start(config *measurement.Config, SSHToMasterSupported bool) error {
	if err := p.populateProfileConfig(config); err != nil {
		return err
	}
	if len(p.config.hosts) < 1 {
		klog.Warning("Profile measurements will be disabled due to no MasterIps")
		return nil
	}
	k8sClient := config.ClusterFramework.GetClientSets().GetClient()
	if p.shouldExposeAPIServerDebugEndpoint() {
		if err := exposeAPIServerDebugEndpoint(k8sClient); err != nil {
			klog.Warningf("error while exposing kube-apiserver /debug endpoint: %v", err)
		}
	}

	p.summaries = make([]measurement.Summary, 0)
	p.isRunning = true
	p.stopCh = make(chan struct{})
	p.wg.Add(1)

	profileFrequency := 5 * time.Minute
	go func() {
		defer p.wg.Done()
		for {
			select {
			case <-p.stopCh:
				return
			case <-time.After(profileFrequency):
				profileSummaries, err := p.gatherProfile(k8sClient, SSHToMasterSupported, config)
				if err != nil {
					klog.Errorf("failed to gather profile for %#v: %v", *p.config, err)
					continue
				}
				if profileSummaries != nil {
					p.summaries = append(p.summaries, profileSummaries...)
				}
			}
		}
	}()
	return nil
}

func (p *profileMeasurement) stop() {
	if !p.isRunning {
		return
	}
	close(p.stopCh)
	p.wg.Wait()
}

// Execute gathers memory profile of a given component.
func (p *profileMeasurement) Execute(config *measurement.Config) ([]measurement.Summary, error) {
	provider := config.ClusterFramework.GetClusterConfig().Provider
	SSHToMasterSupported := provider.Features().SupportSSHToMaster
	APIServerPprofEnabled := config.ClusterFramework.GetClusterConfig().APIServerPprofByClientEnabled

	if !SSHToMasterSupported && APIServerPprofEnabled {
		klog.Warningf("fetching profile data from is not possible from provider: %s", provider.Name())
		return nil, nil
	}

	action, err := util.GetString(config.Params, "action")
	if err != nil {
		return nil, err
	}

	switch action {
	case "start":
		if p.isRunning {
			klog.V(2).Infof("%s: measurement already running", p)
			return nil, nil
		}
		return nil, p.start(config, SSHToMasterSupported)
	case "gather":
		p.stop()
		return p.summaries, nil
	default:
		return nil, fmt.Errorf("unknown action %v", action)
	}
}

// Dispose cleans up after the measurement.
func (*profileMeasurement) Dispose() {}

// String returns string representation of this measurement.
func (p *profileMeasurement) String() string {
	return p.name
}

func (p *profileMeasurement) gatherProfile(c clientset.Interface, SSHToMasterSupported bool, config *measurement.Config) ([]measurement.Summary, error) {
	getCommand, err := p.getProfileCommand(config)
	if err != nil {
		return nil, goerrors.Errorf("profile gathering failed during retrieving profile command: %v", err)
	}

	var summaries []measurement.Summary
	for _, host := range p.config.hosts {
		profilePrefix := fmt.Sprintf("%s_%s_%s", host, p.config.componentName, p.name)

		// Get the profile data over SSH.
		// Start by checking that the provider allows us to do so.
		if !SSHToMasterSupported {
			// SSH to master for this provider is not possible.
			// For kube-apiserver, we can still fetch the profile using a RESTClient and pprof.
			// TODO(#246): This will connect to a random master in HA (multi-master) clusters, fix it.
			if p.config.componentName == "kube-apiserver" {
				body, err := c.CoreV1().RESTClient().Get().AbsPath("/debug/pprof/" + p.config.kind).DoRaw(context.TODO())
				if err != nil {
					return nil, err
				}
				summary := measurement.CreateSummary(profilePrefix, "pprof", string(body))
				summaries = append(summaries, summary)
				break
			}
			// Only logging error for gke. SSHing to gke master is not supported.
			klog.Warningf("%s: failed to execute curl command on master through SSH", p.name)
			return nil, nil
		}

		sshResult, err := measurementutil.SSH(getCommand, host+":22", p.config.provider)
		if err != nil {
			return nil, fmt.Errorf("failed to execute curl command on master node %s through SSH: %v", host, err)
		}
		summaries = append(summaries, measurement.CreateSummary(profilePrefix, "pprof", sshResult.Stdout))
	}

	return summaries, nil
}

func (p *profileMeasurement) shouldExposeAPIServerDebugEndpoint() bool {
	return p.config.componentName == "kube-apiserver"
}

func (p *profileMeasurement) getProfileCommand(config *measurement.Config) (string, error) {
	profileProtocol, profilePort, err := config.ClusterFramework.GetClusterConfig().Provider.GetComponentProtocolAndPort(p.config.componentName)
	if err != nil {
		return "", goerrors.Errorf("get profile command failed finding component protocol/port: %v", err)
	}

	var command string
	if p.config.componentName == "etcd" {
		etcdCert := config.ClusterFramework.GetClusterConfig().EtcdCertificatePath
		etcdKey := config.ClusterFramework.GetClusterConfig().EtcdKeyPath
		command = fmt.Sprintf("curl -s -k --cert %s --key %s %slocalhost:%v/debug/pprof/%s", etcdCert, etcdKey, profileProtocol, profilePort, p.config.kind)
	} else {
		command = fmt.Sprintf("curl -s -k %slocalhost:%v/debug/pprof/%s", profileProtocol, profilePort, p.config.kind)
	}

	return command, nil
}

func exposeAPIServerDebugEndpoint(c clientset.Interface) error {
	klog.V(2).Info("Exposing kube-apiserver debug endpoint for anonymous access")
	createClusterRole := func() error {
		_, err := c.RbacV1().ClusterRoles().Create(context.TODO(), &rbacv1.ClusterRole{
			ObjectMeta: metav1.ObjectMeta{Name: "apiserver-debug-viewer"},
			Rules: []rbacv1.PolicyRule{
				{Verbs: []string{"get"}, NonResourceURLs: []string{"/debug/*"}},
			},
		}, metav1.CreateOptions{})
		return err
	}
	createClusterRoleBinding := func() error {
		_, err := c.RbacV1().ClusterRoleBindings().Create(context.TODO(), &rbacv1.ClusterRoleBinding{
			ObjectMeta: metav1.ObjectMeta{Name: "anonymous:apiserver-debug-viewer"},
			RoleRef:    rbacv1.RoleRef{Kind: "ClusterRole", Name: "apiserver-debug-viewer"},
			Subjects: []rbacv1.Subject{
				{Kind: "User", Name: "system:anonymous"},
			},
		}, metav1.CreateOptions{})
		return err
	}
	if err := retryCreateFunction(createClusterRole); err != nil {
		return err
	}
	if err := retryCreateFunction(createClusterRoleBinding); err != nil {
		return err
	}
	return nil
}

func retryCreateFunction(f func() error) error {
	return client.RetryWithExponentialBackOff(
		client.RetryFunction(f, client.Allow(apierrs.IsAlreadyExists)))
}
<|endoftext|>


<commit_before>// Copyright 2017 Jeff Foley. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package datasrcs

import (
	"bufio"
	"context"
	"encoding/json"
	"fmt"
	"strings"
	"time"

	"github.com/OWASP/Amass/v3/config"
	"github.com/OWASP/Amass/v3/eventbus"
	"github.com/OWASP/Amass/v3/net/http"
	"github.com/OWASP/Amass/v3/requests"
	"github.com/OWASP/Amass/v3/stringset"
	"github.com/OWASP/Amass/v3/systems"
)

// DNSDB is the Service that handles access to the DNSDB data source.
type DNSDB struct {
	requests.BaseService

	API        *config.APIKey
	SourceType string
	sys        systems.System
}

// NewDNSDB returns he object initialized, but not yet started.
func NewDNSDB(sys systems.System) *DNSDB {
	d := &DNSDB{
		SourceType: requests.SCRAPE,
		sys:        sys,
	}

	d.BaseService = *requests.NewBaseService(d, "DNSDB")
	return d
}

// Type implements the Service interface.
func (d *DNSDB) Type() string {
	return d.SourceType
}

// OnStart implements the Service interface.
func (d *DNSDB) OnStart() error {
	d.BaseService.OnStart()

	d.API = d.sys.Config().GetAPIKey(d.String())
	if d.API == nil || d.API.Key == "" {
		d.sys.Config().Log.Printf("%s: API key data was not provided", d.String())
	}

	d.SetRateLimit(2 * time.Minute)
	return nil
}

// OnDNSRequest implements the Service interface.
func (d *DNSDB) OnDNSRequest(ctx context.Context, req *requests.DNSRequest) {
	cfg := ctx.Value(requests.ContextConfig).(*config.Config)
	bus := ctx.Value(requests.ContextEventBus).(*eventbus.EventBus)
	if cfg == nil || bus == nil {
		return
	}

	if !cfg.IsDomainInScope(req.Domain) {
		return
	}

	if d.API == nil || d.API.Key == "" {
		return
	}

	d.CheckRateLimit()
	bus.Publish(requests.LogTopic, eventbus.PriorityHigh,
		fmt.Sprintf("Querying %s for %s subdomains", d.String(), req.Domain))

	headers := map[string]string{
		"X-API-Key":    d.API.Key,
		"Accept":       "application/json",
		"Content-Type": "application/json",
	}

	url := d.getURL(req.Domain)
	page, err := http.RequestWebPage(url, nil, headers, "", "")
	if err != nil {
		bus.Publish(requests.LogTopic, eventbus.PriorityHigh, fmt.Sprintf("%s: %s: %v", d.String(), url, err))
		return
	}

	for _, name := range d.parse(ctx, page, req.Domain) {
		bus.Publish(requests.NewNameTopic, eventbus.PriorityHigh, &requests.DNSRequest{
			Name:   name,
			Domain: req.Domain,
			Tag:    requests.API,
			Source: d.String(),
		})
	}
}

func (d *DNSDB) getURL(domain string) string {
	return fmt.Sprintf("https://api.dnsdb.info/lookup/rrset/name/*.%s", domain)
}

func (d *DNSDB) parse(ctx context.Context, page, domain string) []string {
	cfg := ctx.Value(requests.ContextConfig).(*config.Config)
	if cfg == nil {
		return []string{}
	}

	re := cfg.DomainRegex(domain)
	if re == nil {
		return []string{}
	}

	unique := stringset.New()
	scanner := bufio.NewScanner(strings.NewReader(page))
	for scanner.Scan() {
		// Get the next line of JSON
		line := scanner.Text()
		if line == "" {
			continue
		}

		var j struct {
			Name string `json:"rrname"`
		}
		err := json.Unmarshal([]byte(line), &j)
		if err != nil {
			continue
		}
		if re.MatchString(j.Name) {
			unique.Insert(j.Name)
		}
	}

	return unique.Slice()
}
<commit_msg>small tweak to the DNSDB data source<commit_after>// Copyright 2017 Jeff Foley. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package datasrcs

import (
	"bufio"
	"context"
	"encoding/json"
	"fmt"
	"strings"
	"time"

	"github.com/OWASP/Amass/v3/config"
	"github.com/OWASP/Amass/v3/eventbus"
	"github.com/OWASP/Amass/v3/net/http"
	"github.com/OWASP/Amass/v3/requests"
	"github.com/OWASP/Amass/v3/stringset"
	"github.com/OWASP/Amass/v3/systems"
)

// DNSDB is the Service that handles access to the DNSDB data source.
type DNSDB struct {
	requests.BaseService

	API        *config.APIKey
	SourceType string
	sys        systems.System
}

// NewDNSDB returns he object initialized, but not yet started.
func NewDNSDB(sys systems.System) *DNSDB {
	d := &DNSDB{
		SourceType: requests.SCRAPE,
		sys:        sys,
	}

	d.BaseService = *requests.NewBaseService(d, "DNSDB")
	return d
}

// Type implements the Service interface.
func (d *DNSDB) Type() string {
	return d.SourceType
}

// OnStart implements the Service interface.
func (d *DNSDB) OnStart() error {
	d.BaseService.OnStart()

	d.API = d.sys.Config().GetAPIKey(d.String())
	if d.API == nil || d.API.Key == "" {
		d.sys.Config().Log.Printf("%s: API key data was not provided", d.String())
	}

	d.SetRateLimit(2 * time.Minute)
	return nil
}

// OnDNSRequest implements the Service interface.
func (d *DNSDB) OnDNSRequest(ctx context.Context, req *requests.DNSRequest) {
	cfg := ctx.Value(requests.ContextConfig).(*config.Config)
	bus := ctx.Value(requests.ContextEventBus).(*eventbus.EventBus)
	if cfg == nil || bus == nil {
		return
	}

	if !cfg.IsDomainInScope(req.Domain) {
		return
	}

	if d.API == nil || d.API.Key == "" {
		return
	}

	d.CheckRateLimit()
	bus.Publish(requests.LogTopic, eventbus.PriorityHigh,
		fmt.Sprintf("Querying %s for %s subdomains", d.String(), req.Domain))

	headers := map[string]string{
		"X-API-Key":    d.API.Key,
		"Accept":       "application/json",
		"Content-Type": "application/json",
	}

	url := d.getURL(req.Domain)
	page, err := http.RequestWebPage(url, nil, headers, "", "")
	if err != nil {
		bus.Publish(requests.LogTopic, eventbus.PriorityHigh, fmt.Sprintf("%s: %s: %v", d.String(), url, err))
		return
	}

	for _, name := range d.parse(ctx, page, req.Domain) {
		bus.Publish(requests.NewNameTopic, eventbus.PriorityHigh, &requests.DNSRequest{
			Name:   name,
			Domain: req.Domain,
			Tag:    requests.API,
			Source: d.String(),
		})
	}
}

func (d *DNSDB) getURL(domain string) string {
	return fmt.Sprintf("https://api.dnsdb.info/lookup/rrset/name/*.%s?limit=10000000", domain)
}

func (d *DNSDB) parse(ctx context.Context, page, domain string) []string {
	cfg := ctx.Value(requests.ContextConfig).(*config.Config)
	if cfg == nil {
		return []string{}
	}

	re := cfg.DomainRegex(domain)
	if re == nil {
		return []string{}
	}

	unique := stringset.New()
	scanner := bufio.NewScanner(strings.NewReader(page))
	for scanner.Scan() {
		// Get the next line of JSON
		line := scanner.Text()
		if line == "" {
			continue
		}

		var j struct {
			Name string `json:"rrname"`
		}
		err := json.Unmarshal([]byte(line), &j)
		if err != nil {
			continue
		}
		if re.MatchString(j.Name) {
			unique.Insert(j.Name)
		}
	}

	return unique.Slice()
}
<|endoftext|>


<commit_before>package main

import (
	_ "github.com/Workiva/go-datastructures/augmentedtree"
	_ "github.com/Workiva/go-datastructures/bitarray"
	_ "github.com/Workiva/go-datastructures/futures"
	_ "github.com/Workiva/go-datastructures/graph"
	_ "github.com/Workiva/go-datastructures/rangetree"
	_ "github.com/Workiva/go-datastructures/set"
	_ "github.com/Workiva/go-datastructures/threadsafe/err"
)
<commit_msg>Fixed up package.<commit_after>package datastructures

import (
	_ "github.com/Workiva/go-datastructures/augmentedtree"
	_ "github.com/Workiva/go-datastructures/bitarray"
	_ "github.com/Workiva/go-datastructures/futures"
	_ "github.com/Workiva/go-datastructures/graph"
	_ "github.com/Workiva/go-datastructures/rangetree"
	_ "github.com/Workiva/go-datastructures/set"
	_ "github.com/Workiva/go-datastructures/threadsafe/err"
)
<|endoftext|>


<commit_before>package restful

// Copyright 2013 Ernest Micklei. All rights reserved.
// Use of this source code is governed by a license
// that can be found in the LICENSE file.

import "strings"

// CrossOriginResourceSharing is used to create a Container Filter that implements CORS.
// Cross-origin resource sharing (CORS) is a mechanism that allows JavaScript on a web page
// to make XMLHttpRequests to another domain, not the domain the JavaScript originated from.
//
// http://en.wikipedia.org/wiki/Cross-origin_resource_sharing
// http://enable-cors.org/server.html
// http://www.html5rocks.com/en/tutorials/cors/#toc-handling-a-not-so-simple-request
type CrossOriginResourceSharing struct {
	ExposeHeaders  []string // list of Header names
	AllowedHeaders []string // list of Header names
	CookiesAllowed bool
	Container      *Container
}

// Filter is a filter function that implements the CORS flow as documented on http://enable-cors.org/server.html
// and http://www.html5rocks.com/static/images/cors_server_flowchart.png
func (c CrossOriginResourceSharing) Filter(req *Request, resp *Response, chain *FilterChain) {
	if origin := req.Request.Header.Get(HEADER_Origin); len(origin) == 0 {
		chain.ProcessFilter(req, resp)
		return
	}
	if req.Request.Method != "OPTIONS" {
		c.doActualRequest(req, resp, chain)
		return
	}
	if acrm := req.Request.Header.Get(HEADER_AccessControlRequestMethod); acrm != "" {
		c.doPreflightRequest(req, resp, chain)
	} else {
		c.doActualRequest(req, resp, chain)
	}
}

func (c CrossOriginResourceSharing) doActualRequest(req *Request, resp *Response, chain *FilterChain) {
	resp.AddHeader(HEADER_AccessControlExposeHeaders, toCommaSeparated(c.AllowedHeaders))
	c.checkAndSetExposeHeaders(resp)
	c.setAllowOriginHeader(req, resp)
	c.checkAndSetAllowCredentials(resp)
	// continue processing the response
	chain.ProcessFilter(req, resp)
}

func (c CrossOriginResourceSharing) doPreflightRequest(req *Request, resp *Response, chain *FilterChain) {
	allowedMethods := c.Container.computeAllowedMethods(req)
	if !c.isValidAccessControlRequestMethod(req.Request.Header.Get(HEADER_AccessControlRequestMethod), allowedMethods) {
		chain.ProcessFilter(req, resp)
		return
	}
	acrhs := req.Request.Header.Get(HEADER_AccessControlRequestHeaders)
	if len(acrhs) > 0 {
		for _, each := range strings.Split(acrhs, ",") {
			if !c.isValidAccessControlRequestHeader(strings.Trim(each, " ")) {
				chain.ProcessFilter(req, resp)
				return
			}
		}
	}
	resp.AddHeader(HEADER_AccessControlAllowMethods, toCommaSeparated(allowedMethods))
	resp.AddHeader(HEADER_AccessControlAllowHeaders, acrhs)
	c.setAllowOriginHeader(req, resp)
	c.checkAndSetAllowCredentials(resp)
	// return http 200 response, no body
}

func (c CrossOriginResourceSharing) setAllowOriginHeader(req *Request, resp *Response) {
	origin := req.Request.Header.Get(HEADER_Origin)
	resp.AddHeader(HEADER_AccessControlAllowOrigin, origin)
}

func (c CrossOriginResourceSharing) checkAndSetExposeHeaders(resp *Response) {
	if len(c.ExposeHeaders) > 0 {
		resp.AddHeader(HEADER_AccessControlExposeHeaders, toCommaSeparated(c.ExposeHeaders))
	}
}

func (c CrossOriginResourceSharing) checkAndSetAllowCredentials(resp *Response) {
	if c.CookiesAllowed {
		resp.AddHeader(HEADER_AccessControlAllowCredentials, "true")
	}
}

func (c CrossOriginResourceSharing) isValidAccessControlRequestMethod(method string, allowedMethods []string) bool {
	for _, each := range allowedMethods {
		if each == method {
			return true
		}
	}
	return false
}

func (c CrossOriginResourceSharing) isValidAccessControlRequestHeader(header string) bool {
	for _, each := range c.AllowedHeaders {
		if strings.ToLower(each) == strings.ToLower(header) {
			return true
		}
	}
	return false
}
<commit_msg>Work on Issue #129<commit_after>package restful

// Copyright 2013 Ernest Micklei. All rights reserved.
// Use of this source code is governed by a license
// that can be found in the LICENSE file.

import "strings"

// CrossOriginResourceSharing is used to create a Container Filter that implements CORS.
// Cross-origin resource sharing (CORS) is a mechanism that allows JavaScript on a web page
// to make XMLHttpRequests to another domain, not the domain the JavaScript originated from.
//
// http://en.wikipedia.org/wiki/Cross-origin_resource_sharing
// http://enable-cors.org/server.html
// http://www.html5rocks.com/en/tutorials/cors/#toc-handling-a-not-so-simple-request
type CrossOriginResourceSharing struct {
	ExposeHeaders  []string // list of Header names
	AllowedHeaders []string // list of Header names
	AllowedDomains []string
	CookiesAllowed bool
	Container      *Container
}

// Filter is a filter function that implements the CORS flow as documented on http://enable-cors.org/server.html
// and http://www.html5rocks.com/static/images/cors_server_flowchart.png
func (c CrossOriginResourceSharing) Filter(req *Request, resp *Response, chain *FilterChain) {
	if origin := req.Request.Header.Get(HEADER_Origin); len(origin) == 0 {
		chain.ProcessFilter(req, resp)
		return
	}
	if req.Request.Method != "OPTIONS" {
		c.doActualRequest(req, resp, chain)
		return
	}
	if acrm := req.Request.Header.Get(HEADER_AccessControlRequestMethod); acrm != "" {
		c.doPreflightRequest(req, resp, chain)
	} else {
		c.doActualRequest(req, resp, chain)
	}
}

func (c CrossOriginResourceSharing) doActualRequest(req *Request, resp *Response, chain *FilterChain) {
	resp.AddHeader(HEADER_AccessControlExposeHeaders, toCommaSeparated(c.AllowedHeaders))
	c.checkAndSetExposeHeaders(resp)
	c.setAllowOriginHeader(req, resp)
	c.checkAndSetAllowCredentials(resp)
	// continue processing the response
	chain.ProcessFilter(req, resp)
}

func (c CrossOriginResourceSharing) doPreflightRequest(req *Request, resp *Response, chain *FilterChain) {
	allowedMethods := c.Container.computeAllowedMethods(req)
	if !c.isValidAccessControlRequestMethod(req.Request.Header.Get(HEADER_AccessControlRequestMethod), allowedMethods) {
		chain.ProcessFilter(req, resp)
		return
	}
	acrhs := req.Request.Header.Get(HEADER_AccessControlRequestHeaders)
	if len(acrhs) > 0 {
		for _, each := range strings.Split(acrhs, ",") {
			if !c.isValidAccessControlRequestHeader(strings.Trim(each, " ")) {
				chain.ProcessFilter(req, resp)
				return
			}
		}
	}
	resp.AddHeader(HEADER_AccessControlAllowMethods, toCommaSeparated(allowedMethods))
	resp.AddHeader(HEADER_AccessControlAllowHeaders, acrhs)
	c.setAllowOriginHeader(req, resp)
	c.checkAndSetAllowCredentials(resp)
	// return http 200 response, no body
}

func (c CrossOriginResourceSharing) isOriginAllowed(req *Request) bool {
	origin := req.Request.Header.Get(HEADER_Origin)
	if len(origin) == 0 {
		return false
	}
	if len(c.AllowedDomains) == 0 {
		return true
	}
	allowed := false
	for _, each := range c.AllowedDomains {
		if each == origin {
			allowed = true
			break
		}
	}
	return allowed
}

func (c CrossOriginResourceSharing) setAllowOriginHeader(req *Request, resp *Response) {
	origin := req.Request.Header.Get(HEADER_Origin)
	resp.AddHeader(HEADER_AccessControlAllowOrigin, origin)
}

func (c CrossOriginResourceSharing) checkAndSetExposeHeaders(resp *Response) {
	if len(c.ExposeHeaders) > 0 {
		resp.AddHeader(HEADER_AccessControlExposeHeaders, toCommaSeparated(c.ExposeHeaders))
	}
}

func (c CrossOriginResourceSharing) checkAndSetAllowCredentials(resp *Response) {
	if c.CookiesAllowed {
		resp.AddHeader(HEADER_AccessControlAllowCredentials, "true")
	}
}

func (c CrossOriginResourceSharing) isValidAccessControlRequestMethod(method string, allowedMethods []string) bool {
	for _, each := range allowedMethods {
		if each == method {
			return true
		}
	}
	return false
}

func (c CrossOriginResourceSharing) isValidAccessControlRequestHeader(header string) bool {
	for _, each := range c.AllowedHeaders {
		if strings.ToLower(each) == strings.ToLower(header) {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>// Copyright 2009 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.

/*
An example of wrapping a C library in Go. This is the GNU
multiprecision library gmp's integer type mpz_t wrapped to look like
the Go package big's integer type Int.

This is a syntactically valid Go program—it can be parsed with the Go
parser and processed by godoc—but it is not compiled directly by 6g.
Instead, a separate tool, cgo, processes it to produce three output
files.  The first two, 6g.go and 6c.c, are a Go source file for 6g and
a C source file for 6c; both compile as part of the named package
(gmp, in this example).  The third, gcc.c, is a C source file for gcc;
it compiles into a shared object (.so) that is dynamically linked into
any 6.out that imports the first two files.

The stanza

	// #include <gmp.h>
	import "C"

is a signal to cgo.  The doc comment on the import of "C" provides
additional context for the C file.  Here it is just a single #include
but it could contain arbitrary C definitions to be imported and used.

Cgo recognizes any use of a qualified identifier C.xxx and uses gcc to
find the definition of xxx.  If xxx is a type, cgo replaces C.xxx with
a Go translation.  C arithmetic types translate to precisely-sized Go
arithmetic types.  A C struct translates to a Go struct, field by
field; unrepresentable fields are replaced with opaque byte arrays.  A
C union translates into a struct containing the first union member and
perhaps additional padding.  C arrays become Go arrays.  C pointers
become Go pointers.  C function pointers become Go's uintptr.
C void pointer's become Go's unsafe.Pointer.

For example, mpz_t is defined in <gmp.h> as:

	typedef unsigned long int mp_limb_t;

	typedef struct
	{
		int _mp_alloc;
		int _mp_size;
		mp_limb_t *_mp_d;
	} __mpz_struct;

	typedef __mpz_struct mpz_t[1];

Cgo generates:

	type _C_int int32
	type _C_mp_limb_t uint64
	type _C___mpz_struct struct {
		_mp_alloc _C_int;
		_mp_size _C_int;
		_mp_d *_C_mp_limb_t;
	}
	type _C_mpz_t [1]_C___mpz_struct

and then replaces each occurrence of a type C.xxx with _C_xxx.

If xxx is data, cgo arranges for C.xxx to refer to the C variable,
with the type translated as described above.  To do this, cgo must
introduce a Go variable that points at the C variable (the linker can
be told to initialize this pointer).  For example, if the gmp library
provided

	mpz_t zero;

then cgo would rewrite a reference to C.zero by introducing

	var _C_zero *C.mpz_t

and then replacing all instances of C.zero with (*_C_zero).

Cgo's most interesting translation is for functions.  If xxx is a C
function, then cgo rewrites C.xxx into a new function _C_xxx that
calls the C xxx in a standard pthread.  The new function translates
its arguments, calls xxx, and translates the return value.

Translation of parameters and the return value follows the type
translation above except that arrays passed as parameters translate
explicitly in Go to pointers to arrays, as they do (implicitly) in C.

Garbage collection is the big problem.  It is fine for the Go world to
have pointers into the C world and to free those pointers when they
are no longer needed.  To help, the Go code can define Go objects
holding the C pointers and use runtime.SetFinalizer on those Go objects.

It is much more difficult for the C world to have pointers into the Go
world, because the Go garbage collector is unaware of the memory
allocated by C.  The most important consideration is not to
constrain future implementations, so the rule is that Go code can
hand a Go pointer to C code but must separately arrange for
Go to hang on to a reference to the pointer until C is done with it.
*/
package gmp

/*
#cgo LDFLAGS: -lgmp
#include <gmp.h>
#include <stdlib.h>

// gmp 5.0.0+ changed the type of the 3rd argument to mp_bitcnt_t,
// so, to support older versions, we wrap these two functions.
void _mpz_mul_2exp(mpz_ptr a, mpz_ptr b, unsigned long n) {
	mpz_mul_2exp(a, b, n);
}
void _mpz_div_2exp(mpz_ptr a, mpz_ptr b, unsigned long n) {
	mpz_div_2exp(a, b, n);
}
*/
import "C"

import (
	"os"
	"unsafe"
)

/*
 * one of a kind
 */

// An Int represents a signed multi-precision integer.
// The zero value for an Int represents the value 0.
type Int struct {
	i    C.mpz_t
	init bool
}

// NewInt returns a new Int initialized to x.
func NewInt(x int64) *Int { return new(Int).SetInt64(x) }

// Int promises that the zero value is a 0, but in gmp
// the zero value is a crash.  To bridge the gap, the
// init bool says whether this is a valid gmp value.
// doinit initializes z.i if it needs it.  This is not inherent
// to FFI, just a mismatch between Go's convention of
// making zero values useful and gmp's decision not to.
func (z *Int) doinit() {
	if z.init {
		return
	}
	z.init = true
	C.mpz_init(&z.i[0])
}

// Bytes returns z's representation as a big-endian byte array.
func (z *Int) Bytes() []byte {
	b := make([]byte, (z.Len()+7)/8)
	n := C.size_t(len(b))
	C.mpz_export(unsafe.Pointer(&b[0]), &n, 1, 1, 1, 0, &z.i[0])
	return b[0:n]
}

// Len returns the length of z in bits.  0 is considered to have length 1.
func (z *Int) Len() int {
	z.doinit()
	return int(C.mpz_sizeinbase(&z.i[0], 2))
}

// Set sets z = x and returns z.
func (z *Int) Set(x *Int) *Int {
	z.doinit()
	C.mpz_set(&z.i[0], &x.i[0])
	return z
}

// SetBytes interprets b as the bytes of a big-endian integer
// and sets z to that value.
func (z *Int) SetBytes(b []byte) *Int {
	z.doinit()
	if len(b) == 0 {
		z.SetInt64(0)
	} else {
		C.mpz_import(&z.i[0], C.size_t(len(b)), 1, 1, 1, 0, unsafe.Pointer(&b[0]))
	}
	return z
}

// SetInt64 sets z = x and returns z.
func (z *Int) SetInt64(x int64) *Int {
	z.doinit()
	// TODO(rsc): more work on 32-bit platforms
	C.mpz_set_si(&z.i[0], C.long(x))
	return z
}

// SetString interprets s as a number in the given base
// and sets z to that value.  The base must be in the range [2,36].
// SetString returns an error if s cannot be parsed or the base is invalid.
func (z *Int) SetString(s string, base int) error {
	z.doinit()
	if base < 2 || base > 36 {
		return os.ErrInvalid
	}
	p := C.CString(s)
	defer C.free(unsafe.Pointer(p))
	if C.mpz_set_str(&z.i[0], p, C.int(base)) < 0 {
		return os.ErrInvalid
	}
	return nil
}

// String returns the decimal representation of z.
func (z *Int) String() string {
	if z == nil {
		return "nil"
	}
	z.doinit()
	p := C.mpz_get_str(nil, 10, &z.i[0])
	s := C.GoString(p)
	C.free(unsafe.Pointer(p))
	return s
}

func (z *Int) destroy() {
	if z.init {
		C.mpz_clear(&z.i[0])
	}
	z.init = false
}

/*
 * arithmetic
 */

// Add sets z = x + y and returns z.
func (z *Int) Add(x, y *Int) *Int {
	x.doinit()
	y.doinit()
	z.doinit()
	C.mpz_add(&z.i[0], &x.i[0], &y.i[0])
	return z
}

// Sub sets z = x - y and returns z.
func (z *Int) Sub(x, y *Int) *Int {
	x.doinit()
	y.doinit()
	z.doinit()
	C.mpz_sub(&z.i[0], &x.i[0], &y.i[0])
	return z
}

// Mul sets z = x * y and returns z.
func (z *Int) Mul(x, y *Int) *Int {
	x.doinit()
	y.doinit()
	z.doinit()
	C.mpz_mul(&z.i[0], &x.i[0], &y.i[0])
	return z
}

// Div sets z = x / y, rounding toward zero, and returns z.
func (z *Int) Div(x, y *Int) *Int {
	x.doinit()
	y.doinit()
	z.doinit()
	C.mpz_tdiv_q(&z.i[0], &x.i[0], &y.i[0])
	return z
}

// Mod sets z = x % y and returns z.
// Like the result of the Go % operator, z has the same sign as x.
func (z *Int) Mod(x, y *Int) *Int {
	x.doinit()
	y.doinit()
	z.doinit()
	C.mpz_tdiv_r(&z.i[0], &x.i[0], &y.i[0])
	return z
}

// Lsh sets z = x << s and returns z.
func (z *Int) Lsh(x *Int, s uint) *Int {
	x.doinit()
	z.doinit()
	C._mpz_mul_2exp(&z.i[0], &x.i[0], C.ulong(s))
	return z
}

// Rsh sets z = x >> s and returns z.
func (z *Int) Rsh(x *Int, s uint) *Int {
	x.doinit()
	z.doinit()
	C._mpz_div_2exp(&z.i[0], &x.i[0], C.ulong(s))
	return z
}

// Exp sets z = x^y % m and returns z.
// If m == nil, Exp sets z = x^y.
func (z *Int) Exp(x, y, m *Int) *Int {
	m.doinit()
	x.doinit()
	y.doinit()
	z.doinit()
	if m == nil {
		C.mpz_pow_ui(&z.i[0], &x.i[0], C.mpz_get_ui(&y.i[0]))
	} else {
		C.mpz_powm(&z.i[0], &x.i[0], &y.i[0], &m.i[0])
	}
	return z
}

func (z *Int) Int64() int64 {
	if !z.init {
		return 0
	}
	return int64(C.mpz_get_si(&z.i[0]))
}

// Neg sets z = -x and returns z.
func (z *Int) Neg(x *Int) *Int {
	x.doinit()
	z.doinit()
	C.mpz_neg(&z.i[0], &x.i[0])
	return z
}

// Abs sets z to the absolute value of x and returns z.
func (z *Int) Abs(x *Int) *Int {
	x.doinit()
	z.doinit()
	C.mpz_abs(&z.i[0], &x.i[0])
	return z
}

/*
 * functions without a clear receiver
 */

// CmpInt compares x and y. The result is
//
//   -1 if x <  y
//    0 if x == y
//   +1 if x >  y
//
func CmpInt(x, y *Int) int {
	x.doinit()
	y.doinit()
	switch cmp := C.mpz_cmp(&x.i[0], &y.i[0]); {
	case cmp < 0:
		return -1
	case cmp == 0:
		return 0
	}
	return +1
}

// DivModInt sets q = x / y and r = x % y.
func DivModInt(q, r, x, y *Int) {
	q.doinit()
	r.doinit()
	x.doinit()
	y.doinit()
	C.mpz_tdiv_qr(&q.i[0], &r.i[0], &x.i[0], &y.i[0])
}

// GcdInt sets d to the greatest common divisor of a and b,
// which must be positive numbers.
// If x and y are not nil, GcdInt sets x and y such that d = a*x + b*y.
// If either a or b is not positive, GcdInt sets d = x = y = 0.
func GcdInt(d, x, y, a, b *Int) {
	d.doinit()
	x.doinit()
	y.doinit()
	a.doinit()
	b.doinit()
	C.mpz_gcdext(&d.i[0], &x.i[0], &y.i[0], &a.i[0], &b.i[0])
}

// ProbablyPrime performs n Miller-Rabin tests to check whether z is prime.
// If it returns true, z is prime with probability 1 - 1/4^n.
// If it returns false, z is not prime.
func (z *Int) ProbablyPrime(n int) bool {
	z.doinit()
	return int(C.mpz_probab_prime_p(&z.i[0], C.int(n))) > 0
}
<commit_msg>misc/cgo/gmp: fix typo.<commit_after>// Copyright 2009 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.

/*
An example of wrapping a C library in Go. This is the GNU
multiprecision library gmp's integer type mpz_t wrapped to look like
the Go package big's integer type Int.

This is a syntactically valid Go program—it can be parsed with the Go
parser and processed by godoc—but it is not compiled directly by 6g.
Instead, a separate tool, cgo, processes it to produce three output
files.  The first two, 6g.go and 6c.c, are a Go source file for 6g and
a C source file for 6c; both compile as part of the named package
(gmp, in this example).  The third, gcc.c, is a C source file for gcc;
it compiles into a shared object (.so) that is dynamically linked into
any 6.out that imports the first two files.

The stanza

	// #include <gmp.h>
	import "C"

is a signal to cgo.  The doc comment on the import of "C" provides
additional context for the C file.  Here it is just a single #include
but it could contain arbitrary C definitions to be imported and used.

Cgo recognizes any use of a qualified identifier C.xxx and uses gcc to
find the definition of xxx.  If xxx is a type, cgo replaces C.xxx with
a Go translation.  C arithmetic types translate to precisely-sized Go
arithmetic types.  A C struct translates to a Go struct, field by
field; unrepresentable fields are replaced with opaque byte arrays.  A
C union translates into a struct containing the first union member and
perhaps additional padding.  C arrays become Go arrays.  C pointers
become Go pointers.  C function pointers become Go's uintptr.
C void pointers become Go's unsafe.Pointer.

For example, mpz_t is defined in <gmp.h> as:

	typedef unsigned long int mp_limb_t;

	typedef struct
	{
		int _mp_alloc;
		int _mp_size;
		mp_limb_t *_mp_d;
	} __mpz_struct;

	typedef __mpz_struct mpz_t[1];

Cgo generates:

	type _C_int int32
	type _C_mp_limb_t uint64
	type _C___mpz_struct struct {
		_mp_alloc _C_int;
		_mp_size _C_int;
		_mp_d *_C_mp_limb_t;
	}
	type _C_mpz_t [1]_C___mpz_struct

and then replaces each occurrence of a type C.xxx with _C_xxx.

If xxx is data, cgo arranges for C.xxx to refer to the C variable,
with the type translated as described above.  To do this, cgo must
introduce a Go variable that points at the C variable (the linker can
be told to initialize this pointer).  For example, if the gmp library
provided

	mpz_t zero;

then cgo would rewrite a reference to C.zero by introducing

	var _C_zero *C.mpz_t

and then replacing all instances of C.zero with (*_C_zero).

Cgo's most interesting translation is for functions.  If xxx is a C
function, then cgo rewrites C.xxx into a new function _C_xxx that
calls the C xxx in a standard pthread.  The new function translates
its arguments, calls xxx, and translates the return value.

Translation of parameters and the return value follows the type
translation above except that arrays passed as parameters translate
explicitly in Go to pointers to arrays, as they do (implicitly) in C.

Garbage collection is the big problem.  It is fine for the Go world to
have pointers into the C world and to free those pointers when they
are no longer needed.  To help, the Go code can define Go objects
holding the C pointers and use runtime.SetFinalizer on those Go objects.

It is much more difficult for the C world to have pointers into the Go
world, because the Go garbage collector is unaware of the memory
allocated by C.  The most important consideration is not to
constrain future implementations, so the rule is that Go code can
hand a Go pointer to C code but must separately arrange for
Go to hang on to a reference to the pointer until C is done with it.
*/
package gmp

/*
#cgo LDFLAGS: -lgmp
#include <gmp.h>
#include <stdlib.h>

// gmp 5.0.0+ changed the type of the 3rd argument to mp_bitcnt_t,
// so, to support older versions, we wrap these two functions.
void _mpz_mul_2exp(mpz_ptr a, mpz_ptr b, unsigned long n) {
	mpz_mul_2exp(a, b, n);
}
void _mpz_div_2exp(mpz_ptr a, mpz_ptr b, unsigned long n) {
	mpz_div_2exp(a, b, n);
}
*/
import "C"

import (
	"os"
	"unsafe"
)

/*
 * one of a kind
 */

// An Int represents a signed multi-precision integer.
// The zero value for an Int represents the value 0.
type Int struct {
	i    C.mpz_t
	init bool
}

// NewInt returns a new Int initialized to x.
func NewInt(x int64) *Int { return new(Int).SetInt64(x) }

// Int promises that the zero value is a 0, but in gmp
// the zero value is a crash.  To bridge the gap, the
// init bool says whether this is a valid gmp value.
// doinit initializes z.i if it needs it.  This is not inherent
// to FFI, just a mismatch between Go's convention of
// making zero values useful and gmp's decision not to.
func (z *Int) doinit() {
	if z.init {
		return
	}
	z.init = true
	C.mpz_init(&z.i[0])
}

// Bytes returns z's representation as a big-endian byte array.
func (z *Int) Bytes() []byte {
	b := make([]byte, (z.Len()+7)/8)
	n := C.size_t(len(b))
	C.mpz_export(unsafe.Pointer(&b[0]), &n, 1, 1, 1, 0, &z.i[0])
	return b[0:n]
}

// Len returns the length of z in bits.  0 is considered to have length 1.
func (z *Int) Len() int {
	z.doinit()
	return int(C.mpz_sizeinbase(&z.i[0], 2))
}

// Set sets z = x and returns z.
func (z *Int) Set(x *Int) *Int {
	z.doinit()
	C.mpz_set(&z.i[0], &x.i[0])
	return z
}

// SetBytes interprets b as the bytes of a big-endian integer
// and sets z to that value.
func (z *Int) SetBytes(b []byte) *Int {
	z.doinit()
	if len(b) == 0 {
		z.SetInt64(0)
	} else {
		C.mpz_import(&z.i[0], C.size_t(len(b)), 1, 1, 1, 0, unsafe.Pointer(&b[0]))
	}
	return z
}

// SetInt64 sets z = x and returns z.
func (z *Int) SetInt64(x int64) *Int {
	z.doinit()
	// TODO(rsc): more work on 32-bit platforms
	C.mpz_set_si(&z.i[0], C.long(x))
	return z
}

// SetString interprets s as a number in the given base
// and sets z to that value.  The base must be in the range [2,36].
// SetString returns an error if s cannot be parsed or the base is invalid.
func (z *Int) SetString(s string, base int) error {
	z.doinit()
	if base < 2 || base > 36 {
		return os.ErrInvalid
	}
	p := C.CString(s)
	defer C.free(unsafe.Pointer(p))
	if C.mpz_set_str(&z.i[0], p, C.int(base)) < 0 {
		return os.ErrInvalid
	}
	return nil
}

// String returns the decimal representation of z.
func (z *Int) String() string {
	if z == nil {
		return "nil"
	}
	z.doinit()
	p := C.mpz_get_str(nil, 10, &z.i[0])
	s := C.GoString(p)
	C.free(unsafe.Pointer(p))
	return s
}

func (z *Int) destroy() {
	if z.init {
		C.mpz_clear(&z.i[0])
	}
	z.init = false
}

/*
 * arithmetic
 */

// Add sets z = x + y and returns z.
func (z *Int) Add(x, y *Int) *Int {
	x.doinit()
	y.doinit()
	z.doinit()
	C.mpz_add(&z.i[0], &x.i[0], &y.i[0])
	return z
}

// Sub sets z = x - y and returns z.
func (z *Int) Sub(x, y *Int) *Int {
	x.doinit()
	y.doinit()
	z.doinit()
	C.mpz_sub(&z.i[0], &x.i[0], &y.i[0])
	return z
}

// Mul sets z = x * y and returns z.
func (z *Int) Mul(x, y *Int) *Int {
	x.doinit()
	y.doinit()
	z.doinit()
	C.mpz_mul(&z.i[0], &x.i[0], &y.i[0])
	return z
}

// Div sets z = x / y, rounding toward zero, and returns z.
func (z *Int) Div(x, y *Int) *Int {
	x.doinit()
	y.doinit()
	z.doinit()
	C.mpz_tdiv_q(&z.i[0], &x.i[0], &y.i[0])
	return z
}

// Mod sets z = x % y and returns z.
// Like the result of the Go % operator, z has the same sign as x.
func (z *Int) Mod(x, y *Int) *Int {
	x.doinit()
	y.doinit()
	z.doinit()
	C.mpz_tdiv_r(&z.i[0], &x.i[0], &y.i[0])
	return z
}

// Lsh sets z = x << s and returns z.
func (z *Int) Lsh(x *Int, s uint) *Int {
	x.doinit()
	z.doinit()
	C._mpz_mul_2exp(&z.i[0], &x.i[0], C.ulong(s))
	return z
}

// Rsh sets z = x >> s and returns z.
func (z *Int) Rsh(x *Int, s uint) *Int {
	x.doinit()
	z.doinit()
	C._mpz_div_2exp(&z.i[0], &x.i[0], C.ulong(s))
	return z
}

// Exp sets z = x^y % m and returns z.
// If m == nil, Exp sets z = x^y.
func (z *Int) Exp(x, y, m *Int) *Int {
	m.doinit()
	x.doinit()
	y.doinit()
	z.doinit()
	if m == nil {
		C.mpz_pow_ui(&z.i[0], &x.i[0], C.mpz_get_ui(&y.i[0]))
	} else {
		C.mpz_powm(&z.i[0], &x.i[0], &y.i[0], &m.i[0])
	}
	return z
}

func (z *Int) Int64() int64 {
	if !z.init {
		return 0
	}
	return int64(C.mpz_get_si(&z.i[0]))
}

// Neg sets z = -x and returns z.
func (z *Int) Neg(x *Int) *Int {
	x.doinit()
	z.doinit()
	C.mpz_neg(&z.i[0], &x.i[0])
	return z
}

// Abs sets z to the absolute value of x and returns z.
func (z *Int) Abs(x *Int) *Int {
	x.doinit()
	z.doinit()
	C.mpz_abs(&z.i[0], &x.i[0])
	return z
}

/*
 * functions without a clear receiver
 */

// CmpInt compares x and y. The result is
//
//   -1 if x <  y
//    0 if x == y
//   +1 if x >  y
//
func CmpInt(x, y *Int) int {
	x.doinit()
	y.doinit()
	switch cmp := C.mpz_cmp(&x.i[0], &y.i[0]); {
	case cmp < 0:
		return -1
	case cmp == 0:
		return 0
	}
	return +1
}

// DivModInt sets q = x / y and r = x % y.
func DivModInt(q, r, x, y *Int) {
	q.doinit()
	r.doinit()
	x.doinit()
	y.doinit()
	C.mpz_tdiv_qr(&q.i[0], &r.i[0], &x.i[0], &y.i[0])
}

// GcdInt sets d to the greatest common divisor of a and b,
// which must be positive numbers.
// If x and y are not nil, GcdInt sets x and y such that d = a*x + b*y.
// If either a or b is not positive, GcdInt sets d = x = y = 0.
func GcdInt(d, x, y, a, b *Int) {
	d.doinit()
	x.doinit()
	y.doinit()
	a.doinit()
	b.doinit()
	C.mpz_gcdext(&d.i[0], &x.i[0], &y.i[0], &a.i[0], &b.i[0])
}

// ProbablyPrime performs n Miller-Rabin tests to check whether z is prime.
// If it returns true, z is prime with probability 1 - 1/4^n.
// If it returns false, z is not prime.
func (z *Int) ProbablyPrime(n int) bool {
	z.doinit()
	return int(C.mpz_probab_prime_p(&z.i[0], C.int(n))) > 0
}
<|endoftext|>


<commit_before>// Copyright 2009 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 fmt

/*
	C-like printf, but because of reflection knowledge does not need
	to be told about sizes and signedness (no %llud etc. - just %d).
*/

import (
	"fmt";
	"reflect";
	"os";
)

const Runeself = 0x80
const AllocSize = 32

export type P struct {
	n	int;
	buf	*[]byte;
	fmt	*Fmt;
}

export func Printer() *P {
	p := new(P);
	p.fmt = fmt.New();
	return p;
}

func (p *P) ensure(n int) {
	if p.buf == nil || len(p.buf) < n {
		newn := AllocSize;
		if p.buf != nil {
			newn += len(p.buf);
		}
		if newn < n {
			newn = n + AllocSize
		}
		b := new([]byte, newn);
		for i := 0; i < p.n; i++ {
			b[i] = p.buf[i];
		}
		p.buf = b;
	}
}

func (p *P) addstr(s string) {
	n := len(s);
	p.ensure(p.n + n);
	for i := 0; i < n; i++ {
		p.buf[p.n] = s[i];
		p.n++;
	}
}

func (p *P) addbytes(b *[]byte, start, end int) {
	p.ensure(p.n + end-start);
	for i := start; i < end; i++ {
		p.buf[p.n] = b[i];
		p.n++;
	}
}

func (p *P) add(c int) {
	p.ensure(p.n + 1);
	if c < Runeself {
		p.buf[p.n] = byte(c);
		p.n++;
	} else {
		p.addstr(string(c));
	}
}

func (p *P) reset() {
	p.n = 0;
}

export type Writer interface {
	Write(b *[]byte) (ret int, err *os.Error);
}

func (p *P) doprintf(format string, v reflect.StructValue);
func (p *P) doprint(v reflect.StructValue, addspace, addnewline bool);

// These routines end in 'f' and take a format string.

func (p *P) fprintf(w Writer, format string, a ...) (n int, error *os.Error) {
	v := reflect.NewValue(a).(reflect.PtrValue).Sub().(reflect.StructValue);
	p.doprintf(format, v);
	n, error = w.Write(p.buf[0:p.n]);
	p.reset();
	return n, error;
}

func (p *P) printf(format string, v ...) (n int, errno *os.Error) {
	n, errno = p.fprintf(os.Stdout, format, v);
	return n, errno;
}

func (p *P) sprintf(format string, v ...) string {
	p.doprintf(format, reflect.NewValue(v).(reflect.StructValue));
	s := string(p.buf)[0 : p.n];
	p.reset();
	return s;
}

// These routines do not take a format string and add spaces only
// when the operand on neither side is a string.

func (p *P) fprint(w Writer, a ...) (n int, error *os.Error) {
	v := reflect.NewValue(a).(reflect.PtrValue).Sub().(reflect.StructValue);
	p.doprint(v, false, false);
	n, error = w.Write(p.buf[0:p.n]);
	p.reset();
	return n, error;
}

func (p *P) print(v ...) (n int, errno *os.Error) {
	n, errno = p.fprint(os.Stdout, v);
	return n, errno;
}

func (p *P) sprint(v ...) string {
	p.doprint(reflect.NewValue(v).(reflect.StructValue), false, false);
	s := string(p.buf)[0 : p.n];
	p.reset();
	return s;
}

// These routines end in 'ln', do not take a format string,
// always add spaces between operands, and add a newline
// after the last operand.

func (p *P) fprintln(w Writer, a ...) (n int, error *os.Error) {
	v := reflect.NewValue(a).(reflect.PtrValue).Sub().(reflect.StructValue);
	p.doprint(v, true, true);
	n, error = w.Write(p.buf[0:p.n]);
	p.reset();
	return n, error;
}

func (p *P) println(v ...) (n int, errno *os.Error) {
	n, errno = p.fprintln(os.Stdout, v);
	return n, errno;
}

func (p *P) sprintln(v ...) string {
	p.doprint(reflect.NewValue(v).(reflect.StructValue), true, true);
	s := string(p.buf)[0 : p.n];
	p.reset();
	return s;
}

// Getters for the fields of the argument structure.

func getInt(v reflect.Value) (val int64, signed, ok bool) {
	switch v.Kind() {
	case reflect.IntKind:
		return int64(v.(reflect.IntValue).Get()), true, true;
	case reflect.Int8Kind:
		return int64(v.(reflect.Int8Value).Get()), true, true;
	case reflect.Int16Kind:
		return int64(v.(reflect.Int16Value).Get()), true, true;
	case reflect.Int32Kind:
		return int64(v.(reflect.Int32Value).Get()), true, true;
	case reflect.Int64Kind:
		return int64(v.(reflect.Int64Value).Get()), true, true;
	case reflect.UintKind:
		return int64(v.(reflect.UintValue).Get()), false, true;
	case reflect.Uint8Kind:
		return int64(v.(reflect.Uint8Value).Get()), false, true;
	case reflect.Uint16Kind:
		return int64(v.(reflect.Uint16Value).Get()), false, true;
	case reflect.Uint32Kind:
		return int64(v.(reflect.Uint32Value).Get()), false, true;
	case reflect.Uint64Kind:
		return int64(v.(reflect.Uint64Value).Get()), false, true;
	}
	return 0, false, false;
}

func getString(v reflect.Value) (val string, ok bool) {
	switch v.Kind() {
	case reflect.StringKind:
		return v.(reflect.StringValue).Get(), true;
	}
	return "", false;
}

func getFloat(v reflect.Value) (val float64, ok bool) {
	switch v.Kind() {
	case reflect.FloatKind:
		return float64(v.(reflect.FloatValue).Get()), true;
	case reflect.Float32Kind:
		return float64(v.(reflect.Float32Value).Get()), true;
	case reflect.Float64Kind:
		return float64(v.(reflect.Float64Value).Get()), true;
	case reflect.Float80Kind:
		break;	// TODO: what to do here?
	}
	return 0.0, false;
}

func getPtr(v reflect.Value) (val uint64, ok bool) {
	switch v.Kind() {
	case reflect.PtrKind:
		return v.(reflect.PtrValue).Get(), true;
	}
	return 0, false;
}

// Convert ASCII to integer.

func parsenum(s string, start, end int) (n int, got bool, newi int) {
	if start >= end {
		return 0, false, end
	}
	if s[start] == '-' {
		a, b, c := parsenum(s, start+1, end);
		if b {
			return -a, b, c;
		}
	}
	isnum := false;
	num := 0;
	for '0' <= s[start] && s[start] <= '9' {
		num = num*10 + int(s[start] - '0');
		start++;
		isnum = true;
	}
	return num, isnum, start;
}

func (p *P) doprintf(format string, v reflect.StructValue) {
	p.ensure(len(format));	// a good starting size
	end := len(format) - 1;
	fieldnum := 0;	// we process one field per non-trivial format
	for i := 0; i <= end;  {
		c, w := sys.stringtorune(format, i);
		if c != '%' || i == end {
			p.add(c);
			i += w;
			continue;
		}
		var got bool;
		// saw % - do we have %20 (width)?
		w, got, i = parsenum(format, i+1, end);
		if got {
			p.fmt.w(w);
		}
		// do we have %.20 (precision)?
		if i < end && format[i] == '.' {
			w, got, i = parsenum(format, i+1, end);
			if got {
				p.fmt.p(w);
			}
		}
		c, w = sys.stringtorune(format, i);
		i += w;
		// percent is special - absorbs no operand
		if c == '%' {
			p.add('%');	// TODO: should we bother with width & prec?
			continue;
		}
		if fieldnum >= v.Len() {	// out of operands
			p.addstr("???");
			continue;
		}
		field := v.Field(fieldnum);
		fieldnum++;
		s := "";
		switch c {
			// bool
			case 't':
				if field.(reflect.BoolValue).Get() {
					s = "true";
				} else {
					s = "false";
				}

			// int
			case 'b':
				if v, signed, ok := getInt(field); ok {
					s = p.fmt.b64(uint64(v)).str()	// always unsigned
				} else {
					s = "%b%"
				}
			case 'd':
				if v, signed, ok := getInt(field); ok {
					if signed {
						s = p.fmt.d64(v).str()
					} else {
						s = p.fmt.ud64(uint64(v)).str()
					}
				} else {
					s = "%d%"
				}
			case 'o':
				if v, signed, ok := getInt(field); ok {
					if signed {
						s = p.fmt.o64(v).str()
					} else {
						s = p.fmt.uo64(uint64(v)).str()
					}
				} else {
					s= "%o%"
				}
			case 'x':
				if v, signed, ok := getInt(field); ok {
					if signed {
						s = p.fmt.x64(v).str()
					} else {
						s = p.fmt.ux64(uint64(v)).str()
					}
				} else {
					s = "%x%"
				}

			// float
			case 'e':
				if v, ok := getFloat(field); ok {
					s = p.fmt.e64(v).str()
				} else {
					s = "%e%"
				}
			case 'f':
				if v, ok := getFloat(field); ok {
					s = p.fmt.f64(v).str()
				} else {
					s = "%f%";
				}
			case 'g':
				if v, ok := getFloat(field); ok {
					s = p.fmt.g64(v).str()
				} else {
					s = "%g%"
				}

			// string
			case 's':
				if v, ok := getString(field); ok {
					s = p.fmt.s(v).str()
				} else {
					s = "%s%"
				}

			// pointer
			case 'p':
				if v, ok := getPtr(field); ok {
					s = "0x" + p.fmt.uX64(v).str()
				} else {
					s = "%p%"
				}

			default:
				s = "?" + string(c) + "?";
		}
		p.addstr(s);
	}
}

func (p *P) doprint(v reflect.StructValue, addspace, addnewline bool) {
	prev_string := false;
	for fieldnum := 0; fieldnum < v.Len();  fieldnum++ {
		// always add spaces if we're doing println
		field := v.Field(fieldnum);
		s := "";
		if fieldnum > 0 {
			if addspace {
				p.add(' ')
			} else if field.Kind() != reflect.StringKind && !prev_string{
				// if not doing println, add spaces if neither side is a string
				p.add(' ')
			}
		}
		switch field.Kind() {
		case reflect.BoolKind:
			s = p.fmt.boolean(field.(reflect.BoolValue).Get()).str();
		case reflect.IntKind, reflect.Int8Kind, reflect.Int16Kind, reflect.Int32Kind, reflect.Int64Kind:
			v, signed, ok := getInt(field);
			s = p.fmt.d64(v).str();
		case reflect.UintKind, reflect.Uint8Kind, reflect.Uint16Kind, reflect.Uint32Kind, reflect.Uint64Kind:
			v, signed, ok := getInt(field);
			s = p.fmt.ud64(uint64(v)).str();
		case reflect.FloatKind, reflect.Float32Kind, reflect.Float64Kind, reflect.Float80Kind:
			v, ok := getFloat(field);
			s = p.fmt.g64(v).str();
		case reflect.StringKind:
			v, ok := getString(field);
			s = p.fmt.s(v).str();
		case reflect.PtrKind:
			v, ok := getPtr(field);
			p.add('0');
			p.add('x');
			s = p.fmt.uX64(v).str();
		case reflect.StructKind:
			p.add('{');
			p.doprint(field, true, false);
			p.add('}');
		default:
			s = "???";
		}
		p.addstr(s);
		prev_string = field.Kind() == reflect.StringKind;
	}
	if addnewline {
		p.add('\n')
	}
}
<commit_msg>prepare for recursive printfs<commit_after>// Copyright 2009 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 fmt

/*
	C-like printf, but because of reflection knowledge does not need
	to be told about sizes and signedness (no %llud etc. - just %d).
*/

import (
	"fmt";
	"reflect";
	"os";
)

const Runeself = 0x80
const AllocSize = 32

type P struct {
	n	int;
	buf	*[]byte;
	fmt	*Fmt;
}

func Printer() *P {
	p := new(P);
	p.fmt = fmt.New();
	return p;
}

func (p *P) ensure(n int) {
	if p.buf == nil || len(p.buf) < n {
		newn := AllocSize;
		if p.buf != nil {
			newn += len(p.buf);
		}
		if newn < n {
			newn = n + AllocSize
		}
		b := new([]byte, newn);
		for i := 0; i < p.n; i++ {
			b[i] = p.buf[i];
		}
		p.buf = b;
	}
}

func (p *P) addstr(s string) {
	n := len(s);
	p.ensure(p.n + n);
	for i := 0; i < n; i++ {
		p.buf[p.n] = s[i];
		p.n++;
	}
}

func (p *P) addbytes(b *[]byte, start, end int) {
	p.ensure(p.n + end-start);
	for i := start; i < end; i++ {
		p.buf[p.n] = b[i];
		p.n++;
	}
}

func (p *P) add(c int) {
	p.ensure(p.n + 1);
	if c < Runeself {
		p.buf[p.n] = byte(c);
		p.n++;
	} else {
		p.addstr(string(c));
	}
}

// Implement Write so we can call fprintf on a P, for
// recursive use in custom verbs.
func (p *P) Write(b *[]byte) (ret int, err *os.Error) {
	p.addbytes(b, 0, len(b));
	return len(b), nil;
}

export type Writer interface {
	Write(b *[]byte) (ret int, err *os.Error);
}

func (p *P) doprintf(format string, v reflect.StructValue);
func (p *P) doprint(v reflect.StructValue, addspace, addnewline bool);

// These routines end in 'f' and take a format string.

export func fprintf(w Writer, format string, a ...) (n int, error *os.Error) {
	v := reflect.NewValue(a).(reflect.PtrValue).Sub().(reflect.StructValue);
	p := Printer();
	p.doprintf(format, v);
	n, error = w.Write(p.buf[0:p.n]);
	return n, error;
}

export func printf(format string, v ...) (n int, errno *os.Error) {
	n, errno = fprintf(os.Stdout, format, v);
	return n, errno;
}

export func sprintf(format string, v ...) string {
	p := Printer();
	p.doprintf(format, reflect.NewValue(v).(reflect.StructValue));
	s := string(p.buf)[0 : p.n];
	return s;
}

// These routines do not take a format string and add spaces only
// when the operand on neither side is a string.

export func fprint(w Writer, a ...) (n int, error *os.Error) {
	v := reflect.NewValue(a).(reflect.PtrValue).Sub().(reflect.StructValue);
	p := Printer();
	p.doprint(v, false, false);
	n, error = w.Write(p.buf[0:p.n]);
	return n, error;
}

export func print(v ...) (n int, errno *os.Error) {
	n, errno = fprint(os.Stdout, v);
	return n, errno;
}

export func sprint(v ...) string {
	p := Printer();
	p.doprint(reflect.NewValue(v).(reflect.StructValue), false, false);
	s := string(p.buf)[0 : p.n];
	return s;
}

// These routines end in 'ln', do not take a format string,
// always add spaces between operands, and add a newline
// after the last operand.

export func fprintln(w Writer, a ...) (n int, error *os.Error) {
	v := reflect.NewValue(a).(reflect.PtrValue).Sub().(reflect.StructValue);
	p := Printer();
	p.doprint(v, true, true);
	n, error = w.Write(p.buf[0:p.n]);
	return n, error;
}

export func println(v ...) (n int, errno *os.Error) {
	n, errno = fprintln(os.Stdout, v);
	return n, errno;
}

export func sprintln(v ...) string {
	p := Printer();
	p.doprint(reflect.NewValue(v).(reflect.StructValue), true, true);
	s := string(p.buf)[0 : p.n];
	return s;
}

// Getters for the fields of the argument structure.

func getInt(v reflect.Value) (val int64, signed, ok bool) {
	switch v.Kind() {
	case reflect.IntKind:
		return int64(v.(reflect.IntValue).Get()), true, true;
	case reflect.Int8Kind:
		return int64(v.(reflect.Int8Value).Get()), true, true;
	case reflect.Int16Kind:
		return int64(v.(reflect.Int16Value).Get()), true, true;
	case reflect.Int32Kind:
		return int64(v.(reflect.Int32Value).Get()), true, true;
	case reflect.Int64Kind:
		return int64(v.(reflect.Int64Value).Get()), true, true;
	case reflect.UintKind:
		return int64(v.(reflect.UintValue).Get()), false, true;
	case reflect.Uint8Kind:
		return int64(v.(reflect.Uint8Value).Get()), false, true;
	case reflect.Uint16Kind:
		return int64(v.(reflect.Uint16Value).Get()), false, true;
	case reflect.Uint32Kind:
		return int64(v.(reflect.Uint32Value).Get()), false, true;
	case reflect.Uint64Kind:
		return int64(v.(reflect.Uint64Value).Get()), false, true;
	}
	return 0, false, false;
}

func getString(v reflect.Value) (val string, ok bool) {
	switch v.Kind() {
	case reflect.StringKind:
		return v.(reflect.StringValue).Get(), true;
	}
	return "", false;
}

func getFloat(v reflect.Value) (val float64, ok bool) {
	switch v.Kind() {
	case reflect.FloatKind:
		return float64(v.(reflect.FloatValue).Get()), true;
	case reflect.Float32Kind:
		return float64(v.(reflect.Float32Value).Get()), true;
	case reflect.Float64Kind:
		return float64(v.(reflect.Float64Value).Get()), true;
	case reflect.Float80Kind:
		break;	// TODO: what to do here?
	}
	return 0.0, false;
}

func getPtr(v reflect.Value) (val uint64, ok bool) {
	switch v.Kind() {
	case reflect.PtrKind:
		return v.(reflect.PtrValue).Get(), true;
	}
	return 0, false;
}

// Convert ASCII to integer.

func parsenum(s string, start, end int) (n int, got bool, newi int) {
	if start >= end {
		return 0, false, end
	}
	if s[start] == '-' {
		a, b, c := parsenum(s, start+1, end);
		if b {
			return -a, b, c;
		}
	}
	isnum := false;
	num := 0;
	for '0' <= s[start] && s[start] <= '9' {
		num = num*10 + int(s[start] - '0');
		start++;
		isnum = true;
	}
	return num, isnum, start;
}

func (p *P) doprintf(format string, v reflect.StructValue) {
	p.ensure(len(format));	// a good starting size
	end := len(format) - 1;
	fieldnum := 0;	// we process one field per non-trivial format
	for i := 0; i <= end;  {
		c, w := sys.stringtorune(format, i);
		if c != '%' || i == end {
			p.add(c);
			i += w;
			continue;
		}
		var got bool;
		// saw % - do we have %20 (width)?
		w, got, i = parsenum(format, i+1, end);
		if got {
			p.fmt.w(w);
		}
		// do we have %.20 (precision)?
		if i < end && format[i] == '.' {
			w, got, i = parsenum(format, i+1, end);
			if got {
				p.fmt.p(w);
			}
		}
		c, w = sys.stringtorune(format, i);
		i += w;
		// percent is special - absorbs no operand
		if c == '%' {
			p.add('%');	// TODO: should we bother with width & prec?
			continue;
		}
		if fieldnum >= v.Len() {	// out of operands
			p.addstr("???");
			continue;
		}
		field := v.Field(fieldnum);
		fieldnum++;
		s := "";
		switch c {
			// bool
			case 't':
				if field.(reflect.BoolValue).Get() {
					s = "true";
				} else {
					s = "false";
				}

			// int
			case 'b':
				if v, signed, ok := getInt(field); ok {
					s = p.fmt.b64(uint64(v)).str()	// always unsigned
				} else {
					s = "%b%"
				}
			case 'd':
				if v, signed, ok := getInt(field); ok {
					if signed {
						s = p.fmt.d64(v).str()
					} else {
						s = p.fmt.ud64(uint64(v)).str()
					}
				} else {
					s = "%d%"
				}
			case 'o':
				if v, signed, ok := getInt(field); ok {
					if signed {
						s = p.fmt.o64(v).str()
					} else {
						s = p.fmt.uo64(uint64(v)).str()
					}
				} else {
					s= "%o%"
				}
			case 'x':
				if v, signed, ok := getInt(field); ok {
					if signed {
						s = p.fmt.x64(v).str()
					} else {
						s = p.fmt.ux64(uint64(v)).str()
					}
				} else {
					s = "%x%"
				}

			// float
			case 'e':
				if v, ok := getFloat(field); ok {
					s = p.fmt.e64(v).str()
				} else {
					s = "%e%"
				}
			case 'f':
				if v, ok := getFloat(field); ok {
					s = p.fmt.f64(v).str()
				} else {
					s = "%f%";
				}
			case 'g':
				if v, ok := getFloat(field); ok {
					s = p.fmt.g64(v).str()
				} else {
					s = "%g%"
				}

			// string
			case 's':
				if v, ok := getString(field); ok {
					s = p.fmt.s(v).str()
				} else {
					s = "%s%"
				}

			// pointer
			case 'p':
				if v, ok := getPtr(field); ok {
					s = "0x" + p.fmt.uX64(v).str()
				} else {
					s = "%p%"
				}

			default:
				s = "?" + string(c) + "?";
		}
		p.addstr(s);
	}
}

func (p *P) doprint(v reflect.StructValue, addspace, addnewline bool) {
	prev_string := false;
	for fieldnum := 0; fieldnum < v.Len();  fieldnum++ {
		// always add spaces if we're doing println
		field := v.Field(fieldnum);
		s := "";
		if fieldnum > 0 {
			if addspace {
				p.add(' ')
			} else if field.Kind() != reflect.StringKind && !prev_string{
				// if not doing println, add spaces if neither side is a string
				p.add(' ')
			}
		}
		switch field.Kind() {
		case reflect.BoolKind:
			s = p.fmt.boolean(field.(reflect.BoolValue).Get()).str();
		case reflect.IntKind, reflect.Int8Kind, reflect.Int16Kind, reflect.Int32Kind, reflect.Int64Kind:
			v, signed, ok := getInt(field);
			s = p.fmt.d64(v).str();
		case reflect.UintKind, reflect.Uint8Kind, reflect.Uint16Kind, reflect.Uint32Kind, reflect.Uint64Kind:
			v, signed, ok := getInt(field);
			s = p.fmt.ud64(uint64(v)).str();
		case reflect.FloatKind, reflect.Float32Kind, reflect.Float64Kind, reflect.Float80Kind:
			v, ok := getFloat(field);
			s = p.fmt.g64(v).str();
		case reflect.StringKind:
			v, ok := getString(field);
			s = p.fmt.s(v).str();
		case reflect.PtrKind:
			v, ok := getPtr(field);
			p.add('0');
			p.add('x');
			s = p.fmt.uX64(v).str();
		case reflect.StructKind:
			p.add('{');
			p.doprint(field, true, false);
			p.add('}');
		default:
			s = "???";
		}
		p.addstr(s);
		prev_string = field.Kind() == reflect.StringKind;
	}
	if addnewline {
		p.add('\n')
	}
}
<|endoftext|>


<commit_before>package sarama

import (
	"encoding/binary"
	"fmt"
	"hash/crc32"
)

const (
	crcIEEE = iota
	crcCastagnoli
)

var castagnoliTable = crc32.MakeTable(crc32.Castagnoli)

// crc32Field implements the pushEncoder and pushDecoder interfaces for calculating CRC32s.
type crc32Field struct {
	startOffset int
	polynomial  int
}

func (c *crc32Field) saveOffset(in int) {
	c.startOffset = in
}

func (c *crc32Field) reserveLength() int {
	return 4
}

func newCRC32Field(polynomial int) *crc32Field {
	return &crc32Field{polynomial: polynomial}
}

func (c *crc32Field) run(curOffset int, buf []byte) error {
	crc, err := c.crc(curOffset, buf)
	if err != nil {
		return err
	}
	binary.BigEndian.PutUint32(buf[c.startOffset:], crc)
	return nil
}

func (c *crc32Field) check(curOffset int, buf []byte) error {
	crc, err := c.crc(curOffset, buf)
	if err != nil {
		return err
	}

	expected := binary.BigEndian.Uint32(buf[c.startOffset:])
	if crc != expected {
		return PacketDecodingError{fmt.Sprintf("CRC didn't match expected %#x got %#x", expected, crc)}
	}

	return nil
}
func (c *crc32Field) crc(curOffset int, buf []byte) (uint32, error) {
	var tab *crc32.Table
	switch c.polynomial {
	case crcIEEE:
		tab = crc32.IEEETable
	case crcCastagnoli:
		tab = castagnoliTable
	default:
		return 0, PacketDecodingError{"invalid CRC type"}
	}
	return crc32.Checksum(buf[c.startOffset+4:curOffset], tab), nil
}
<commit_msg>Make polynomial a type<commit_after>package sarama

import (
	"encoding/binary"
	"fmt"
	"hash/crc32"
)

type crcPolynomial int8

const (
	crcIEEE crcPolynomial = iota
	crcCastagnoli
)

var castagnoliTable = crc32.MakeTable(crc32.Castagnoli)

// crc32Field implements the pushEncoder and pushDecoder interfaces for calculating CRC32s.
type crc32Field struct {
	startOffset int
	polynomial  crcPolynomial
}

func (c *crc32Field) saveOffset(in int) {
	c.startOffset = in
}

func (c *crc32Field) reserveLength() int {
	return 4
}

func newCRC32Field(polynomial crcPolynomial) *crc32Field {
	return &crc32Field{polynomial: polynomial}
}

func (c *crc32Field) run(curOffset int, buf []byte) error {
	crc, err := c.crc(curOffset, buf)
	if err != nil {
		return err
	}
	binary.BigEndian.PutUint32(buf[c.startOffset:], crc)
	return nil
}

func (c *crc32Field) check(curOffset int, buf []byte) error {
	crc, err := c.crc(curOffset, buf)
	if err != nil {
		return err
	}

	expected := binary.BigEndian.Uint32(buf[c.startOffset:])
	if crc != expected {
		return PacketDecodingError{fmt.Sprintf("CRC didn't match expected %#x got %#x", expected, crc)}
	}

	return nil
}
func (c *crc32Field) crc(curOffset int, buf []byte) (uint32, error) {
	var tab *crc32.Table
	switch c.polynomial {
	case crcIEEE:
		tab = crc32.IEEETable
	case crcCastagnoli:
		tab = castagnoliTable
	default:
		return 0, PacketDecodingError{"invalid CRC type"}
	}
	return crc32.Checksum(buf[c.startOffset+4:curOffset], tab), nil
}
<|endoftext|>


<commit_before>package capn_test

import (
	"fmt"
	"testing"

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

func TestCreationOfZDate(t *testing.T) {
	const n = 1
	packed := false
	seg, _ := zdateFilledSegment(n, packed)
	text := CapnpDecodeSegment(seg, "", "test.capnp", "Z")

	//expectedText := `(year = 2004, month = 12, day = 7)`
	expectedText := `(zdatevec = [(year = 2004, month = 12, day = 7)])`

	cv.Convey("Given a go-capnproto created Zdate", t, func() {
		cv.Convey("When we decode it with capnp", func() {
			cv.Convey(fmt.Sprintf("Then we should get the expected text '%s'", expectedText), func() {
				cv.So(text, cv.ShouldEqual, expectedText)
			})
		})
	})
}

func TestCreationOfManyZDate(t *testing.T) {
	const n = 10
	packed := false
	seg, _ := zdateFilledSegment(n, packed)
	text := CapnpDecodeSegment(seg, "", "test.capnp", "Z")

	expectedText := `(zdatevec = [(year = 2004, month = 12, day = 7), (year = 2005, month = 12, day = 7), (year = 2006, month = 12, day = 7), (year = 2007, month = 12, day = 7), (year = 2008, month = 12, day = 7), (year = 2009, month = 12, day = 7), (year = 2010, month = 12, day = 7), (year = 2011, month = 12, day = 7), (year = 2012, month = 12, day = 7), (year = 2013, month = 12, day = 7)])`

	cv.Convey("Given a go-capnproto created segment with 10 Zdate", t, func() {
		cv.Convey("When we decode it with capnp", func() {
			cv.Convey(fmt.Sprintf("Then we should get the expected text '%s'", expectedText), func() {
				cv.So(text, cv.ShouldEqual, expectedText)
			})
		})
	})
}
<commit_msg>add test for packed zdate and for zdata correct creation<commit_after>package capn_test

import (
	"fmt"
	"testing"

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

func TestCreationOfZDate(t *testing.T) {
	const n = 1
	packed := false
	seg, _ := zdateFilledSegment(n, packed)
	text := CapnpDecodeSegment(seg, "", "test.capnp", "Z")

	//expectedText := `(year = 2004, month = 12, day = 7)`
	expectedText := `(zdatevec = [(year = 2004, month = 12, day = 7)])`

	cv.Convey("Given a go-capnproto created Zdate", t, func() {
		cv.Convey("When we decode it with capnp", func() {
			cv.Convey(fmt.Sprintf("Then we should get the expected text '%s'", expectedText), func() {
				cv.So(text, cv.ShouldEqual, expectedText)
			})
		})
	})
}

func TestCreationOfManyZDate(t *testing.T) {
	const n = 10
	packed := false
	seg, _ := zdateFilledSegment(n, packed)
	text := CapnpDecodeSegment(seg, "", "test.capnp", "Z")

	expectedText := `(zdatevec = [(year = 2004, month = 12, day = 7), (year = 2005, month = 12, day = 7), (year = 2006, month = 12, day = 7), (year = 2007, month = 12, day = 7), (year = 2008, month = 12, day = 7), (year = 2009, month = 12, day = 7), (year = 2010, month = 12, day = 7), (year = 2011, month = 12, day = 7), (year = 2012, month = 12, day = 7), (year = 2013, month = 12, day = 7)])`

	cv.Convey("Given a go-capnproto created segment with 10 Zdate", t, func() {
		cv.Convey("When we decode it with capnp", func() {
			cv.Convey(fmt.Sprintf("Then we should get the expected text '%s'", expectedText), func() {
				cv.So(text, cv.ShouldEqual, expectedText)
			})
		})
	})
}

func TestCreationOfManyZDatePacked(t *testing.T) {
	const n = 10
	packed := true
	seg, _ := zdateFilledSegment(n, packed)
	text := CapnpDecodeSegment(seg, "", "test.capnp", "Z")

	expectedText := `(zdatevec = [(year = 2004, month = 12, day = 7), (year = 2005, month = 12, day = 7), (year = 2006, month = 12, day = 7), (year = 2007, month = 12, day = 7), (year = 2008, month = 12, day = 7), (year = 2009, month = 12, day = 7), (year = 2010, month = 12, day = 7), (year = 2011, month = 12, day = 7), (year = 2012, month = 12, day = 7), (year = 2013, month = 12, day = 7)])`

	cv.Convey("Given a go-capnproto created a PACKED segment with 10 Zdate", t, func() {
		cv.Convey("When we decode it with capnp", func() {
			cv.Convey(fmt.Sprintf("Then we should get the expected text '%s'", expectedText), func() {
				cv.So(text, cv.ShouldEqual, expectedText)
			})
		})
	})
}

/// now for Zdata (not Zdate)

func TestCreationOfZData(t *testing.T) {
	const n = 20
	seg, _ := zdataFilledSegment(n)
	text := CapnpDecodeSegment(seg, "", "test.capnp", "Z")

	expectedText := `(zdata = (data = "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13"))`

	cv.Convey("Given a go-capnproto created Zdata DATA element with n=20", t, func() {
		cv.Convey("When we decode it with capnp", func() {
			cv.Convey(fmt.Sprintf("Then we should get the expected text '%s'", expectedText), func() {
				cv.So(text, cv.ShouldEqual, expectedText)
			})
			cv.Convey("And our data should contain Z_ZDATA with contents 0,1,2,...,n", func() {
				z := ReadRootZ(seg)
				cv.So(z.Which(), cv.ShouldEqual, Z_ZDATA)

				var data []byte = z.Zdata().Data()
				cv.So(len(data), cv.ShouldEqual, n)
				for i := range data {
					cv.So(data[i], cv.ShouldEqual, i)
				}

			})
		})
	})

}
<|endoftext|>


<commit_before>// The magick package is a hacked up port of the minimal functionality we need
// to satisfy the IIIFImage interface.  Code is based in part on
// github.com/quirkey/magick
package magick

/*
#cgo pkg-config: MagickCore
#include <magick/MagickCore.h>
*/
import "C"
import (
	"fmt"
	"os"
	"unsafe"
)

func init() {
	path, _ := os.Getwd()
	cPath := C.CString(path)
	defer C.free(unsafe.Pointer(cPath))
	C.MagickCoreGenesis(cPath, C.MagickFalse)
}

func makeError(exception *C.ExceptionInfo) (error) {
	return fmt.Errorf("%s: %s - %s", exception.severity, exception.reason, exception.description)
}
<commit_msg>Fix formatting of magick.go<commit_after>// The magick package is a hacked up port of the minimal functionality we need
// to satisfy the IIIFImage interface.  Code is based in part on
// github.com/quirkey/magick
package magick

/*
#cgo pkg-config: MagickCore
#include <magick/MagickCore.h>
*/
import "C"
import (
	"fmt"
	"os"
	"unsafe"
)

func init() {
	path, _ := os.Getwd()
	cPath := C.CString(path)
	defer C.free(unsafe.Pointer(cPath))
	C.MagickCoreGenesis(cPath, C.MagickFalse)
}

func makeError(exception *C.ExceptionInfo) error {
	return fmt.Errorf("%s: %s - %s", exception.severity, exception.reason, exception.description)
}
<|endoftext|>


<commit_before>package orchestrators

import (
	log "github.com/Sirupsen/logrus"
	"github.com/camptocamp/conplicity/handler"
	"github.com/camptocamp/conplicity/volume"
)

// Orchestrator implements a container Orchestrator interface
type Orchestrator interface {
	GetHandler() *handler.Conplicity
	GetVolumes() ([]*volume.Volume, error)
	LaunchContainer(image string, env map[string]string, cmd []string, v []*volume.Volume) (state int, stdout string, err error)
	GetMountedVolumes() ([]*volume.MountedVolumes, error)
	ContainerExec(containerID string, command []string) error
}

// GetOrchestrator returns the Orchestrator as specified in configuration
func GetOrchestrator(c *handler.Conplicity) Orchestrator {
	orch := c.Config.Orchestrator
	log.Debugf("orchestrator=%s", orch)

	switch orch {
	case "docker":
		return NewDockerOrchestrator(c)
	}

	log.Fatalf("Unknown orchestrator %s", orch)
	return nil
}
<commit_msg>Update volumes variable name for LaunchContainer<commit_after>package orchestrators

import (
	log "github.com/Sirupsen/logrus"
	"github.com/camptocamp/conplicity/handler"
	"github.com/camptocamp/conplicity/volume"
)

// Orchestrator implements a container Orchestrator interface
type Orchestrator interface {
	GetHandler() *handler.Conplicity
	GetVolumes() ([]*volume.Volume, error)
	LaunchContainer(image string, env map[string]string, cmd []string, volumes []*volume.Volume) (state int, stdout string, err error)
	GetMountedVolumes() ([]*volume.MountedVolumes, error)
	ContainerExec(containerID string, command []string) error
}

// GetOrchestrator returns the Orchestrator as specified in configuration
func GetOrchestrator(c *handler.Conplicity) Orchestrator {
	orch := c.Config.Orchestrator
	log.Debugf("orchestrator=%s", orch)

	switch orch {
	case "docker":
		return NewDockerOrchestrator(c)
	}

	log.Fatalf("Unknown orchestrator %s", orch)
	return nil
}
<|endoftext|>